diff --git a/build.gradle b/build.gradle index 793a5e98..428719d5 100644 --- a/build.gradle +++ b/build.gradle @@ -119,6 +119,9 @@ dependencies { // PostgreSQL compile 'org.postgresql:postgresql:42.1.4' + // MariaDB/MySQL + compile 'org.mariadb.jdbc:mariadb-java-client:2.1.2' + // Twilio SDK for SMS compile 'com.twilio.sdk:twilio:7.14.5' diff --git a/docs/README.md b/docs/README.md index c951e3aa..32201b0d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -17,6 +17,7 @@ - [SQL](backends/sql.md) - [REST](backends/rest.md) - [Google Firebase](backends/firebase.md) + - [Wordpress](backends/wordpress.md) - Notifications - Handlers - [Basic](threepids/notifications/basic-handler.md) diff --git a/docs/backends/README.md b/docs/backends/README.md index 0dbc07b2..e6930e47 100644 --- a/docs/backends/README.md +++ b/docs/backends/README.md @@ -2,4 +2,5 @@ - [Samba / Active Directory / LDAP](ldap.md) - [SQL Databases](sql.md) - [Website / Web service / Web app](rest.md) -- [Google Firebase](firebase.md) \ No newline at end of file +- [Google Firebase](firebase.md) +- [Wordpress](wordpress.md) \ No newline at end of file diff --git a/docs/backends/wordpress.md b/docs/backends/wordpress.md new file mode 100644 index 00000000..fc3ef209 --- /dev/null +++ b/docs/backends/wordpress.md @@ -0,0 +1,55 @@ +# Wordpress +This Identity store allows you to use user accounts registered on your Wordpress setup. +Two types of connections are required for full support: +- [REST API](https://developer.wordpress.org/rest-api/) with JWT authentication +- Direct SQL access + +This Identity store supports the following features: +- [Authentication](../features/authentication.md) +- [Directory](../features/directory-users.md) +- [Identity](../features/identity.md) + +## Requirements +- [Wordpress](https://wordpress.org/download/) >= 4.4 +- Permalink structure set to `Post Name` +- [JWT Auth plugin for REST API](https://wordpress.org/plugins/jwt-authentication-for-wp-rest-api/) +- SQL Credentials to the Wordpress Database + +## Configuration +### Wordpress +#### JWT Auth +Set a JWT secret into `wp-config.php` like so: +``` +define('JWT_AUTH_SECRET_KEY', 'your-top-secret-key'); +``` +`your-top-secret-key` should be set to a randomly generated value which is kept secret. + +#### Rewrite of `index.php` +Wordpress is normally configured with rewrite of `index.php` so it does not appear in URLs. +If this is not the case for your installation, the mxisd URL will need to be appended with `/index.php` + +### mxisd +Enable in the configuration: +``` +wordpress.enabled: true +``` +Configure the URL to your Wordpress installation - see above about added `/index.php`: +``` +wordpress.rest.base: 'http://localhost:8080' +``` +Configure the SQL connection to your Wordpress database: +``` +wordpress.sql.connection: '//127.0.0.1/wordpress?user=root&password=example' +``` + +--- + +By default, MySQL database is expected. If you use another database, use: +``` +wordpress.sql.type: 'jdbc-scheme' +``` +With possible values: +- `mysql` +- `mariadb` +- `postgresql` +- `sqlite` diff --git a/docs/features/authentication.md b/docs/features/authentication.md index 4297a15c..3586cdd9 100644 --- a/docs/features/authentication.md +++ b/docs/features/authentication.md @@ -115,8 +115,8 @@ Steps of user authentication using a 3PID: - Homeserver - Compatible Identity backends: - LDAP - - SQL - REST + - Wordpress ### Configuration @@ -160,12 +160,3 @@ value is the base internal URL of the Homeserver, without any /_matrix/.. or tra #### Backends The Backends should be configured as described in the documentation of the [Directory User](directory-users.md) feature. - - - - - - - - - diff --git a/docs/features/directory-users.md b/docs/features/directory-users.md index e6b090f8..01b9b5aa 100644 --- a/docs/features/directory-users.md +++ b/docs/features/directory-users.md @@ -219,6 +219,9 @@ For each query, `type` can be used to tell mxisd how to process the ID column: #### REST See the [dedicated document](../backends/rest.md) +#### Wordpress +See the [dedicated document](../backends/wordpress.md) + ## Next steps ### Homeserver results You can configure if the Homeserver should be queried at all when doing a directory search. diff --git a/docs/getting-started.md b/docs/getting-started.md index bb799144..ecfe1982 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -143,3 +143,4 @@ Use your Identity stores: - [SQL Database](backends/sql.md) - [Website / Web service / Web app](backends/rest.md) - [Google Firebase](backends/firebase.md) +- [Wordpress](backends/wordpress.md) 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 be112f51..7c0bd0bd 100644 --- a/src/main/java/io/kamax/mxisd/auth/provider/BackendAuthResult.java +++ b/src/main/java/io/kamax/mxisd/auth/provider/BackendAuthResult.java @@ -66,7 +66,6 @@ public static BackendAuthResult success(String id, String type, String displayNa public void succeed(String id, String type, String displayName) { this.success = true; this.id = new UserID(type, id); - this.profile = new BackendAuthProfile(); this.profile.displayName = displayName; } diff --git a/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressAuthData.java b/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressAuthData.java new file mode 100644 index 00000000..34c7733b --- /dev/null +++ b/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressAuthData.java @@ -0,0 +1,62 @@ +/* + * 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.backend.wordpress; + +public class WordpressAuthData { + + public String token; + private String userEmail; + private String userNicename; + private String userDisplayName; + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public String getUserEmail() { + return userEmail; + } + + public void setUserEmail(String userEmail) { + this.userEmail = userEmail; + } + + public String getUserNicename() { + return userNicename; + } + + public void setUserNicename(String userNicename) { + this.userNicename = userNicename; + } + + public String getUserDisplayName() { + return userDisplayName; + } + + public void setUserDisplayName(String userDisplayName) { + this.userDisplayName = userDisplayName; + } + +} diff --git a/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressAuthProvider.java b/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressAuthProvider.java new file mode 100644 index 00000000..2ea550d6 --- /dev/null +++ b/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressAuthProvider.java @@ -0,0 +1,68 @@ +/* + * 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.backend.wordpress; + +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; +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; + +@Component +public class WordpressAuthProvider implements AuthenticatorProvider { + + private final Logger log = LoggerFactory.getLogger(WordpressAuthProvider.class); + + private WordpressRestBackend wordpress; + + @Autowired + public WordpressAuthProvider(WordpressRestBackend wordpress) { + this.wordpress = wordpress; + } + + @Override + public boolean isEnabled() { + return wordpress.isEnabled(); + } + + @Override + public BackendAuthResult authenticate(_MatrixID mxid, String password) { + try { + WordpressAuthData data = wordpress.authenticate(mxid.getLocalPart(), password); + BackendAuthResult result = new BackendAuthResult(); + if (StringUtils.isNotBlank(data.getUserEmail())) { + result.withThreePid(new ThreePid("email", data.getUserEmail())); + } + result.succeed(mxid.getId(), UserIdType.MatrixID.getId(), data.getUserDisplayName()); + return result; + } catch (IllegalArgumentException e) { + log.error("Authentication failed for {}: {}", mxid.getId(), e.getMessage()); + return BackendAuthResult.failure(); + } + + } + +} diff --git a/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressDirectoryProvider.java b/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressDirectoryProvider.java new file mode 100644 index 00000000..4caf77c1 --- /dev/null +++ b/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressDirectoryProvider.java @@ -0,0 +1,112 @@ +/* + * 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.backend.wordpress; + +import io.kamax.matrix.MatrixID; +import io.kamax.mxisd.config.MatrixConfig; +import io.kamax.mxisd.config.wordpress.WordpressConfig; +import io.kamax.mxisd.controller.directory.v1.io.UserDirectorySearchResult; +import io.kamax.mxisd.directory.IDirectoryProvider; +import io.kamax.mxisd.exception.InternalServerError; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Optional; + +@Component +public class WordpressDirectoryProvider implements IDirectoryProvider { + + private final Logger log = LoggerFactory.getLogger(WordpressDirectoryProvider.class); + + private WordpressConfig cfg; + private WordressSqlBackend wordpress; + private MatrixConfig mxCfg; + + @Autowired + public WordpressDirectoryProvider(WordpressConfig cfg, WordressSqlBackend wordpress, MatrixConfig mxCfg) { + this.cfg = cfg; + this.wordpress = wordpress; + this.mxCfg = mxCfg; + } + + @Override + public boolean isEnabled() { + return wordpress.isEnabled(); + } + + protected void setParameters(PreparedStatement stmt, String searchTerm) throws SQLException { + for (int i = 1; i <= stmt.getParameterMetaData().getParameterCount(); i++) { + stmt.setString(i, "%" + searchTerm + "%"); + } + } + + protected Optional processRow(ResultSet rSet) throws SQLException { + UserDirectorySearchResult.Result item = new UserDirectorySearchResult.Result(); + item.setUserId(rSet.getString(1)); + item.setDisplayName(rSet.getString(2)); + return Optional.of(item); + } + + public UserDirectorySearchResult search(String searchTerm, String query) { + try (Connection conn = wordpress.getConnection()) { + log.info("Will execute query: {}", query); + try (PreparedStatement stmt = conn.prepareStatement(query)) { + setParameters(stmt, searchTerm); + + try (ResultSet rSet = stmt.executeQuery()) { + UserDirectorySearchResult result = new UserDirectorySearchResult(); + result.setLimited(false); + + while (rSet.next()) { + processRow(rSet).ifPresent(e -> { + e.setUserId(MatrixID.from(e.getUserId(), mxCfg.getDomain()).valid().getId()); + result.addResult(e); + }); + } + + return result; + } + } + } catch (SQLException e) { + e.printStackTrace(); + throw new InternalServerError(e); + } + } + + @Override + public UserDirectorySearchResult searchByDisplayName(String searchTerm) { + log.info("Searching users by display name using '{}'", searchTerm); + return search(searchTerm, cfg.getSql().getQuery().getDirectory().get("name")); + } + + @Override + public UserDirectorySearchResult searchBy3pid(String searchTerm) { + log.info("Searching users by 3PID using '{}'", searchTerm); + return search(searchTerm, cfg.getSql().getQuery().getDirectory().get("threepid")); + } + +} diff --git a/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressRestBackend.java b/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressRestBackend.java new file mode 100644 index 00000000..57c592d6 --- /dev/null +++ b/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressRestBackend.java @@ -0,0 +1,143 @@ +/* + * 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.backend.wordpress; + +import com.google.gson.JsonObject; +import io.kamax.matrix.json.GsonUtil; +import io.kamax.matrix.json.InvalidJsonException; +import io.kamax.mxisd.config.wordpress.WordpressConfig; +import io.kamax.mxisd.util.RestClientUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +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.stereotype.Component; + +import java.io.IOException; + +@Component +public class WordpressRestBackend { + + private final Logger log = LoggerFactory.getLogger(WordpressRestBackend.class); + private final String jsonPath = "/wp-json"; + private final String jwtPath = "/jwt-auth/v1"; + + private WordpressConfig cfg; + private CloseableHttpClient client; + + private String jsonEndpoint; + private String jwtEndpoint; + + private String token; + + @Autowired + public WordpressRestBackend(WordpressConfig cfg, CloseableHttpClient client) { + this.cfg = cfg; + this.client = client; + + if (!cfg.isEnabled()) { + return; + } + + jsonEndpoint = cfg.getRest().getBase() + jsonPath; + jwtEndpoint = jsonEndpoint + jwtPath; + validateConfig(); + } + + private void validateConfig() { + log.info("Validating JWT auth endpoint"); + try (CloseableHttpResponse res = client.execute(new HttpGet(jwtEndpoint))) { + int status = res.getStatusLine().getStatusCode(); + if (status != 200) { + log.warn("JWT auth endpoint check failed: Got status code {}", status); + return; + } + + String data = EntityUtils.toString(res.getEntity()); + if (StringUtils.isBlank(data)) { + log.warn("JWT auth endpoint check failed: Got no/empty body data"); + } + + JsonObject body = GsonUtil.parseObj(data); + if (!body.has("namespace")) { + log.warn("JWT auth endpoint check failed: invalid namespace"); + } + + log.info("JWT auth endpoint check succeeded"); + } catch (InvalidJsonException e) { + log.warn("JWT auth endpoint check failed: Invalid JSON response: {}", e.getMessage()); + } catch (IOException e) { + log.warn("JWT auth endpoint check failed: Could not read API endpoint: {}", e.getMessage()); + } + } + + public boolean isEnabled() { + return cfg.isEnabled(); + } + + protected WordpressAuthData authenticate(String username, String password) { + JsonObject body = new JsonObject(); + body.addProperty("username", username); + body.addProperty("password", password); + HttpPost req = RestClientUtils.post(jwtEndpoint + "/token", body); + try (CloseableHttpResponse res = client.execute(req)) { + int status = res.getStatusLine().getStatusCode(); + String bodyRes = EntityUtils.toString(res.getEntity()); + if (status != 200) { + throw new IllegalArgumentException(bodyRes); + } + + return GsonUtil.get().fromJson(bodyRes, WordpressAuthData.class); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected void authenticate() { + WordpressAuthData data = authenticate( + cfg.getRest().getCredential().getUsername(), + cfg.getRest().getCredential().getPassword()); + log.info("Internal authentication: success, logged in as " + data.getUserNicename()); + token = data.getToken(); + } + + protected CloseableHttpResponse runRequest(HttpRequestBase request) throws IOException { + request.setHeader("Authorization", "Bearer " + token); + return client.execute(request); + } + + public CloseableHttpResponse withAuthentication(HttpRequestBase request) throws IOException { + CloseableHttpResponse response = runRequest(request); + if (response.getStatusLine().getStatusCode() == 403) { //FIXME we should check the JWT expiration time + authenticate(); + response = runRequest(request); + } + + return response; + } + +} diff --git a/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressThreePidProvider.java b/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressThreePidProvider.java new file mode 100644 index 00000000..10cbfd6c --- /dev/null +++ b/src/main/java/io/kamax/mxisd/backend/wordpress/WordpressThreePidProvider.java @@ -0,0 +1,114 @@ +/* + * 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.backend.wordpress; + +import io.kamax.matrix.MatrixID; +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; +import io.kamax.mxisd.lookup.SingleLookupRequest; +import io.kamax.mxisd.lookup.ThreePidMapping; +import io.kamax.mxisd.lookup.provider.IThreePidProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +@Component +public class WordpressThreePidProvider implements IThreePidProvider { + + private final Logger log = LoggerFactory.getLogger(WordpressThreePidProvider.class); + + private MatrixConfig mxCfg; + private WordpressConfig cfg; + private WordressSqlBackend wordpress; + + @Autowired + public WordpressThreePidProvider(MatrixConfig mxCfg, WordpressConfig cfg, WordressSqlBackend wordpress) { + this.mxCfg = mxCfg; + this.cfg = cfg; + this.wordpress = wordpress; + } + + @Override + public boolean isEnabled() { + return wordpress.isEnabled(); + } + + @Override + public boolean isLocal() { + return true; + } + + @Override + public int getPriority() { + return 15; + } + + protected Optional<_MatrixID> find(ThreePid tpid) { + String query = cfg.getSql().getQuery().getThreepid().get(tpid.getMedium()); + if (Objects.isNull(query)) { + return Optional.empty(); + } + + try (Connection conn = wordpress.getConnection()) { + PreparedStatement stmt = conn.prepareStatement(query); + stmt.setString(1, tpid.getAddress()); + + try (ResultSet rSet = stmt.executeQuery()) { + while (rSet.next()) { + String uid = rSet.getString("uid"); + log.info("Found match: {}", uid); + return Optional.of(MatrixID.from(uid, mxCfg.getDomain()).valid()); + } + + log.info("No match found in Wordpress"); + return Optional.empty(); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + @Override + public Optional find(SingleLookupRequest request) { + return find(new ThreePid(request.getType(), request.getThreePid())).map(mxid -> new SingleLookupReply(request, mxid)); + } + + @Override + public List populate(List mappings) { + for (ThreePidMapping tpidMap : mappings) { + find(new ThreePid(tpidMap.getMedium(), tpidMap.getValue())).ifPresent(mxid -> tpidMap.setMxid(mxid.getId())); + } + return mappings; + } + +} diff --git a/src/main/java/io/kamax/mxisd/backend/wordpress/WordressSqlBackend.java b/src/main/java/io/kamax/mxisd/backend/wordpress/WordressSqlBackend.java new file mode 100644 index 00000000..8ada21fa --- /dev/null +++ b/src/main/java/io/kamax/mxisd/backend/wordpress/WordressSqlBackend.java @@ -0,0 +1,61 @@ +/* + * 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.backend.wordpress; + +import com.mchange.v2.c3p0.ComboPooledDataSource; +import io.kamax.mxisd.config.wordpress.WordpressConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.sql.Connection; +import java.sql.SQLException; + +@Component +public class WordressSqlBackend { + + private Logger log = LoggerFactory.getLogger(WordressSqlBackend.class); + + private WordpressConfig cfg; + + private ComboPooledDataSource ds; + + @Autowired + public WordressSqlBackend(WordpressConfig cfg) { + this.cfg = cfg; + + ds = new ComboPooledDataSource(); + ds.setJdbcUrl("jdbc:" + cfg.getSql().getType() + ":" + cfg.getSql().getConnection()); + ds.setMinPoolSize(1); + ds.setMaxPoolSize(10); + ds.setAcquireIncrement(2); + } + + public boolean isEnabled() { + return cfg.isEnabled(); + } + + public Connection getConnection() throws SQLException { + return ds.getConnection(); + } + +} diff --git a/src/main/java/io/kamax/mxisd/config/wordpress/WordpressConfig.java b/src/main/java/io/kamax/mxisd/config/wordpress/WordpressConfig.java new file mode 100644 index 00000000..d4ce42ae --- /dev/null +++ b/src/main/java/io/kamax/mxisd/config/wordpress/WordpressConfig.java @@ -0,0 +1,175 @@ +/* + * 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.config.wordpress; + +import io.kamax.mxisd.exception.ConfigurationException; +import org.apache.commons.lang.StringUtils; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; +import java.util.Map; + +@Configuration +@ConfigurationProperties("wordpress") +public class WordpressConfig { + + public static class Credential { + + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + } + + public static class Rest { + + private Credential credential = new Credential(); + private String base; + + public String getBase() { + return base; + } + + public void setBase(String base) { + this.base = base; + } + + public Credential getCredential() { + return credential; + } + + public void setCredential(Credential credential) { + this.credential = credential; + } + + } + + public static class Query { + + private Map threepid; + private Map directory; + + public Map getThreepid() { + return threepid; + } + + public void setThreepid(Map threepid) { + this.threepid = threepid; + } + + public Map getDirectory() { + return directory; + } + + public void setDirectory(Map directory) { + this.directory = directory; + } + + } + + public static class Sql { + + private String type; + private String connection; + private Query query; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getConnection() { + return connection; + } + + public void setConnection(String connection) { + this.connection = connection; + } + + public Query getQuery() { + return query; + } + + public void setQuery(Query query) { + this.query = query; + } + + } + + private boolean enabled; + private Rest rest = new Rest(); + private Sql sql = new Sql(); + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public Rest getRest() { + return rest; + } + + public void setRest(Rest rest) { + this.rest = rest; + } + + public Sql getSql() { + return sql; + } + + public void setSql(Sql sql) { + this.sql = sql; + } + + @PostConstruct + public void build() { + if (!isEnabled()) { + return; + } + + if (StringUtils.isBlank(getRest().getBase())) { + throw new ConfigurationException("wordpress.rest.base"); + } + } + +} diff --git a/src/main/java/io/kamax/mxisd/util/RestClientUtils.java b/src/main/java/io/kamax/mxisd/util/RestClientUtils.java index 1c23a83b..2b1e42a9 100644 --- a/src/main/java/io/kamax/mxisd/util/RestClientUtils.java +++ b/src/main/java/io/kamax/mxisd/util/RestClientUtils.java @@ -20,9 +20,7 @@ package io.kamax.mxisd.util; -import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; @@ -31,7 +29,7 @@ public class RestClientUtils { - private static Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); + private static Gson gson = GsonUtil.build(); public static HttpPost post(String url, String body) { StringEntity entity = new StringEntity(body, StandardCharsets.UTF_8); diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 4168fef4..9ecc5cc7 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -156,6 +156,17 @@ synapseSql: enabled: false type: 'sqlite' +wordpress: + enabled: false + sql: + type: 'mysql' + query: + threepid: + email: 'SELECT user_login as uid FROM wp_users WHERE user_email = ?' + directory: + name: "SELECT DISTINCT user_login, display_name FROM wp_users u LEFT JOIN wp_usermeta m ON m.user_id = u.id WHERE u.display_name LIKE ? OR (m.meta_key = 'nickname' AND m.meta_value = ?) OR (m.meta_key = 'first_name' AND m.meta_value = ?) OR (m.meta_key = 'last_name' AND m.meta_value = ?);" + threepid: 'SELECT DISTINCT user_login, display_name FROM wp_users WHERE user_email LIKE ?' + forward: servers: - 'https://matrix.org'