diff --git a/docs/features/profile.md b/docs/features/profile.md new file mode 100644 index 0000000..f5a817c --- /dev/null +++ b/docs/features/profile.md @@ -0,0 +1,12 @@ +# Profile enhancement + +## Configuration + +### Reverse proxy + +#### Apache +``` +ProxyPassMatch "^/_matrix/client/r0/profile/([^/]+)$" "http://127.0.0.1:8090/_matrix/client/r0/profile/$1" +ProxyPassMatch "^/_matrix/client/r0/profile/([^/]+)/(.+)" "http://127.0.0.1:8008/_matrix/client/r0/profile/$1/$2" + +``` diff --git a/src/main/java/io/kamax/mxisd/ThreePid.java b/src/main/java/io/kamax/mxisd/ThreePid.java deleted file mode 100644 index 5215c1f..0000000 --- a/src/main/java/io/kamax/mxisd/ThreePid.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; - -// FIXME this should be in matrix-java-sdk -public class ThreePid { - - private String medium; - private String address; - - public ThreePid(ThreePid tpid) { - this(tpid.getMedium(), tpid.getAddress()); - } - - public ThreePid(String medium, String address) { - this.medium = medium; - this.address = address; - } - - public String getMedium() { - return medium; - } - - public String getAddress() { - return address; - } - - @Override - public String toString() { - return getMedium() + ":" + getAddress(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ThreePid threePid = (ThreePid) o; - - if (!medium.equals(threePid.medium)) return false; - return address.equals(threePid.address); - } - - @Override - public int hashCode() { - int result = medium.hashCode(); - result = 31 * result + address.hashCode(); - return result; - } - -} diff --git a/src/main/java/io/kamax/mxisd/auth/AuthManager.java b/src/main/java/io/kamax/mxisd/auth/AuthManager.java index 3ea0ebe..5404bde 100644 --- a/src/main/java/io/kamax/mxisd/auth/AuthManager.java +++ b/src/main/java/io/kamax/mxisd/auth/AuthManager.java @@ -21,8 +21,8 @@ package io.kamax.mxisd.auth; import io.kamax.matrix.MatrixID; +import io.kamax.matrix.ThreePid; import io.kamax.matrix._MatrixID; -import io.kamax.mxisd.ThreePid; import io.kamax.mxisd.UserIdType; import io.kamax.mxisd.auth.provider.AuthenticatorProvider; import io.kamax.mxisd.auth.provider.BackendAuthResult; diff --git a/src/main/java/io/kamax/mxisd/auth/UserAuthResult.java b/src/main/java/io/kamax/mxisd/auth/UserAuthResult.java index a6c8f33..fb5f290 100644 --- a/src/main/java/io/kamax/mxisd/auth/UserAuthResult.java +++ b/src/main/java/io/kamax/mxisd/auth/UserAuthResult.java @@ -20,7 +20,7 @@ package io.kamax.mxisd.auth; -import io.kamax.mxisd.ThreePid; +import io.kamax.matrix.ThreePid; import java.util.Collections; import java.util.HashSet; diff --git a/src/main/java/io/kamax/mxisd/auth/provider/BackendAuthResult.java b/src/main/java/io/kamax/mxisd/auth/provider/BackendAuthResult.java index 7c0bd0b..a89566d 100644 --- a/src/main/java/io/kamax/mxisd/auth/provider/BackendAuthResult.java +++ b/src/main/java/io/kamax/mxisd/auth/provider/BackendAuthResult.java @@ -20,7 +20,7 @@ package io.kamax.mxisd.auth.provider; -import io.kamax.mxisd.ThreePid; +import io.kamax.matrix.ThreePid; import io.kamax.mxisd.UserID; import io.kamax.mxisd.UserIdType; diff --git a/src/main/java/io/kamax/mxisd/backend/firebase/GoogleFirebaseAuthenticator.java b/src/main/java/io/kamax/mxisd/backend/firebase/GoogleFirebaseAuthenticator.java index 441a003..cb8b8bb 100644 --- a/src/main/java/io/kamax/mxisd/backend/firebase/GoogleFirebaseAuthenticator.java +++ b/src/main/java/io/kamax/mxisd/backend/firebase/GoogleFirebaseAuthenticator.java @@ -23,9 +23,9 @@ package io.kamax.mxisd.backend.firebase; import com.google.firebase.auth.UserInfo; import com.google.i18n.phonenumbers.NumberParseException; import com.google.i18n.phonenumbers.PhoneNumberUtil; +import io.kamax.matrix.ThreePid; import io.kamax.matrix.ThreePidMedium; import io.kamax.matrix._MatrixID; -import io.kamax.mxisd.ThreePid; import io.kamax.mxisd.UserIdType; import io.kamax.mxisd.auth.provider.AuthenticatorProvider; import io.kamax.mxisd.auth.provider.BackendAuthResult; diff --git a/src/main/java/io/kamax/mxisd/backend/ldap/LdapAuthProvider.java b/src/main/java/io/kamax/mxisd/backend/ldap/LdapAuthProvider.java index 79865c3..946515a 100644 --- a/src/main/java/io/kamax/mxisd/backend/ldap/LdapAuthProvider.java +++ b/src/main/java/io/kamax/mxisd/backend/ldap/LdapAuthProvider.java @@ -22,9 +22,9 @@ package io.kamax.mxisd.backend.ldap; import com.google.i18n.phonenumbers.NumberParseException; import com.google.i18n.phonenumbers.PhoneNumberUtil; +import io.kamax.matrix.ThreePid; import io.kamax.matrix.ThreePidMedium; import io.kamax.matrix._MatrixID; -import io.kamax.mxisd.ThreePid; import io.kamax.mxisd.UserIdType; import io.kamax.mxisd.auth.provider.AuthenticatorProvider; import io.kamax.mxisd.auth.provider.BackendAuthResult; 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 526491e..befcf7a 100644 --- a/src/main/java/io/kamax/mxisd/backend/memory/MemoryIdentityStore.java +++ b/src/main/java/io/kamax/mxisd/backend/memory/MemoryIdentityStore.java @@ -23,6 +23,7 @@ package io.kamax.mxisd.backend.memory; import io.kamax.matrix.MatrixID; import io.kamax.matrix.ThreePid; import io.kamax.matrix._MatrixID; +import io.kamax.matrix._ThreePid; import io.kamax.mxisd.UserIdType; import io.kamax.mxisd.auth.provider.AuthenticatorProvider; import io.kamax.mxisd.auth.provider.BackendAuthResult; @@ -34,18 +35,20 @@ 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; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; @Component -public class MemoryIdentityStore implements AuthenticatorProvider, IThreePidProvider { +public class MemoryIdentityStore implements AuthenticatorProvider, IThreePidProvider, ProfileProvider { private final Logger logger = LoggerFactory.getLogger(MemoryIdentityStore.class); @@ -59,7 +62,9 @@ public class MemoryIdentityStore implements AuthenticatorProvider, IThreePidProv } public Optional findByUsername(String username) { - return cfg.getIdentities().stream().filter(id -> StringUtils.equals(id.getUsername(), username)).findFirst(); + return cfg.getIdentities().stream() + .filter(id -> StringUtils.equals(id.getUsername(), username)) + .findFirst(); } @Override @@ -67,6 +72,20 @@ public class MemoryIdentityStore implements AuthenticatorProvider, IThreePidProv return cfg.isEnabled(); } + @Override + public List<_ThreePid> getThreepids(_MatrixID mxid) { + List<_ThreePid> l = new ArrayList<>(); + findByUsername(mxid.getLocalPart()).ifPresent(c -> l.addAll(c.getThreepids())); + return l; + } + + @Override + public List getRoles(_MatrixID mxid) { + List l = new ArrayList<>(); + findByUsername(mxid.getLocalPart()).ifPresent(c -> l.addAll(c.getRoles())); + return l; + } + @Override public boolean isLocal() { return true; 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 ff1b9ed..9ee66b2 100644 --- a/src/main/java/io/kamax/mxisd/backend/sql/SqlThreePidProvider.java +++ b/src/main/java/io/kamax/mxisd/backend/sql/SqlThreePidProvider.java @@ -21,12 +21,16 @@ 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; @@ -36,10 +40,11 @@ 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 { +public abstract class SqlThreePidProvider implements IThreePidProvider, ProfileProvider { private Logger log = LoggerFactory.getLogger(SqlThreePidProvider.class); @@ -109,4 +114,31 @@ public abstract class SqlThreePidProvider implements IThreePidProvider { 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/wordpress/WordpressAuthProvider.java b/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressAuthProvider.java index 2ea550d..5514158 100644 --- a/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressAuthProvider.java +++ b/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressAuthProvider.java @@ -20,8 +20,8 @@ package io.kamax.mxisd.backend.wordpress; +import io.kamax.matrix.ThreePid; import io.kamax.matrix._MatrixID; -import io.kamax.mxisd.ThreePid; import io.kamax.mxisd.UserIdType; import io.kamax.mxisd.auth.provider.AuthenticatorProvider; import io.kamax.mxisd.auth.provider.BackendAuthResult; diff --git a/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressThreePidProvider.java b/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressThreePidProvider.java index 10cbfd6..450e43d 100644 --- a/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressThreePidProvider.java +++ b/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressThreePidProvider.java @@ -21,8 +21,8 @@ package io.kamax.mxisd.backend.wordpress; import io.kamax.matrix.MatrixID; +import io.kamax.matrix.ThreePid; import io.kamax.matrix._MatrixID; -import io.kamax.mxisd.ThreePid; import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.config.wordpress.WordpressConfig; import io.kamax.mxisd.lookup.SingleLookupReply; 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 4dde336..8919646 100644 --- a/src/main/java/io/kamax/mxisd/config/memory/MemoryIdentityConfig.java +++ b/src/main/java/io/kamax/mxisd/config/memory/MemoryIdentityConfig.java @@ -31,6 +31,7 @@ public class MemoryIdentityConfig { private String username; private String password; private List threepids = new ArrayList<>(); + private List roles = new ArrayList<>(); public String getUsername() { return username; @@ -56,4 +57,12 @@ public class MemoryIdentityConfig { this.threepids = threepids; } + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } + } diff --git a/src/main/java/io/kamax/mxisd/config/memory/MemoryThreePid.java b/src/main/java/io/kamax/mxisd/config/memory/MemoryThreePid.java index 2a7719f..8a2a9d5 100644 --- a/src/main/java/io/kamax/mxisd/config/memory/MemoryThreePid.java +++ b/src/main/java/io/kamax/mxisd/config/memory/MemoryThreePid.java @@ -20,14 +20,16 @@ package io.kamax.mxisd.config.memory; +import io.kamax.matrix._ThreePid; import org.springframework.stereotype.Component; @Component -public class MemoryThreePid { +public class MemoryThreePid implements _ThreePid { private String medium; private String address; + @Override public String getMedium() { return medium; } @@ -36,6 +38,7 @@ public class MemoryThreePid { this.medium = medium; } + @Override public String getAddress() { return address; } 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 a70d4c5..2192211 100644 --- a/src/main/java/io/kamax/mxisd/config/sql/SqlConfig.java +++ b/src/main/java/io/kamax/mxisd/config/sql/SqlConfig.java @@ -37,22 +37,22 @@ public abstract class SqlConfig { public static class Type { - private GenericSqlProviderConfig.Query name = new GenericSqlProviderConfig.Query(); - private GenericSqlProviderConfig.Query threepid = new GenericSqlProviderConfig.Query(); + private Query name = new Query(); + private Query threepid = new Query(); - public GenericSqlProviderConfig.Query getName() { + public Query getName() { return name; } - public void setName(GenericSqlProviderConfig.Query name) { + public void setName(Query name) { this.name = name; } - public GenericSqlProviderConfig.Query getThreepid() { + public Query getThreepid() { return threepid; } - public void setThreepid(GenericSqlProviderConfig.Query threepid) { + public void setThreepid(Query threepid) { this.threepid = threepid; } @@ -75,7 +75,7 @@ public abstract class SqlConfig { public static class Directory { private Boolean enabled; - private GenericSqlProviderConfig.Type query = new GenericSqlProviderConfig.Type(); + private Type query = new Type(); public Boolean isEnabled() { return enabled; @@ -85,11 +85,11 @@ public abstract class SqlConfig { this.enabled = enabled; } - public GenericSqlProviderConfig.Type getQuery() { + public Type getQuery() { return query; } - public void setQuery(GenericSqlProviderConfig.Type query) { + public void setQuery(Type query) { this.query = query; } @@ -136,12 +136,41 @@ public abstract class SqlConfig { } + public static class ProfileThreepids { + + private String query; + + public String getQuery() { + return query; + } + + public void setQuery(String query) { + this.query = query; + } + + } + + public static class Profile { + + private ProfileThreepids threepid = new ProfileThreepids(); + + public ProfileThreepids getThreepid() { + return threepid; + } + + public void setThreepid(ProfileThreepids threepid) { + this.threepid = threepid; + } + + } + private boolean enabled; private String type; private String connection; - private GenericSqlProviderConfig.Auth auth = new GenericSqlProviderConfig.Auth(); - private GenericSqlProviderConfig.Directory directory = new GenericSqlProviderConfig.Directory(); - private GenericSqlProviderConfig.Identity identity = new GenericSqlProviderConfig.Identity(); + private Auth auth = new Auth(); + private Directory directory = new Directory(); + private Identity identity = new Identity(); + private Profile profile = new Profile(); public boolean isEnabled() { return enabled; @@ -167,30 +196,38 @@ public abstract class SqlConfig { this.connection = connection; } - public GenericSqlProviderConfig.Auth getAuth() { + public Auth getAuth() { return auth; } - public void setAuth(GenericSqlProviderConfig.Auth auth) { + public void setAuth(Auth auth) { this.auth = auth; } - public GenericSqlProviderConfig.Directory getDirectory() { + public Directory getDirectory() { return directory; } - public void setDirectory(GenericSqlProviderConfig.Directory directory) { + public void setDirectory(Directory directory) { this.directory = directory; } - public GenericSqlProviderConfig.Identity getIdentity() { + public Identity getIdentity() { return identity; } - public void setIdentity(GenericSqlProviderConfig.Identity identity) { + public void setIdentity(Identity identity) { this.identity = identity; } + public Profile getProfile() { + return profile; + } + + public void setProfile(Profile profile) { + this.profile = profile; + } + protected abstract String getProviderName(); protected void doBuild() { @@ -222,6 +259,7 @@ 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()); } } diff --git a/src/main/java/io/kamax/mxisd/controller/auth/v1/io/CredentialsValidationResponse.java b/src/main/java/io/kamax/mxisd/controller/auth/v1/io/CredentialsValidationResponse.java index 5e3fccb..2083991 100644 --- a/src/main/java/io/kamax/mxisd/controller/auth/v1/io/CredentialsValidationResponse.java +++ b/src/main/java/io/kamax/mxisd/controller/auth/v1/io/CredentialsValidationResponse.java @@ -20,7 +20,7 @@ package io.kamax.mxisd.controller.auth.v1.io; -import io.kamax.mxisd.ThreePid; +import io.kamax.matrix.ThreePid; import java.util.HashSet; import java.util.Set; diff --git a/src/main/java/io/kamax/mxisd/controller/identity/v1/SessionRestController.java b/src/main/java/io/kamax/mxisd/controller/identity/v1/SessionRestController.java index f877f68..8577c2b 100644 --- a/src/main/java/io/kamax/mxisd/controller/identity/v1/SessionRestController.java +++ b/src/main/java/io/kamax/mxisd/controller/identity/v1/SessionRestController.java @@ -22,8 +22,8 @@ package io.kamax.mxisd.controller.identity.v1; import com.google.gson.Gson; import com.google.gson.JsonObject; +import io.kamax.matrix.ThreePid; import io.kamax.matrix.ThreePidMedium; -import io.kamax.mxisd.ThreePid; import io.kamax.mxisd.config.ServerConfig; import io.kamax.mxisd.config.ViewConfig; import io.kamax.mxisd.controller.identity.v1.io.SessionEmailTokenRequestJson; diff --git a/src/main/java/io/kamax/mxisd/controller/profile/v1/ProfileController.java b/src/main/java/io/kamax/mxisd/controller/profile/v1/ProfileController.java new file mode 100644 index 0000000..a862fa9 --- /dev/null +++ b/src/main/java/io/kamax/mxisd/controller/profile/v1/ProfileController.java @@ -0,0 +1,99 @@ +/* + * mxisd - Matrix Identity Server Daemon + * Copyright (C) 2018 Kamax Sàrl + * + * 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.controller.profile.v1; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import io.kamax.matrix.MatrixID; +import io.kamax.matrix._ThreePid; +import io.kamax.mxisd.dns.ClientDnsOverwrite; +import io.kamax.mxisd.profile.ProfileManager; +import io.kamax.mxisd.util.GsonUtil; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URI; +import java.util.List; +import java.util.Objects; + +@RestController +@CrossOrigin +@RequestMapping(path = "/_matrix/client/r0/profile", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) +public class ProfileController { + + private final Logger log = LoggerFactory.getLogger(ProfileController.class); + private final ProfileManager mgr; + private final CloseableHttpClient client; + private final ClientDnsOverwrite dns; + private final JsonParser parser; + private final Gson gson; + + @Autowired + public ProfileController(ProfileManager mgr, CloseableHttpClient client, ClientDnsOverwrite dns) { + this.mgr = mgr; + this.client = client; + this.dns = dns; + this.parser = new JsonParser(); + this.gson = GsonUtil.build(); + } + + // FIXME do properly in the SDK (headers, check access token, etc.) + private String resolveProxyUrl(HttpServletRequest req) { + URI target = URI.create(req.getRequestURL().toString() + (Objects.isNull(req.getQueryString()) ? "" : "?" + req.getQueryString())); + URIBuilder builder = dns.transform(target); + String urlToLogin = builder.toString(); + log.info("Proxy resolution: {} to {}", target.toString(), urlToLogin); + return urlToLogin; + } + + @RequestMapping("/{userId:.+}") + public String getProfile(HttpServletRequest req, HttpServletResponse res, @PathVariable String userId) { + try (CloseableHttpResponse hsResponse = client.execute(new HttpGet(resolveProxyUrl(req)))) { + res.setStatus(hsResponse.getStatusLine().getStatusCode()); + JsonElement el = parser.parse(EntityUtils.toString(hsResponse.getEntity())); + List<_ThreePid> list = mgr.getThreepids(MatrixID.asAcceptable(userId)); + if (!list.isEmpty() && el.isJsonObject()) { + JsonObject obj = el.getAsJsonObject(); + obj.add("threepids", GsonUtil.build().toJsonTree(list)); + } + return gson.toJson(el); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/io/kamax/mxisd/controller/profile/v1/ProfileInternalController.java b/src/main/java/io/kamax/mxisd/controller/profile/v1/ProfileInternalController.java new file mode 100644 index 0000000..0f206ad --- /dev/null +++ b/src/main/java/io/kamax/mxisd/controller/profile/v1/ProfileInternalController.java @@ -0,0 +1,58 @@ +/* + * 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.controller.profile.v1; + +import io.kamax.matrix.MatrixID; +import io.kamax.matrix._MatrixID; +import io.kamax.matrix.json.GsonUtil; +import io.kamax.mxisd.profile.ProfileManager; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; + +import static org.springframework.web.bind.annotation.RequestMethod.GET; + +@RestController +@CrossOrigin +@RequestMapping(produces = MediaType.APPLICATION_JSON_UTF8_VALUE) +public class ProfileInternalController { + + private final ProfileManager mgr; + + public ProfileInternalController(ProfileManager mgr) { + this.mgr = mgr; + } + + @RequestMapping(method = GET, path = "/_matrix-internal/profile/v1/{userId:.+}") + public String getProfile(@PathVariable String userId) throws UnsupportedEncodingException { + userId = URLDecoder.decode(userId, StandardCharsets.UTF_8.name()); + _MatrixID mxId = MatrixID.asAcceptable(userId); + + return GsonUtil.get().toJson(GsonUtil.makeObj("roles", GsonUtil.asArray(mgr.getRoles(mxId)))); + } + +} diff --git a/src/main/java/io/kamax/mxisd/lookup/ThreePidMapping.java b/src/main/java/io/kamax/mxisd/lookup/ThreePidMapping.java index 26b15ec..4b4fb5a 100644 --- a/src/main/java/io/kamax/mxisd/lookup/ThreePidMapping.java +++ b/src/main/java/io/kamax/mxisd/lookup/ThreePidMapping.java @@ -21,7 +21,7 @@ package io.kamax.mxisd.lookup; import com.google.gson.Gson; -import io.kamax.mxisd.ThreePid; +import io.kamax.matrix.ThreePid; public class ThreePidMapping { diff --git a/src/main/java/io/kamax/mxisd/lookup/ThreePidValidation.java b/src/main/java/io/kamax/mxisd/lookup/ThreePidValidation.java index 206d9d4..afe0b17 100644 --- a/src/main/java/io/kamax/mxisd/lookup/ThreePidValidation.java +++ b/src/main/java/io/kamax/mxisd/lookup/ThreePidValidation.java @@ -20,7 +20,7 @@ package io.kamax.mxisd.lookup; -import io.kamax.mxisd.ThreePid; +import io.kamax.matrix.ThreePid; import java.time.Instant; @@ -29,7 +29,7 @@ public class ThreePidValidation extends ThreePid { private Instant validation; public ThreePidValidation(ThreePid tpid, Instant validation) { - super(tpid); + super(tpid.getMedium(), tpid.getAddress()); this.validation = validation; } diff --git a/src/main/java/io/kamax/mxisd/profile/ProfileManager.java b/src/main/java/io/kamax/mxisd/profile/ProfileManager.java new file mode 100644 index 0000000..17a6935 --- /dev/null +++ b/src/main/java/io/kamax/mxisd/profile/ProfileManager.java @@ -0,0 +1,58 @@ +/* + * mxisd - Matrix Identity Server Daemon + * Copyright (C) 2018 Kamax Sàrl + * + * 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.profile; + +import io.kamax.matrix._MatrixID; +import io.kamax.matrix._ThreePid; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Component +public class ProfileManager { + + private List providers; + + public ProfileManager(List providers) { + this.providers = providers.stream() + .filter(ProfileProvider::isEnabled) + .collect(Collectors.toList()); + } + + public List get(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 List getRoles(_MatrixID mxid) { + return get(p -> p.getRoles(mxid)); + } + +} diff --git a/src/main/java/io/kamax/mxisd/profile/ProfileProvider.java b/src/main/java/io/kamax/mxisd/profile/ProfileProvider.java new file mode 100644 index 0000000..8320f3c --- /dev/null +++ b/src/main/java/io/kamax/mxisd/profile/ProfileProvider.java @@ -0,0 +1,36 @@ +/* + * mxisd - Matrix Identity Server Daemon + * Copyright (C) 2018 Kamax Sàrl + * + * 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.profile; + +import io.kamax.matrix._MatrixID; +import io.kamax.matrix._ThreePid; + +import java.util.List; + +public interface ProfileProvider { + + boolean isEnabled(); + + List<_ThreePid> getThreepids(_MatrixID mxid); + + List getRoles(_MatrixID mxid); + +} diff --git a/src/main/java/io/kamax/mxisd/session/SessionMananger.java b/src/main/java/io/kamax/mxisd/session/SessionMananger.java index 1e56014..52719ea 100644 --- a/src/main/java/io/kamax/mxisd/session/SessionMananger.java +++ b/src/main/java/io/kamax/mxisd/session/SessionMananger.java @@ -25,9 +25,9 @@ import com.google.i18n.phonenumbers.NumberParseException; import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.i18n.phonenumbers.Phonenumber; import io.kamax.matrix.MatrixID; +import io.kamax.matrix.ThreePid; import io.kamax.matrix.ThreePidMedium; import io.kamax.matrix._MatrixID; -import io.kamax.mxisd.ThreePid; import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.config.SessionConfig; import io.kamax.mxisd.controller.identity.v1.io.RequestTokenResponse; diff --git a/src/main/java/io/kamax/mxisd/storage/IStorage.java b/src/main/java/io/kamax/mxisd/storage/IStorage.java index 329dfd0..cd0f956 100644 --- a/src/main/java/io/kamax/mxisd/storage/IStorage.java +++ b/src/main/java/io/kamax/mxisd/storage/IStorage.java @@ -20,7 +20,7 @@ package io.kamax.mxisd.storage; -import io.kamax.mxisd.ThreePid; +import io.kamax.matrix.ThreePid; import io.kamax.mxisd.invitation.IThreePidInviteReply; import io.kamax.mxisd.storage.dao.IThreePidSessionDao; import io.kamax.mxisd.storage.ormlite.ThreePidInviteIO; diff --git a/src/main/java/io/kamax/mxisd/storage/ormlite/OrmLiteSqliteStorage.java b/src/main/java/io/kamax/mxisd/storage/ormlite/OrmLiteSqliteStorage.java index 2ae81ee..06dab5b 100644 --- a/src/main/java/io/kamax/mxisd/storage/ormlite/OrmLiteSqliteStorage.java +++ b/src/main/java/io/kamax/mxisd/storage/ormlite/OrmLiteSqliteStorage.java @@ -26,7 +26,7 @@ import com.j256.ormlite.dao.DaoManager; import com.j256.ormlite.jdbc.JdbcConnectionSource; import com.j256.ormlite.support.ConnectionSource; import com.j256.ormlite.table.TableUtils; -import io.kamax.mxisd.ThreePid; +import io.kamax.matrix.ThreePid; import io.kamax.mxisd.exception.InternalServerError; import io.kamax.mxisd.invitation.IThreePidInviteReply; import io.kamax.mxisd.storage.IStorage; diff --git a/src/main/java/io/kamax/mxisd/storage/ormlite/dao/ThreePidSessionDao.java b/src/main/java/io/kamax/mxisd/storage/ormlite/dao/ThreePidSessionDao.java index fc74bf6..823f4cc 100644 --- a/src/main/java/io/kamax/mxisd/storage/ormlite/dao/ThreePidSessionDao.java +++ b/src/main/java/io/kamax/mxisd/storage/ormlite/dao/ThreePidSessionDao.java @@ -22,7 +22,7 @@ package io.kamax.mxisd.storage.ormlite.dao; import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; -import io.kamax.mxisd.ThreePid; +import io.kamax.matrix.ThreePid; import io.kamax.mxisd.storage.dao.IThreePidSessionDao; @DatabaseTable(tableName = "session_3pid") 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 f457a1e..715792b 100644 --- a/src/main/java/io/kamax/mxisd/threepid/notification/PlaceholderNotificationGenerator.java +++ b/src/main/java/io/kamax/mxisd/threepid/notification/PlaceholderNotificationGenerator.java @@ -20,7 +20,7 @@ package io.kamax.mxisd.threepid.notification; -import io.kamax.mxisd.ThreePid; +import io.kamax.matrix.ThreePid; import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.config.ServerConfig; import io.kamax.mxisd.controller.identity.v1.IdentityAPIv1; diff --git a/src/main/java/io/kamax/mxisd/threepid/notification/email/EmailNotificationGenerator.java b/src/main/java/io/kamax/mxisd/threepid/notification/email/EmailNotificationGenerator.java index a0d1348..e86fb7d 100644 --- a/src/main/java/io/kamax/mxisd/threepid/notification/email/EmailNotificationGenerator.java +++ b/src/main/java/io/kamax/mxisd/threepid/notification/email/EmailNotificationGenerator.java @@ -20,7 +20,7 @@ package io.kamax.mxisd.threepid.notification.email; -import io.kamax.mxisd.ThreePid; +import io.kamax.matrix.ThreePid; import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.config.ServerConfig; import io.kamax.mxisd.config.threepid.medium.EmailConfig; diff --git a/src/main/java/io/kamax/mxisd/threepid/session/IThreePidSession.java b/src/main/java/io/kamax/mxisd/threepid/session/IThreePidSession.java index 8611855..c1faca8 100644 --- a/src/main/java/io/kamax/mxisd/threepid/session/IThreePidSession.java +++ b/src/main/java/io/kamax/mxisd/threepid/session/IThreePidSession.java @@ -20,7 +20,7 @@ package io.kamax.mxisd.threepid.session; -import io.kamax.mxisd.ThreePid; +import io.kamax.matrix.ThreePid; import java.time.Instant; import java.util.Optional; diff --git a/src/main/java/io/kamax/mxisd/threepid/session/ThreePidSession.java b/src/main/java/io/kamax/mxisd/threepid/session/ThreePidSession.java index 035a60a..15a2fbb 100644 --- a/src/main/java/io/kamax/mxisd/threepid/session/ThreePidSession.java +++ b/src/main/java/io/kamax/mxisd/threepid/session/ThreePidSession.java @@ -20,7 +20,7 @@ package io.kamax.mxisd.threepid.session; -import io.kamax.mxisd.ThreePid; +import io.kamax.matrix.ThreePid; import io.kamax.mxisd.exception.BadRequestException; import io.kamax.mxisd.exception.InvalidCredentialsException; import io.kamax.mxisd.storage.dao.IThreePidSessionDao; @@ -76,7 +76,7 @@ public class ThreePidSession implements IThreePidSession { public ThreePidSession(String id, String server, ThreePid tPid, String secret, int attempt, String nextLink, String token) { this.id = id; this.server = server; - this.tPid = new ThreePid(tPid); + this.tPid = new ThreePid(tPid.getMedium(), tPid.getAddress()); this.secret = secret; this.attempt = attempt; this.nextLink = nextLink; diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 9ecc5cc..06b9cf1 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -151,10 +151,16 @@ sql: identity: type: 'mxid' query: 'SELECT user_id AS uid FROM user_threepids WHERE medium = ? AND address = ?' + profile: + 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