MSC2140 Add option to enable/disable v1 and v2 api.

This commit is contained in:
Anatoly Sablin
2019-08-31 23:09:20 +03:00
parent 36f22e5ca6
commit f1dd309551
20 changed files with 201 additions and 32 deletions

View File

@@ -20,7 +20,9 @@
package io.kamax.mxisd;
import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.config.MxisdConfig;
import io.kamax.mxisd.http.undertow.handler.ApiHandler;
import io.kamax.mxisd.http.undertow.handler.InternalInfoHandler;
import io.kamax.mxisd.http.undertow.handler.OptionsHandler;
import io.kamax.mxisd.http.undertow.handler.SaneHandler;
@@ -39,11 +41,16 @@ import io.kamax.mxisd.http.undertow.handler.profile.v1.ProfileHandler;
import io.kamax.mxisd.http.undertow.handler.register.v1.Register3pidRequestTokenHandler;
import io.kamax.mxisd.http.undertow.handler.status.StatusHandler;
import io.kamax.mxisd.http.undertow.handler.status.VersionHandler;
import io.kamax.mxisd.matrix.IdentityServiceAPI;
import io.undertow.Handlers;
import io.undertow.Undertow;
import io.undertow.server.HttpHandler;
import io.undertow.server.RoutingHandler;
import io.undertow.util.HttpString;
import io.undertow.util.Methods;
import java.util.Objects;
import java.util.function.Supplier;
public class HttpMxisd {
@@ -91,22 +98,22 @@ public class HttpMxisd {
.post(UserDirectorySearchHandler.Path, SaneHandler.around(new UserDirectorySearchHandler(m.getDirectory())))
// Key endpoints
.get(KeyGetHandler.Path, SaneHandler.around(new KeyGetHandler(m.getKeyManager())))
.get(RegularKeyIsValidHandler.Path, SaneHandler.around(new RegularKeyIsValidHandler(m.getKeyManager())))
.get(EphemeralKeyIsValidHandler.Path, SaneHandler.around(new EphemeralKeyIsValidHandler(m.getKeyManager())))
.get(KeyGetHandler.Path, SaneHandler.around(new KeyGetHandler(m.getKeyManager()))) // to v2
.get(RegularKeyIsValidHandler.Path, SaneHandler.around(new RegularKeyIsValidHandler(m.getKeyManager()))) // to v2
.get(EphemeralKeyIsValidHandler.Path, SaneHandler.around(new EphemeralKeyIsValidHandler(m.getKeyManager()))) // to v2
// Identity endpoints
.get(HelloHandler.Path, helloHandler)
.get(HelloHandler.Path + "/", helloHandler) // Be lax with possibly trailing slash
.get(SingleLookupHandler.Path, SaneHandler.around(new SingleLookupHandler(m.getConfig(), m.getIdentity(), m.getSign())))
.post(BulkLookupHandler.Path, SaneHandler.around(new BulkLookupHandler(m.getIdentity())))
.post(StoreInviteHandler.Path, storeInvHandler)
.post(SessionStartHandler.Path, SaneHandler.around(new SessionStartHandler(m.getSession())))
.get(SessionValidateHandler.Path, SaneHandler.around(new SessionValidationGetHandler(m.getSession(), m.getConfig())))
.post(SessionValidateHandler.Path, SaneHandler.around(new SessionValidationPostHandler(m.getSession())))
.get(SessionTpidGetValidatedHandler.Path, SaneHandler.around(new SessionTpidGetValidatedHandler(m.getSession())))
.post(SessionTpidBindHandler.Path, SaneHandler.around(new SessionTpidBindHandler(m.getSession(), m.getInvite(), m.getSign())))
.post(SessionTpidUnbindHandler.Path, SaneHandler.around(new SessionTpidUnbindHandler(m.getSession())))
.get(HelloHandler.Path, helloHandler) // to v2
.get(HelloHandler.Path + "/", helloHandler) // Be lax with possibly trailing slash // to v2
.get(SingleLookupHandler.Path, SaneHandler.around(new SingleLookupHandler(m.getConfig(), m.getIdentity(), m.getSign()))) // to v2
.post(BulkLookupHandler.Path, SaneHandler.around(new BulkLookupHandler(m.getIdentity()))) // to v2
.post(StoreInviteHandler.Path, storeInvHandler) // to v2
.post(SessionStartHandler.Path, SaneHandler.around(new SessionStartHandler(m.getSession()))) // to v2
.get(SessionValidateHandler.Path, SaneHandler.around(new SessionValidationGetHandler(m.getSession(), m.getConfig()))) // to v2
.post(SessionValidateHandler.Path, SaneHandler.around(new SessionValidationPostHandler(m.getSession()))) // to v2
.get(SessionTpidGetValidatedHandler.Path, SaneHandler.around(new SessionTpidGetValidatedHandler(m.getSession()))) // to v2
.post(SessionTpidBindHandler.Path, SaneHandler.around(new SessionTpidBindHandler(m.getSession(), m.getInvite(), m.getSign()))) // to v2
.post(SessionTpidUnbindHandler.Path, SaneHandler.around(new SessionTpidUnbindHandler(m.getSession()))) // to v2
.post(SignEd25519Handler.Path, SaneHandler.around(new SignEd25519Handler(m.getConfig(), m.getInvite(), m.getSign())))
// Profile endpoints
@@ -143,4 +150,18 @@ public class HttpMxisd {
m.stop();
}
private RoutingHandler attachHandler(RoutingHandler routingHandler, HttpString method, ApiHandler handler, Supplier<HttpHandler> handlerSupplier) {
final MatrixConfig matrixConfig = m.getConfig().getMatrix();
if (matrixConfig.isV1()) {
return routingHandler.add(method, handler.getPath(IdentityServiceAPI.V1), handlerSupplier.get());
}
if (matrixConfig.isV2()) {
return routingHandler.add(method, handler.getPath(IdentityServiceAPI.V2), handlerSupplier.get());
}
return routingHandler;
}
private HttpHandler sane(HttpHandler httpHandler) {
return SaneHandler.around(httpHandler);
}
}

View File

@@ -63,6 +63,8 @@ public class MatrixConfig {
private String domain;
private Identity identity = new Identity();
private boolean v1 = true;
private boolean v2 = true;
public String getDomain() {
return domain;
@@ -80,6 +82,22 @@ public class MatrixConfig {
this.identity = identity;
}
public boolean isV1() {
return v1;
}
public void setV1(boolean v1) {
this.v1 = v1;
}
public boolean isV2() {
return v2;
}
public void setV2(boolean v2) {
this.v2 = v2;
}
public void build() {
log.info("--- Matrix config ---");
@@ -90,6 +108,11 @@ public class MatrixConfig {
log.info("Domain: {}", getDomain());
log.info("Identity:");
log.info("\tServers: {}", GsonUtil.get().toJson(identity.getServers()));
log.info("API v1: {}", v1);
log.info("API v2: {}", v2);
if (v1) {
log.warn("API v1 is deprecated via MSC2140: https://github.com/matrix-org/matrix-doc/pull/2140 and will be deleted in future releases.");
log.warn("Please upgrade your homeserver and enable only API v2.");
}
}
}

View File

@@ -79,5 +79,4 @@ public class ServerConfig {
log.info("Port: {}", getPort());
log.info("Public URL: {}", getPublicUrl());
}
}

View File

@@ -25,8 +25,6 @@ public class IsAPIv1 {
public static final String Base = "/_matrix/identity/api/v1";
public static String getValidate(String medium, String sid, String secret, String token) {
// FIXME use some kind of URLBuilder
return Base + "/validate/" + medium + "/submitToken?sid=" + sid + "&client_secret=" + secret + "&token=" + token;
return String.format("%s/validate/%s/submitToken?sid=%s&client_secret=%s&token=%s", Base, medium, sid, secret, token);
}
}

View File

@@ -0,0 +1,31 @@
/*
* 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.http;
public class IsAPIv2 {
public static final String Base = "/_matrix/identity/v2";
public static String getValidate(String medium, String sid, String secret, String token) {
return String.format("%s/validate/%s/submitToken?sid=%s&client_secret=%s&token=%s", Base, medium, sid, secret, token);
}
}

View File

@@ -0,0 +1,22 @@
package io.kamax.mxisd.http.undertow.handler;
import io.kamax.mxisd.http.IsAPIv1;
import io.kamax.mxisd.http.IsAPIv2;
import io.kamax.mxisd.matrix.IdentityServiceAPI;
import io.undertow.server.HttpHandler;
public interface ApiHandler extends HttpHandler {
default String getPath(IdentityServiceAPI api) {
switch (api) {
case V2:
return IsAPIv2.Base + getHandlerPath();
case V1:
return IsAPIv1.Base + getHandlerPath();
default:
throw new IllegalArgumentException("Unknown api version: " + api);
}
}
String getHandlerPath();
}

View File

@@ -23,6 +23,7 @@ package io.kamax.mxisd.http.undertow.handler.identity.v1;
import io.kamax.mxisd.http.IsAPIv1;
import io.kamax.mxisd.http.io.identity.ClientBulkLookupAnswer;
import io.kamax.mxisd.http.io.identity.ClientBulkLookupRequest;
import io.kamax.mxisd.http.undertow.handler.ApiHandler;
import io.kamax.mxisd.lookup.BulkLookupRequest;
import io.kamax.mxisd.lookup.ThreePidMapping;
import io.kamax.mxisd.lookup.strategy.LookupStrategy;
@@ -33,7 +34,7 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
public class BulkLookupHandler extends LookupHandler {
public class BulkLookupHandler extends LookupHandler implements ApiHandler {
public static final String Path = IsAPIv1.Base + "/bulk_lookup";
@@ -69,4 +70,8 @@ public class BulkLookupHandler extends LookupHandler {
respondJson(exchange, answer);
}
@Override
public String getHandlerPath() {
return "/bulk_lookup";
}
}

View File

@@ -23,11 +23,12 @@ package io.kamax.mxisd.http.undertow.handler.identity.v1;
import io.kamax.mxisd.crypto.KeyManager;
import io.kamax.mxisd.crypto.KeyType;
import io.kamax.mxisd.http.IsAPIv1;
import io.kamax.mxisd.http.undertow.handler.ApiHandler;
import io.undertow.server.HttpServerExchange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EphemeralKeyIsValidHandler extends KeyIsValidHandler {
public class EphemeralKeyIsValidHandler extends KeyIsValidHandler implements ApiHandler {
public static final String Path = IsAPIv1.Base + "/pubkey/ephemeral/isvalid";
@@ -48,4 +49,8 @@ public class EphemeralKeyIsValidHandler extends KeyIsValidHandler {
respondJson(exchange, mgr.isValid(KeyType.Ephemeral, pubKey) ? validKey : invalidKey);
}
@Override
public String getHandlerPath() {
return "/pubkey/ephemeral/isvalid";
}
}

View File

@@ -22,9 +22,10 @@ package io.kamax.mxisd.http.undertow.handler.identity.v1;
import io.kamax.mxisd.http.IsAPIv1;
import io.kamax.mxisd.http.undertow.handler.BasicHttpHandler;
import io.kamax.mxisd.http.undertow.handler.ApiHandler;
import io.undertow.server.HttpServerExchange;
public class HelloHandler extends BasicHttpHandler {
public class HelloHandler extends BasicHttpHandler implements ApiHandler {
public static final String Path = IsAPIv1.Base;
@@ -33,4 +34,8 @@ public class HelloHandler extends BasicHttpHandler {
respondJson(exchange, "{}");
}
@Override
public String getHandlerPath() {
return "";
}
}

View File

@@ -26,12 +26,13 @@ import io.kamax.mxisd.crypto.KeyManager;
import io.kamax.mxisd.crypto.KeyType;
import io.kamax.mxisd.http.IsAPIv1;
import io.kamax.mxisd.http.undertow.handler.BasicHttpHandler;
import io.kamax.mxisd.http.undertow.handler.ApiHandler;
import io.undertow.server.HttpServerExchange;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class KeyGetHandler extends BasicHttpHandler {
public class KeyGetHandler extends BasicHttpHandler implements ApiHandler {
public static final String Key = "key";
public static final String Path = IsAPIv1.Base + "/pubkey/{" + Key + "}";
@@ -61,4 +62,8 @@ public class KeyGetHandler extends BasicHttpHandler {
respond(exchange, obj);
}
@Override
public String getHandlerPath() {
return "/pubkey/{" + Key + "}";
}
}

View File

@@ -23,11 +23,12 @@ package io.kamax.mxisd.http.undertow.handler.identity.v1;
import io.kamax.mxisd.crypto.KeyManager;
import io.kamax.mxisd.crypto.KeyType;
import io.kamax.mxisd.http.IsAPIv1;
import io.kamax.mxisd.http.undertow.handler.ApiHandler;
import io.undertow.server.HttpServerExchange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RegularKeyIsValidHandler extends KeyIsValidHandler {
public class RegularKeyIsValidHandler extends KeyIsValidHandler implements ApiHandler {
public static final String Path = IsAPIv1.Base + "/pubkey/isvalid";
@@ -48,4 +49,8 @@ public class RegularKeyIsValidHandler extends KeyIsValidHandler {
respondJson(exchange, mgr.isValid(KeyType.Regular, pubKey) ? validKey : invalidKey);
}
@Override
public String getHandlerPath() {
return "/pubkey/isvalid";
}
}

View File

@@ -28,13 +28,14 @@ import io.kamax.mxisd.http.io.identity.RequestTokenResponse;
import io.kamax.mxisd.http.io.identity.SessionEmailTokenRequestJson;
import io.kamax.mxisd.http.io.identity.SessionPhoneTokenRequestJson;
import io.kamax.mxisd.http.undertow.handler.BasicHttpHandler;
import io.kamax.mxisd.http.undertow.handler.ApiHandler;
import io.kamax.mxisd.session.SessionManager;
import io.undertow.server.HttpServerExchange;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SessionStartHandler extends BasicHttpHandler {
public class SessionStartHandler extends BasicHttpHandler implements ApiHandler {
public static final String Medium = "medium";
public static final String Path = IsAPIv1.Base + "/validate/{" + Medium + "}/requestToken";
@@ -84,4 +85,8 @@ public class SessionStartHandler extends BasicHttpHandler {
}
}
@Override
public String getHandlerPath() {
return "/validate/{" + Medium + "}/requestToken";
}
}

View File

@@ -28,6 +28,7 @@ import io.kamax.mxisd.http.IsAPIv1;
import io.kamax.mxisd.http.io.identity.BindRequest;
import io.kamax.mxisd.http.io.identity.SingeLookupReplyJson;
import io.kamax.mxisd.http.undertow.handler.BasicHttpHandler;
import io.kamax.mxisd.http.undertow.handler.ApiHandler;
import io.kamax.mxisd.invitation.InvitationManager;
import io.kamax.mxisd.lookup.SingleLookupReply;
import io.kamax.mxisd.session.SessionManager;
@@ -42,7 +43,7 @@ import java.nio.charset.StandardCharsets;
import java.util.Deque;
import java.util.Map;
public class SessionTpidBindHandler extends BasicHttpHandler {
public class SessionTpidBindHandler extends BasicHttpHandler implements ApiHandler {
public static final String Path = IsAPIv1.Base + "/3pid/bind";
@@ -97,4 +98,8 @@ public class SessionTpidBindHandler extends BasicHttpHandler {
}
}
@Override
public String getHandlerPath() {
return "/3pid/bind";
}
}

View File

@@ -24,13 +24,14 @@ import com.google.gson.JsonObject;
import io.kamax.mxisd.exception.SessionNotValidatedException;
import io.kamax.mxisd.http.IsAPIv1;
import io.kamax.mxisd.http.undertow.handler.BasicHttpHandler;
import io.kamax.mxisd.http.undertow.handler.ApiHandler;
import io.kamax.mxisd.lookup.ThreePidValidation;
import io.kamax.mxisd.session.SessionManager;
import io.undertow.server.HttpServerExchange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SessionTpidGetValidatedHandler extends BasicHttpHandler {
public class SessionTpidGetValidatedHandler extends BasicHttpHandler implements ApiHandler {
public static final String Path = IsAPIv1.Base + "/3pid/getValidated3pid";
@@ -62,4 +63,8 @@ public class SessionTpidGetValidatedHandler extends BasicHttpHandler {
}
}
@Override
public String getHandlerPath() {
return "/3pid/getValidated3pid";
}
}

View File

@@ -23,12 +23,13 @@ package io.kamax.mxisd.http.undertow.handler.identity.v1;
import com.google.gson.JsonObject;
import io.kamax.mxisd.http.IsAPIv1;
import io.kamax.mxisd.http.undertow.handler.BasicHttpHandler;
import io.kamax.mxisd.http.undertow.handler.ApiHandler;
import io.kamax.mxisd.session.SessionManager;
import io.undertow.server.HttpServerExchange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SessionTpidUnbindHandler extends BasicHttpHandler {
public class SessionTpidUnbindHandler extends BasicHttpHandler implements ApiHandler {
public static final String Path = IsAPIv1.Base + "/3pid/unbind";
@@ -48,4 +49,9 @@ public class SessionTpidUnbindHandler extends BasicHttpHandler {
sessionMgr.unbind(auth, body);
writeBodyAsUtf8(exchange, "{}");
}
@Override
public String getHandlerPath() {
return "/3pid/unbind";
}
}

View File

@@ -22,13 +22,14 @@ package io.kamax.mxisd.http.undertow.handler.identity.v1;
import io.kamax.mxisd.http.IsAPIv1;
import io.kamax.mxisd.http.undertow.handler.BasicHttpHandler;
import io.kamax.mxisd.http.undertow.handler.ApiHandler;
import io.kamax.mxisd.session.SessionManager;
import io.kamax.mxisd.session.ValidationResult;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class SessionValidateHandler extends BasicHttpHandler {
public abstract class SessionValidateHandler extends BasicHttpHandler implements ApiHandler {
public static final String Path = IsAPIv1.Base + "/validate/{medium}/submitToken";
@@ -52,4 +53,8 @@ public abstract class SessionValidateHandler extends BasicHttpHandler {
return mgr.validate(sid, secret, token);
}
@Override
public String getHandlerPath() {
return "/validate/{medium}/submitToken";
}
}

View File

@@ -29,13 +29,14 @@ import io.kamax.mxisd.config.MxisdConfig;
import io.kamax.mxisd.crypto.SignatureManager;
import io.kamax.mxisd.http.IsAPIv1;
import io.kamax.mxisd.http.undertow.handler.BasicHttpHandler;
import io.kamax.mxisd.http.undertow.handler.ApiHandler;
import io.kamax.mxisd.invitation.IThreePidInviteReply;
import io.kamax.mxisd.invitation.InvitationManager;
import io.undertow.server.HttpServerExchange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SignEd25519Handler extends BasicHttpHandler {
public class SignEd25519Handler extends BasicHttpHandler implements ApiHandler {
public static final String Path = IsAPIv1.Base + "/sign-ed25519";
@@ -72,4 +73,8 @@ public class SignEd25519Handler extends BasicHttpHandler {
respondJson(exchange, res);
}
@Override
public String getHandlerPath() {
return "/sign-ed25519";
}
}

View File

@@ -27,6 +27,7 @@ import io.kamax.mxisd.config.ServerConfig;
import io.kamax.mxisd.crypto.SignatureManager;
import io.kamax.mxisd.http.IsAPIv1;
import io.kamax.mxisd.http.io.identity.SingeLookupReplyJson;
import io.kamax.mxisd.http.undertow.handler.ApiHandler;
import io.kamax.mxisd.lookup.SingleLookupReply;
import io.kamax.mxisd.lookup.SingleLookupRequest;
import io.kamax.mxisd.lookup.strategy.LookupStrategy;
@@ -36,7 +37,7 @@ import org.slf4j.LoggerFactory;
import java.util.Optional;
public class SingleLookupHandler extends LookupHandler {
public class SingleLookupHandler extends LookupHandler implements ApiHandler {
public static final String Path = IsAPIv1.Base + "/lookup";
@@ -77,4 +78,8 @@ public class SingleLookupHandler extends LookupHandler {
}
}
@Override
public String getHandlerPath() {
return "/lookup";
}
}

View File

@@ -32,6 +32,7 @@ import io.kamax.mxisd.http.IsAPIv1;
import io.kamax.mxisd.http.io.identity.StoreInviteRequest;
import io.kamax.mxisd.http.io.identity.ThreePidInviteReplyIO;
import io.kamax.mxisd.http.undertow.handler.BasicHttpHandler;
import io.kamax.mxisd.http.undertow.handler.ApiHandler;
import io.kamax.mxisd.invitation.IThreePidInvite;
import io.kamax.mxisd.invitation.IThreePidInviteReply;
import io.kamax.mxisd.invitation.InvitationManager;
@@ -45,7 +46,7 @@ import java.nio.charset.StandardCharsets;
import java.util.Deque;
import java.util.Map;
public class StoreInviteHandler extends BasicHttpHandler {
public class StoreInviteHandler extends BasicHttpHandler implements ApiHandler {
public static final String Path = IsAPIv1.Base + "/store-invite";
@@ -100,4 +101,8 @@ public class StoreInviteHandler extends BasicHttpHandler {
respondJson(exchange, new ThreePidInviteReplyIO(reply, keyMgr.getPublicKeyBase64(keyMgr.getServerSigningKey().getId()), cfg.getPublicUrl()));
}
@Override
public String getHandlerPath() {
return "/store-invite";
}
}

View File

@@ -0,0 +1,9 @@
package io.kamax.mxisd.matrix;
public enum IdentityServiceAPI {
@Deprecated
V1,
V2
}