diff --git a/src/main/java/io/kamax/mxisd/as/AppServiceHandler.java b/src/main/java/io/kamax/mxisd/as/AppServiceHandler.java index 258bb48..11cf4c1 100644 --- a/src/main/java/io/kamax/mxisd/as/AppServiceHandler.java +++ b/src/main/java/io/kamax/mxisd/as/AppServiceHandler.java @@ -23,8 +23,10 @@ package io.kamax.mxisd.as; import com.google.gson.JsonObject; import io.kamax.matrix.MatrixID; import io.kamax.matrix._MatrixID; +import io.kamax.matrix._ThreePid; import io.kamax.matrix.event.EventKey; import io.kamax.matrix.json.GsonUtil; +import io.kamax.mxisd.backend.sql.synapse.Synapse; import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.notification.NotificationManager; import io.kamax.mxisd.profile.ProfileManager; @@ -36,6 +38,7 @@ import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.List; +import java.util.Map; @Component public class AppServiceHandler { @@ -45,12 +48,14 @@ public class AppServiceHandler { private MatrixConfig cfg; private ProfileManager profiler; private NotificationManager notif; + private Synapse synapse; @Autowired - public AppServiceHandler(MatrixConfig cfg, ProfileManager profiler, NotificationManager notif) { + public AppServiceHandler(MatrixConfig cfg, ProfileManager profiler, NotificationManager notif, Synapse synapse) { this.cfg = cfg; this.profiler = profiler; this.notif = notif; + this.synapse = synapse; } public void processTransaction(List eventsJson) { @@ -66,22 +71,27 @@ public class AppServiceHandler { String roomId = GsonUtil.getStringOrNull(ev, "room_id"); _MatrixID sender = MatrixID.asAcceptable(GsonUtil.getStringOrNull(ev, "sender")); EventKey.StateKey.findString(ev).ifPresent(id -> { - log.info("Got invite for {}", id); + _MatrixID mxid = MatrixID.asAcceptable(id); if (!StringUtils.equals(mxid.getDomain(), cfg.getDomain())) { - log.info("Ignoring invite for {}: not a local user"); + log.debug("Ignoring invite for {}: not a local user"); return; } + log.info("Got invite for {}", id); - profiler.getThreepids(mxid).forEach(tpid -> { + for (_ThreePid tpid : profiler.getThreepids(mxid)) { if (!StringUtils.equals("email", tpid.getMedium())) { - return; + continue; } log.info("Found an email address to notify about room invitation: {}", tpid.getAddress()); - IMatrixIdInvite inv = new MatrixIdInvite(roomId, sender, mxid, tpid.getMedium(), tpid.getAddress(), new HashMap<>()); + Map properties = new HashMap<>(); + profiler.getDisplayName(mxid).ifPresent(name -> properties.put("sender_display_name", name)); + synapse.getRoomName(roomId).ifPresent(name -> properties.put("room_name", name)); + + IMatrixIdInvite inv = new MatrixIdInvite(roomId, sender, mxid, tpid.getMedium(), tpid.getAddress(), properties); notif.sendForInvite(inv); - }); + } }); }); } diff --git a/src/main/java/io/kamax/mxisd/backend/memory/MemoryIdentityStore.java b/src/main/java/io/kamax/mxisd/backend/memory/MemoryIdentityStore.java index bd6ee43..f4e0203 100644 --- a/src/main/java/io/kamax/mxisd/backend/memory/MemoryIdentityStore.java +++ b/src/main/java/io/kamax/mxisd/backend/memory/MemoryIdentityStore.java @@ -1,6 +1,6 @@ /* * mxisd - Matrix Identity Server Daemon - * Copyright (C) 2018 Maxime Dor + * Copyright (C) 2018 Kamax Sarl * * https://www.kamax.io/ * @@ -76,6 +76,11 @@ public class MemoryIdentityStore implements AuthenticatorProvider, IDirectoryPro return cfg.isEnabled(); } + @Override + public Optional getDisplayName(_MatrixID mxid) { + return findByUsername(mxid.getLocalPart()).map(MemoryIdentityConfig::getDisplayName); + } + private UserDirectorySearchResult search( Predicate predicate, Function mapper diff --git a/src/main/java/io/kamax/mxisd/backend/sql/SqlConnectionPool.java b/src/main/java/io/kamax/mxisd/backend/sql/SqlConnectionPool.java index 5515cb7..4f3224c 100644 --- a/src/main/java/io/kamax/mxisd/backend/sql/SqlConnectionPool.java +++ b/src/main/java/io/kamax/mxisd/backend/sql/SqlConnectionPool.java @@ -1,8 +1,8 @@ /* * mxisd - Matrix Identity Server Daemon - * Copyright (C) 2017 Maxime Dor + * Copyright (C) 2017 Kamax Sarl * - * https://max.kamax.io/ + * https://www.kamax.io/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -28,6 +28,12 @@ import java.sql.SQLException; public class SqlConnectionPool { + public interface SqlFunction { + + R run(T connection) throws SQLException; + + } + private ComboPooledDataSource ds; public SqlConnectionPool(SqlConfig cfg) { @@ -42,4 +48,12 @@ public class SqlConnectionPool { return ds.getConnection(); } + public T withConnFunction(SqlFunction function) { + try (Connection conn = get()) { + return function.run(conn); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + } diff --git a/src/main/java/io/kamax/mxisd/backend/sql/SqlProfileProvider.java b/src/main/java/io/kamax/mxisd/backend/sql/SqlProfileProvider.java new file mode 100644 index 0000000..9cacf77 --- /dev/null +++ b/src/main/java/io/kamax/mxisd/backend/sql/SqlProfileProvider.java @@ -0,0 +1,105 @@ +/* + * mxisd - Matrix Identity Server Daemon + * Copyright (C) 2018 Kamax Sarl + * + * https://www.kamax.io/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.kamax.mxisd.backend.sql; + +import io.kamax.matrix.ThreePid; +import io.kamax.matrix._MatrixID; +import io.kamax.matrix._ThreePid; +import io.kamax.mxisd.config.sql.SqlConfig; +import io.kamax.mxisd.profile.ProfileProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +public abstract class SqlProfileProvider implements ProfileProvider { + + private Logger log = LoggerFactory.getLogger(SqlProfileProvider.class); + + private SqlConfig.Profile cfg; + + private SqlConnectionPool pool; + + public SqlProfileProvider(SqlConfig cfg) { + this.cfg = cfg.getProfile(); + this.pool = new SqlConnectionPool(cfg); + } + + @Override + public boolean isEnabled() { + return cfg.isEnabled(); + } + + @Override + public Optional getDisplayName(_MatrixID user) { + String stmtSql = cfg.getDisplayName().getQuery(); + try (Connection conn = pool.get()) { + try (PreparedStatement stmt = conn.prepareStatement(stmtSql)) { + stmt.setString(1, user.getId()); + + try (ResultSet rSet = stmt.executeQuery()) { + if (!rSet.next()) { + return Optional.empty(); + } + + return Optional.ofNullable(rSet.getString(1)); + } + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + @Override + public List<_ThreePid> getThreepids(_MatrixID user) { + List<_ThreePid> threepids = new ArrayList<>(); + + String stmtSql = cfg.getThreepid().getQuery(); + try (Connection conn = pool.get()) { + PreparedStatement stmt = conn.prepareStatement(stmtSql); + stmt.setString(1, user.getId()); + + ResultSet rSet = stmt.executeQuery(); + while (rSet.next()) { + String medium = rSet.getString(1); + String address = rSet.getString(2); + threepids.add(new ThreePid(medium, address)); + } + + return threepids; + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + @Override + public List getRoles(_MatrixID user) { + return Collections.emptyList(); + } + +} diff --git a/src/main/java/io/kamax/mxisd/backend/sql/SqlThreePidProvider.java b/src/main/java/io/kamax/mxisd/backend/sql/SqlThreePidProvider.java index 9ee66b2..fc91485 100644 --- a/src/main/java/io/kamax/mxisd/backend/sql/SqlThreePidProvider.java +++ b/src/main/java/io/kamax/mxisd/backend/sql/SqlThreePidProvider.java @@ -1,8 +1,8 @@ /* * mxisd - Matrix Identity Server Daemon - * Copyright (C) 2017 Maxime Dor + * Copyright (C) 2017 Kamax Sarl * - * https://max.kamax.io/ + * https://www.kamax.io/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -21,16 +21,12 @@ package io.kamax.mxisd.backend.sql; import io.kamax.matrix.MatrixID; -import io.kamax.matrix.ThreePid; -import io.kamax.matrix._MatrixID; -import io.kamax.matrix._ThreePid; import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.config.sql.SqlConfig; import io.kamax.mxisd.lookup.SingleLookupReply; import io.kamax.mxisd.lookup.SingleLookupRequest; import io.kamax.mxisd.lookup.ThreePidMapping; import io.kamax.mxisd.lookup.provider.IThreePidProvider; -import io.kamax.mxisd.profile.ProfileProvider; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,11 +36,10 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Optional; -public abstract class SqlThreePidProvider implements IThreePidProvider, ProfileProvider { +public abstract class SqlThreePidProvider implements IThreePidProvider { private Logger log = LoggerFactory.getLogger(SqlThreePidProvider.class); @@ -114,31 +109,4 @@ public abstract class SqlThreePidProvider implements IThreePidProvider, ProfileP return new ArrayList<>(); } - @Override - public List<_ThreePid> getThreepids(_MatrixID mxid) { - List<_ThreePid> threepids = new ArrayList<>(); - - String stmtSql = cfg.getProfile().getThreepid().getQuery(); - try (Connection conn = pool.get()) { - PreparedStatement stmt = conn.prepareStatement(stmtSql); - stmt.setString(1, mxid.getId()); - - ResultSet rSet = stmt.executeQuery(); - while (rSet.next()) { - String medium = rSet.getString("medium"); - String address = rSet.getString("address"); - threepids.add(new ThreePid(medium, address)); - } - - return threepids; - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - @Override - public List getRoles(_MatrixID mxid) { - return Collections.emptyList(); - } - } diff --git a/src/main/java/io/kamax/mxisd/backend/sql/SynapseSqlDirectoryProvider.java b/src/main/java/io/kamax/mxisd/backend/sql/SynapseSqlDirectoryProvider.java deleted file mode 100644 index 5391efe..0000000 --- a/src/main/java/io/kamax/mxisd/backend/sql/SynapseSqlDirectoryProvider.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * mxisd - Matrix Identity Server Daemon - * Copyright (C) 2017 Maxime Dor - * - * https://max.kamax.io/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package io.kamax.mxisd.backend.sql; - -import io.kamax.mxisd.config.MatrixConfig; -import io.kamax.mxisd.config.sql.GenericSqlProviderConfig; -import io.kamax.mxisd.config.sql.synapse.SynapseSqlProviderConfig; -import io.kamax.mxisd.exception.ConfigurationException; -import org.apache.commons.lang.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.sql.PreparedStatement; -import java.sql.SQLException; - -@Component -public class SynapseSqlDirectoryProvider extends GenericSqlDirectoryProvider { - - @Autowired - public SynapseSqlDirectoryProvider(SynapseSqlProviderConfig cfg, MatrixConfig mxCfg) { - super(cfg, mxCfg); - - if (StringUtils.equals("sqlite", cfg.getType())) { - String userId = "'@' || p.user_id || ':" + mxCfg.getDomain() + "'"; - GenericSqlProviderConfig.Type queries = cfg.getDirectory().getQuery(); - queries.getName().setValue( - "select " + userId + ", displayname from profiles p where displayname like ?"); - queries.getThreepid().setValue( - "select t.user_id, p.displayname " + - "from user_threepids t JOIN profiles p on t.user_id = " + userId + " " + - "where t.address like ?"); - } else if (StringUtils.equals("postgresql", cfg.getType())) { - String userId = "concat('@',p.user_id,':" + mxCfg.getDomain() + "')"; - GenericSqlProviderConfig.Type queries = cfg.getDirectory().getQuery(); - queries.getName().setValue( - "select " + userId + ", displayname from profiles p where displayname ilike ?"); - queries.getThreepid().setValue( - "select t.user_id, p.displayname " + - "from user_threepids t JOIN profiles p on t.user_id = " + userId + " " + - "where t.address ilike ?"); - } else { - throw new ConfigurationException("Invalid SQL type"); - } - } - - @Override - protected void setParameters(PreparedStatement stmt, String searchTerm) throws SQLException { - stmt.setString(1, "%" + searchTerm + "%"); - } - -} diff --git a/src/main/java/io/kamax/mxisd/backend/sql/GenericSqlAuthProvider.java b/src/main/java/io/kamax/mxisd/backend/sql/generic/GenericSqlAuthProvider.java similarity index 85% rename from src/main/java/io/kamax/mxisd/backend/sql/GenericSqlAuthProvider.java rename to src/main/java/io/kamax/mxisd/backend/sql/generic/GenericSqlAuthProvider.java index a44fa32..caae3dd 100644 --- a/src/main/java/io/kamax/mxisd/backend/sql/GenericSqlAuthProvider.java +++ b/src/main/java/io/kamax/mxisd/backend/sql/generic/GenericSqlAuthProvider.java @@ -1,8 +1,8 @@ /* * mxisd - Matrix Identity Server Daemon - * Copyright (C) 2017 Maxime Dor + * Copyright (C) 2017 Kamax Sarl * - * https://max.kamax.io/ + * https://www.kamax.io/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -18,13 +18,12 @@ * along with this program. If not, see . */ -package io.kamax.mxisd.backend.sql; +package io.kamax.mxisd.backend.sql.generic; import io.kamax.matrix._MatrixID; import io.kamax.mxisd.auth.provider.AuthenticatorProvider; import io.kamax.mxisd.auth.provider.BackendAuthResult; -import io.kamax.mxisd.config.ServerConfig; -import io.kamax.mxisd.config.sql.GenericSqlProviderConfig; +import io.kamax.mxisd.config.sql.generic.GenericSqlProviderConfig; import io.kamax.mxisd.invitation.InvitationManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,9 +35,6 @@ public class GenericSqlAuthProvider implements AuthenticatorProvider { private Logger log = LoggerFactory.getLogger(GenericSqlAuthProvider.class); - @Autowired - private ServerConfig srvCfg; - @Autowired private GenericSqlProviderConfig cfg; @@ -47,7 +43,7 @@ public class GenericSqlAuthProvider implements AuthenticatorProvider { @Override public boolean isEnabled() { - return cfg.isEnabled(); + return cfg.getAuth().isEnabled(); } @Override diff --git a/src/main/java/io/kamax/mxisd/backend/sql/GenericSqlDirectoryProvider.java b/src/main/java/io/kamax/mxisd/backend/sql/generic/GenericSqlDirectoryProvider.java similarity index 92% rename from src/main/java/io/kamax/mxisd/backend/sql/GenericSqlDirectoryProvider.java rename to src/main/java/io/kamax/mxisd/backend/sql/generic/GenericSqlDirectoryProvider.java index 463f28e..eb24b52 100644 --- a/src/main/java/io/kamax/mxisd/backend/sql/GenericSqlDirectoryProvider.java +++ b/src/main/java/io/kamax/mxisd/backend/sql/generic/GenericSqlDirectoryProvider.java @@ -1,8 +1,8 @@ /* * mxisd - Matrix Identity Server Daemon - * Copyright (C) 2017 Maxime Dor + * Copyright (C) 2017 Kamax Sarl * - * https://max.kamax.io/ + * https://www.kamax.io/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -18,12 +18,13 @@ * along with this program. If not, see . */ -package io.kamax.mxisd.backend.sql; +package io.kamax.mxisd.backend.sql.generic; import io.kamax.matrix.MatrixID; +import io.kamax.mxisd.backend.sql.SqlConnectionPool; import io.kamax.mxisd.config.MatrixConfig; -import io.kamax.mxisd.config.sql.GenericSqlProviderConfig; import io.kamax.mxisd.config.sql.SqlConfig; +import io.kamax.mxisd.config.sql.generic.GenericSqlProviderConfig; import io.kamax.mxisd.controller.directory.v1.io.UserDirectorySearchResult; import io.kamax.mxisd.directory.IDirectoryProvider; import io.kamax.mxisd.exception.InternalServerError; @@ -44,7 +45,7 @@ public abstract class GenericSqlDirectoryProvider implements IDirectoryProvider private Logger log = LoggerFactory.getLogger(GenericSqlDirectoryProvider.class); protected SqlConfig cfg; - private MatrixConfig mxCfg; + protected MatrixConfig mxCfg; private SqlConnectionPool pool; @@ -56,7 +57,7 @@ public abstract class GenericSqlDirectoryProvider implements IDirectoryProvider @Override public boolean isEnabled() { - return cfg.isEnabled(); + return cfg.getDirectory().isEnabled(); } protected void setParameters(PreparedStatement stmt, String searchTerm) throws SQLException { diff --git a/src/main/java/io/kamax/mxisd/backend/sql/generic/GenericSqlProfileProvider.java b/src/main/java/io/kamax/mxisd/backend/sql/generic/GenericSqlProfileProvider.java new file mode 100644 index 0000000..bbe5ec9 --- /dev/null +++ b/src/main/java/io/kamax/mxisd/backend/sql/generic/GenericSqlProfileProvider.java @@ -0,0 +1,34 @@ +/* + * mxisd - Matrix Identity Server Daemon + * Copyright (C) 2018 Kamax Sarl + * + * https://www.kamax.io/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.kamax.mxisd.backend.sql.generic; + +import io.kamax.mxisd.backend.sql.SqlProfileProvider; +import io.kamax.mxisd.config.sql.generic.GenericSqlProviderConfig; +import org.springframework.stereotype.Component; + +@Component +public class GenericSqlProfileProvider extends SqlProfileProvider { + + public GenericSqlProfileProvider(GenericSqlProviderConfig cfg) { + super(cfg); + } + +} diff --git a/src/main/java/io/kamax/mxisd/backend/sql/GenericSqlThreePidProvider.java b/src/main/java/io/kamax/mxisd/backend/sql/generic/GenericSqlThreePidProvider.java similarity index 83% rename from src/main/java/io/kamax/mxisd/backend/sql/GenericSqlThreePidProvider.java rename to src/main/java/io/kamax/mxisd/backend/sql/generic/GenericSqlThreePidProvider.java index 095e910..ddd2087 100644 --- a/src/main/java/io/kamax/mxisd/backend/sql/GenericSqlThreePidProvider.java +++ b/src/main/java/io/kamax/mxisd/backend/sql/generic/GenericSqlThreePidProvider.java @@ -1,8 +1,8 @@ /* * mxisd - Matrix Identity Server Daemon - * Copyright (C) 2017 Maxime Dor + * Copyright (C) 2017 Kamax Sarl * - * https://max.kamax.io/ + * https://www.kamax.io/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -18,10 +18,11 @@ * along with this program. If not, see . */ -package io.kamax.mxisd.backend.sql; +package io.kamax.mxisd.backend.sql.generic; +import io.kamax.mxisd.backend.sql.SqlThreePidProvider; import io.kamax.mxisd.config.MatrixConfig; -import io.kamax.mxisd.config.sql.GenericSqlProviderConfig; +import io.kamax.mxisd.config.sql.generic.GenericSqlProviderConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; diff --git a/src/main/java/io/kamax/mxisd/backend/sql/synapse/Synapse.java b/src/main/java/io/kamax/mxisd/backend/sql/synapse/Synapse.java new file mode 100644 index 0000000..c62fef1 --- /dev/null +++ b/src/main/java/io/kamax/mxisd/backend/sql/synapse/Synapse.java @@ -0,0 +1,55 @@ +/* + * mxisd - Matrix Identity Server Daemon + * Copyright (C) 2018 Kamax Sarl + * + * https://www.kamax.io/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.kamax.mxisd.backend.sql.synapse; + +import io.kamax.mxisd.backend.sql.SqlConnectionPool; +import io.kamax.mxisd.config.sql.synapse.SynapseSqlProviderConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.Optional; + +@Component +public class Synapse { + + private SqlConnectionPool pool; + + @Autowired + public Synapse(SynapseSqlProviderConfig sqlCfg) { + this.pool = new SqlConnectionPool(sqlCfg); + } + + public Optional getRoomName(String id) { + return pool.withConnFunction(conn -> { + PreparedStatement stmt = conn.prepareStatement(SynapseQueries.getRoomName()); + stmt.setString(1, id); + ResultSet rSet = stmt.executeQuery(); + if (!rSet.next()) { + return Optional.empty(); + } + + return Optional.ofNullable(rSet.getString(1)); + }); + } + +} diff --git a/src/main/java/io/kamax/mxisd/backend/sql/synapse/SynapseQueries.java b/src/main/java/io/kamax/mxisd/backend/sql/synapse/SynapseQueries.java new file mode 100644 index 0000000..c775c66 --- /dev/null +++ b/src/main/java/io/kamax/mxisd/backend/sql/synapse/SynapseQueries.java @@ -0,0 +1,74 @@ +/* + * mxisd - Matrix Identity Server Daemon + * Copyright (C) 2018 Kamax Sarl + * + * https://www.kamax.io/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.kamax.mxisd.backend.sql.synapse; + +import io.kamax.mxisd.exception.ConfigurationException; +import org.apache.commons.lang.StringUtils; + +public class SynapseQueries { + + public static String getUserId(String type, String domain) { + if (StringUtils.equals("sqlite", type)) { + return "'@' || p.user_id || ':" + domain + "'"; + } else if (StringUtils.equals("postgresql", type)) { + return "concat('@',p.user_id,':" + domain + "')"; + } else { + throw new ConfigurationException("Invalid Synapse SQL type: " + type); + } + } + + public static String getDisplayName() { + return "SELECT displayname FROM profiles WHERE user_id = ?"; + } + + public static String getThreepids() { + return "SELECT medium, address FROM user_threepids WHERE user_id = ?"; + } + + public static String findByDisplayName(String type, String domain) { + if (StringUtils.equals("sqlite", type)) { + return "select " + getUserId(type, domain) + ", displayname from profiles p where displayname like ?"; + } else if (StringUtils.equals("postgresql", type)) { + return "select " + getUserId(type, domain) + ", displayname from profiles p where displayname ilike ?"; + } else { + throw new ConfigurationException("Invalid Synapse SQL type: " + type); + } + } + + public static String findByThreePidAddress(String type, String domain) { + if (StringUtils.equals("sqlite", type)) { + return "select t.user_id, p.displayname " + + "from user_threepids t JOIN profiles p on t.user_id = " + getUserId(type, domain) + " " + + "where t.address like ?"; + } else if (StringUtils.equals("postgresql", type)) { + return "select t.user_id, p.displayname " + + "from user_threepids t JOIN profiles p on t.user_id = " + getUserId(type, domain) + " " + + "where t.address ilike ?"; + } else { + throw new ConfigurationException("Invalid Synapse SQL type: " + type); + } + } + + public static String getRoomName() { + return "select r.name from room_names r, events e, (select r1.room_id,max(e1.origin_server_ts) ts from room_names r1, events e1 where r1.event_id = e1.event_id group by r1.room_id) rle where e.origin_server_ts = rle.ts and r.event_id = e.event_id and r.room_id = ?"; + } + +} diff --git a/src/main/java/io/kamax/mxisd/backend/sql/synapse/SynapseSqlDirectoryProvider.java b/src/main/java/io/kamax/mxisd/backend/sql/synapse/SynapseSqlDirectoryProvider.java new file mode 100644 index 0000000..bc83e81 --- /dev/null +++ b/src/main/java/io/kamax/mxisd/backend/sql/synapse/SynapseSqlDirectoryProvider.java @@ -0,0 +1,63 @@ +/* + * mxisd - Matrix Identity Server Daemon + * Copyright (C) 2017 Kamax Sarl + * + * https://www.kamax.io/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.kamax.mxisd.backend.sql.synapse; + +import io.kamax.mxisd.backend.sql.generic.GenericSqlDirectoryProvider; +import io.kamax.mxisd.config.MatrixConfig; +import io.kamax.mxisd.config.sql.generic.GenericSqlProviderConfig; +import io.kamax.mxisd.config.sql.synapse.SynapseSqlProviderConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Objects; + +@Component +public class SynapseSqlDirectoryProvider extends GenericSqlDirectoryProvider { + + @Autowired + public SynapseSqlDirectoryProvider(SynapseSqlProviderConfig cfg, MatrixConfig mxCfg) { + super(cfg, mxCfg); + } + + @Override + protected void setParameters(PreparedStatement stmt, String searchTerm) throws SQLException { + stmt.setString(1, "%" + searchTerm + "%"); + } + + @PostConstruct + public void build() { + if (!isEnabled()) { + return; + } + + GenericSqlProviderConfig.Type queries = cfg.getDirectory().getQuery(); + if (Objects.isNull(queries.getName().getValue())) { + queries.getName().setValue(SynapseQueries.findByDisplayName(cfg.getType(), mxCfg.getDomain())); + } + if (Objects.isNull(queries.getThreepid().getValue())) { + queries.getThreepid().setValue(SynapseQueries.findByThreePidAddress(cfg.getType(), mxCfg.getDomain())); + } + } + +} diff --git a/src/main/java/io/kamax/mxisd/backend/sql/synapse/SynapseSqlProfileProvider.java b/src/main/java/io/kamax/mxisd/backend/sql/synapse/SynapseSqlProfileProvider.java new file mode 100644 index 0000000..e32f8b8 --- /dev/null +++ b/src/main/java/io/kamax/mxisd/backend/sql/synapse/SynapseSqlProfileProvider.java @@ -0,0 +1,36 @@ +/* + * mxisd - Matrix Identity Server Daemon + * Copyright (C) 2018 Kamax Sarl + * + * https://www.kamax.io/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.kamax.mxisd.backend.sql.synapse; + +import io.kamax.mxisd.backend.sql.SqlProfileProvider; +import io.kamax.mxisd.config.sql.synapse.SynapseSqlProviderConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class SynapseSqlProfileProvider extends SqlProfileProvider { + + @Autowired + public SynapseSqlProfileProvider(SynapseSqlProviderConfig cfg) { + super(cfg); + } + +} diff --git a/src/main/java/io/kamax/mxisd/backend/sql/SynapseSqlThreePidProvider.java b/src/main/java/io/kamax/mxisd/backend/sql/synapse/SynapseSqlThreePidProvider.java similarity index 88% rename from src/main/java/io/kamax/mxisd/backend/sql/SynapseSqlThreePidProvider.java rename to src/main/java/io/kamax/mxisd/backend/sql/synapse/SynapseSqlThreePidProvider.java index ffb1fd1..1d8dd80 100644 --- a/src/main/java/io/kamax/mxisd/backend/sql/SynapseSqlThreePidProvider.java +++ b/src/main/java/io/kamax/mxisd/backend/sql/synapse/SynapseSqlThreePidProvider.java @@ -1,8 +1,8 @@ /* * mxisd - Matrix Identity Server Daemon - * Copyright (C) 2017 Maxime Dor + * Copyright (C) 2017 Kamax Sarl * - * https://max.kamax.io/ + * https://www.kamax.io/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -18,8 +18,9 @@ * along with this program. If not, see . */ -package io.kamax.mxisd.backend.sql; +package io.kamax.mxisd.backend.sql.synapse; +import io.kamax.mxisd.backend.sql.SqlThreePidProvider; import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.config.sql.synapse.SynapseSqlProviderConfig; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/main/java/io/kamax/mxisd/config/memory/MemoryIdentityConfig.java b/src/main/java/io/kamax/mxisd/config/memory/MemoryIdentityConfig.java index 8919646..78a1710 100644 --- a/src/main/java/io/kamax/mxisd/config/memory/MemoryIdentityConfig.java +++ b/src/main/java/io/kamax/mxisd/config/memory/MemoryIdentityConfig.java @@ -30,6 +30,7 @@ public class MemoryIdentityConfig { private String username; private String password; + private String displayName; private List threepids = new ArrayList<>(); private List roles = new ArrayList<>(); @@ -49,6 +50,14 @@ public class MemoryIdentityConfig { this.password = password; } + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + public List getThreepids() { return threepids; } diff --git a/src/main/java/io/kamax/mxisd/config/sql/SqlConfig.java b/src/main/java/io/kamax/mxisd/config/sql/SqlConfig.java index 2192211..bd9d027 100644 --- a/src/main/java/io/kamax/mxisd/config/sql/SqlConfig.java +++ b/src/main/java/io/kamax/mxisd/config/sql/SqlConfig.java @@ -1,3 +1,23 @@ +/* + * mxisd - Matrix Identity Server Daemon + * Copyright (C) 2017 Kamax Sarl + * + * https://www.kamax.io/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + package io.kamax.mxisd.config.sql; import io.kamax.mxisd.util.GsonUtil; @@ -7,10 +27,11 @@ import org.slf4j.LoggerFactory; import javax.annotation.PostConstruct; import java.util.HashMap; import java.util.Map; +import java.util.Objects; public abstract class SqlConfig { - private Logger log = LoggerFactory.getLogger(SqlConfig.class); + private transient Logger log = LoggerFactory.getLogger(SqlConfig.class); public static class Query { @@ -136,6 +157,20 @@ public abstract class SqlConfig { } + public static class ProfileDisplayName { + + private String query; + + public String getQuery() { + return query; + } + + public void setQuery(String query) { + this.query = query; + } + + } + public static class ProfileThreepids { private String query; @@ -152,8 +187,26 @@ public abstract class SqlConfig { public static class Profile { + private Boolean enabled; + private ProfileDisplayName displayName = new ProfileDisplayName(); private ProfileThreepids threepid = new ProfileThreepids(); + public Boolean isEnabled() { + return enabled; + } + + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } + + public ProfileDisplayName getDisplayName() { + return displayName; + } + + public void setDisplayName(ProfileDisplayName displayName) { + this.displayName = displayName; + } + public ProfileThreepids getThreepid() { return threepid; } @@ -230,7 +283,8 @@ public abstract class SqlConfig { protected abstract String getProviderName(); - protected void doBuild() { + @PostConstruct + public void build() { if (getAuth().isEnabled() == null) { getAuth().setEnabled(isEnabled()); } @@ -242,14 +296,15 @@ public abstract class SqlConfig { if (getIdentity().isEnabled() == null) { getIdentity().setEnabled(isEnabled()); } + + if (Objects.isNull(getProfile().isEnabled())) { + getProfile().setEnabled(isEnabled()); + } } - @PostConstruct - public void build() { + protected void printConfig() { log.info("--- " + getProviderName() + " Provider config ---"); - doBuild(); - log.info("Enabled: {}", isEnabled()); if (isEnabled()) { log.info("Type: {}", getType()); @@ -259,7 +314,12 @@ public abstract class SqlConfig { log.info("Identity type: {}", getIdentity().getType()); log.info("3PID mapping query: {}", getIdentity().getQuery()); log.info("Identity medium queries: {}", GsonUtil.build().toJson(getIdentity().getMedium())); - log.info("Profile 3PID query: {}", getProfile().getThreepid().getQuery()); + log.info("Profile:"); + log.info("\tEnabled: {}", getProfile().isEnabled()); + if (getProfile().isEnabled()) { + log.info("\tDisplay name query: {}", getProfile().getDisplayName().getQuery()); + log.info("\tProfile 3PID query: {}", getProfile().getThreepid().getQuery()); + } } } diff --git a/src/main/java/io/kamax/mxisd/config/sql/GenericSqlProviderConfig.java b/src/main/java/io/kamax/mxisd/config/sql/generic/GenericSqlProviderConfig.java similarity index 88% rename from src/main/java/io/kamax/mxisd/config/sql/GenericSqlProviderConfig.java rename to src/main/java/io/kamax/mxisd/config/sql/generic/GenericSqlProviderConfig.java index 1106f3e..8c69b81 100644 --- a/src/main/java/io/kamax/mxisd/config/sql/GenericSqlProviderConfig.java +++ b/src/main/java/io/kamax/mxisd/config/sql/generic/GenericSqlProviderConfig.java @@ -1,8 +1,8 @@ /* * mxisd - Matrix Identity Server Daemon - * Copyright (C) 2017 Maxime Dor + * Copyright (C) 2017 Kamax Sarl * - * https://max.kamax.io/ + * https://www.kamax.io/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -18,8 +18,9 @@ * along with this program. If not, see . */ -package io.kamax.mxisd.config.sql; +package io.kamax.mxisd.config.sql.generic; +import io.kamax.mxisd.config.sql.SqlConfig; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; diff --git a/src/main/java/io/kamax/mxisd/config/sql/synapse/SynapseSqlProviderConfig.java b/src/main/java/io/kamax/mxisd/config/sql/synapse/SynapseSqlProviderConfig.java index 81bd1bb..9766ea2 100644 --- a/src/main/java/io/kamax/mxisd/config/sql/synapse/SynapseSqlProviderConfig.java +++ b/src/main/java/io/kamax/mxisd/config/sql/synapse/SynapseSqlProviderConfig.java @@ -1,8 +1,8 @@ /* * mxisd - Matrix Identity Server Daemon - * Copyright (C) 2017 Maxime Dor + * Copyright (C) 2017 Kamax Sarl * - * https://max.kamax.io/ + * https://www.kamax.io/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -20,6 +20,7 @@ package io.kamax.mxisd.config.sql.synapse; +import io.kamax.mxisd.backend.sql.synapse.SynapseQueries; import io.kamax.mxisd.config.sql.SqlConfig; import org.apache.commons.lang.StringUtils; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -38,22 +39,26 @@ public class SynapseSqlProviderConfig extends SqlConfig { @PostConstruct public void doBuild() { - super.doBuild(); + getAuth().setEnabled(false); // Synapse does the auth, we only act as a directory/identity service. + // FIXME check that the DB is not the mxisd one // See https://matrix.to/#/!NPRUEisLjcaMtHIzDr:kamax.io/$1509377583327omXkC:kamax.io - getAuth().setEnabled(false); // Synapse does the auth, we only act as a directory/identity service. - - if (getDirectory().isEnabled()) { - //FIXME set default queries for name and threepid + if (getIdentity().isEnabled() && StringUtils.isBlank(getIdentity().getType())) { + getIdentity().setType("mxid"); + getIdentity().setQuery("SELECT user_id AS uid FROM user_threepids WHERE medium = ? AND address = ?"); } - if (getIdentity().isEnabled()) { - if (StringUtils.isBlank(getIdentity().getType())) { - getIdentity().setType("mxid"); - getIdentity().setQuery("SELECT user_id AS uid FROM user_threepids WHERE medium = ? AND address = ?"); + if (getProfile().isEnabled()) { + if (StringUtils.isBlank(getProfile().getDisplayName().getQuery())) { + getProfile().getDisplayName().setQuery(SynapseQueries.getDisplayName()); + } + if (StringUtils.isBlank(getProfile().getThreepid().getQuery())) { + getProfile().getThreepid().setQuery(SynapseQueries.getThreepids()); } } + + printConfig(); } } diff --git a/src/main/java/io/kamax/mxisd/profile/ProfileManager.java b/src/main/java/io/kamax/mxisd/profile/ProfileManager.java index 17a6935..76c0abb 100644 --- a/src/main/java/io/kamax/mxisd/profile/ProfileManager.java +++ b/src/main/java/io/kamax/mxisd/profile/ProfileManager.java @@ -22,37 +22,65 @@ package io.kamax.mxisd.profile; import io.kamax.matrix._MatrixID; import io.kamax.matrix._ThreePid; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import javax.annotation.PostConstruct; import java.util.Collection; import java.util.List; +import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; @Component public class ProfileManager { + private final Logger log = LoggerFactory.getLogger(ProfileManager.class); + private List providers; + @Autowired public ProfileManager(List providers) { - this.providers = providers.stream() - .filter(ProfileProvider::isEnabled) - .collect(Collectors.toList()); + this.providers = providers; } - public List get(Function> function) { + @PostConstruct + public void build() { + providers = providers.stream() + .filter(ProfileProvider::isEnabled) + .collect(Collectors.toList()); + + log.info("--- Profile providers ---"); + this.providers.forEach(pp -> log.info("\t- {}", pp.getClass().getSimpleName())); + } + + public List getList(Function> function) { return providers.stream() .map(function) .flatMap(Collection::stream) .collect(Collectors.toList()); } - public List<_ThreePid> getThreepids(_MatrixID mxid) { - return get(p -> p.getThreepids(mxid)); + public Optional getOpt(Function> function) { + return providers.stream() + .map(function) + .filter(Optional::isPresent) + .map(Optional::get) + .findFirst(); } - public List getRoles(_MatrixID mxid) { - return get(p -> p.getRoles(mxid)); + public Optional getDisplayName(_MatrixID user) { + return getOpt(p -> p.getDisplayName(user)); + } + + public List<_ThreePid> getThreepids(_MatrixID user) { + return getList(p -> p.getThreepids(user)); + } + + public List getRoles(_MatrixID user) { + return getList(p -> p.getRoles(user)); } } diff --git a/src/main/java/io/kamax/mxisd/profile/ProfileProvider.java b/src/main/java/io/kamax/mxisd/profile/ProfileProvider.java index 8320f3c..5b03ee7 100644 --- a/src/main/java/io/kamax/mxisd/profile/ProfileProvider.java +++ b/src/main/java/io/kamax/mxisd/profile/ProfileProvider.java @@ -24,13 +24,16 @@ import io.kamax.matrix._MatrixID; import io.kamax.matrix._ThreePid; import java.util.List; +import java.util.Optional; public interface ProfileProvider { boolean isEnabled(); - List<_ThreePid> getThreepids(_MatrixID mxid); + Optional getDisplayName(_MatrixID userId); - List getRoles(_MatrixID mxid); + List<_ThreePid> getThreepids(_MatrixID userId); + + List getRoles(_MatrixID userId); } diff --git a/src/main/java/io/kamax/mxisd/threepid/notification/PlaceholderNotificationGenerator.java b/src/main/java/io/kamax/mxisd/threepid/notification/PlaceholderNotificationGenerator.java index f05907e..482c793 100644 --- a/src/main/java/io/kamax/mxisd/threepid/notification/PlaceholderNotificationGenerator.java +++ b/src/main/java/io/kamax/mxisd/threepid/notification/PlaceholderNotificationGenerator.java @@ -51,10 +51,19 @@ public abstract class PlaceholderNotificationGenerator { } protected String populateForInvite(IMatrixIdInvite invite, String input) { + String senderName = invite.getProperties().getOrDefault("sender_display_name", ""); + String senderNameOrId = StringUtils.defaultIfBlank(senderName, invite.getSender().getId()); + String roomName = invite.getProperties().getOrDefault("room_name", ""); + String roomNameOrId = StringUtils.defaultIfBlank(roomName, invite.getRoomId()); + return populateForCommon(new ThreePid(invite.getMedium(), invite.getAddress()), input) .replace("%SENDER_ID%", invite.getSender().getId()) + .replace("%SENDER_NAME%", senderName) + .replace("%SENDER_NAME_OR_ID%", senderNameOrId) .replace("%RECIPIENT_ID%", invite.getInvitee().getId()) - .replace("%ROOM_ID%", invite.getRoomId()); + .replace("%ROOM_ID%", invite.getRoomId()) + .replace("%ROOM_NAME%", roomName) + .replace("%ROOM_NAME_OR_ID%", roomNameOrId); } protected String populateForReply(IThreePidInviteReply invite, String input) { diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 28e12f2..ab2ad47 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -138,7 +138,6 @@ netiq: firebase: enabled: false - sql: enabled: false type: 'sqlite' @@ -161,13 +160,6 @@ sql: threepid: query: 'SELECT medium, address FROM user_threepids WHERE user_id = ?' -synapseSql: - enabled: false - type: 'sqlite' - profile: - threepid: - query: 'SELECT medium, address FROM user_threepids WHERE user_id = ?' - wordpress: enabled: false sql: