Add extra placeholders for Matrix ID room invites notifications

- Sender display name, if available
- Room name, if available
This commit is contained in:
Max Dor
2018-10-09 02:47:15 +02:00
parent b3aefbed77
commit 3eee4eaccf
23 changed files with 577 additions and 176 deletions

View File

@@ -23,8 +23,10 @@ package io.kamax.mxisd.as;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import io.kamax.matrix.MatrixID; import io.kamax.matrix.MatrixID;
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.event.EventKey;
import io.kamax.matrix.json.GsonUtil; import io.kamax.matrix.json.GsonUtil;
import io.kamax.mxisd.backend.sql.synapse.Synapse;
import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.notification.NotificationManager; import io.kamax.mxisd.notification.NotificationManager;
import io.kamax.mxisd.profile.ProfileManager; import io.kamax.mxisd.profile.ProfileManager;
@@ -36,6 +38,7 @@ import org.springframework.stereotype.Component;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
@Component @Component
public class AppServiceHandler { public class AppServiceHandler {
@@ -45,12 +48,14 @@ public class AppServiceHandler {
private MatrixConfig cfg; private MatrixConfig cfg;
private ProfileManager profiler; private ProfileManager profiler;
private NotificationManager notif; private NotificationManager notif;
private Synapse synapse;
@Autowired @Autowired
public AppServiceHandler(MatrixConfig cfg, ProfileManager profiler, NotificationManager notif) { public AppServiceHandler(MatrixConfig cfg, ProfileManager profiler, NotificationManager notif, Synapse synapse) {
this.cfg = cfg; this.cfg = cfg;
this.profiler = profiler; this.profiler = profiler;
this.notif = notif; this.notif = notif;
this.synapse = synapse;
} }
public void processTransaction(List<JsonObject> eventsJson) { public void processTransaction(List<JsonObject> eventsJson) {
@@ -66,22 +71,27 @@ public class AppServiceHandler {
String roomId = GsonUtil.getStringOrNull(ev, "room_id"); String roomId = GsonUtil.getStringOrNull(ev, "room_id");
_MatrixID sender = MatrixID.asAcceptable(GsonUtil.getStringOrNull(ev, "sender")); _MatrixID sender = MatrixID.asAcceptable(GsonUtil.getStringOrNull(ev, "sender"));
EventKey.StateKey.findString(ev).ifPresent(id -> { EventKey.StateKey.findString(ev).ifPresent(id -> {
log.info("Got invite for {}", id);
_MatrixID mxid = MatrixID.asAcceptable(id); _MatrixID mxid = MatrixID.asAcceptable(id);
if (!StringUtils.equals(mxid.getDomain(), cfg.getDomain())) { 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; return;
} }
log.info("Got invite for {}", id);
profiler.getThreepids(mxid).forEach(tpid -> { for (_ThreePid tpid : profiler.getThreepids(mxid)) {
if (!StringUtils.equals("email", tpid.getMedium())) { if (!StringUtils.equals("email", tpid.getMedium())) {
return; continue;
} }
log.info("Found an email address to notify about room invitation: {}", tpid.getAddress()); 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<String, String> 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); notif.sendForInvite(inv);
}); }
}); });
}); });
} }

View File

@@ -1,6 +1,6 @@
/* /*
* mxisd - Matrix Identity Server Daemon * mxisd - Matrix Identity Server Daemon
* Copyright (C) 2018 Maxime Dor * Copyright (C) 2018 Kamax Sarl
* *
* https://www.kamax.io/ * https://www.kamax.io/
* *
@@ -76,6 +76,11 @@ public class MemoryIdentityStore implements AuthenticatorProvider, IDirectoryPro
return cfg.isEnabled(); return cfg.isEnabled();
} }
@Override
public Optional<String> getDisplayName(_MatrixID mxid) {
return findByUsername(mxid.getLocalPart()).map(MemoryIdentityConfig::getDisplayName);
}
private UserDirectorySearchResult search( private UserDirectorySearchResult search(
Predicate<MemoryIdentityConfig> predicate, Predicate<MemoryIdentityConfig> predicate,
Function<MemoryIdentityConfig, UserDirectorySearchResult.Result> mapper Function<MemoryIdentityConfig, UserDirectorySearchResult.Result> mapper

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * 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 * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -28,6 +28,12 @@ import java.sql.SQLException;
public class SqlConnectionPool { public class SqlConnectionPool {
public interface SqlFunction<T, R> {
R run(T connection) throws SQLException;
}
private ComboPooledDataSource ds; private ComboPooledDataSource ds;
public SqlConnectionPool(SqlConfig cfg) { public SqlConnectionPool(SqlConfig cfg) {
@@ -42,4 +48,12 @@ public class SqlConnectionPool {
return ds.getConnection(); return ds.getConnection();
} }
public <T> T withConnFunction(SqlFunction<Connection, T> function) {
try (Connection conn = get()) {
return function.run(conn);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
} }

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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<String> 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<String> getRoles(_MatrixID user) {
return Collections.emptyList();
}
}

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * 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 * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -21,16 +21,12 @@
package io.kamax.mxisd.backend.sql; package io.kamax.mxisd.backend.sql;
import io.kamax.matrix.MatrixID; 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.MatrixConfig;
import io.kamax.mxisd.config.sql.SqlConfig; import io.kamax.mxisd.config.sql.SqlConfig;
import io.kamax.mxisd.lookup.SingleLookupReply; import io.kamax.mxisd.lookup.SingleLookupReply;
import io.kamax.mxisd.lookup.SingleLookupRequest; import io.kamax.mxisd.lookup.SingleLookupRequest;
import io.kamax.mxisd.lookup.ThreePidMapping; import io.kamax.mxisd.lookup.ThreePidMapping;
import io.kamax.mxisd.lookup.provider.IThreePidProvider; import io.kamax.mxisd.lookup.provider.IThreePidProvider;
import io.kamax.mxisd.profile.ProfileProvider;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -40,11 +36,10 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
public abstract class SqlThreePidProvider implements IThreePidProvider, ProfileProvider { public abstract class SqlThreePidProvider implements IThreePidProvider {
private Logger log = LoggerFactory.getLogger(SqlThreePidProvider.class); private Logger log = LoggerFactory.getLogger(SqlThreePidProvider.class);
@@ -114,31 +109,4 @@ public abstract class SqlThreePidProvider implements IThreePidProvider, ProfileP
return new ArrayList<>(); 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<String> getRoles(_MatrixID mxid) {
return Collections.emptyList();
}
} }

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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 + "%");
}
}

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * 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 * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -18,13 +18,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package io.kamax.mxisd.backend.sql; package io.kamax.mxisd.backend.sql.generic;
import io.kamax.matrix._MatrixID; import io.kamax.matrix._MatrixID;
import io.kamax.mxisd.auth.provider.AuthenticatorProvider; import io.kamax.mxisd.auth.provider.AuthenticatorProvider;
import io.kamax.mxisd.auth.provider.BackendAuthResult; import io.kamax.mxisd.auth.provider.BackendAuthResult;
import io.kamax.mxisd.config.ServerConfig; import io.kamax.mxisd.config.sql.generic.GenericSqlProviderConfig;
import io.kamax.mxisd.config.sql.GenericSqlProviderConfig;
import io.kamax.mxisd.invitation.InvitationManager; import io.kamax.mxisd.invitation.InvitationManager;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -36,9 +35,6 @@ public class GenericSqlAuthProvider implements AuthenticatorProvider {
private Logger log = LoggerFactory.getLogger(GenericSqlAuthProvider.class); private Logger log = LoggerFactory.getLogger(GenericSqlAuthProvider.class);
@Autowired
private ServerConfig srvCfg;
@Autowired @Autowired
private GenericSqlProviderConfig cfg; private GenericSqlProviderConfig cfg;
@@ -47,7 +43,7 @@ public class GenericSqlAuthProvider implements AuthenticatorProvider {
@Override @Override
public boolean isEnabled() { public boolean isEnabled() {
return cfg.isEnabled(); return cfg.getAuth().isEnabled();
} }
@Override @Override

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * 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 * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -18,12 +18,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package io.kamax.mxisd.backend.sql; package io.kamax.mxisd.backend.sql.generic;
import io.kamax.matrix.MatrixID; import io.kamax.matrix.MatrixID;
import io.kamax.mxisd.backend.sql.SqlConnectionPool;
import io.kamax.mxisd.config.MatrixConfig; 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.SqlConfig;
import io.kamax.mxisd.config.sql.generic.GenericSqlProviderConfig;
import io.kamax.mxisd.controller.directory.v1.io.UserDirectorySearchResult; import io.kamax.mxisd.controller.directory.v1.io.UserDirectorySearchResult;
import io.kamax.mxisd.directory.IDirectoryProvider; import io.kamax.mxisd.directory.IDirectoryProvider;
import io.kamax.mxisd.exception.InternalServerError; import io.kamax.mxisd.exception.InternalServerError;
@@ -44,7 +45,7 @@ public abstract class GenericSqlDirectoryProvider implements IDirectoryProvider
private Logger log = LoggerFactory.getLogger(GenericSqlDirectoryProvider.class); private Logger log = LoggerFactory.getLogger(GenericSqlDirectoryProvider.class);
protected SqlConfig cfg; protected SqlConfig cfg;
private MatrixConfig mxCfg; protected MatrixConfig mxCfg;
private SqlConnectionPool pool; private SqlConnectionPool pool;
@@ -56,7 +57,7 @@ public abstract class GenericSqlDirectoryProvider implements IDirectoryProvider
@Override @Override
public boolean isEnabled() { public boolean isEnabled() {
return cfg.isEnabled(); return cfg.getDirectory().isEnabled();
} }
protected void setParameters(PreparedStatement stmt, String searchTerm) throws SQLException { protected void setParameters(PreparedStatement stmt, String searchTerm) throws SQLException {

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * 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 * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -18,10 +18,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
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.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.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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<String> 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));
});
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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 = ?";
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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()));
}
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * 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 * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -18,8 +18,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
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.MatrixConfig;
import io.kamax.mxisd.config.sql.synapse.SynapseSqlProviderConfig; import io.kamax.mxisd.config.sql.synapse.SynapseSqlProviderConfig;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;

View File

@@ -30,6 +30,7 @@ public class MemoryIdentityConfig {
private String username; private String username;
private String password; private String password;
private String displayName;
private List<MemoryThreePid> threepids = new ArrayList<>(); private List<MemoryThreePid> threepids = new ArrayList<>();
private List<String> roles = new ArrayList<>(); private List<String> roles = new ArrayList<>();
@@ -49,6 +50,14 @@ public class MemoryIdentityConfig {
this.password = password; this.password = password;
} }
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public List<MemoryThreePid> getThreepids() { public List<MemoryThreePid> getThreepids() {
return threepids; return threepids;
} }

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
package io.kamax.mxisd.config.sql; package io.kamax.mxisd.config.sql;
import io.kamax.mxisd.util.GsonUtil; import io.kamax.mxisd.util.GsonUtil;
@@ -7,10 +27,11 @@ import org.slf4j.LoggerFactory;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects;
public abstract class SqlConfig { public abstract class SqlConfig {
private Logger log = LoggerFactory.getLogger(SqlConfig.class); private transient Logger log = LoggerFactory.getLogger(SqlConfig.class);
public static class Query { 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 { public static class ProfileThreepids {
private String query; private String query;
@@ -152,8 +187,26 @@ public abstract class SqlConfig {
public static class Profile { public static class Profile {
private Boolean enabled;
private ProfileDisplayName displayName = new ProfileDisplayName();
private ProfileThreepids threepid = new ProfileThreepids(); 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() { public ProfileThreepids getThreepid() {
return threepid; return threepid;
} }
@@ -230,7 +283,8 @@ public abstract class SqlConfig {
protected abstract String getProviderName(); protected abstract String getProviderName();
protected void doBuild() { @PostConstruct
public void build() {
if (getAuth().isEnabled() == null) { if (getAuth().isEnabled() == null) {
getAuth().setEnabled(isEnabled()); getAuth().setEnabled(isEnabled());
} }
@@ -242,14 +296,15 @@ public abstract class SqlConfig {
if (getIdentity().isEnabled() == null) { if (getIdentity().isEnabled() == null) {
getIdentity().setEnabled(isEnabled()); getIdentity().setEnabled(isEnabled());
} }
if (Objects.isNull(getProfile().isEnabled())) {
getProfile().setEnabled(isEnabled());
}
} }
@PostConstruct protected void printConfig() {
public void build() {
log.info("--- " + getProviderName() + " Provider config ---"); log.info("--- " + getProviderName() + " Provider config ---");
doBuild();
log.info("Enabled: {}", isEnabled()); log.info("Enabled: {}", isEnabled());
if (isEnabled()) { if (isEnabled()) {
log.info("Type: {}", getType()); log.info("Type: {}", getType());
@@ -259,7 +314,12 @@ public abstract class SqlConfig {
log.info("Identity type: {}", getIdentity().getType()); log.info("Identity type: {}", getIdentity().getType());
log.info("3PID mapping query: {}", getIdentity().getQuery()); log.info("3PID mapping query: {}", getIdentity().getQuery());
log.info("Identity medium queries: {}", GsonUtil.build().toJson(getIdentity().getMedium())); 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());
}
} }
} }

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * 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 * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -18,8 +18,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
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.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;

View File

@@ -1,8 +1,8 @@
/* /*
* mxisd - Matrix Identity Server Daemon * 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 * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@@ -20,6 +20,7 @@
package io.kamax.mxisd.config.sql.synapse; package io.kamax.mxisd.config.sql.synapse;
import io.kamax.mxisd.backend.sql.synapse.SynapseQueries;
import io.kamax.mxisd.config.sql.SqlConfig; import io.kamax.mxisd.config.sql.SqlConfig;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -38,22 +39,26 @@ public class SynapseSqlProviderConfig extends SqlConfig {
@PostConstruct @PostConstruct
public void doBuild() { 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 // FIXME check that the DB is not the mxisd one
// See https://matrix.to/#/!NPRUEisLjcaMtHIzDr:kamax.io/$1509377583327omXkC:kamax.io // 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 (getIdentity().isEnabled() && StringUtils.isBlank(getIdentity().getType())) {
getIdentity().setType("mxid");
if (getDirectory().isEnabled()) { getIdentity().setQuery("SELECT user_id AS uid FROM user_threepids WHERE medium = ? AND address = ?");
//FIXME set default queries for name and threepid
} }
if (getIdentity().isEnabled()) { if (getProfile().isEnabled()) {
if (StringUtils.isBlank(getIdentity().getType())) { if (StringUtils.isBlank(getProfile().getDisplayName().getQuery())) {
getIdentity().setType("mxid"); getProfile().getDisplayName().setQuery(SynapseQueries.getDisplayName());
getIdentity().setQuery("SELECT user_id AS uid FROM user_threepids WHERE medium = ? AND address = ?"); }
if (StringUtils.isBlank(getProfile().getThreepid().getQuery())) {
getProfile().getThreepid().setQuery(SynapseQueries.getThreepids());
} }
} }
printConfig();
} }
} }

View File

@@ -22,37 +22,65 @@ package io.kamax.mxisd.profile;
import io.kamax.matrix._MatrixID; import io.kamax.matrix._MatrixID;
import io.kamax.matrix._ThreePid; 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 org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Component @Component
public class ProfileManager { public class ProfileManager {
private final Logger log = LoggerFactory.getLogger(ProfileManager.class);
private List<ProfileProvider> providers; private List<ProfileProvider> providers;
@Autowired
public ProfileManager(List<ProfileProvider> providers) { public ProfileManager(List<ProfileProvider> providers) {
this.providers = providers.stream() this.providers = providers;
.filter(ProfileProvider::isEnabled)
.collect(Collectors.toList());
} }
public <T> List<T> get(Function<ProfileProvider, List<T>> 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 <T> List<T> getList(Function<ProfileProvider, List<T>> function) {
return providers.stream() return providers.stream()
.map(function) .map(function)
.flatMap(Collection::stream) .flatMap(Collection::stream)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public List<_ThreePid> getThreepids(_MatrixID mxid) { public <T> Optional<T> getOpt(Function<ProfileProvider, Optional<T>> function) {
return get(p -> p.getThreepids(mxid)); return providers.stream()
.map(function)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
} }
public List<String> getRoles(_MatrixID mxid) { public Optional<String> getDisplayName(_MatrixID user) {
return get(p -> p.getRoles(mxid)); return getOpt(p -> p.getDisplayName(user));
}
public List<_ThreePid> getThreepids(_MatrixID user) {
return getList(p -> p.getThreepids(user));
}
public List<String> getRoles(_MatrixID user) {
return getList(p -> p.getRoles(user));
} }
} }

View File

@@ -24,13 +24,16 @@ import io.kamax.matrix._MatrixID;
import io.kamax.matrix._ThreePid; import io.kamax.matrix._ThreePid;
import java.util.List; import java.util.List;
import java.util.Optional;
public interface ProfileProvider { public interface ProfileProvider {
boolean isEnabled(); boolean isEnabled();
List<_ThreePid> getThreepids(_MatrixID mxid); Optional<String> getDisplayName(_MatrixID userId);
List<String> getRoles(_MatrixID mxid); List<_ThreePid> getThreepids(_MatrixID userId);
List<String> getRoles(_MatrixID userId);
} }

View File

@@ -51,10 +51,19 @@ public abstract class PlaceholderNotificationGenerator {
} }
protected String populateForInvite(IMatrixIdInvite invite, String input) { 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) return populateForCommon(new ThreePid(invite.getMedium(), invite.getAddress()), input)
.replace("%SENDER_ID%", invite.getSender().getId()) .replace("%SENDER_ID%", invite.getSender().getId())
.replace("%SENDER_NAME%", senderName)
.replace("%SENDER_NAME_OR_ID%", senderNameOrId)
.replace("%RECIPIENT_ID%", invite.getInvitee().getId()) .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) { protected String populateForReply(IThreePidInviteReply invite, String input) {

View File

@@ -138,7 +138,6 @@ netiq:
firebase: firebase:
enabled: false enabled: false
sql: sql:
enabled: false enabled: false
type: 'sqlite' type: 'sqlite'
@@ -161,13 +160,6 @@ sql:
threepid: threepid:
query: 'SELECT medium, address FROM user_threepids WHERE user_id = ?' 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: wordpress:
enabled: false enabled: false
sql: sql: