Polishing, prepare for proxying 3PID sessions

This commit is contained in:
Maxime Dor
2017-09-21 07:26:33 +02:00
parent ace6019197
commit a4b4a3f24c
13 changed files with 217 additions and 119 deletions

View File

@@ -42,6 +42,7 @@ public class SessionConfig {
public static class PolicySource {
private boolean enabled;
private boolean alwaysValidate;
private boolean toLocal;
private boolean toRemote;
@@ -53,6 +54,14 @@ public class SessionConfig {
this.enabled = enabled;
}
public boolean isAlwaysValidate() {
return alwaysValidate;
}
public void setAlwaysValidate(boolean alwaysValidate) {
this.alwaysValidate = alwaysValidate;
}
public boolean toLocal() {
return toLocal;
}
@@ -98,6 +107,10 @@ public class SessionConfig {
public PolicySource forRemote() {
return forRemote;
}
public PolicySource forIf(boolean isLocal) {
return isLocal ? forLocal : forRemote;
}
}
private PolicyTemplate bind = new PolicyTemplate();

View File

@@ -45,13 +45,36 @@ public class EmailTemplateConfig {
public static class Session {
private String validation;
public static class SessionValidation {
public String getValidation() {
private String local;
private String remote;
public String getLocal() {
return local;
}
public void setLocal(String local) {
this.local = local;
}
public String getRemote() {
return remote;
}
public void setRemote(String remote) {
this.remote = remote;
}
}
private SessionValidation validation;
public SessionValidation getValidation() {
return validation;
}
public void setValidation(String validation) {
public void setValidation(SessionValidation validation) {
this.validation = validation;
}
@@ -76,7 +99,9 @@ public class EmailTemplateConfig {
public void build() {
log.info("--- E-mail Generator templates config ---");
log.info("Invite: {}", getName(getInvite()));
log.info("Session validation: {}", getName(getSession().getValidation()));
log.info("Session validation:");
log.info("\tLocal: {}", getName(getSession().getValidation().getLocal()));
log.info("\tRemote: {}", getName(getSession().getValidation().getRemote()));
}
}

View File

@@ -0,0 +1,27 @@
/*
* 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.controller.v1.remote;
public class RemoteIdentityAPIv1 {
public static final String BASE = "/_matrix/identity-remote/api/v1";
}

View File

@@ -20,14 +20,13 @@
package io.kamax.mxisd.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(value = HttpStatus.FORBIDDEN)
public class NotAllowedException extends RuntimeException {
import org.apache.http.HttpStatus;
public class NotAllowedException extends MatrixException {
public NotAllowedException(String s) {
super(s);
super(HttpStatus.SC_FORBIDDEN, "M_FORBIDDEN", s);
}
}

View File

@@ -31,4 +31,6 @@ public interface INotificationHandler {
void sendForValidation(IThreePidSession session);
void sendForRemoteValidation(IThreePidSession session);
}

View File

@@ -63,7 +63,7 @@ public class NotificationManager {
}
public void sendforRemoteValidation(IThreePidSession session) {
throw new NotImplementedException("Remote publish of 3PID bind");
ensureMedium(session.getThreePid().getMedium()).sendForRemoteValidation(session);
}
}

View File

@@ -114,24 +114,14 @@ public class SessionMananger {
} else {
log.info("No existing session for {}", tpid);
boolean isLocalDomain = isLocal(tpid);
log.info("Is 3PID bound to local domain? {}", isLocalDomain);
boolean isLocal = isLocal(tpid);
log.info("Is 3PID bound to local domain? {}", isLocal);
if (isLocalDomain && (!policy.forLocal().isEnabled() || !policy.forLocal().toLocal())) {
throw new NotAllowedException("Validating local 3PID is not allowed");
}
// We lookup if the 3PID is already known locally.
boolean knownLocal = isKnownLocal(tpid);
log.info("Mapping with {} is " + (knownLocal ? "already" : "not") + " known locally", tpid);
if (!isLocalDomain && (
!policy.forRemote().isEnabled() || (
!policy.forRemote().toLocal() &&
!policy.forRemote().toRemote()
)
)) {
throw new NotAllowedException("Validating unknown remote 3PID is not allowed");
// This might need a configuration by medium type?
SessionConfig.Policy.PolicyTemplate.PolicySource policySource = policy.forIf(isLocal);
if (!policySource.isEnabled() || (!policySource.toLocal() && !policySource.toRemote())) {
log.info("Session for {}: cancelled due to policy", tpid);
throw new NotAllowedException("Validating " + (isLocal ? "local" : "remote") + " 3PID is not allowed");
}
String sessionId;
@@ -144,14 +134,12 @@ public class SessionMananger {
log.info("Generated new session {} to validate {} from server {}", sessionId, tpid, server);
// This might need a configuration by medium type?
if (!isLocalDomain) {
if (policy.forRemote().toLocal() && policy.forRemote().toRemote()) {
log.info("Session {} for {}: sending local validation notification", sessionId, tpid);
notifMgr.sendForValidation(session);
} else {
log.info("Session {} for {}: sending remote-only validation notification", sessionId, tpid);
notifMgr.sendforRemoteValidation(session);
}
if (policySource.toLocal()) {
log.info("Session {} for {}: sending local validation notification", sessionId, tpid);
notifMgr.sendForValidation(session);
} else {
log.info("Session {} for {}: sending remote-only validation notification", sessionId, tpid);
notifMgr.sendforRemoteValidation(session);
}
storage.insertThreePidSession(session.getDao());

View File

@@ -33,6 +33,6 @@ public interface INotificationGenerator {
String getForValidation(IThreePidSession session);
String getForRemotePublishingValidation(IThreePidSession session);
String getForRemoteValidation(IThreePidSession session);
}

View File

@@ -26,8 +26,8 @@ import io.kamax.mxisd.config.ServerConfig;
import io.kamax.mxisd.config.threepid.medium.EmailConfig;
import io.kamax.mxisd.config.threepid.medium.EmailTemplateConfig;
import io.kamax.mxisd.controller.v1.IdentityAPIv1;
import io.kamax.mxisd.controller.v1.remote.RemoteIdentityAPIv1;
import io.kamax.mxisd.exception.InternalServerError;
import io.kamax.mxisd.exception.NotImplementedException;
import io.kamax.mxisd.invitation.IThreePidInviteReply;
import io.kamax.mxisd.threepid.session.IThreePidSession;
import org.apache.commons.io.IOUtils;
@@ -121,8 +121,9 @@ public class EmailNotificationGenerator implements IEmailNotificationGenerator {
@Override
public String getForValidation(IThreePidSession session) {
log.info("Generating notification content for 3PID Session validation");
String templateBody = getTemplateAndPopulate(templateCfg.getSession().getValidation(), session.getThreePid());
String templateBody = getTemplateAndPopulate(templateCfg.getSession().getValidation().getLocal(), session.getThreePid());
// FIXME should have a global link builder, most likely in the SDK?
String validationLink = srvCfg.getPublicUrl() + IdentityAPIv1.BASE +
"/validate/" + session.getThreePid().getMedium() +
"/submitToken?sid=" + session.getId() + "&client_secret=" + session.getSecret() +
@@ -135,8 +136,19 @@ public class EmailNotificationGenerator implements IEmailNotificationGenerator {
}
@Override
public String getForRemotePublishingValidation(IThreePidSession session) {
throw new NotImplementedException("");
public String getForRemoteValidation(IThreePidSession session) {
log.info("Generating notification content for 3PID Session validation");
String templateBody = getTemplateAndPopulate(templateCfg.getSession().getValidation().getLocal(), session.getThreePid());
// FIXME should have a global link builder, specific to mxisd
String nextStepLink = srvCfg.getPublicUrl() + RemoteIdentityAPIv1.BASE +
"/validate/requestToken?sid=" + session.getId() + "&client_secret=" + session.getSecret();
templateBody = templateBody.replace("%SESSION_ID%", session.getId());
templateBody = templateBody.replace("%SESSION_SECRET%", session.getSecret());
templateBody = templateBody.replace("%NEXT_STEP_LINK%", nextStepLink);
return templateBody;
}
}

View File

@@ -43,6 +43,7 @@ public class EmailNotificationHandler implements INotificationHandler {
@Autowired
public EmailNotificationHandler(EmailConfig cfg, List<IEmailNotificationGenerator> generators, List<IEmailConnector> connectors) {
this.cfg = cfg;
generator = generators.stream()
.filter(o -> StringUtils.equals(cfg.getGenerator(), o.getId()))
.findFirst()
@@ -59,24 +60,28 @@ public class EmailNotificationHandler implements INotificationHandler {
return ThreePidMedium.Email.getId();
}
@Override
public void sendForInvite(IThreePidInviteReply invite) {
private void send(String recipient, String content) {
connector.send(
cfg.getIdentity().getFrom(),
cfg.getIdentity().getName(),
invite.getInvite().getAddress(),
generator.getForInvite(invite)
recipient,
content
);
}
@Override
public void sendForInvite(IThreePidInviteReply invite) {
send(invite.getInvite().getAddress(), generator.getForInvite(invite));
}
@Override
public void sendForValidation(IThreePidSession session) {
connector.send(
cfg.getIdentity().getFrom(),
cfg.getIdentity().getName(),
session.getThreePid().getAddress(),
generator.getForValidation(session)
);
send(session.getThreePid().getAddress(), generator.getForValidation(session));
}
@Override
public void sendForRemoteValidation(IThreePidSession session) {
send(session.getThreePid().getAddress(), generator.getForRemoteValidation(session));
}
}