Compare commits
8 Commits
v0.3.0-rc.
...
v0.3.0
Author | SHA1 | Date | |
---|---|---|---|
|
c816217b22 | ||
|
2e7b5d2a87 | ||
|
09208d55d7 | ||
|
05c76a657e | ||
|
f3bbc7c7c6 | ||
|
61addd297a | ||
|
1de0951733 | ||
|
d348ebd813 |
@@ -171,10 +171,8 @@ systemctl start mxisd
|
|||||||
After following the specific instructions to create a config file from the sample:
|
After following the specific instructions to create a config file from the sample:
|
||||||
1. Set the `matrix.domain` value to the domain value used in your Home Server configuration
|
1. Set the `matrix.domain` value to the domain value used in your Home Server configuration
|
||||||
2. Set an absolute location for the signing keys using `key.path`
|
2. Set an absolute location for the signing keys using `key.path`
|
||||||
3. Configure the E-mail notification sender with items starting with:
|
3. Configure the E-mail notification sender following [the documentation](docs/threepids/medium/email/smtp-connector.md)
|
||||||
- `threepid.medium.email.identity`
|
4. If you would like to support Phone number validation, see the [Twilio configuration](docs/threepids/medium/msisdn/twilio-connector.md)
|
||||||
- `threepid.medium.email.connectors.smtp`
|
|
||||||
4. If you would like to support Phone number validation, see the [Twilio configuration](docs/threepids/msisdn/twilio-connector.md)
|
|
||||||
|
|
||||||
In case your IS public domain does not match your Matrix domain, see `server.name` and `server.publicUrl`
|
In case your IS public domain does not match your Matrix domain, see `server.name` and `server.publicUrl`
|
||||||
config items.
|
config items.
|
||||||
|
@@ -119,6 +119,9 @@ dependencies {
|
|||||||
// Twilio SDK for SMS
|
// Twilio SDK for SMS
|
||||||
compile 'com.twilio.sdk:twilio:7.14.5'
|
compile 'com.twilio.sdk:twilio:7.14.5'
|
||||||
|
|
||||||
|
// SendGrid SDK to send emails from GCE
|
||||||
|
compile 'com.sendgrid:sendgrid-java:2.2.2'
|
||||||
|
|
||||||
testCompile 'junit:junit:4.12'
|
testCompile 'junit:junit:4.12'
|
||||||
testCompile 'com.github.tomakehurst:wiremock:2.8.0'
|
testCompile 'com.github.tomakehurst:wiremock:2.8.0'
|
||||||
}
|
}
|
||||||
|
@@ -48,4 +48,22 @@ public class ThreePid {
|
|||||||
return getMedium() + ":" + getAddress();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -71,14 +71,14 @@ public class AuthManager {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
UserAuthResult authResult = new UserAuthResult().success(mxId, result.getProfile().getDisplayName());
|
UserAuthResult authResult = new UserAuthResult().success(result.getProfile().getDisplayName());
|
||||||
for (ThreePid pid : result.getProfile().getThreePids()) {
|
for (ThreePid pid : result.getProfile().getThreePids()) {
|
||||||
authResult.withThreePid(pid.getMedium(), pid.getAddress());
|
authResult.withThreePid(pid.getMedium(), pid.getAddress());
|
||||||
}
|
}
|
||||||
log.info("{} was authenticated by {}, publishing 3PID mappings, if any", id, provider.getClass().getSimpleName());
|
log.info("{} was authenticated by {}, publishing 3PID mappings, if any", id, provider.getClass().getSimpleName());
|
||||||
for (ThreePid pid : authResult.getThreePids()) {
|
for (ThreePid pid : authResult.getThreePids()) {
|
||||||
log.info("Processing {} for {}", pid, id);
|
log.info("Processing {} for {}", pid, id);
|
||||||
invMgr.publishMappingIfInvited(new ThreePidMapping(pid, authResult.getMxid()));
|
invMgr.publishMappingIfInvited(new ThreePidMapping(pid, mxId));
|
||||||
}
|
}
|
||||||
|
|
||||||
invMgr.lookupMappingsForInvites();
|
invMgr.lookupMappingsForInvites();
|
||||||
|
@@ -20,31 +20,30 @@
|
|||||||
|
|
||||||
package io.kamax.mxisd.auth;
|
package io.kamax.mxisd.auth;
|
||||||
|
|
||||||
import io.kamax.matrix.ThreePidMedium;
|
|
||||||
import io.kamax.mxisd.ThreePid;
|
import io.kamax.mxisd.ThreePid;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class UserAuthResult {
|
public class UserAuthResult {
|
||||||
|
|
||||||
private boolean success;
|
private boolean success;
|
||||||
private String mxid;
|
|
||||||
private String displayName;
|
private String displayName;
|
||||||
private List<ThreePid> threePids = new ArrayList<>();
|
private String photo;
|
||||||
|
private Set<ThreePid> threePids = new HashSet<>();
|
||||||
|
|
||||||
public UserAuthResult failure() {
|
public UserAuthResult failure() {
|
||||||
success = false;
|
success = false;
|
||||||
mxid = null;
|
|
||||||
displayName = null;
|
displayName = null;
|
||||||
|
photo = null;
|
||||||
|
threePids.clear();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserAuthResult success(String mxid, String displayName) {
|
public UserAuthResult success(String displayName) {
|
||||||
setSuccess(true);
|
setSuccess(true);
|
||||||
setMxid(mxid);
|
|
||||||
setDisplayName(displayName);
|
setDisplayName(displayName);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
@@ -58,14 +57,6 @@ public class UserAuthResult {
|
|||||||
this.success = success;
|
this.success = success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMxid() {
|
|
||||||
return mxid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMxid(String mxid) {
|
|
||||||
this.mxid = mxid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDisplayName() {
|
public String getDisplayName() {
|
||||||
return displayName;
|
return displayName;
|
||||||
}
|
}
|
||||||
@@ -74,8 +65,12 @@ public class UserAuthResult {
|
|||||||
this.displayName = displayName;
|
this.displayName = displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserAuthResult withThreePid(ThreePidMedium medium, String address) {
|
public String getPhoto() {
|
||||||
return withThreePid(medium.getId(), address);
|
return photo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhoto(String photo) {
|
||||||
|
this.photo = photo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserAuthResult withThreePid(String medium, String address) {
|
public UserAuthResult withThreePid(String medium, String address) {
|
||||||
@@ -84,8 +79,8 @@ public class UserAuthResult {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ThreePid> getThreePids() {
|
public Set<ThreePid> getThreePids() {
|
||||||
return Collections.unmodifiableList(threePids);
|
return Collections.unmodifiableSet(threePids);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -24,21 +24,21 @@ import io.kamax.mxisd.ThreePid;
|
|||||||
import io.kamax.mxisd.UserID;
|
import io.kamax.mxisd.UserID;
|
||||||
import io.kamax.mxisd.UserIdType;
|
import io.kamax.mxisd.UserIdType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.Set;
|
||||||
|
|
||||||
public class BackendAuthResult {
|
public class BackendAuthResult {
|
||||||
|
|
||||||
public static class BackendAuthProfile {
|
public static class BackendAuthProfile {
|
||||||
|
|
||||||
private String displayName;
|
private String displayName;
|
||||||
private List<ThreePid> threePids = new ArrayList<>();
|
private Set<ThreePid> threePids = new HashSet<>();
|
||||||
|
|
||||||
public String getDisplayName() {
|
public String getDisplayName() {
|
||||||
return displayName;
|
return displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ThreePid> getThreePids() {
|
public Set<ThreePid> getThreePids() {
|
||||||
return threePids;
|
return threePids;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -25,6 +25,9 @@ import com.google.firebase.FirebaseOptions;
|
|||||||
import com.google.firebase.auth.FirebaseAuth;
|
import com.google.firebase.auth.FirebaseAuth;
|
||||||
import com.google.firebase.auth.FirebaseCredential;
|
import com.google.firebase.auth.FirebaseCredential;
|
||||||
import com.google.firebase.auth.FirebaseCredentials;
|
import com.google.firebase.auth.FirebaseCredentials;
|
||||||
|
import com.google.firebase.auth.UserInfo;
|
||||||
|
import com.google.i18n.phonenumbers.NumberParseException;
|
||||||
|
import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
||||||
import io.kamax.matrix.ThreePidMedium;
|
import io.kamax.matrix.ThreePidMedium;
|
||||||
import io.kamax.matrix._MatrixID;
|
import io.kamax.matrix._MatrixID;
|
||||||
import io.kamax.mxisd.ThreePid;
|
import io.kamax.mxisd.ThreePid;
|
||||||
@@ -48,14 +51,7 @@ public class GoogleFirebaseAuthenticator implements AuthenticatorProvider {
|
|||||||
private FirebaseApp fbApp;
|
private FirebaseApp fbApp;
|
||||||
private FirebaseAuth fbAuth;
|
private FirebaseAuth fbAuth;
|
||||||
|
|
||||||
private void waitOnLatch(BackendAuthResult result, CountDownLatch l, String purpose) {
|
private PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
|
||||||
try {
|
|
||||||
l.await(30, TimeUnit.SECONDS);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
log.warn("Interrupted while waiting for " + purpose);
|
|
||||||
result.fail();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public GoogleFirebaseAuthenticator(boolean isEnabled) {
|
public GoogleFirebaseAuthenticator(boolean isEnabled) {
|
||||||
this.isEnabled = isEnabled;
|
this.isEnabled = isEnabled;
|
||||||
@@ -73,6 +69,42 @@ public class GoogleFirebaseAuthenticator implements AuthenticatorProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void waitOnLatch(BackendAuthResult result, CountDownLatch l, String purpose) {
|
||||||
|
try {
|
||||||
|
l.await(30, TimeUnit.SECONDS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.warn("Interrupted while waiting for " + purpose);
|
||||||
|
result.fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toEmail(BackendAuthResult result, String email) {
|
||||||
|
if (StringUtils.isBlank(email)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.withThreePid(new ThreePid(ThreePidMedium.Email.getId(), email));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toMsisdn(BackendAuthResult result, String phoneNumber) {
|
||||||
|
if (StringUtils.isBlank(phoneNumber)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String number = phoneUtil.format(
|
||||||
|
phoneUtil.parse(
|
||||||
|
phoneNumber,
|
||||||
|
null // No default region
|
||||||
|
),
|
||||||
|
PhoneNumberUtil.PhoneNumberFormat.E164
|
||||||
|
).substring(1); // We want without the leading +
|
||||||
|
result.withThreePid(new ThreePid(ThreePidMedium.PhoneNumber.getId(), number));
|
||||||
|
} catch (NumberParseException e) {
|
||||||
|
log.warn("Invalid phone number: {}", phoneNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private FirebaseCredential getCreds(String credsPath) throws IOException {
|
private FirebaseCredential getCreds(String credsPath) throws IOException {
|
||||||
if (StringUtils.isNotBlank(credsPath)) {
|
if (StringUtils.isNotBlank(credsPath)) {
|
||||||
return FirebaseCredentials.fromCertificate(new FileInputStream(credsPath));
|
return FirebaseCredentials.fromCertificate(new FileInputStream(credsPath));
|
||||||
@@ -131,14 +163,15 @@ public class GoogleFirebaseAuthenticator implements AuthenticatorProvider {
|
|||||||
CountDownLatch userRecordLatch = new CountDownLatch(1);
|
CountDownLatch userRecordLatch = new CountDownLatch(1);
|
||||||
fbAuth.getUser(token.getUid()).addOnSuccessListener(user -> {
|
fbAuth.getUser(token.getUid()).addOnSuccessListener(user -> {
|
||||||
try {
|
try {
|
||||||
if (StringUtils.isNotBlank(user.getEmail())) {
|
toEmail(result, user.getEmail());
|
||||||
result.withThreePid(new ThreePid(ThreePidMedium.Email.getId(), user.getEmail()));
|
toMsisdn(result, user.getPhoneNumber());
|
||||||
}
|
|
||||||
|
for (UserInfo info : user.getProviderData()) {
|
||||||
if (StringUtils.isNotBlank(user.getPhoneNumber())) {
|
toEmail(result, info.getEmail());
|
||||||
result.withThreePid(new ThreePid(ThreePidMedium.PhoneNumber.getId(), user.getPhoneNumber()));
|
toMsisdn(result, info.getPhoneNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.info("Got {} 3PIDs in profile", result.getProfile().getThreePids().size());
|
||||||
} finally {
|
} finally {
|
||||||
userRecordLatch.countDown();
|
userRecordLatch.countDown();
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,202 @@
|
|||||||
|
/*
|
||||||
|
* 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.config.threepid.connector;
|
||||||
|
|
||||||
|
import io.kamax.mxisd.util.GsonUtil;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties("notification.handlers.sendgrid")
|
||||||
|
public class EmailSendGridConfig {
|
||||||
|
|
||||||
|
public static class EmailTemplate {
|
||||||
|
|
||||||
|
public static class EmailBody {
|
||||||
|
|
||||||
|
private String text;
|
||||||
|
private String html;
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setText(String text) {
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHtml() {
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHtml(String html) {
|
||||||
|
this.html = html;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String subject;
|
||||||
|
private EmailBody body = new EmailBody();
|
||||||
|
|
||||||
|
public String getSubject() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubject(String subject) {
|
||||||
|
this.subject = subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmailBody getBody() {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBody(EmailBody body) {
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Api {
|
||||||
|
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Identity {
|
||||||
|
|
||||||
|
private String from;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getFrom() {
|
||||||
|
return from;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFrom(String from) {
|
||||||
|
this.from = from;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Templates {
|
||||||
|
|
||||||
|
public static class TemplateSession {
|
||||||
|
|
||||||
|
private EmailTemplate local = new EmailTemplate();
|
||||||
|
private EmailTemplate remote = new EmailTemplate();
|
||||||
|
|
||||||
|
public EmailTemplate getLocal() {
|
||||||
|
return local;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocal(EmailTemplate local) {
|
||||||
|
this.local = local;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmailTemplate getRemote() {
|
||||||
|
return remote;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRemote(EmailTemplate remote) {
|
||||||
|
this.remote = remote;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private EmailTemplate invite = new EmailTemplate();
|
||||||
|
private TemplateSession session = new TemplateSession();
|
||||||
|
|
||||||
|
public EmailTemplate getInvite() {
|
||||||
|
return invite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInvite(EmailTemplate invite) {
|
||||||
|
this.invite = invite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TemplateSession getSession() {
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSession(TemplateSession session) {
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Logger log = LoggerFactory.getLogger(EmailSendGridConfig.class);
|
||||||
|
|
||||||
|
private Api api = new Api();
|
||||||
|
private Identity identity = new Identity();
|
||||||
|
private Templates templates = new Templates();
|
||||||
|
|
||||||
|
public Api getApi() {
|
||||||
|
return api;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApi(Api api) {
|
||||||
|
this.api = api;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Identity getIdentity() {
|
||||||
|
return identity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIdentity(Identity identity) {
|
||||||
|
this.identity = identity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Templates getTemplates() {
|
||||||
|
return templates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTemplates(Templates templates) {
|
||||||
|
this.templates = templates;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void build() {
|
||||||
|
log.info("--- Email SendGrid connector config ---");
|
||||||
|
log.info("API key configured?: {}", StringUtils.isNotBlank(api.getKey()));
|
||||||
|
log.info("Identity: {}", GsonUtil.build().toJson(identity));
|
||||||
|
log.info("Templates: {}", GsonUtil.build().toJson(templates));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* 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.config.threepid.notification;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties("notification")
|
||||||
|
public class NotificationConfig {
|
||||||
|
|
||||||
|
private Logger log = LoggerFactory.getLogger(NotificationConfig.class);
|
||||||
|
|
||||||
|
private Map<String, String> handler = new HashMap<>();
|
||||||
|
|
||||||
|
public Map<String, String> getHandler() {
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHandler(Map<String, String> handler) {
|
||||||
|
this.handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void build() {
|
||||||
|
log.info("--- Notification config ---");
|
||||||
|
log.info("Handlers:");
|
||||||
|
handler.forEach((k, v) -> {
|
||||||
|
log.info("\t{}: {}", k, v);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -18,15 +18,17 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1;
|
package io.kamax.mxisd.controller.auth.v1;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
|
||||||
import io.kamax.mxisd.auth.AuthManager;
|
import io.kamax.mxisd.auth.AuthManager;
|
||||||
import io.kamax.mxisd.auth.UserAuthResult;
|
import io.kamax.mxisd.auth.UserAuthResult;
|
||||||
import org.apache.commons.io.IOUtils;
|
import io.kamax.mxisd.controller.auth.v1.io.CredentialsValidationResponse;
|
||||||
|
import io.kamax.mxisd.exception.JsonMemberNotFoundException;
|
||||||
|
import io.kamax.mxisd.util.GsonParser;
|
||||||
|
import io.kamax.mxisd.util.GsonUtil;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -38,7 +40,6 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@CrossOrigin
|
@CrossOrigin
|
||||||
@@ -47,7 +48,8 @@ public class AuthController {
|
|||||||
|
|
||||||
private Logger log = LoggerFactory.getLogger(AuthController.class);
|
private Logger log = LoggerFactory.getLogger(AuthController.class);
|
||||||
|
|
||||||
private Gson gson = new Gson();
|
private Gson gson = GsonUtil.build();
|
||||||
|
private GsonParser parser = new GsonParser(gson);
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AuthManager mgr;
|
private AuthManager mgr;
|
||||||
@@ -55,14 +57,9 @@ public class AuthController {
|
|||||||
@RequestMapping(value = "/_matrix-internal/identity/v1/check_credentials", method = RequestMethod.POST)
|
@RequestMapping(value = "/_matrix-internal/identity/v1/check_credentials", method = RequestMethod.POST)
|
||||||
public String checkCredentials(HttpServletRequest req) {
|
public String checkCredentials(HttpServletRequest req) {
|
||||||
try {
|
try {
|
||||||
JsonElement el = new JsonParser().parse(IOUtils.toString(req.getInputStream(), StandardCharsets.UTF_8));
|
JsonObject authData = parser.parse(req.getInputStream(), "user");
|
||||||
if (!el.isJsonObject() || !el.getAsJsonObject().has("user")) {
|
|
||||||
throw new IllegalArgumentException("Missing user key");
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonObject authData = el.getAsJsonObject().get("user").getAsJsonObject();
|
|
||||||
if (!authData.has("id") || !authData.has("password")) {
|
if (!authData.has("id") || !authData.has("password")) {
|
||||||
throw new IllegalArgumentException("Missing id or password keys");
|
throw new JsonMemberNotFoundException("Missing id or password keys");
|
||||||
}
|
}
|
||||||
|
|
||||||
String id = authData.get("id").getAsString();
|
String id = authData.get("id").getAsString();
|
||||||
@@ -70,16 +67,17 @@ public class AuthController {
|
|||||||
String password = authData.get("password").getAsString();
|
String password = authData.get("password").getAsString();
|
||||||
|
|
||||||
UserAuthResult result = mgr.authenticate(id, password);
|
UserAuthResult result = mgr.authenticate(id, password);
|
||||||
|
CredentialsValidationResponse response = new CredentialsValidationResponse(result.isSuccess());
|
||||||
|
|
||||||
JsonObject authObj = new JsonObject();
|
|
||||||
authObj.addProperty("success", result.isSuccess());
|
|
||||||
if (result.isSuccess()) {
|
if (result.isSuccess()) {
|
||||||
authObj.addProperty("mxid", result.getMxid());
|
response.setDisplayName(result.getDisplayName());
|
||||||
authObj.addProperty("display_name", result.getDisplayName());
|
response.getProfile().setThreePids(result.getThreePids());
|
||||||
}
|
}
|
||||||
JsonObject obj = new JsonObject();
|
JsonElement authObj = gson.toJsonTree(response);
|
||||||
|
|
||||||
obj.add("authentication", authObj);
|
JsonObject obj = new JsonObject();
|
||||||
|
obj.add("auth", authObj);
|
||||||
|
obj.add("authentication", authObj); // TODO remove later, legacy support
|
||||||
return gson.toJson(obj);
|
return gson.toJson(obj);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* 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.auth.v1.io;
|
||||||
|
|
||||||
|
import io.kamax.mxisd.ThreePid;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class CredentialsValidationResponse {
|
||||||
|
|
||||||
|
public static class Profile {
|
||||||
|
|
||||||
|
private String displayName;
|
||||||
|
private Set<ThreePid> threePids = new HashSet<>();
|
||||||
|
|
||||||
|
public String getDisplayName() {
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<ThreePid> getThreePids() {
|
||||||
|
return threePids;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setThreePids(Set<ThreePid> threePids) {
|
||||||
|
this.threePids = new HashSet<>(threePids);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean success;
|
||||||
|
private String displayName; // TODO remove later, legacy support
|
||||||
|
private Profile profile = new Profile();
|
||||||
|
|
||||||
|
public CredentialsValidationResponse(boolean success) {
|
||||||
|
this.success = success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuccess() {
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplayName() {
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDisplayName(String displayName) {
|
||||||
|
this.displayName = displayName;
|
||||||
|
this.profile.displayName = displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Profile getProfile() {
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -18,7 +18,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1;
|
package io.kamax.mxisd.controller.identity.v1;
|
||||||
|
|
||||||
import io.kamax.mxisd.lookup.ThreePidMapping;
|
import io.kamax.mxisd.lookup.ThreePidMapping;
|
||||||
|
|
@@ -18,7 +18,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1;
|
package io.kamax.mxisd.controller.identity.v1;
|
||||||
|
|
||||||
import io.kamax.mxisd.lookup.ThreePidMapping;
|
import io.kamax.mxisd.lookup.ThreePidMapping;
|
||||||
|
|
@@ -18,14 +18,11 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1;
|
package io.kamax.mxisd.controller.identity.v1;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import io.kamax.mxisd.exception.BadRequestException;
|
import io.kamax.mxisd.exception.*;
|
||||||
import io.kamax.mxisd.exception.InternalServerError;
|
|
||||||
import io.kamax.mxisd.exception.MappingAlreadyExistsException;
|
|
||||||
import io.kamax.mxisd.exception.MatrixException;
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -78,6 +75,18 @@ public class DefaultExceptionHandler {
|
|||||||
return handle("M_INVALID_BODY", e.getMessage());
|
return handle("M_INVALID_BODY", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||||
|
@ExceptionHandler(InvalidResponseJsonException.class)
|
||||||
|
public String handle(InvalidResponseJsonException e) {
|
||||||
|
return handle("M_INVALID_JSON", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||||
|
@ExceptionHandler(JsonMemberNotFoundException.class)
|
||||||
|
public String handle(JsonMemberNotFoundException e) {
|
||||||
|
return handle("M_JSON_MISSING_KEYS", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||||
@ExceptionHandler(MappingAlreadyExistsException.class)
|
@ExceptionHandler(MappingAlreadyExistsException.class)
|
||||||
public String handle(MappingAlreadyExistsException e) {
|
public String handle(MappingAlreadyExistsException e) {
|
@@ -18,7 +18,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1;
|
package io.kamax.mxisd.controller.identity.v1;
|
||||||
|
|
||||||
public class IdentityAPIv1 {
|
public class IdentityAPIv1 {
|
||||||
|
|
@@ -18,12 +18,12 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1;
|
package io.kamax.mxisd.controller.identity.v1;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import io.kamax.matrix.MatrixID;
|
import io.kamax.matrix.MatrixID;
|
||||||
import io.kamax.mxisd.config.ServerConfig;
|
import io.kamax.mxisd.config.ServerConfig;
|
||||||
import io.kamax.mxisd.controller.v1.io.ThreePidInviteReplyIO;
|
import io.kamax.mxisd.controller.identity.v1.io.ThreePidInviteReplyIO;
|
||||||
import io.kamax.mxisd.invitation.IThreePidInvite;
|
import io.kamax.mxisd.invitation.IThreePidInvite;
|
||||||
import io.kamax.mxisd.invitation.IThreePidInviteReply;
|
import io.kamax.mxisd.invitation.IThreePidInviteReply;
|
||||||
import io.kamax.mxisd.invitation.InvitationManager;
|
import io.kamax.mxisd.invitation.InvitationManager;
|
@@ -18,11 +18,11 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1;
|
package io.kamax.mxisd.controller.identity.v1;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import io.kamax.mxisd.controller.v1.io.KeyValidityJson;
|
import io.kamax.mxisd.controller.identity.v1.io.KeyValidityJson;
|
||||||
import io.kamax.mxisd.exception.BadRequestException;
|
import io.kamax.mxisd.exception.BadRequestException;
|
||||||
import io.kamax.mxisd.key.KeyManager;
|
import io.kamax.mxisd.key.KeyManager;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
@@ -18,11 +18,11 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1;
|
package io.kamax.mxisd.controller.identity.v1;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import io.kamax.mxisd.controller.v1.io.SingeLookupReplyJson;
|
import io.kamax.mxisd.controller.identity.v1.io.SingeLookupReplyJson;
|
||||||
import io.kamax.mxisd.exception.InternalServerError;
|
import io.kamax.mxisd.exception.InternalServerError;
|
||||||
import io.kamax.mxisd.lookup.*;
|
import io.kamax.mxisd.lookup.*;
|
||||||
import io.kamax.mxisd.lookup.strategy.LookupStrategy;
|
import io.kamax.mxisd.lookup.strategy.LookupStrategy;
|
@@ -18,11 +18,11 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1;
|
package io.kamax.mxisd.controller.identity.v1;
|
||||||
|
|
||||||
import io.kamax.mxisd.config.ServerConfig;
|
import io.kamax.mxisd.config.ServerConfig;
|
||||||
import io.kamax.mxisd.config.ViewConfig;
|
import io.kamax.mxisd.config.ViewConfig;
|
||||||
import io.kamax.mxisd.controller.v1.remote.RemoteIdentityAPIv1;
|
import io.kamax.mxisd.controller.identity.v1.remote.RemoteIdentityAPIv1;
|
||||||
import io.kamax.mxisd.exception.InternalServerError;
|
import io.kamax.mxisd.exception.InternalServerError;
|
||||||
import io.kamax.mxisd.session.SessionMananger;
|
import io.kamax.mxisd.session.SessionMananger;
|
||||||
import io.kamax.mxisd.session.ValidationResult;
|
import io.kamax.mxisd.session.ValidationResult;
|
@@ -18,7 +18,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1;
|
package io.kamax.mxisd.controller.identity.v1;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
@@ -26,9 +26,9 @@ import io.kamax.matrix.ThreePidMedium;
|
|||||||
import io.kamax.mxisd.ThreePid;
|
import io.kamax.mxisd.ThreePid;
|
||||||
import io.kamax.mxisd.config.ServerConfig;
|
import io.kamax.mxisd.config.ServerConfig;
|
||||||
import io.kamax.mxisd.config.ViewConfig;
|
import io.kamax.mxisd.config.ViewConfig;
|
||||||
import io.kamax.mxisd.controller.v1.io.SessionEmailTokenRequestJson;
|
import io.kamax.mxisd.controller.identity.v1.io.SessionEmailTokenRequestJson;
|
||||||
import io.kamax.mxisd.controller.v1.io.SessionPhoneTokenRequestJson;
|
import io.kamax.mxisd.controller.identity.v1.io.SessionPhoneTokenRequestJson;
|
||||||
import io.kamax.mxisd.controller.v1.io.SuccessStatusJson;
|
import io.kamax.mxisd.controller.identity.v1.io.SuccessStatusJson;
|
||||||
import io.kamax.mxisd.exception.BadRequestException;
|
import io.kamax.mxisd.exception.BadRequestException;
|
||||||
import io.kamax.mxisd.exception.SessionNotValidatedException;
|
import io.kamax.mxisd.exception.SessionNotValidatedException;
|
||||||
import io.kamax.mxisd.invitation.InvitationManager;
|
import io.kamax.mxisd.invitation.InvitationManager;
|
@@ -18,7 +18,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1;
|
package io.kamax.mxisd.controller.identity.v1;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
@@ -18,7 +18,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1.io;
|
package io.kamax.mxisd.controller.identity.v1.io;
|
||||||
|
|
||||||
public abstract class GenericTokenRequestJson {
|
public abstract class GenericTokenRequestJson {
|
||||||
|
|
@@ -18,7 +18,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1.io;
|
package io.kamax.mxisd.controller.identity.v1.io;
|
||||||
|
|
||||||
public class KeyValidityJson {
|
public class KeyValidityJson {
|
||||||
|
|
@@ -18,7 +18,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1.io;
|
package io.kamax.mxisd.controller.identity.v1.io;
|
||||||
|
|
||||||
public class RequestTokenResponse {
|
public class RequestTokenResponse {
|
||||||
|
|
@@ -18,7 +18,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1.io;
|
package io.kamax.mxisd.controller.identity.v1.io;
|
||||||
|
|
||||||
public class SessionEmailTokenRequestJson extends GenericTokenRequestJson {
|
public class SessionEmailTokenRequestJson extends GenericTokenRequestJson {
|
||||||
|
|
@@ -18,7 +18,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1.io;
|
package io.kamax.mxisd.controller.identity.v1.io;
|
||||||
|
|
||||||
import com.google.i18n.phonenumbers.NumberParseException;
|
import com.google.i18n.phonenumbers.NumberParseException;
|
||||||
import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
@@ -18,7 +18,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1.io;
|
package io.kamax.mxisd.controller.identity.v1.io;
|
||||||
|
|
||||||
import io.kamax.mxisd.lookup.SingleLookupReply;
|
import io.kamax.mxisd.lookup.SingleLookupReply;
|
||||||
|
|
@@ -18,7 +18,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1.io;
|
package io.kamax.mxisd.controller.identity.v1.io;
|
||||||
|
|
||||||
public class SuccessStatusJson {
|
public class SuccessStatusJson {
|
||||||
|
|
@@ -18,7 +18,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1.io;
|
package io.kamax.mxisd.controller.identity.v1.io;
|
||||||
|
|
||||||
import io.kamax.mxisd.invitation.IThreePidInviteReply;
|
import io.kamax.mxisd.invitation.IThreePidInviteReply;
|
||||||
|
|
@@ -18,7 +18,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.controller.v1.remote;
|
package io.kamax.mxisd.controller.identity.v1.remote;
|
||||||
|
|
||||||
public class RemoteIdentityAPIv1 {
|
public class RemoteIdentityAPIv1 {
|
||||||
|
|
@@ -1,4 +1,4 @@
|
|||||||
package io.kamax.mxisd.controller.v1.remote;
|
package io.kamax.mxisd.controller.identity.v1.remote;
|
||||||
|
|
||||||
import io.kamax.mxisd.config.ViewConfig;
|
import io.kamax.mxisd.config.ViewConfig;
|
||||||
import io.kamax.mxisd.exception.SessionNotValidatedException;
|
import io.kamax.mxisd.exception.SessionNotValidatedException;
|
||||||
@@ -14,8 +14,8 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import static io.kamax.mxisd.controller.v1.remote.RemoteIdentityAPIv1.SESSION_CHECK;
|
import static io.kamax.mxisd.controller.identity.v1.remote.RemoteIdentityAPIv1.SESSION_CHECK;
|
||||||
import static io.kamax.mxisd.controller.v1.remote.RemoteIdentityAPIv1.SESSION_REQUEST_TOKEN;
|
import static io.kamax.mxisd.controller.identity.v1.remote.RemoteIdentityAPIv1.SESSION_REQUEST_TOKEN;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
public class RemoteSessionController {
|
public class RemoteSessionController {
|
@@ -206,9 +206,16 @@ public class InvitationManager {
|
|||||||
|
|
||||||
String invId = getId(invitation);
|
String invId = getId(invitation);
|
||||||
log.info("Handling invite for {}:{} from {} in room {}", invitation.getMedium(), invitation.getAddress(), invitation.getSender(), invitation.getRoomId());
|
log.info("Handling invite for {}:{} from {} in room {}", invitation.getMedium(), invitation.getAddress(), invitation.getSender(), invitation.getRoomId());
|
||||||
if (invitations.containsKey(invId)) {
|
IThreePidInviteReply reply = invitations.get(invId);
|
||||||
|
if (reply != null) {
|
||||||
log.info("Invite is already pending for {}:{}, returning data", invitation.getMedium(), invitation.getAddress());
|
log.info("Invite is already pending for {}:{}, returning data", invitation.getMedium(), invitation.getAddress());
|
||||||
return invitations.get(invId);
|
if (!StringUtils.equals(invitation.getRoomId(), reply.getInvite().getRoomId())) {
|
||||||
|
log.info("Sending new notification as new invite room {} is different from the original {}", invitation.getRoomId(), reply.getInvite().getRoomId());
|
||||||
|
notifMgr.sendForInvite(new ThreePidInviteReply(reply.getId(), invitation, reply.getToken(), reply.getDisplayName()));
|
||||||
|
} else {
|
||||||
|
// FIXME we should check attempt and send if bigger
|
||||||
|
}
|
||||||
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<?> result = lookupMgr.find(invitation.getMedium(), invitation.getAddress(), true);
|
Optional<?> result = lookupMgr.find(invitation.getMedium(), invitation.getAddress(), true);
|
||||||
@@ -220,7 +227,7 @@ public class InvitationManager {
|
|||||||
String token = RandomStringUtils.randomAlphanumeric(64);
|
String token = RandomStringUtils.randomAlphanumeric(64);
|
||||||
String displayName = invitation.getAddress().substring(0, 3) + "...";
|
String displayName = invitation.getAddress().substring(0, 3) + "...";
|
||||||
|
|
||||||
IThreePidInviteReply reply = new ThreePidInviteReply(invId, invitation, token, displayName);
|
reply = new ThreePidInviteReply(invId, invitation, token, displayName);
|
||||||
|
|
||||||
log.info("Performing invite to {}:{}", invitation.getMedium(), invitation.getAddress());
|
log.info("Performing invite to {}:{}", invitation.getMedium(), invitation.getAddress());
|
||||||
notifMgr.sendForInvite(reply);
|
notifMgr.sendForInvite(reply);
|
||||||
|
@@ -24,7 +24,7 @@ import com.google.gson.Gson;
|
|||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import io.kamax.matrix.MatrixID;
|
import io.kamax.matrix.MatrixID;
|
||||||
import io.kamax.matrix._MatrixID;
|
import io.kamax.matrix._MatrixID;
|
||||||
import io.kamax.mxisd.controller.v1.io.SingeLookupReplyJson;
|
import io.kamax.mxisd.controller.identity.v1.io.SingeLookupReplyJson;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
|
||||||
|
@@ -23,7 +23,7 @@ package io.kamax.mxisd.lookup.provider;
|
|||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import io.kamax.mxisd.controller.v1.ClientBulkLookupRequest;
|
import io.kamax.mxisd.controller.identity.v1.ClientBulkLookupRequest;
|
||||||
import io.kamax.mxisd.exception.InvalidResponseJsonException;
|
import io.kamax.mxisd.exception.InvalidResponseJsonException;
|
||||||
import io.kamax.mxisd.lookup.SingleLookupReply;
|
import io.kamax.mxisd.lookup.SingleLookupReply;
|
||||||
import io.kamax.mxisd.lookup.SingleLookupRequest;
|
import io.kamax.mxisd.lookup.SingleLookupRequest;
|
||||||
|
@@ -25,6 +25,8 @@ import io.kamax.mxisd.threepid.session.IThreePidSession;
|
|||||||
|
|
||||||
public interface INotificationHandler {
|
public interface INotificationHandler {
|
||||||
|
|
||||||
|
String getId();
|
||||||
|
|
||||||
String getMedium();
|
String getMedium();
|
||||||
|
|
||||||
void sendForInvite(IThreePidInviteReply invite);
|
void sendForInvite(IThreePidInviteReply invite);
|
||||||
|
@@ -20,9 +20,13 @@
|
|||||||
|
|
||||||
package io.kamax.mxisd.notification;
|
package io.kamax.mxisd.notification;
|
||||||
|
|
||||||
|
import io.kamax.mxisd.config.threepid.notification.NotificationConfig;
|
||||||
import io.kamax.mxisd.exception.NotImplementedException;
|
import io.kamax.mxisd.exception.NotImplementedException;
|
||||||
import io.kamax.mxisd.invitation.IThreePidInviteReply;
|
import io.kamax.mxisd.invitation.IThreePidInviteReply;
|
||||||
import io.kamax.mxisd.threepid.session.IThreePidSession;
|
import io.kamax.mxisd.threepid.session.IThreePidSession;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@@ -33,12 +37,25 @@ import java.util.Map;
|
|||||||
@Component
|
@Component
|
||||||
public class NotificationManager {
|
public class NotificationManager {
|
||||||
|
|
||||||
|
private Logger log = LoggerFactory.getLogger(NotificationManager.class);
|
||||||
|
|
||||||
private Map<String, INotificationHandler> handlers;
|
private Map<String, INotificationHandler> handlers;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public NotificationManager(List<INotificationHandler> handlers) {
|
public NotificationManager(NotificationConfig cfg, List<INotificationHandler> handlers) {
|
||||||
this.handlers = new HashMap<>();
|
this.handlers = new HashMap<>();
|
||||||
handlers.forEach(h -> this.handlers.put(h.getMedium(), h));
|
handlers.forEach(h -> {
|
||||||
|
log.info("Found handler {} for medium {}", h.getId(), h.getMedium());
|
||||||
|
String handlerId = cfg.getHandler().get(h.getMedium());
|
||||||
|
if (StringUtils.isBlank(handlerId) || StringUtils.equals(handlerId, h.getId())) {
|
||||||
|
this.handlers.put(h.getMedium(), h);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
log.info("--- Notification handler ---");
|
||||||
|
this.handlers.forEach((k, v) -> {
|
||||||
|
log.info("\tHandler for {}: {}", k, v.getId());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private INotificationHandler ensureMedium(String medium) {
|
private INotificationHandler ensureMedium(String medium) {
|
||||||
@@ -46,7 +63,6 @@ public class NotificationManager {
|
|||||||
if (handler == null) {
|
if (handler == null) {
|
||||||
throw new NotImplementedException(medium + " is not a supported 3PID medium type");
|
throw new NotImplementedException(medium + " is not a supported 3PID medium type");
|
||||||
}
|
}
|
||||||
|
|
||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -30,8 +30,8 @@ import io.kamax.matrix._MatrixID;
|
|||||||
import io.kamax.mxisd.ThreePid;
|
import io.kamax.mxisd.ThreePid;
|
||||||
import io.kamax.mxisd.config.MatrixConfig;
|
import io.kamax.mxisd.config.MatrixConfig;
|
||||||
import io.kamax.mxisd.config.SessionConfig;
|
import io.kamax.mxisd.config.SessionConfig;
|
||||||
import io.kamax.mxisd.controller.v1.io.RequestTokenResponse;
|
import io.kamax.mxisd.controller.identity.v1.io.RequestTokenResponse;
|
||||||
import io.kamax.mxisd.controller.v1.remote.RemoteIdentityAPIv1;
|
import io.kamax.mxisd.controller.identity.v1.remote.RemoteIdentityAPIv1;
|
||||||
import io.kamax.mxisd.exception.*;
|
import io.kamax.mxisd.exception.*;
|
||||||
import io.kamax.mxisd.lookup.ThreePidValidation;
|
import io.kamax.mxisd.lookup.ThreePidValidation;
|
||||||
import io.kamax.mxisd.matrix.IdentityServerUtils;
|
import io.kamax.mxisd.matrix.IdentityServerUtils;
|
||||||
|
@@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* 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.sendgrid.SendGrid;
|
||||||
|
import com.sendgrid.SendGridException;
|
||||||
|
import io.kamax.matrix.ThreePidMedium;
|
||||||
|
import io.kamax.mxisd.config.MatrixConfig;
|
||||||
|
import io.kamax.mxisd.config.ServerConfig;
|
||||||
|
import io.kamax.mxisd.config.threepid.connector.EmailSendGridConfig;
|
||||||
|
import io.kamax.mxisd.invitation.IThreePidInviteReply;
|
||||||
|
import io.kamax.mxisd.notification.INotificationHandler;
|
||||||
|
import io.kamax.mxisd.threepid.notification.PlaceholderNotificationGenerator;
|
||||||
|
import io.kamax.mxisd.threepid.session.IThreePidSession;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
import static com.sendgrid.SendGrid.Email;
|
||||||
|
import static com.sendgrid.SendGrid.Response;
|
||||||
|
import static io.kamax.mxisd.config.threepid.connector.EmailSendGridConfig.EmailTemplate;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class EmailSendGridNotificationHandler extends PlaceholderNotificationGenerator implements INotificationHandler {
|
||||||
|
|
||||||
|
private Logger log = LoggerFactory.getLogger(EmailSendGridNotificationHandler.class);
|
||||||
|
|
||||||
|
private EmailSendGridConfig cfg;
|
||||||
|
private SendGrid sendgrid;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public EmailSendGridNotificationHandler(MatrixConfig mxCfg, ServerConfig srvCfg, EmailSendGridConfig cfg) {
|
||||||
|
super(mxCfg, srvCfg);
|
||||||
|
this.cfg = cfg;
|
||||||
|
this.sendgrid = new SendGrid(cfg.getApi().getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "sendgrid";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMedium() {
|
||||||
|
return ThreePidMedium.Email.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Email getEmail() {
|
||||||
|
Email email = new Email();
|
||||||
|
email.setFrom(cfg.getIdentity().getFrom());
|
||||||
|
email.setFromName(cfg.getIdentity().getName());
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getFromFile(String path) {
|
||||||
|
try {
|
||||||
|
return IOUtils.toString(new FileInputStream(path), StandardCharsets.UTF_8);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Couldn't create notification content using file " + path, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendForInvite(IThreePidInviteReply invite) {
|
||||||
|
EmailTemplate template = cfg.getTemplates().getInvite();
|
||||||
|
Email email = getEmail();
|
||||||
|
email.setSubject(populateForInvite(invite, template.getSubject()));
|
||||||
|
email.setText(populateForInvite(invite, getFromFile(template.getBody().getText())));
|
||||||
|
email.setHtml(populateForInvite(invite, getFromFile(template.getBody().getHtml())));
|
||||||
|
|
||||||
|
send(invite.getInvite().getAddress(), email);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendForValidation(IThreePidSession session) {
|
||||||
|
EmailTemplate template = cfg.getTemplates().getSession().getLocal();
|
||||||
|
Email email = getEmail();
|
||||||
|
email.setSubject(populateForValidation(session, template.getSubject()));
|
||||||
|
email.setText(populateForValidation(session, getFromFile(template.getBody().getText())));
|
||||||
|
email.setHtml(populateForValidation(session, getFromFile(template.getBody().getHtml())));
|
||||||
|
|
||||||
|
send(session.getThreePid().getAddress(), email);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendForRemoteValidation(IThreePidSession session) {
|
||||||
|
EmailTemplate template = cfg.getTemplates().getSession().getLocal();
|
||||||
|
Email email = getEmail();
|
||||||
|
email.setSubject(populateForRemoteValidation(session, template.getSubject()));
|
||||||
|
email.setText(populateForRemoteValidation(session, getFromFile(template.getBody().getText())));
|
||||||
|
email.setHtml(populateForRemoteValidation(session, getFromFile(template.getBody().getHtml())));
|
||||||
|
|
||||||
|
send(session.getThreePid().getAddress(), email);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void send(String recipient, Email email) {
|
||||||
|
try {
|
||||||
|
email.addTo(recipient);
|
||||||
|
email.setFrom(cfg.getIdentity().getFrom());
|
||||||
|
email.setFromName(cfg.getIdentity().getName());
|
||||||
|
Response response = sendgrid.send(email);
|
||||||
|
if (response.getStatus()) {
|
||||||
|
log.info("Successfully sent email to {} using SendGrid", recipient);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Error sending via SendGrid to " + recipient + ": " + response.getMessage());
|
||||||
|
}
|
||||||
|
} catch (SendGridException e) {
|
||||||
|
throw new RuntimeException("Unable to send e-mail invite via SendGrid to " + recipient, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -20,17 +20,14 @@
|
|||||||
|
|
||||||
package io.kamax.mxisd.threepid.notification;
|
package io.kamax.mxisd.threepid.notification;
|
||||||
|
|
||||||
import io.kamax.mxisd.ThreePid;
|
|
||||||
import io.kamax.mxisd.config.MatrixConfig;
|
import io.kamax.mxisd.config.MatrixConfig;
|
||||||
import io.kamax.mxisd.config.ServerConfig;
|
import io.kamax.mxisd.config.ServerConfig;
|
||||||
import io.kamax.mxisd.config.threepid.medium.GenericTemplateConfig;
|
import io.kamax.mxisd.config.threepid.medium.GenericTemplateConfig;
|
||||||
import io.kamax.mxisd.controller.v1.IdentityAPIv1;
|
|
||||||
import io.kamax.mxisd.exception.InternalServerError;
|
import io.kamax.mxisd.exception.InternalServerError;
|
||||||
import io.kamax.mxisd.invitation.IThreePidInviteReply;
|
import io.kamax.mxisd.invitation.IThreePidInviteReply;
|
||||||
import io.kamax.mxisd.threepid.session.IThreePidSession;
|
import io.kamax.mxisd.threepid.session.IThreePidSession;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.commons.lang.WordUtils;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -43,39 +40,20 @@ import java.io.InputStream;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public abstract class GenericTemplateNotificationGenerator implements INotificationGenerator {
|
public abstract class GenericTemplateNotificationGenerator extends PlaceholderNotificationGenerator implements INotificationGenerator {
|
||||||
|
|
||||||
private Logger log = LoggerFactory.getLogger(GenericTemplateNotificationGenerator.class);
|
private Logger log = LoggerFactory.getLogger(GenericTemplateNotificationGenerator.class);
|
||||||
|
|
||||||
private MatrixConfig mxCfg;
|
|
||||||
private ServerConfig srvCfg;
|
|
||||||
private GenericTemplateConfig cfg;
|
private GenericTemplateConfig cfg;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ApplicationContext app;
|
private ApplicationContext app;
|
||||||
|
|
||||||
public GenericTemplateNotificationGenerator(MatrixConfig mxCfg, ServerConfig srvCfg, GenericTemplateConfig cfg) {
|
public GenericTemplateNotificationGenerator(MatrixConfig mxCfg, ServerConfig srvCfg, GenericTemplateConfig cfg) {
|
||||||
this.mxCfg = mxCfg;
|
super(mxCfg, srvCfg);
|
||||||
this.srvCfg = srvCfg;
|
|
||||||
this.cfg = cfg;
|
this.cfg = cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String populateForCommon(String body, ThreePid recipient) {
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String populateCommon(String body, ThreePid recipient) {
|
|
||||||
body = populateForCommon(body, recipient);
|
|
||||||
|
|
||||||
String domainPretty = WordUtils.capitalizeFully(mxCfg.getDomain());
|
|
||||||
body = body.replace("%DOMAIN%", mxCfg.getDomain());
|
|
||||||
body = body.replace("%DOMAIN_PRETTY%", domainPretty);
|
|
||||||
body = body.replace("%RECIPIENT_MEDIUM%", recipient.getMedium());
|
|
||||||
body = body.replace("%RECIPIENT_ADDRESS%", recipient.getAddress());
|
|
||||||
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTemplateContent(String location) {
|
private String getTemplateContent(String location) {
|
||||||
try {
|
try {
|
||||||
InputStream is = StringUtils.startsWith(location, "classpath:") ?
|
InputStream is = StringUtils.startsWith(location, "classpath:") ?
|
||||||
@@ -86,65 +64,22 @@ public abstract class GenericTemplateNotificationGenerator implements INotificat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getTemplateAndPopulate(String location, ThreePid recipient) {
|
|
||||||
return populateCommon(getTemplateContent(location), recipient);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getForInvite(IThreePidInviteReply invite) {
|
public String getForInvite(IThreePidInviteReply invite) {
|
||||||
ThreePid tpid = new ThreePid(invite.getInvite().getMedium(), invite.getInvite().getAddress());
|
log.info("Generating notification content for 3PID invite");
|
||||||
String templateBody = getTemplateAndPopulate(cfg.getInvite(), tpid);
|
return populateForInvite(invite, getTemplateContent(cfg.getInvite()));
|
||||||
|
|
||||||
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
|
@Override
|
||||||
public String getForValidation(IThreePidSession session) {
|
public String getForValidation(IThreePidSession session) {
|
||||||
log.info("Generating notification content for 3PID Session validation");
|
log.info("Generating notification content for 3PID Session validation");
|
||||||
String templateBody = getTemplateAndPopulate(cfg.getSession().getValidation().getLocal(), session.getThreePid());
|
return populateForValidation(session, getTemplateContent(cfg.getSession().getValidation().getLocal()));
|
||||||
|
|
||||||
String validationLink = srvCfg.getPublicUrl() + IdentityAPIv1.getValidate(
|
|
||||||
session.getThreePid().getMedium(),
|
|
||||||
session.getId(),
|
|
||||||
session.getSecret(),
|
|
||||||
session.getToken());
|
|
||||||
|
|
||||||
templateBody = templateBody.replace("%VALIDATION_LINK%", validationLink);
|
|
||||||
templateBody = templateBody.replace("%VALIDATION_TOKEN%", session.getToken());
|
|
||||||
|
|
||||||
return templateBody;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getForRemoteValidation(IThreePidSession session) {
|
public String getForRemoteValidation(IThreePidSession session) {
|
||||||
log.info("Generating notification content for remote-only 3PID session");
|
log.info("Generating notification content for remote-only 3PID session");
|
||||||
String templateBody = getTemplateAndPopulate(cfg.getSession().getValidation().getRemote(), session.getThreePid());
|
return populateForRemoteValidation(session, getTemplateContent(cfg.getSession().getValidation().getRemote()));
|
||||||
|
|
||||||
String validationLink = srvCfg.getPublicUrl() + IdentityAPIv1.getValidate(
|
|
||||||
session.getThreePid().getMedium(),
|
|
||||||
session.getId(),
|
|
||||||
session.getSecret(),
|
|
||||||
session.getToken());
|
|
||||||
|
|
||||||
templateBody = templateBody.replace("%VALIDATION_LINK%", validationLink);
|
|
||||||
templateBody = templateBody.replace("%VALIDATION_TOKEN%", session.getToken());
|
|
||||||
templateBody = templateBody.replace("%NEXT_URL%", validationLink);
|
|
||||||
|
|
||||||
return templateBody;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* 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.ThreePid;
|
||||||
|
import io.kamax.mxisd.config.MatrixConfig;
|
||||||
|
import io.kamax.mxisd.config.ServerConfig;
|
||||||
|
import io.kamax.mxisd.controller.identity.v1.IdentityAPIv1;
|
||||||
|
import io.kamax.mxisd.invitation.IThreePidInviteReply;
|
||||||
|
import io.kamax.mxisd.threepid.session.IThreePidSession;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.commons.lang.WordUtils;
|
||||||
|
|
||||||
|
public abstract class PlaceholderNotificationGenerator {
|
||||||
|
|
||||||
|
private MatrixConfig mxCfg;
|
||||||
|
private ServerConfig srvCfg;
|
||||||
|
|
||||||
|
public PlaceholderNotificationGenerator(MatrixConfig mxCfg, ServerConfig srvCfg) {
|
||||||
|
this.mxCfg = mxCfg;
|
||||||
|
this.srvCfg = srvCfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String populateForCommon(String input, ThreePid recipient) {
|
||||||
|
String domainPretty = WordUtils.capitalizeFully(mxCfg.getDomain());
|
||||||
|
|
||||||
|
return input
|
||||||
|
.replace("%DOMAIN%", mxCfg.getDomain())
|
||||||
|
.replace("%DOMAIN_PRETTY%", domainPretty)
|
||||||
|
.replace("%RECIPIENT_MEDIUM%", recipient.getMedium())
|
||||||
|
.replace("%RECIPIENT_ADDRESS%", recipient.getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String populateForInvite(IThreePidInviteReply invite, String input) {
|
||||||
|
ThreePid tpid = new ThreePid(invite.getInvite().getMedium(), invite.getInvite().getAddress());
|
||||||
|
|
||||||
|
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());
|
||||||
|
|
||||||
|
return populateForCommon(input, tpid)
|
||||||
|
.replace("%SENDER_ID%", invite.getInvite().getSender().getId())
|
||||||
|
.replace("%SENDER_NAME%", senderName)
|
||||||
|
.replace("%SENDER_NAME_OR_ID%", senderNameOrId)
|
||||||
|
.replace("%INVITE_MEDIUM%", tpid.getMedium())
|
||||||
|
.replace("%INVITE_ADDRESS%", tpid.getAddress())
|
||||||
|
.replace("%ROOM_ID%", invite.getInvite().getRoomId())
|
||||||
|
.replace("%ROOM_NAME%", roomName)
|
||||||
|
.replace("%ROOM_NAME_OR_ID%", roomNameOrId);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String populateForValidation(IThreePidSession session, String input) {
|
||||||
|
String validationLink = srvCfg.getPublicUrl() + IdentityAPIv1.getValidate(
|
||||||
|
session.getThreePid().getMedium(),
|
||||||
|
session.getId(),
|
||||||
|
session.getSecret(),
|
||||||
|
session.getToken()
|
||||||
|
);
|
||||||
|
|
||||||
|
return populateForCommon(input, session.getThreePid())
|
||||||
|
.replace("%VALIDATION_LINK%", validationLink)
|
||||||
|
.replace("%VALIDATION_TOKEN%", session.getToken())
|
||||||
|
.replace("%NEXT_URL%", validationLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String populateForRemoteValidation(IThreePidSession session, String input) {
|
||||||
|
return populateForValidation(session, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -47,6 +47,7 @@ public class EmailNotificationGenerator extends GenericTemplateNotificationGener
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String populateForCommon(String body, ThreePid recipient) {
|
protected String populateForCommon(String body, ThreePid recipient) {
|
||||||
|
body = super.populateForCommon(body, recipient);
|
||||||
body = body.replace("%FROM_EMAIL%", cfg.getIdentity().getFrom());
|
body = body.replace("%FROM_EMAIL%", cfg.getIdentity().getFrom());
|
||||||
body = body.replace("%FROM_NAME%", cfg.getIdentity().getName());
|
body = body.replace("%FROM_NAME%", cfg.getIdentity().getName());
|
||||||
return body;
|
return body;
|
||||||
|
@@ -30,16 +30,21 @@ import org.springframework.stereotype.Component;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class EmailNotificationHandler extends GenericNotificationHandler<IEmailConnector, IEmailNotificationGenerator> {
|
public class EmailRawNotificationHandler extends GenericNotificationHandler<IEmailConnector, IEmailNotificationGenerator> {
|
||||||
|
|
||||||
private EmailConfig cfg;
|
private EmailConfig cfg;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public EmailNotificationHandler(EmailConfig cfg, List<IEmailNotificationGenerator> generators, List<IEmailConnector> connectors) {
|
public EmailRawNotificationHandler(EmailConfig cfg, List<IEmailNotificationGenerator> generators, List<IEmailConnector> connectors) {
|
||||||
this.cfg = cfg;
|
this.cfg = cfg;
|
||||||
process(connectors, generators);
|
process(connectors, generators);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "raw";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMedium() {
|
public String getMedium() {
|
||||||
return ThreePidMedium.Email.getId();
|
return ThreePidMedium.Email.getId();
|
@@ -40,6 +40,11 @@ public class PhoneNotificationHandler extends GenericNotificationHandler<IPhoneC
|
|||||||
process(connectors, generators);
|
process(connectors, generators);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "raw";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMedium() {
|
public String getMedium() {
|
||||||
return ThreePidMedium.PhoneNumber.getId();
|
return ThreePidMedium.PhoneNumber.getId();
|
||||||
|
33
src/main/java/io/kamax/mxisd/util/GsonUtil.java
Normal file
33
src/main/java/io/kamax/mxisd/util/GsonUtil.java
Normal file
@@ -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.util;
|
||||||
|
|
||||||
|
import com.google.gson.FieldNamingPolicy;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
|
public class GsonUtil {
|
||||||
|
|
||||||
|
public static Gson build() {
|
||||||
|
return new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -97,6 +97,7 @@ threepid:
|
|||||||
validation:
|
validation:
|
||||||
local: 'classpath:threepids/email/validate-local-template.eml'
|
local: 'classpath:threepids/email/validate-local-template.eml'
|
||||||
remote: 'classpath:threepids/email/validate-remote-template.eml'
|
remote: 'classpath:threepids/email/validate-remote-template.eml'
|
||||||
|
|
||||||
msisdn:
|
msisdn:
|
||||||
connector: 'twilio'
|
connector: 'twilio'
|
||||||
generator: 'template'
|
generator: 'template'
|
||||||
@@ -130,6 +131,35 @@ session:
|
|||||||
enabled: true
|
enabled: true
|
||||||
server: 'root'
|
server: 'root'
|
||||||
|
|
||||||
|
notification:
|
||||||
|
# handler:
|
||||||
|
# 3PID-medium: 'handlerId'
|
||||||
|
handlers:
|
||||||
|
sendgrid:
|
||||||
|
api:
|
||||||
|
key: ''
|
||||||
|
identity:
|
||||||
|
from: ''
|
||||||
|
name: ''
|
||||||
|
templates:
|
||||||
|
invite:
|
||||||
|
subject: ''
|
||||||
|
body:
|
||||||
|
text: ''
|
||||||
|
html: ''
|
||||||
|
session:
|
||||||
|
validation:
|
||||||
|
local:
|
||||||
|
subject: ''
|
||||||
|
body:
|
||||||
|
text: ''
|
||||||
|
html: ''
|
||||||
|
remote:
|
||||||
|
subject: ''
|
||||||
|
body:
|
||||||
|
text: ''
|
||||||
|
html: ''
|
||||||
|
|
||||||
view:
|
view:
|
||||||
session:
|
session:
|
||||||
local:
|
local:
|
||||||
|
Reference in New Issue
Block a user