Bye bye Groovy, you won't be missed :(
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.threepid.connector;
|
||||
|
||||
public interface IThreePidConnector {
|
||||
|
||||
String getId();
|
||||
|
||||
String getMedium();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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.threepid.connector.email;
|
||||
|
||||
import com.sun.mail.smtp.SMTPTransport;
|
||||
import io.kamax.matrix.ThreePidMedium;
|
||||
import io.kamax.mxisd.config.threepid.connector.EmailSmtpConfig;
|
||||
import io.kamax.mxisd.exception.InternalServerError;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
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 javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
|
||||
@Component
|
||||
public class EmailSmtpConnector implements IEmailConnector {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(EmailSmtpConnector.class);
|
||||
|
||||
private EmailSmtpConfig cfg;
|
||||
private Session session;
|
||||
|
||||
@Autowired
|
||||
public EmailSmtpConnector(EmailSmtpConfig cfg) {
|
||||
this.cfg = cfg;
|
||||
session = Session.getInstance(System.getProperties());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "smtp";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMedium() {
|
||||
return ThreePidMedium.Email.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(String senderAddress, String senderName, String recipient, String content) {
|
||||
if (StringUtils.isBlank(content)) {
|
||||
throw new InternalServerError("Notification content is empty");
|
||||
}
|
||||
|
||||
try {
|
||||
InternetAddress sender = new InternetAddress(senderAddress, senderName);
|
||||
MimeMessage msg = new MimeMessage(session, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
|
||||
msg.setHeader("X-Mailer", "mxisd"); // FIXME set version
|
||||
msg.setSentDate(new Date());
|
||||
msg.setFrom(sender);
|
||||
msg.setRecipients(Message.RecipientType.TO, recipient);
|
||||
msg.saveChanges();
|
||||
|
||||
log.info("Sending invite to {} via SMTP using {}:{}", recipient, cfg.getHost(), cfg.getPort());
|
||||
SMTPTransport transport = (SMTPTransport) session.getTransport("smtp");
|
||||
transport.setStartTLS(cfg.getTls() > 0);
|
||||
transport.setRequireStartTLS(cfg.getTls() > 1);
|
||||
|
||||
log.info("Connecting to {}:{}", cfg.getHost(), cfg.getPort());
|
||||
transport.connect(cfg.getHost(), cfg.getPort(), cfg.getLogin(), cfg.getPassword());
|
||||
try {
|
||||
transport.sendMessage(msg, InternetAddress.parse(recipient));
|
||||
log.info("Invite to {} was sent", recipient);
|
||||
} finally {
|
||||
transport.close();
|
||||
}
|
||||
} catch (UnsupportedEncodingException | MessagingException e) {
|
||||
throw new RuntimeException("Unable to send e-mail invite to " + recipient, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.threepid.connector.email;
|
||||
|
||||
import io.kamax.matrix.ThreePidMedium;
|
||||
import io.kamax.mxisd.threepid.connector.IThreePidConnector;
|
||||
|
||||
public interface IEmailConnector extends IThreePidConnector {
|
||||
|
||||
@Override
|
||||
default String getMedium() {
|
||||
return ThreePidMedium.Email.getId();
|
||||
}
|
||||
|
||||
void send(String senderAddress, String senderName, String recipient, String content);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.threepid.notification;
|
||||
|
||||
import io.kamax.mxisd.invitation.IThreePidInviteReply;
|
||||
import io.kamax.mxisd.threepid.session.IThreePidSession;
|
||||
|
||||
public interface INotificationGenerator {
|
||||
|
||||
String getId();
|
||||
|
||||
String getMedium();
|
||||
|
||||
String getForInvite(IThreePidInviteReply invite);
|
||||
|
||||
String getForValidation(IThreePidSession session);
|
||||
|
||||
String getForRemoteValidation(IThreePidSession session);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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.threepid.notification.email;
|
||||
|
||||
import io.kamax.mxisd.ThreePid;
|
||||
import io.kamax.mxisd.config.MatrixConfig;
|
||||
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.exception.InternalServerError;
|
||||
import io.kamax.mxisd.invitation.IThreePidInviteReply;
|
||||
import io.kamax.mxisd.threepid.session.IThreePidSession;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.WordUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
@Component
|
||||
public class EmailNotificationGenerator implements IEmailNotificationGenerator {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(EmailNotificationGenerator.class);
|
||||
|
||||
private EmailConfig cfg;
|
||||
private EmailTemplateConfig templateCfg;
|
||||
private MatrixConfig mxCfg;
|
||||
private ServerConfig srvCfg;
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext app;
|
||||
|
||||
@Autowired
|
||||
public EmailNotificationGenerator(EmailTemplateConfig templateCfg, EmailConfig cfg, MatrixConfig mxCfg, ServerConfig srvCfg) {
|
||||
this.cfg = cfg;
|
||||
this.templateCfg = templateCfg;
|
||||
this.mxCfg = mxCfg;
|
||||
this.srvCfg = srvCfg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "template";
|
||||
}
|
||||
|
||||
private String getTemplateContent(String location) {
|
||||
try {
|
||||
InputStream is = StringUtils.startsWith(location, "classpath:") ?
|
||||
app.getResource(location).getInputStream() : new FileInputStream(location);
|
||||
return IOUtils.toString(is, StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
throw new InternalServerError("Unable to read template content at " + location + ": " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private String populateCommon(String content, ThreePid recipient) {
|
||||
String domainPretty = WordUtils.capitalizeFully(mxCfg.getDomain());
|
||||
|
||||
content = content.replace("%DOMAIN%", mxCfg.getDomain());
|
||||
content = content.replace("%DOMAIN_PRETTY%", domainPretty);
|
||||
content = content.replace("%FROM_EMAIL%", cfg.getIdentity().getFrom());
|
||||
content = content.replace("%FROM_NAME%", cfg.getIdentity().getName());
|
||||
content = content.replace("%RECIPIENT_MEDIUM%", recipient.getMedium());
|
||||
content = content.replace("%RECIPIENT_ADDRESS%", recipient.getAddress());
|
||||
return content;
|
||||
}
|
||||
|
||||
private String getTemplateAndPopulate(String location, ThreePid recipient) {
|
||||
return populateCommon(getTemplateContent(location), recipient);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getForInvite(IThreePidInviteReply invite) {
|
||||
ThreePid tpid = new ThreePid(invite.getInvite().getMedium(), invite.getInvite().getAddress());
|
||||
String templateBody = getTemplateAndPopulate(templateCfg.getInvite(), tpid);
|
||||
|
||||
String senderName = invite.getInvite().getProperties().getOrDefault("sender_display_name", "");
|
||||
String senderNameOrId = StringUtils.defaultIfBlank(senderName, invite.getInvite().getSender().getId());
|
||||
String roomName = invite.getInvite().getProperties().getOrDefault("room_name", "");
|
||||
String roomNameOrId = StringUtils.defaultIfBlank(roomName, invite.getInvite().getRoomId());
|
||||
|
||||
templateBody = templateBody.replace("%SENDER_ID%", invite.getInvite().getSender().getId());
|
||||
templateBody = templateBody.replace("%SENDER_NAME%", senderName);
|
||||
templateBody = templateBody.replace("%SENDER_NAME_OR_ID%", senderNameOrId);
|
||||
templateBody = templateBody.replace("%INVITE_MEDIUM%", tpid.getMedium());
|
||||
templateBody = templateBody.replace("%INVITE_ADDRESS%", tpid.getAddress());
|
||||
templateBody = templateBody.replace("%ROOM_ID%", invite.getInvite().getRoomId());
|
||||
templateBody = templateBody.replace("%ROOM_NAME%", roomName);
|
||||
templateBody = templateBody.replace("%ROOM_NAME_OR_ID%", roomNameOrId);
|
||||
|
||||
return templateBody;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getForValidation(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, most likely in the SDK?
|
||||
String validationLink = srvCfg.getPublicUrl() + IdentityAPIv1.BASE +
|
||||
"/validate/" + session.getThreePid().getMedium() +
|
||||
"/submitToken?sid=" + session.getId() + "&client_secret=" + session.getSecret() +
|
||||
"&token=" + session.getToken();
|
||||
|
||||
templateBody = templateBody.replace("%VALIDATION_LINK%", validationLink);
|
||||
templateBody = templateBody.replace("%VALIDATION_TOKEN%", session.getToken());
|
||||
|
||||
return templateBody;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getForRemoteValidation(IThreePidSession session) {
|
||||
log.info("Generating notification content for remote-only 3PID session");
|
||||
String templateBody = getTemplateAndPopulate(templateCfg.getSession().getValidation().getRemote(), 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() +
|
||||
"&token=" + session.getToken();
|
||||
|
||||
templateBody = templateBody.replace("%NEXT_URL%", validationLink);
|
||||
|
||||
return templateBody;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.threepid.notification.email;
|
||||
|
||||
import io.kamax.matrix.ThreePidMedium;
|
||||
import io.kamax.mxisd.config.threepid.medium.EmailConfig;
|
||||
import io.kamax.mxisd.exception.ConfigurationException;
|
||||
import io.kamax.mxisd.invitation.IThreePidInviteReply;
|
||||
import io.kamax.mxisd.notification.INotificationHandler;
|
||||
import io.kamax.mxisd.threepid.connector.email.IEmailConnector;
|
||||
import io.kamax.mxisd.threepid.session.IThreePidSession;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class EmailNotificationHandler implements INotificationHandler {
|
||||
|
||||
private EmailConfig cfg;
|
||||
private IEmailNotificationGenerator generator;
|
||||
private IEmailConnector connector;
|
||||
|
||||
@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()
|
||||
.orElseThrow(() -> new ConfigurationException("Email notification generator [" + cfg.getGenerator() + "] could not be found"));
|
||||
|
||||
connector = connectors.stream()
|
||||
.filter(o -> StringUtils.equals(cfg.getConnector(), o.getId()))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new ConfigurationException("Email sender connector [" + cfg.getConnector() + "] could not be found"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMedium() {
|
||||
return ThreePidMedium.Email.getId();
|
||||
}
|
||||
|
||||
private void send(String recipient, String content) {
|
||||
connector.send(
|
||||
cfg.getIdentity().getFrom(),
|
||||
cfg.getIdentity().getName(),
|
||||
recipient,
|
||||
content
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendForInvite(IThreePidInviteReply invite) {
|
||||
send(invite.getInvite().getAddress(), generator.getForInvite(invite));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendForValidation(IThreePidSession session) {
|
||||
send(session.getThreePid().getAddress(), generator.getForValidation(session));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendForRemoteValidation(IThreePidSession session) {
|
||||
send(session.getThreePid().getAddress(), generator.getForRemoteValidation(session));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.threepid.notification.email;
|
||||
|
||||
import io.kamax.matrix.ThreePidMedium;
|
||||
import io.kamax.mxisd.threepid.notification.INotificationGenerator;
|
||||
|
||||
public interface IEmailNotificationGenerator extends INotificationGenerator {
|
||||
|
||||
@Override
|
||||
default String getMedium() {
|
||||
return ThreePidMedium.Email.getId();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.threepid.session;
|
||||
|
||||
import io.kamax.mxisd.ThreePid;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface IThreePidSession {
|
||||
|
||||
String getId();
|
||||
|
||||
Instant getCreationTime();
|
||||
|
||||
String getServer();
|
||||
|
||||
ThreePid getThreePid();
|
||||
|
||||
String getSecret();
|
||||
|
||||
int getAttempt();
|
||||
|
||||
void increaseAttempt();
|
||||
|
||||
Optional<String> getNextLink();
|
||||
|
||||
String getToken();
|
||||
|
||||
void validate(String token);
|
||||
|
||||
boolean isValidated();
|
||||
|
||||
Instant getValidationTime();
|
||||
|
||||
boolean isRemote();
|
||||
|
||||
String getRemoteServer();
|
||||
|
||||
String getRemoteId();
|
||||
|
||||
String getRemoteSecret();
|
||||
|
||||
int getRemoteAttempt();
|
||||
|
||||
void setRemoteData(String server, String id, String secret, int attempt);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
* 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.threepid.session;
|
||||
|
||||
import io.kamax.mxisd.ThreePid;
|
||||
import io.kamax.mxisd.exception.BadRequestException;
|
||||
import io.kamax.mxisd.exception.InvalidCredentialsException;
|
||||
import io.kamax.mxisd.storage.dao.IThreePidSessionDao;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ThreePidSession implements IThreePidSession {
|
||||
|
||||
private String id;
|
||||
private Instant timestamp;
|
||||
private String server;
|
||||
private ThreePid tPid;
|
||||
private String secret;
|
||||
private String nextLink;
|
||||
private String token;
|
||||
private int attempt;
|
||||
private Instant validationTimestamp;
|
||||
private boolean isValidated;
|
||||
private boolean isRemote;
|
||||
private String remoteServer;
|
||||
private String remoteId;
|
||||
private String remoteSecret;
|
||||
private int remoteAttempt;
|
||||
private boolean isRemoteValidated;
|
||||
|
||||
public ThreePidSession(IThreePidSessionDao dao) {
|
||||
this(
|
||||
dao.getId(),
|
||||
dao.getServer(),
|
||||
new ThreePid(dao.getMedium(), dao.getAddress()),
|
||||
dao.getSecret(),
|
||||
dao.getAttempt(),
|
||||
dao.getNextLink(),
|
||||
dao.getToken()
|
||||
);
|
||||
timestamp = Instant.ofEpochMilli(dao.getCreationTime());
|
||||
isValidated = dao.getValidated();
|
||||
if (isValidated) {
|
||||
validationTimestamp = Instant.ofEpochMilli(dao.getValidationTime());
|
||||
}
|
||||
|
||||
isRemote = dao.isRemote();
|
||||
remoteServer = dao.getRemoteServer();
|
||||
remoteId = dao.getRemoteId();
|
||||
remoteSecret = dao.getRemoteSecret();
|
||||
remoteAttempt = dao.getRemoteAttempt();
|
||||
isRemoteValidated = dao.isRemoteValidated();
|
||||
}
|
||||
|
||||
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.secret = secret;
|
||||
this.attempt = attempt;
|
||||
this.nextLink = nextLink;
|
||||
this.token = token;
|
||||
|
||||
this.timestamp = Instant.now();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant getCreationTime() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThreePid getThreePid() {
|
||||
return tPid;
|
||||
}
|
||||
|
||||
public String getSecret() {
|
||||
return secret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAttempt() {
|
||||
return attempt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void increaseAttempt() {
|
||||
attempt++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getNextLink() {
|
||||
return Optional.ofNullable(nextLink);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public synchronized void setAttempt(int attempt) {
|
||||
if (isValidated()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
this.attempt = attempt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant getValidationTime() {
|
||||
return validationTimestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRemote() {
|
||||
return isRemote;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteServer() {
|
||||
return remoteServer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteId() {
|
||||
return remoteId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteSecret() {
|
||||
return remoteSecret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRemoteAttempt() {
|
||||
return remoteAttempt;
|
||||
}
|
||||
|
||||
public int increaseAndGetRemoteAttempt() {
|
||||
return ++remoteAttempt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRemoteData(String server, String id, String secret, int attempt) {
|
||||
this.remoteServer = server;
|
||||
this.remoteId = id;
|
||||
this.remoteSecret = secret;
|
||||
this.attempt = attempt;
|
||||
this.isRemote = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidated() {
|
||||
return isValidated;
|
||||
}
|
||||
|
||||
public synchronized void validate(String token) {
|
||||
if (Instant.now().minus(24, ChronoUnit.HOURS).isAfter(getCreationTime())) {
|
||||
throw new BadRequestException("Session " + getId() + " has expired");
|
||||
}
|
||||
|
||||
if (!StringUtils.equals(this.token, token)) {
|
||||
throw new InvalidCredentialsException();
|
||||
}
|
||||
|
||||
if (isValidated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
validationTimestamp = Instant.now();
|
||||
isValidated = true;
|
||||
}
|
||||
|
||||
public boolean isRemoteValidated() {
|
||||
return isRemoteValidated;
|
||||
}
|
||||
|
||||
public void validateRemote() {
|
||||
this.isRemoteValidated = true;
|
||||
}
|
||||
|
||||
public IThreePidSessionDao getDao() {
|
||||
return new IThreePidSessionDao() {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCreationTime() {
|
||||
return timestamp.toEpochMilli();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMedium() {
|
||||
return tPid.getMedium();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAddress() {
|
||||
return tPid.getAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSecret() {
|
||||
return secret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAttempt() {
|
||||
return attempt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNextLink() {
|
||||
return nextLink;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getValidated() {
|
||||
return isValidated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getValidationTime() {
|
||||
return isValidated ? validationTimestamp.toEpochMilli() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRemote() {
|
||||
return isRemote;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteServer() {
|
||||
return remoteServer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteId() {
|
||||
return remoteId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteSecret() {
|
||||
return remoteSecret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRemoteAttempt() {
|
||||
return remoteAttempt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRemoteValidated() {
|
||||
return isRemoteValidated;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user