Bye bye Groovy, you won't be missed :(
This commit is contained in:
@@ -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;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
class MatrixIdentityServerApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(MatrixIdentityServerApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
51
src/main/java/io/kamax/mxisd/ThreePid.java
Normal file
51
src/main/java/io/kamax/mxisd/ThreePid.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
// FIXME this should be in matrix-java-sdk
|
||||
public class ThreePid {
|
||||
|
||||
private String medium;
|
||||
private String address;
|
||||
|
||||
public ThreePid(ThreePid tpid) {
|
||||
this(tpid.getMedium(), tpid.getAddress());
|
||||
}
|
||||
|
||||
public ThreePid(String medium, String address) {
|
||||
this.medium = medium;
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getMedium() {
|
||||
return medium;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getMedium() + ":" + getAddress();
|
||||
}
|
||||
|
||||
}
|
46
src/main/java/io/kamax/mxisd/UserID.java
Normal file
46
src/main/java/io/kamax/mxisd/UserID.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
// FIXME consider integrating in matrix-java-sdk?
|
||||
public class UserID {
|
||||
|
||||
private String type;
|
||||
private String value;
|
||||
|
||||
protected UserID() {
|
||||
// stub for (de)serialization
|
||||
}
|
||||
|
||||
public UserID(String type, String value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
47
src/main/java/io/kamax/mxisd/UserIdType.java
Normal file
47
src/main/java/io/kamax/mxisd/UserIdType.java
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
// FIXME consider integrating in matrix-java-sdk?
|
||||
public enum UserIdType {
|
||||
|
||||
Localpart("localpart"),
|
||||
MatrixID("mxid"),
|
||||
EmailLocalpart("email_localpart"),
|
||||
Email("email");
|
||||
|
||||
private String id;
|
||||
|
||||
UserIdType(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public boolean is(String id) {
|
||||
return StringUtils.equalsIgnoreCase(this.id, id);
|
||||
}
|
||||
|
||||
}
|
93
src/main/java/io/kamax/mxisd/auth/AuthManager.java
Normal file
93
src/main/java/io/kamax/mxisd/auth/AuthManager.java
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.auth;
|
||||
|
||||
import io.kamax.matrix.MatrixID;
|
||||
import io.kamax.matrix._MatrixID;
|
||||
import io.kamax.mxisd.ThreePid;
|
||||
import io.kamax.mxisd.UserIdType;
|
||||
import io.kamax.mxisd.auth.provider.AuthenticatorProvider;
|
||||
import io.kamax.mxisd.auth.provider.BackendAuthResult;
|
||||
import io.kamax.mxisd.config.MatrixConfig;
|
||||
import io.kamax.mxisd.invitation.InvitationManager;
|
||||
import io.kamax.mxisd.lookup.ThreePidMapping;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class AuthManager {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(AuthManager.class);
|
||||
|
||||
@Autowired
|
||||
private List<AuthenticatorProvider> providers = new ArrayList<>();
|
||||
|
||||
@Autowired
|
||||
private MatrixConfig mxCfg;
|
||||
|
||||
@Autowired
|
||||
private InvitationManager invMgr;
|
||||
|
||||
public UserAuthResult authenticate(String id, String password) {
|
||||
_MatrixID mxid = new MatrixID(id);
|
||||
for (AuthenticatorProvider provider : providers) {
|
||||
if (!provider.isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BackendAuthResult result = provider.authenticate(mxid, password);
|
||||
if (result.isSuccess()) {
|
||||
|
||||
String mxId;
|
||||
if (UserIdType.Localpart.is(result.getId().getType())) {
|
||||
mxId = new MatrixID(result.getId().getValue(), mxCfg.getDomain()).getId();
|
||||
} else if (UserIdType.MatrixID.is(result.getId().getType())) {
|
||||
mxId = new MatrixID(result.getId().getValue()).getId();
|
||||
} else {
|
||||
log.warn("Unsupported User ID type {} for backend {}", result.getId().getType(), provider.getClass().getSimpleName());
|
||||
continue;
|
||||
}
|
||||
|
||||
UserAuthResult authResult = new UserAuthResult().success(mxId, result.getProfile().getDisplayName());
|
||||
for (ThreePid pid : result.getProfile().getThreePids()) {
|
||||
authResult.withThreePid(pid.getMedium(), pid.getAddress());
|
||||
}
|
||||
log.info("{} was authenticated by {}, publishing 3PID mappings, if any", id, provider.getClass().getSimpleName());
|
||||
for (ThreePid pid : authResult.getThreePids()) {
|
||||
log.info("Processing {} for {}", pid, id);
|
||||
invMgr.publishMappingIfInvited(new ThreePidMapping(pid, authResult.getMxid()));
|
||||
}
|
||||
|
||||
invMgr.lookupMappingsForInvites();
|
||||
|
||||
return authResult;
|
||||
}
|
||||
}
|
||||
|
||||
return new UserAuthResult().failure();
|
||||
}
|
||||
|
||||
}
|
91
src/main/java/io/kamax/mxisd/auth/UserAuthResult.java
Normal file
91
src/main/java/io/kamax/mxisd/auth/UserAuthResult.java
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.auth;
|
||||
|
||||
import io.kamax.matrix.ThreePidMedium;
|
||||
import io.kamax.mxisd.ThreePid;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class UserAuthResult {
|
||||
|
||||
private boolean success;
|
||||
private String mxid;
|
||||
private String displayName;
|
||||
private List<ThreePid> threePids = new ArrayList<>();
|
||||
|
||||
public UserAuthResult failure() {
|
||||
success = false;
|
||||
mxid = null;
|
||||
displayName = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public UserAuthResult success(String mxid, String displayName) {
|
||||
setSuccess(true);
|
||||
setMxid(mxid);
|
||||
setDisplayName(displayName);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public void setSuccess(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
public String getMxid() {
|
||||
return mxid;
|
||||
}
|
||||
|
||||
public void setMxid(String mxid) {
|
||||
this.mxid = mxid;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public UserAuthResult withThreePid(ThreePidMedium medium, String address) {
|
||||
return withThreePid(medium.getId(), address);
|
||||
}
|
||||
|
||||
public UserAuthResult withThreePid(String medium, String address) {
|
||||
threePids.add(new ThreePid(medium, address));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<ThreePid> getThreePids() {
|
||||
return Collections.unmodifiableList(threePids);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.auth.provider;
|
||||
|
||||
import io.kamax.matrix._MatrixID;
|
||||
|
||||
public interface AuthenticatorProvider {
|
||||
|
||||
boolean isEnabled();
|
||||
|
||||
BackendAuthResult authenticate(_MatrixID mxid, String password);
|
||||
|
||||
}
|
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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.auth.provider;
|
||||
|
||||
import io.kamax.mxisd.ThreePid;
|
||||
import io.kamax.mxisd.UserID;
|
||||
import io.kamax.mxisd.UserIdType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BackendAuthResult {
|
||||
|
||||
public static class BackendAuthProfile {
|
||||
|
||||
private String displayName;
|
||||
private List<ThreePid> threePids = new ArrayList<>();
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public List<ThreePid> getThreePids() {
|
||||
return threePids;
|
||||
}
|
||||
}
|
||||
|
||||
public static BackendAuthResult failure() {
|
||||
BackendAuthResult r = new BackendAuthResult();
|
||||
r.success = false;
|
||||
return r;
|
||||
}
|
||||
|
||||
public void fail() {
|
||||
success = false;
|
||||
}
|
||||
|
||||
public static BackendAuthResult success(String id, UserIdType type, String displayName) {
|
||||
return success(id, type.getId(), displayName);
|
||||
}
|
||||
|
||||
public static BackendAuthResult success(String id, String type, String displayName) {
|
||||
BackendAuthResult r = new BackendAuthResult();
|
||||
r.succeed(id, type, displayName);
|
||||
return r;
|
||||
}
|
||||
|
||||
public void succeed(String id, String type, String displayName) {
|
||||
this.success = true;
|
||||
this.id = new UserID(type, id);
|
||||
this.profile = new BackendAuthProfile();
|
||||
this.profile.displayName = displayName;
|
||||
}
|
||||
|
||||
private Boolean success;
|
||||
private UserID id;
|
||||
private BackendAuthProfile profile = new BackendAuthProfile();
|
||||
|
||||
public Boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public UserID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public BackendAuthProfile getProfile() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
public BackendAuthResult withThreePid(ThreePid threePid) {
|
||||
this.profile.threePids.add(threePid);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* 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.backend.firebase;
|
||||
|
||||
import com.google.firebase.FirebaseApp;
|
||||
import com.google.firebase.FirebaseOptions;
|
||||
import com.google.firebase.auth.FirebaseAuth;
|
||||
import com.google.firebase.auth.FirebaseCredential;
|
||||
import com.google.firebase.auth.FirebaseCredentials;
|
||||
import io.kamax.matrix.ThreePidMedium;
|
||||
import io.kamax.matrix._MatrixID;
|
||||
import io.kamax.mxisd.ThreePid;
|
||||
import io.kamax.mxisd.UserIdType;
|
||||
import io.kamax.mxisd.auth.provider.AuthenticatorProvider;
|
||||
import io.kamax.mxisd.auth.provider.BackendAuthResult;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class GoogleFirebaseAuthenticator implements AuthenticatorProvider {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(GoogleFirebaseAuthenticator.class);
|
||||
|
||||
private boolean isEnabled;
|
||||
private FirebaseApp fbApp;
|
||||
private FirebaseAuth fbAuth;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
public GoogleFirebaseAuthenticator(boolean isEnabled) {
|
||||
this.isEnabled = isEnabled;
|
||||
}
|
||||
|
||||
public GoogleFirebaseAuthenticator(String credsPath, String db) {
|
||||
this(true);
|
||||
try {
|
||||
fbApp = FirebaseApp.initializeApp(getOpts(credsPath, db), "AuthenticationProvider");
|
||||
fbAuth = FirebaseAuth.getInstance(fbApp);
|
||||
|
||||
log.info("Google Firebase Authentication is ready");
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error when initializing Firebase", e);
|
||||
}
|
||||
}
|
||||
|
||||
private FirebaseCredential getCreds(String credsPath) throws IOException {
|
||||
if (StringUtils.isNotBlank(credsPath)) {
|
||||
return FirebaseCredentials.fromCertificate(new FileInputStream(credsPath));
|
||||
} else {
|
||||
return FirebaseCredentials.applicationDefault();
|
||||
}
|
||||
}
|
||||
|
||||
private FirebaseOptions getOpts(String credsPath, String db) throws IOException {
|
||||
if (StringUtils.isBlank(db)) {
|
||||
throw new IllegalArgumentException("Firebase database is not configured");
|
||||
}
|
||||
|
||||
return new FirebaseOptions.Builder()
|
||||
.setCredential(getCreds(credsPath))
|
||||
.setDatabaseUrl(db)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
private void waitOnLatch(CountDownLatch l) {
|
||||
try {
|
||||
l.await(30, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
log.warn("Interrupted while waiting for Firebase auth check");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BackendAuthResult authenticate(_MatrixID mxid, String password) {
|
||||
if (!isEnabled()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
log.info("Trying to authenticate {}", mxid);
|
||||
|
||||
final BackendAuthResult result = BackendAuthResult.failure();
|
||||
|
||||
String localpart = mxid.getLocalPart();
|
||||
CountDownLatch l = new CountDownLatch(1);
|
||||
fbAuth.verifyIdToken(password).addOnSuccessListener(token -> {
|
||||
try {
|
||||
if (!StringUtils.equals(localpart, token.getUid())) {
|
||||
log.info("Failure to authenticate {}: Matrix ID localpart '{}' does not match Firebase UID '{}'", mxid, localpart, token.getUid());
|
||||
result.fail();
|
||||
return;
|
||||
}
|
||||
|
||||
result.succeed(mxid.getId(), UserIdType.MatrixID.getId(), token.getName());
|
||||
log.info("{} was successfully authenticated", mxid);
|
||||
log.info("Fetching profile for {}", mxid);
|
||||
CountDownLatch userRecordLatch = new CountDownLatch(1);
|
||||
fbAuth.getUser(token.getUid()).addOnSuccessListener(user -> {
|
||||
try {
|
||||
if (StringUtils.isNotBlank(user.getEmail())) {
|
||||
result.withThreePid(new ThreePid(ThreePidMedium.Email.getId(), user.getEmail()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(user.getPhoneNumber())) {
|
||||
result.withThreePid(new ThreePid(ThreePidMedium.PhoneNumber.getId(), user.getPhoneNumber()));
|
||||
}
|
||||
|
||||
} finally {
|
||||
userRecordLatch.countDown();
|
||||
}
|
||||
}).addOnFailureListener(e -> {
|
||||
try {
|
||||
log.warn("Unable to fetch Firebase user profile for {}", mxid);
|
||||
result.fail();
|
||||
} finally {
|
||||
userRecordLatch.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
waitOnLatch(result, userRecordLatch, "Firebase user profile");
|
||||
} finally {
|
||||
l.countDown();
|
||||
}
|
||||
}).addOnFailureListener(e -> {
|
||||
try {
|
||||
if (e instanceof IllegalArgumentException) {
|
||||
log.info("Failure to authenticate {}: invalid firebase token", mxid);
|
||||
} else {
|
||||
log.info("Failure to authenticate {}: {}", mxid, e.getMessage(), e);
|
||||
log.info("Exception", e);
|
||||
}
|
||||
|
||||
result.fail();
|
||||
} finally {
|
||||
l.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
waitOnLatch(result, l, "Firebase auth check");
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* 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.backend.firebase;
|
||||
|
||||
import com.google.firebase.FirebaseApp;
|
||||
import com.google.firebase.FirebaseOptions;
|
||||
import com.google.firebase.auth.FirebaseAuth;
|
||||
import com.google.firebase.auth.FirebaseCredential;
|
||||
import com.google.firebase.auth.FirebaseCredentials;
|
||||
import com.google.firebase.auth.UserRecord;
|
||||
import com.google.firebase.tasks.OnFailureListener;
|
||||
import com.google.firebase.tasks.OnSuccessListener;
|
||||
import io.kamax.matrix.MatrixID;
|
||||
import io.kamax.matrix.ThreePidMedium;
|
||||
import io.kamax.mxisd.lookup.SingleLookupReply;
|
||||
import io.kamax.mxisd.lookup.SingleLookupRequest;
|
||||
import io.kamax.mxisd.lookup.ThreePidMapping;
|
||||
import io.kamax.mxisd.lookup.provider.IThreePidProvider;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class GoogleFirebaseProvider implements IThreePidProvider {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(GoogleFirebaseProvider.class);
|
||||
|
||||
private boolean isEnabled;
|
||||
private String domain;
|
||||
private FirebaseAuth fbAuth;
|
||||
|
||||
public GoogleFirebaseProvider(boolean isEnabled) {
|
||||
this.isEnabled = isEnabled;
|
||||
}
|
||||
|
||||
public GoogleFirebaseProvider(String credsPath, String db, String domain) {
|
||||
this(true);
|
||||
this.domain = domain;
|
||||
|
||||
try {
|
||||
FirebaseApp fbApp = FirebaseApp.initializeApp(getOpts(credsPath, db), "ThreePidProvider");
|
||||
fbAuth = FirebaseAuth.getInstance(fbApp);
|
||||
|
||||
log.info("Google Firebase Authentication is ready");
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error when initializing Firebase", e);
|
||||
}
|
||||
}
|
||||
|
||||
private FirebaseCredential getCreds(String credsPath) throws IOException {
|
||||
if (StringUtils.isNotBlank(credsPath)) {
|
||||
return FirebaseCredentials.fromCertificate(new FileInputStream(credsPath));
|
||||
} else {
|
||||
return FirebaseCredentials.applicationDefault();
|
||||
}
|
||||
}
|
||||
|
||||
private FirebaseOptions getOpts(String credsPath, String db) throws IOException {
|
||||
if (StringUtils.isBlank(db)) {
|
||||
throw new IllegalArgumentException("Firebase database is not configured");
|
||||
}
|
||||
|
||||
return new FirebaseOptions.Builder()
|
||||
.setCredential(getCreds(credsPath))
|
||||
.setDatabaseUrl(db)
|
||||
.build();
|
||||
}
|
||||
|
||||
private String getMxid(UserRecord record) {
|
||||
return new MatrixID(record.getUid(), domain).getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 25;
|
||||
}
|
||||
|
||||
private void waitOnLatch(CountDownLatch l) {
|
||||
try {
|
||||
l.await(30, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
log.warn("Interrupted while waiting for Firebase auth check");
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<UserRecord> findInternal(String medium, String address) {
|
||||
final UserRecord[] r = new UserRecord[1];
|
||||
CountDownLatch l = new CountDownLatch(1);
|
||||
|
||||
OnSuccessListener<UserRecord> success = result -> {
|
||||
log.info("Found 3PID match for {}:{} - UID is {}", medium, address, result.getUid());
|
||||
r[0] = result;
|
||||
l.countDown();
|
||||
};
|
||||
|
||||
OnFailureListener failure = e -> {
|
||||
log.info("No 3PID match for {}:{} - {}", medium, address, e.getMessage());
|
||||
r[0] = null;
|
||||
l.countDown();
|
||||
};
|
||||
|
||||
if (ThreePidMedium.Email.is(medium)) {
|
||||
log.info("Performing E-mail 3PID lookup for {}", address);
|
||||
fbAuth.getUserByEmail(address)
|
||||
.addOnSuccessListener(success)
|
||||
.addOnFailureListener(failure);
|
||||
waitOnLatch(l);
|
||||
} else if (ThreePidMedium.PhoneNumber.is(medium)) {
|
||||
log.info("Performing msisdn 3PID lookup for {}", address);
|
||||
fbAuth.getUserByPhoneNumber(address)
|
||||
.addOnSuccessListener(success)
|
||||
.addOnFailureListener(failure);
|
||||
waitOnLatch(l);
|
||||
} else {
|
||||
log.info("{} is not a supported 3PID medium", medium);
|
||||
r[0] = null;
|
||||
}
|
||||
|
||||
return Optional.ofNullable(r[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<SingleLookupReply> find(SingleLookupRequest request) {
|
||||
Optional<UserRecord> urOpt = findInternal(request.getType(), request.getThreePid());
|
||||
return urOpt.map(userRecord -> new SingleLookupReply(request, getMxid(userRecord)));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ThreePidMapping> populate(List<ThreePidMapping> mappings) {
|
||||
List<ThreePidMapping> results = new ArrayList<>();
|
||||
mappings.parallelStream().forEach(o -> {
|
||||
Optional<UserRecord> urOpt = findInternal(o.getMedium(), o.getValue());
|
||||
if (urOpt.isPresent()) {
|
||||
ThreePidMapping result = new ThreePidMapping();
|
||||
result.setMedium(o.getMedium());
|
||||
result.setValue(o.getValue());
|
||||
result.setMxid(getMxid(urOpt.get()));
|
||||
results.add(result);
|
||||
}
|
||||
});
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
130
src/main/java/io/kamax/mxisd/backend/ldap/LdapAuthProvider.java
Normal file
130
src/main/java/io/kamax/mxisd/backend/ldap/LdapAuthProvider.java
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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.backend.ldap;
|
||||
|
||||
import io.kamax.matrix._MatrixID;
|
||||
import io.kamax.mxisd.UserIdType;
|
||||
import io.kamax.mxisd.auth.provider.AuthenticatorProvider;
|
||||
import io.kamax.mxisd.auth.provider.BackendAuthResult;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.directory.api.ldap.model.cursor.CursorException;
|
||||
import org.apache.directory.api.ldap.model.cursor.CursorLdapReferralException;
|
||||
import org.apache.directory.api.ldap.model.cursor.EntryCursor;
|
||||
import org.apache.directory.api.ldap.model.entry.Attribute;
|
||||
import org.apache.directory.api.ldap.model.entry.Entry;
|
||||
import org.apache.directory.api.ldap.model.exception.LdapException;
|
||||
import org.apache.directory.api.ldap.model.message.SearchScope;
|
||||
import org.apache.directory.ldap.client.api.LdapConnection;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
public class LdapAuthProvider extends LdapGenericBackend implements AuthenticatorProvider {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(LdapAuthProvider.class);
|
||||
|
||||
private String getUidAttribute() {
|
||||
return getCfg().getAttribute().getUid().getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return getCfg().isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BackendAuthResult authenticate(_MatrixID mxid, String password) {
|
||||
log.info("Performing auth for {}", mxid);
|
||||
|
||||
LdapConnection conn = getConn();
|
||||
try {
|
||||
bind(conn);
|
||||
|
||||
String uidType = getCfg().getAttribute().getUid().getType();
|
||||
String userFilterValue = StringUtils.equals(LdapThreePidProvider.UID, uidType) ? mxid.getLocalPart() : mxid.getId();
|
||||
if (StringUtils.isBlank(userFilterValue)) {
|
||||
log.warn("Username is empty, failing auth");
|
||||
return BackendAuthResult.failure();
|
||||
}
|
||||
|
||||
String userFilter = "(" + getCfg().getAttribute().getUid().getValue() + "=" + userFilterValue + ")";
|
||||
if (!StringUtils.isBlank(getCfg().getAuth().getFilter())) {
|
||||
userFilter = "(&" + getCfg().getAuth().getFilter() + userFilter + ")";
|
||||
}
|
||||
EntryCursor cursor = conn.search(getCfg().getConn().getBaseDn(), userFilter, SearchScope.SUBTREE, getUidAttribute(), getCfg().getAttribute().getName());
|
||||
try {
|
||||
while (cursor.next()) {
|
||||
Entry entry = cursor.get();
|
||||
String dn = entry.getDn().getName();
|
||||
log.info("Checking possible match, DN: {}", dn);
|
||||
|
||||
Attribute attribute = entry.get(getUidAttribute());
|
||||
if (attribute == null) {
|
||||
log.info("DN {}: no attribute {}, skpping", dn, getUidAttribute());
|
||||
continue;
|
||||
}
|
||||
|
||||
String data = attribute.get().toString();
|
||||
if (data.length() < 1) {
|
||||
log.info("DN {}: empty attribute {}, skipping", getUidAttribute());
|
||||
continue;
|
||||
}
|
||||
|
||||
log.info("Attempting authentication on LDAP for {}", dn);
|
||||
try {
|
||||
conn.bind(entry.getDn(), password);
|
||||
} catch (LdapException e) {
|
||||
log.info("Unable to bind using {} because {}", entry.getDn().getName(), e.getMessage());
|
||||
return BackendAuthResult.failure();
|
||||
}
|
||||
|
||||
Attribute nameAttribute = entry.get(getCfg().getAttribute().getName());
|
||||
String name = nameAttribute != null ? nameAttribute.get().toString() : null;
|
||||
|
||||
log.info("Authentication successful for {}", entry.getDn().getName());
|
||||
log.info("DN {} is a valid match", dn);
|
||||
|
||||
// TODO should we canonicalize the MXID?
|
||||
return BackendAuthResult.success(mxid.getId(), UserIdType.MatrixID, name);
|
||||
}
|
||||
} catch (CursorLdapReferralException e) {
|
||||
log.warn("Entity for {} is only available via referral, skipping", mxid);
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
log.info("No match were found for {}", mxid);
|
||||
return BackendAuthResult.failure();
|
||||
} catch (LdapException | IOException | CursorException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
try {
|
||||
conn.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -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.backend.ldap;
|
||||
|
||||
import io.kamax.mxisd.config.ldap.LdapConfig;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.directory.api.ldap.model.exception.LdapException;
|
||||
import org.apache.directory.ldap.client.api.LdapConnection;
|
||||
import org.apache.directory.ldap.client.api.LdapNetworkConnection;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class LdapGenericBackend {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(LdapGenericBackend.class);
|
||||
|
||||
@Autowired
|
||||
private LdapConfig ldapCfg;
|
||||
|
||||
protected LdapConnection getConn() {
|
||||
return new LdapNetworkConnection(ldapCfg.getConn().getHost(), ldapCfg.getConn().getPort(), ldapCfg.getConn().isTls());
|
||||
}
|
||||
|
||||
protected void bind(LdapConnection conn) throws LdapException {
|
||||
if (StringUtils.isBlank(ldapCfg.getConn().getBindDn()) && StringUtils.isBlank(ldapCfg.getConn().getBindPassword())) {
|
||||
conn.anonymousBind();
|
||||
} else {
|
||||
conn.bind(ldapCfg.getConn().getBindDn(), ldapCfg.getConn().getBindPassword());
|
||||
}
|
||||
}
|
||||
|
||||
protected LdapConfig getCfg() {
|
||||
return ldapCfg;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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.backend.ldap;
|
||||
|
||||
import io.kamax.mxisd.config.MatrixConfig;
|
||||
import io.kamax.mxisd.exception.InternalServerError;
|
||||
import io.kamax.mxisd.lookup.SingleLookupReply;
|
||||
import io.kamax.mxisd.lookup.SingleLookupRequest;
|
||||
import io.kamax.mxisd.lookup.ThreePidMapping;
|
||||
import io.kamax.mxisd.lookup.provider.IThreePidProvider;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.directory.api.ldap.model.cursor.CursorException;
|
||||
import org.apache.directory.api.ldap.model.cursor.CursorLdapReferralException;
|
||||
import org.apache.directory.api.ldap.model.cursor.EntryCursor;
|
||||
import org.apache.directory.api.ldap.model.entry.Attribute;
|
||||
import org.apache.directory.api.ldap.model.entry.Entry;
|
||||
import org.apache.directory.api.ldap.model.exception.LdapException;
|
||||
import org.apache.directory.api.ldap.model.message.SearchScope;
|
||||
import org.apache.directory.ldap.client.api.LdapConnection;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class LdapThreePidProvider extends LdapGenericBackend implements IThreePidProvider {
|
||||
|
||||
public static final String UID = "uid";
|
||||
public static final String MATRIX_ID = "mxid";
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(LdapThreePidProvider.class);
|
||||
|
||||
@Autowired
|
||||
private MatrixConfig mxCfg;
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return getCfg().isEnabled();
|
||||
}
|
||||
|
||||
private String getUidAttribute() {
|
||||
return getCfg().getAttribute().getUid().getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 20;
|
||||
}
|
||||
|
||||
private Optional<String> lookup(LdapConnection conn, String medium, String value) {
|
||||
String uidAttribute = getUidAttribute();
|
||||
|
||||
Optional<String> queryOpt = getCfg().getIdentity().getQuery(medium);
|
||||
if (!queryOpt.isPresent()) {
|
||||
log.warn("{} is not a configured 3PID type for LDAP lookup", medium);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
String searchQuery = queryOpt.get().replaceAll("%3pid", value);
|
||||
try (EntryCursor cursor = conn.search(getCfg().getConn().getBaseDn(), searchQuery, SearchScope.SUBTREE, uidAttribute)) {
|
||||
while (cursor.next()) {
|
||||
Entry entry = cursor.get();
|
||||
log.info("Found possible match, DN: {}", entry.getDn().getName());
|
||||
|
||||
Attribute attribute = entry.get(uidAttribute);
|
||||
if (attribute == null) {
|
||||
log.info("DN {}: no attribute {}, skpping", entry.getDn(), getCfg().getAttribute());
|
||||
continue;
|
||||
}
|
||||
|
||||
String data = attribute.get().toString();
|
||||
if (data.length() < 1) {
|
||||
log.info("DN {}: empty attribute {}, skipping", getCfg().getAttribute());
|
||||
continue;
|
||||
}
|
||||
|
||||
StringBuilder matrixId = new StringBuilder();
|
||||
// TODO Should we turn this block into a map of functions?
|
||||
String uidType = getCfg().getAttribute().getUid().getType();
|
||||
if (StringUtils.equals(UID, uidType)) {
|
||||
matrixId.append("@").append(data).append(":").append(mxCfg.getDomain());
|
||||
} else if (StringUtils.equals(MATRIX_ID, uidType)) {
|
||||
matrixId.append(data);
|
||||
} else {
|
||||
log.warn("Bind was found but type {} is not supported", uidType);
|
||||
continue;
|
||||
}
|
||||
|
||||
log.info("DN {} is a valid match", entry.getDn().getName());
|
||||
return Optional.of(matrixId.toString());
|
||||
}
|
||||
} catch (CursorLdapReferralException e) {
|
||||
log.warn("3PID {} is only available via referral, skipping", value);
|
||||
} catch (IOException | LdapException | CursorException e) {
|
||||
throw new InternalServerError(e);
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<SingleLookupReply> find(SingleLookupRequest request) {
|
||||
log.info("Performing LDAP lookup ${request.getThreePid()} of type ${request.getType()}");
|
||||
|
||||
try (LdapConnection conn = getConn()) {
|
||||
bind(conn);
|
||||
|
||||
Optional<String> mxid = lookup(conn, request.getType(), request.getThreePid());
|
||||
if (mxid.isPresent()) {
|
||||
return Optional.of(new SingleLookupReply(request, mxid.get()));
|
||||
}
|
||||
} catch (LdapException | IOException e) {
|
||||
throw new InternalServerError(e);
|
||||
}
|
||||
|
||||
log.info("No match found");
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ThreePidMapping> populate(List<ThreePidMapping> mappings) {
|
||||
log.info("Looking up {} mappings", mappings.size());
|
||||
List<ThreePidMapping> mappingsFound = new ArrayList<>();
|
||||
|
||||
try (LdapConnection conn = getConn()) {
|
||||
bind(conn);
|
||||
|
||||
for (ThreePidMapping mapping : mappings) {
|
||||
try {
|
||||
Optional<String> mxid = lookup(conn, mapping.getMedium(), mapping.getValue());
|
||||
if (mxid.isPresent()) {
|
||||
mapping.setMxid(mxid.get());
|
||||
mappingsFound.add(mapping);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.warn("{} is not a supported 3PID type for LDAP lookup", mapping.getMedium());
|
||||
}
|
||||
}
|
||||
} catch (LdapException | IOException e) {
|
||||
throw new InternalServerError(e);
|
||||
}
|
||||
|
||||
return mappingsFound;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.backend.rest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class LookupBulkResponseJson {
|
||||
|
||||
private List<LookupSingleResponseJson> lookup = new ArrayList<>();
|
||||
|
||||
public List<LookupSingleResponseJson> getLookup() {
|
||||
return lookup;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.backend.rest;
|
||||
|
||||
public class LookupSingleRequestJson {
|
||||
|
||||
private String medium;
|
||||
private String address;
|
||||
|
||||
public LookupSingleRequestJson(String medium, String address) {
|
||||
this.medium = medium;
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getMedium() {
|
||||
return medium;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.backend.rest;
|
||||
|
||||
import io.kamax.mxisd.UserID;
|
||||
|
||||
public class LookupSingleResponseJson {
|
||||
|
||||
private String medium;
|
||||
private String address;
|
||||
private UserID id;
|
||||
|
||||
public String getMedium() {
|
||||
return medium;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public UserID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.backend.rest;
|
||||
|
||||
import io.kamax.matrix._MatrixID;
|
||||
import io.kamax.mxisd.auth.provider.AuthenticatorProvider;
|
||||
import io.kamax.mxisd.auth.provider.BackendAuthResult;
|
||||
import io.kamax.mxisd.config.rest.RestBackendConfig;
|
||||
import io.kamax.mxisd.util.RestClientUtils;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
public class RestAuthProvider extends RestProvider implements AuthenticatorProvider {
|
||||
|
||||
@Autowired
|
||||
public RestAuthProvider(RestBackendConfig cfg) {
|
||||
super(cfg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return cfg.isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BackendAuthResult authenticate(_MatrixID mxid, String password) {
|
||||
RestAuthRequestJson auth = new RestAuthRequestJson();
|
||||
auth.setMxid(mxid.getId());
|
||||
auth.setLocalpart(mxid.getLocalPart());
|
||||
auth.setDomain(mxid.getDomain());
|
||||
auth.setPassword(password);
|
||||
|
||||
HttpUriRequest req = RestClientUtils.post(cfg.getEndpoints().getAuth(), gson, "auth", auth);
|
||||
try (CloseableHttpResponse res = client.execute(req)) {
|
||||
int status = res.getStatusLine().getStatusCode();
|
||||
if (status < 200 || status >= 300) {
|
||||
return BackendAuthResult.failure();
|
||||
}
|
||||
|
||||
return parser.parse(res, "auth", BackendAuthResult.class);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.backend.rest;
|
||||
|
||||
public class RestAuthRequestJson {
|
||||
|
||||
private String mxid;
|
||||
private String localpart;
|
||||
private String domain;
|
||||
private String password;
|
||||
|
||||
public String getMxid() {
|
||||
return mxid;
|
||||
}
|
||||
|
||||
public void setMxid(String mxid) {
|
||||
this.mxid = mxid;
|
||||
}
|
||||
|
||||
public String getLocalpart() {
|
||||
return localpart;
|
||||
}
|
||||
|
||||
public void setLocalpart(String localpart) {
|
||||
this.localpart = localpart;
|
||||
}
|
||||
|
||||
public String getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
public void setDomain(String domain) {
|
||||
this.domain = domain;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
}
|
46
src/main/java/io/kamax/mxisd/backend/rest/RestProvider.java
Normal file
46
src/main/java/io/kamax/mxisd/backend/rest/RestProvider.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.backend.rest;
|
||||
|
||||
import com.google.gson.FieldNamingPolicy;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import io.kamax.mxisd.config.rest.RestBackendConfig;
|
||||
import io.kamax.mxisd.util.GsonParser;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
|
||||
public class RestProvider {
|
||||
|
||||
protected RestBackendConfig cfg;
|
||||
protected Gson gson;
|
||||
protected GsonParser parser;
|
||||
protected CloseableHttpClient client;
|
||||
|
||||
public RestProvider(RestBackendConfig cfg) {
|
||||
this.cfg = cfg;
|
||||
|
||||
client = HttpClients.createDefault();
|
||||
gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
|
||||
parser = new GsonParser(gson);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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.backend.rest;
|
||||
|
||||
import io.kamax.matrix.MatrixID;
|
||||
import io.kamax.matrix._MatrixID;
|
||||
import io.kamax.mxisd.UserID;
|
||||
import io.kamax.mxisd.UserIdType;
|
||||
import io.kamax.mxisd.config.MatrixConfig;
|
||||
import io.kamax.mxisd.config.rest.RestBackendConfig;
|
||||
import io.kamax.mxisd.lookup.SingleLookupReply;
|
||||
import io.kamax.mxisd.lookup.SingleLookupRequest;
|
||||
import io.kamax.mxisd.lookup.ThreePidMapping;
|
||||
import io.kamax.mxisd.lookup.provider.IThreePidProvider;
|
||||
import io.kamax.mxisd.util.RestClientUtils;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class RestThreePidProvider extends RestProvider implements IThreePidProvider {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(RestThreePidProvider.class);
|
||||
|
||||
private MatrixConfig mxCfg; // FIXME should be done in the lookup manager
|
||||
|
||||
@Autowired
|
||||
public RestThreePidProvider(RestBackendConfig cfg, MatrixConfig mxCfg) {
|
||||
super(cfg);
|
||||
this.mxCfg = mxCfg;
|
||||
}
|
||||
|
||||
// TODO refactor in lookup manager with above FIXME
|
||||
private _MatrixID getMxId(UserID id) {
|
||||
if (UserIdType.Localpart.is(id.getType())) {
|
||||
return new MatrixID(id.getValue(), mxCfg.getDomain());
|
||||
} else {
|
||||
return new MatrixID(id.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return cfg.isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 20;
|
||||
}
|
||||
|
||||
// TODO refactor common code
|
||||
@Override
|
||||
public Optional<SingleLookupReply> find(SingleLookupRequest request) {
|
||||
String endpoint = cfg.getEndpoints().getIdentity().getSingle();
|
||||
HttpUriRequest req = RestClientUtils.post(endpoint, gson, "lookup",
|
||||
new LookupSingleRequestJson(request.getType(), request.getThreePid()));
|
||||
|
||||
try (CloseableHttpResponse res = client.execute(req)) {
|
||||
int status = res.getStatusLine().getStatusCode();
|
||||
if (status < 200 || status >= 300) {
|
||||
log.warn("REST endpoint {} answered with status {}, no binding found", endpoint, status);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Optional<LookupSingleResponseJson> responseOpt = parser.parseOptional(res, "lookup", LookupSingleResponseJson.class);
|
||||
return responseOpt.map(lookupSingleResponseJson -> new SingleLookupReply(request, getMxId(lookupSingleResponseJson.getId())));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO refactor common code
|
||||
@Override
|
||||
public List<ThreePidMapping> populate(List<ThreePidMapping> mappings) {
|
||||
List<LookupSingleRequestJson> ioListRequest = mappings.stream()
|
||||
.map(mapping -> new LookupSingleRequestJson(mapping.getMedium(), mapping.getValue()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
HttpUriRequest req = RestClientUtils.post(
|
||||
cfg.getEndpoints().getIdentity().getBulk(), gson, "lookup", ioListRequest);
|
||||
try (CloseableHttpResponse res = client.execute(req)) {
|
||||
mappings = new ArrayList<>();
|
||||
|
||||
int status = res.getStatusLine().getStatusCode();
|
||||
if (status < 200 || status >= 300) {
|
||||
return mappings;
|
||||
}
|
||||
|
||||
LookupBulkResponseJson listIo = parser.parse(res, LookupBulkResponseJson.class);
|
||||
return listIo.getLookup().stream()
|
||||
.map(io -> new ThreePidMapping(io.getMedium(), io.getAddress(), getMxId(io.getId()).getId()))
|
||||
.collect(Collectors.toList());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.backend.sql;
|
||||
|
||||
import io.kamax.matrix._MatrixID;
|
||||
import io.kamax.mxisd.auth.provider.AuthenticatorProvider;
|
||||
import io.kamax.mxisd.auth.provider.BackendAuthResult;
|
||||
import io.kamax.mxisd.config.ServerConfig;
|
||||
import io.kamax.mxisd.config.sql.SqlProviderConfig;
|
||||
import io.kamax.mxisd.invitation.InvitationManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class SqlAuthProvider implements AuthenticatorProvider {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(SqlAuthProvider.class);
|
||||
|
||||
@Autowired
|
||||
private ServerConfig srvCfg;
|
||||
|
||||
@Autowired
|
||||
private SqlProviderConfig cfg;
|
||||
|
||||
@Autowired
|
||||
private InvitationManager invMgr;
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return cfg.isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BackendAuthResult authenticate(_MatrixID mxid, String password) {
|
||||
log.info("Performing dummy authentication try to force invite mapping refresh");
|
||||
|
||||
invMgr.lookupMappingsForInvites();
|
||||
return BackendAuthResult.failure();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.backend.sql;
|
||||
|
||||
import io.kamax.matrix.MatrixID;
|
||||
import io.kamax.mxisd.config.MatrixConfig;
|
||||
import io.kamax.mxisd.config.sql.SqlProviderConfig;
|
||||
import io.kamax.mxisd.lookup.SingleLookupReply;
|
||||
import io.kamax.mxisd.lookup.SingleLookupRequest;
|
||||
import io.kamax.mxisd.lookup.ThreePidMapping;
|
||||
import io.kamax.mxisd.lookup.provider.IThreePidProvider;
|
||||
import org.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 java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class SqlThreePidProvider implements IThreePidProvider {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(SqlThreePidProvider.class);
|
||||
|
||||
@Autowired
|
||||
private MatrixConfig mxCfg;
|
||||
|
||||
@Autowired
|
||||
private SqlProviderConfig cfg;
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return cfg.isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 20;
|
||||
}
|
||||
|
||||
private Connection getConn() throws SQLException {
|
||||
return DriverManager.getConnection("jdbc:" + cfg.getType() + ":" + cfg.getConnection());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<SingleLookupReply> find(SingleLookupRequest request) {
|
||||
log.info("SQL lookup");
|
||||
String stmtSql = StringUtils.defaultIfBlank(cfg.getIdentity().getMedium().get(request.getType()), cfg.getIdentity().getQuery());
|
||||
log.info("SQL query: {}", stmtSql);
|
||||
try (PreparedStatement stmt = getConn().prepareStatement(stmtSql)) {
|
||||
stmt.setString(1, request.getType().toLowerCase());
|
||||
stmt.setString(2, request.getThreePid().toLowerCase());
|
||||
|
||||
ResultSet rSet = stmt.executeQuery();
|
||||
while (rSet.next()) {
|
||||
String uid = rSet.getString("uid");
|
||||
log.info("Found match: {}", uid);
|
||||
if (StringUtils.equals("uid", cfg.getIdentity().getType())) {
|
||||
log.info("Resolving as localpart");
|
||||
return Optional.of(new SingleLookupReply(request, new MatrixID(uid, mxCfg.getDomain())));
|
||||
}
|
||||
if (StringUtils.equals("mxid", cfg.getIdentity().getType())) {
|
||||
log.info("Resolving as MXID");
|
||||
return Optional.of(new SingleLookupReply(request, new MatrixID(uid)));
|
||||
}
|
||||
|
||||
log.info("Identity type is unknown, skipping");
|
||||
}
|
||||
|
||||
log.info("No match found in SQL");
|
||||
return Optional.empty();
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ThreePidMapping> populate(List<ThreePidMapping> mappings) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
}
|
52
src/main/java/io/kamax/mxisd/config/DnsOverwrite.java
Normal file
52
src/main/java/io/kamax/mxisd/config/DnsOverwrite.java
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties("dns.overwrite")
|
||||
public class DnsOverwrite {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(DnsOverwrite.class);
|
||||
|
||||
@Autowired
|
||||
private ServerConfig srvCfg;
|
||||
|
||||
@Autowired
|
||||
private DnsOverwriteEntry homeserver;
|
||||
|
||||
public Optional<DnsOverwriteEntry> findHost(String lookup) {
|
||||
if (homeserver != null && StringUtils.equalsIgnoreCase(lookup, homeserver.getName())) {
|
||||
return Optional.of(homeserver);
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
67
src/main/java/io/kamax/mxisd/config/DnsOverwriteEntry.java
Normal file
67
src/main/java/io/kamax/mxisd/config/DnsOverwriteEntry.java
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties("dns.overwrite.homeserver")
|
||||
public class DnsOverwriteEntry {
|
||||
|
||||
private String name;
|
||||
private String type;
|
||||
private String value;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getTarget() {
|
||||
if (StringUtils.equals("env", getType())) {
|
||||
return System.getenv(getValue());
|
||||
} else {
|
||||
return getValue();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
101
src/main/java/io/kamax/mxisd/config/FirebaseConfig.java
Normal file
101
src/main/java/io/kamax/mxisd/config/FirebaseConfig.java
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import io.kamax.mxisd.auth.provider.AuthenticatorProvider;
|
||||
import io.kamax.mxisd.backend.firebase.GoogleFirebaseAuthenticator;
|
||||
import io.kamax.mxisd.backend.firebase.GoogleFirebaseProvider;
|
||||
import io.kamax.mxisd.lookup.provider.IThreePidProvider;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties("firebase")
|
||||
public class FirebaseConfig {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(FirebaseConfig.class);
|
||||
|
||||
@Autowired
|
||||
private MatrixConfig mxCfg;
|
||||
|
||||
private boolean enabled;
|
||||
private String credentials;
|
||||
private String database;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public String getCredentials() {
|
||||
return credentials;
|
||||
}
|
||||
|
||||
public void setCredentials(String credentials) {
|
||||
this.credentials = credentials;
|
||||
}
|
||||
|
||||
public String getDatabase() {
|
||||
return database;
|
||||
}
|
||||
|
||||
public void setDatabase(String database) {
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void postConstruct() {
|
||||
log.info("--- Firebase configuration ---");
|
||||
log.info("Enabled: {}", isEnabled());
|
||||
if (isEnabled()) {
|
||||
log.info("Credentials: {}", getCredentials());
|
||||
log.info("Database: {}", getDatabase());
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticatorProvider getAuthProvider() {
|
||||
if (!enabled) {
|
||||
return new GoogleFirebaseAuthenticator(false);
|
||||
} else {
|
||||
return new GoogleFirebaseAuthenticator(credentials, database);
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IThreePidProvider getLookupProvider() {
|
||||
if (!enabled) {
|
||||
return new GoogleFirebaseProvider(false);
|
||||
} else {
|
||||
return new GoogleFirebaseProvider(credentials, database, mxCfg.getDomain());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
43
src/main/java/io/kamax/mxisd/config/ForwardConfig.java
Normal file
43
src/main/java/io/kamax/mxisd/config/ForwardConfig.java
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "forward")
|
||||
public class ForwardConfig {
|
||||
|
||||
private List<String> servers = new ArrayList<>();
|
||||
|
||||
public List<String> getServers() {
|
||||
return servers;
|
||||
}
|
||||
|
||||
public void setServers(List<String> servers) {
|
||||
this.servers = servers;
|
||||
}
|
||||
|
||||
}
|
51
src/main/java/io/kamax/mxisd/config/KeyConfig.java
Normal file
51
src/main/java/io/kamax/mxisd/config/KeyConfig.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import io.kamax.mxisd.exception.ConfigurationException;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "key")
|
||||
public class KeyConfig {
|
||||
|
||||
private String path;
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void build() {
|
||||
if (StringUtils.isBlank(getPath())) {
|
||||
throw new ConfigurationException("key.path");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
94
src/main/java/io/kamax/mxisd/config/MatrixConfig.java
Normal file
94
src/main/java/io/kamax/mxisd/config/MatrixConfig.java
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import io.kamax.mxisd.exception.ConfigurationException;
|
||||
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;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties("matrix")
|
||||
public class MatrixConfig {
|
||||
|
||||
public static class Identity {
|
||||
private Map<String, List<String>> servers = new HashMap<>();
|
||||
|
||||
public Map<String, List<String>> getServers() {
|
||||
return servers;
|
||||
}
|
||||
|
||||
public void setServers(Map<String, List<String>> servers) {
|
||||
this.servers = servers;
|
||||
}
|
||||
|
||||
public List<String> getServers(String label) {
|
||||
if (!servers.containsKey(label)) {
|
||||
throw new RuntimeException("No Identity server list with label '" + label + "'");
|
||||
}
|
||||
|
||||
return servers.get(label);
|
||||
}
|
||||
}
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(MatrixConfig.class);
|
||||
|
||||
private String domain;
|
||||
private Identity identity = new Identity();
|
||||
|
||||
public String getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
public void setDomain(String domain) {
|
||||
this.domain = domain;
|
||||
}
|
||||
|
||||
public Identity getIdentity() {
|
||||
return identity;
|
||||
}
|
||||
|
||||
public void setIdentity(Identity identity) {
|
||||
this.identity = identity;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void build() {
|
||||
log.info("--- Matrix config ---");
|
||||
|
||||
if (StringUtils.isBlank(domain)) {
|
||||
throw new ConfigurationException("matrix.domain");
|
||||
}
|
||||
|
||||
log.info("Domain: {}", getDomain());
|
||||
log.info("Identity:");
|
||||
log.info("\tServers: {}", new Gson().toJson(identity.getServers()));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
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(prefix = "lookup.recursive.bridge")
|
||||
public class RecursiveLookupBridgeConfig {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(RecursiveLookupBridgeConfig.class);
|
||||
|
||||
private boolean enabled;
|
||||
private boolean recursiveOnly;
|
||||
private String server;
|
||||
private Map<String, String> mappings = new HashMap<>();
|
||||
|
||||
public boolean getEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public boolean getRecursiveOnly() {
|
||||
return recursiveOnly;
|
||||
}
|
||||
|
||||
public void setRecursiveOnly(boolean recursiveOnly) {
|
||||
this.recursiveOnly = recursiveOnly;
|
||||
}
|
||||
|
||||
public String getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
public void setServer(String server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public Map<String, String> getMappings() {
|
||||
return mappings;
|
||||
}
|
||||
|
||||
public void setMappings(Map<String, String> mappings) {
|
||||
this.mappings = mappings;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void build() {
|
||||
log.info("--- Bridge integration lookups config ---");
|
||||
log.info("Enabled: {}", getEnabled());
|
||||
if (getEnabled()) {
|
||||
log.info("Recursive only: {}", getRecursiveOnly());
|
||||
log.info("Fallback Server: {}", getServer());
|
||||
log.info("Mappings: {}", mappings.size());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "lookup.recursive")
|
||||
public class RecursiveLookupConfig {
|
||||
|
||||
private boolean enabled;
|
||||
private List<String> allowedCidr;
|
||||
private RecursiveLookupBridgeConfig bridge;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public List<String> getAllowedCidr() {
|
||||
return allowedCidr;
|
||||
}
|
||||
|
||||
public void setAllowedCidr(List<String> allowedCidr) {
|
||||
this.allowedCidr = allowedCidr;
|
||||
}
|
||||
|
||||
public RecursiveLookupBridgeConfig getBridge() {
|
||||
return bridge;
|
||||
}
|
||||
|
||||
public void setBridge(RecursiveLookupBridgeConfig bridge) {
|
||||
this.bridge = bridge;
|
||||
}
|
||||
|
||||
}
|
40
src/main/java/io/kamax/mxisd/config/SQLiteStorageConfig.java
Normal file
40
src/main/java/io/kamax/mxisd/config/SQLiteStorageConfig.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties("storage.provider.sqlite")
|
||||
public class SQLiteStorageConfig {
|
||||
|
||||
private String database;
|
||||
|
||||
public String getDatabase() {
|
||||
return database;
|
||||
}
|
||||
|
||||
public void setDatabase(String database) {
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
}
|
98
src/main/java/io/kamax/mxisd/config/ServerConfig.java
Normal file
98
src/main/java/io/kamax/mxisd/config/ServerConfig.java
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "server")
|
||||
public class ServerConfig {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(ServerConfig.class);
|
||||
|
||||
@Autowired
|
||||
private MatrixConfig mxCfg;
|
||||
|
||||
private String name;
|
||||
private int port;
|
||||
private String publicUrl;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getPublicUrl() {
|
||||
return publicUrl;
|
||||
}
|
||||
|
||||
public void setPublicUrl(String publicUrl) {
|
||||
this.publicUrl = publicUrl;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void build() {
|
||||
log.info("--- Server config ---");
|
||||
|
||||
if (StringUtils.isBlank(getName())) {
|
||||
setName(mxCfg.getDomain());
|
||||
log.debug("server.name is empty, using matrix.domain");
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(getPublicUrl())) {
|
||||
setPublicUrl("https://" + getName());
|
||||
log.debug("Public URL is empty, generating from name");
|
||||
} else {
|
||||
setPublicUrl(StringUtils.replace(getPublicUrl(), "%SERVER_NAME%", getName()));
|
||||
}
|
||||
|
||||
try {
|
||||
new URL(getPublicUrl());
|
||||
} catch (MalformedURLException e) {
|
||||
log.warn("Public URL is not valid: {}", StringUtils.defaultIfBlank(e.getMessage(), "<no reason provided>"));
|
||||
}
|
||||
|
||||
log.info("Name: {}", getName());
|
||||
log.info("Port: {}", getPort());
|
||||
log.info("Public URL: {}", getPublicUrl());
|
||||
}
|
||||
|
||||
}
|
173
src/main/java/io/kamax/mxisd/config/SessionConfig.java
Normal file
173
src/main/java/io/kamax/mxisd/config/SessionConfig.java
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties("session")
|
||||
public class SessionConfig {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(SessionConfig.class);
|
||||
|
||||
public static class Policy {
|
||||
|
||||
public static class PolicyTemplate {
|
||||
|
||||
public static class PolicySource {
|
||||
|
||||
public static class PolicySourceRemote {
|
||||
|
||||
private boolean enabled;
|
||||
private String server;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public String getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
public void setServer(String server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean enabled;
|
||||
private boolean toLocal;
|
||||
private PolicySourceRemote toRemote = new PolicySourceRemote();
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public boolean toLocal() {
|
||||
return toLocal;
|
||||
}
|
||||
|
||||
public void setToLocal(boolean toLocal) {
|
||||
this.toLocal = toLocal;
|
||||
}
|
||||
|
||||
public boolean toRemote() {
|
||||
return toRemote.isEnabled();
|
||||
}
|
||||
|
||||
public PolicySourceRemote getToRemote() {
|
||||
return toRemote;
|
||||
}
|
||||
|
||||
public void setToRemote(PolicySourceRemote toRemote) {
|
||||
this.toRemote = toRemote;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean enabled;
|
||||
private PolicySource forLocal = new PolicySource();
|
||||
private PolicySource forRemote = new PolicySource();
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public PolicySource getForLocal() {
|
||||
return forLocal;
|
||||
}
|
||||
|
||||
public PolicySource forLocal() {
|
||||
return forLocal;
|
||||
}
|
||||
|
||||
public PolicySource getForRemote() {
|
||||
return forRemote;
|
||||
}
|
||||
|
||||
public PolicySource forRemote() {
|
||||
return forRemote;
|
||||
}
|
||||
|
||||
public PolicySource forIf(boolean isLocal) {
|
||||
return isLocal ? forLocal : forRemote;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private PolicyTemplate validation = new PolicyTemplate();
|
||||
|
||||
public PolicyTemplate getValidation() {
|
||||
return validation;
|
||||
}
|
||||
|
||||
public void setValidation(PolicyTemplate validation) {
|
||||
this.validation = validation;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private MatrixConfig mxCfg;
|
||||
private Policy policy = new Policy();
|
||||
|
||||
@Autowired
|
||||
public SessionConfig(MatrixConfig mxCfg) {
|
||||
this.mxCfg = mxCfg;
|
||||
}
|
||||
|
||||
public MatrixConfig getMatrixCfg() {
|
||||
return mxCfg;
|
||||
}
|
||||
|
||||
public Policy getPolicy() {
|
||||
return policy;
|
||||
}
|
||||
|
||||
public void setPolicy(Policy policy) {
|
||||
this.policy = policy;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void build() {
|
||||
log.info("--- Session config ---");
|
||||
log.info("Global Policy: {}", new Gson().toJson(policy));
|
||||
}
|
||||
|
||||
}
|
51
src/main/java/io/kamax/mxisd/config/StorageConfig.java
Normal file
51
src/main/java/io/kamax/mxisd/config/StorageConfig.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import io.kamax.mxisd.exception.ConfigurationException;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties("storage")
|
||||
public class StorageConfig {
|
||||
|
||||
private String backend;
|
||||
|
||||
public String getBackend() {
|
||||
return backend;
|
||||
}
|
||||
|
||||
public void setBackend(String backend) {
|
||||
this.backend = backend;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void postConstruct() {
|
||||
if (StringUtils.isBlank(getBackend())) {
|
||||
throw new ConfigurationException("storage.backend");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
42
src/main/java/io/kamax/mxisd/config/ThymeleafConfig.java
Normal file
42
src/main/java/io/kamax/mxisd/config/ThymeleafConfig.java
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.thymeleaf.resourceresolver.FileResourceResolver;
|
||||
import org.thymeleaf.templateresolver.TemplateResolver;
|
||||
|
||||
@Configuration
|
||||
public class ThymeleafConfig {
|
||||
|
||||
@Bean
|
||||
public TemplateResolver getFileSystemResolver() {
|
||||
TemplateResolver resolver = new TemplateResolver();
|
||||
resolver.setPrefix("");
|
||||
resolver.setSuffix("");
|
||||
resolver.setCacheable(false);
|
||||
resolver.setOrder(1);
|
||||
resolver.setResourceResolver(new FileResourceResolver());
|
||||
return resolver;
|
||||
}
|
||||
|
||||
}
|
144
src/main/java/io/kamax/mxisd/config/ViewConfig.java
Normal file
144
src/main/java/io/kamax/mxisd/config/ViewConfig.java
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
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("view")
|
||||
public class ViewConfig {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(ViewConfig.class);
|
||||
|
||||
public static class Session {
|
||||
|
||||
public static class Paths {
|
||||
|
||||
private String failure;
|
||||
private String success;
|
||||
|
||||
public String getFailure() {
|
||||
return failure;
|
||||
}
|
||||
|
||||
public void setFailure(String failure) {
|
||||
this.failure = failure;
|
||||
}
|
||||
|
||||
public String getSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public void setSuccess(String success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Local {
|
||||
|
||||
private Paths onTokenSubmit = new Paths();
|
||||
|
||||
public Paths getOnTokenSubmit() {
|
||||
return onTokenSubmit;
|
||||
}
|
||||
|
||||
public void setOnTokenSubmit(Paths onTokenSubmit) {
|
||||
this.onTokenSubmit = onTokenSubmit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Remote {
|
||||
|
||||
private Paths onRequest = new Paths();
|
||||
private Paths onCheck = new Paths();
|
||||
|
||||
public Paths getOnRequest() {
|
||||
return onRequest;
|
||||
}
|
||||
|
||||
public void setOnRequest(Paths onRequest) {
|
||||
this.onRequest = onRequest;
|
||||
}
|
||||
|
||||
public Paths getOnCheck() {
|
||||
return onCheck;
|
||||
}
|
||||
|
||||
public void setOnCheck(Paths onCheck) {
|
||||
this.onCheck = onCheck;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Local local = new Local();
|
||||
private Local localRemote = new Local();
|
||||
private Remote remote = new Remote();
|
||||
|
||||
public Local getLocal() {
|
||||
return local;
|
||||
}
|
||||
|
||||
public void setLocal(Local local) {
|
||||
this.local = local;
|
||||
}
|
||||
|
||||
public Local getLocalRemote() {
|
||||
return localRemote;
|
||||
}
|
||||
|
||||
public void setLocalRemote(Local localRemote) {
|
||||
this.localRemote = localRemote;
|
||||
}
|
||||
|
||||
public Remote getRemote() {
|
||||
return remote;
|
||||
}
|
||||
|
||||
public void setRemote(Remote remote) {
|
||||
this.remote = remote;
|
||||
}
|
||||
}
|
||||
|
||||
private Session session = new Session();
|
||||
|
||||
public Session getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
public void setSession(Session session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void build() {
|
||||
log.info("--- View config ---");
|
||||
log.info("Session: {}", new Gson().toJson(session));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.ldap;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "ldap.attribute")
|
||||
public class LdapAttributeConfig {
|
||||
|
||||
private LdapAttributeUidConfig uid;
|
||||
private String name;
|
||||
|
||||
public LdapAttributeUidConfig getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(LdapAttributeUidConfig uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.ldap;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "ldap.attribute.uid")
|
||||
public class LdapAttributeUidConfig {
|
||||
|
||||
private String type;
|
||||
private String value;
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
40
src/main/java/io/kamax/mxisd/config/ldap/LdapAuthConfig.java
Normal file
40
src/main/java/io/kamax/mxisd/config/ldap/LdapAuthConfig.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.ldap;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "ldap.auth")
|
||||
public class LdapAuthConfig {
|
||||
|
||||
private String filter;
|
||||
|
||||
public String getFilter() {
|
||||
return filter;
|
||||
}
|
||||
|
||||
public void setFilter(String filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
}
|
131
src/main/java/io/kamax/mxisd/config/ldap/LdapConfig.java
Normal file
131
src/main/java/io/kamax/mxisd/config/ldap/LdapConfig.java
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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.ldap;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import io.kamax.mxisd.backend.ldap.LdapThreePidProvider;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "ldap")
|
||||
public class LdapConfig {
|
||||
|
||||
private static Gson gson = new Gson();
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(LdapConfig.class);
|
||||
|
||||
private boolean enabled;
|
||||
|
||||
@Autowired
|
||||
private LdapConnectionConfig conn;
|
||||
private LdapAttributeConfig attribute;
|
||||
private LdapAuthConfig auth;
|
||||
private LdapIdentityConfig identity;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public LdapConnectionConfig getConn() {
|
||||
return conn;
|
||||
}
|
||||
|
||||
public void setConn(LdapConnectionConfig conn) {
|
||||
this.conn = conn;
|
||||
}
|
||||
|
||||
public LdapAttributeConfig getAttribute() {
|
||||
return attribute;
|
||||
}
|
||||
|
||||
public void setAttribute(LdapAttributeConfig attribute) {
|
||||
this.attribute = attribute;
|
||||
}
|
||||
|
||||
public LdapAuthConfig getAuth() {
|
||||
return auth;
|
||||
}
|
||||
|
||||
public void setAuth(LdapAuthConfig auth) {
|
||||
this.auth = auth;
|
||||
}
|
||||
|
||||
public LdapIdentityConfig getIdentity() {
|
||||
return identity;
|
||||
}
|
||||
|
||||
public void setIdentity(LdapIdentityConfig identity) {
|
||||
this.identity = identity;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void build() {
|
||||
log.info("--- LDAP Config ---");
|
||||
log.info("Enabled: {}", isEnabled());
|
||||
|
||||
if (!isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(conn.getHost())) {
|
||||
throw new IllegalStateException("LDAP Host must be configured!");
|
||||
}
|
||||
|
||||
if (1 > conn.getPort() || 65535 < conn.getPort()) {
|
||||
throw new IllegalStateException("LDAP port is not valid");
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(attribute.getUid().getType())) {
|
||||
throw new IllegalStateException("Attribute UID Type cannot be empty");
|
||||
}
|
||||
|
||||
|
||||
if (StringUtils.isBlank(attribute.getUid().getValue())) {
|
||||
throw new IllegalStateException("Attribute UID value cannot be empty");
|
||||
}
|
||||
|
||||
String uidType = attribute.getUid().getType();
|
||||
if (!StringUtils.equals(LdapThreePidProvider.UID, uidType) && !StringUtils.equals(LdapThreePidProvider.MATRIX_ID, uidType)) {
|
||||
throw new IllegalArgumentException("Unsupported LDAP UID type: " + uidType);
|
||||
}
|
||||
|
||||
log.info("Host: {}", conn.getHost());
|
||||
log.info("Port: {}", conn.getPort());
|
||||
log.info("Bind DN: {}", conn.getBindDn());
|
||||
log.info("Base DN: {}", conn.getBaseDn());
|
||||
|
||||
log.info("Attribute: {}", gson.toJson(attribute));
|
||||
log.info("Auth: {}", gson.toJson(auth));
|
||||
log.info("Identity: {}", gson.toJson(identity));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.ldap;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "ldap.connection")
|
||||
public class LdapConnectionConfig {
|
||||
|
||||
private boolean tls;
|
||||
private String host;
|
||||
private int port;
|
||||
private String bindDn;
|
||||
private String bindPassword;
|
||||
private String baseDn;
|
||||
|
||||
public boolean isTls() {
|
||||
return tls;
|
||||
}
|
||||
|
||||
public void setTls(boolean tls) {
|
||||
this.tls = tls;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getBindDn() {
|
||||
return bindDn;
|
||||
}
|
||||
|
||||
public void setBindDn(String bindDn) {
|
||||
this.bindDn = bindDn;
|
||||
}
|
||||
|
||||
public String getBindPassword() {
|
||||
return bindPassword;
|
||||
}
|
||||
|
||||
public void setBindPassword(String bindPassword) {
|
||||
this.bindPassword = bindPassword;
|
||||
}
|
||||
|
||||
public String getBaseDn() {
|
||||
return baseDn;
|
||||
}
|
||||
|
||||
public void setBaseDn(String baseDn) {
|
||||
this.baseDn = baseDn;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.ldap;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "ldap.identity")
|
||||
public class LdapIdentityConfig {
|
||||
|
||||
private Map<String, String> medium = new HashMap<>();
|
||||
|
||||
public Map<String, String> getMedium() {
|
||||
return medium;
|
||||
}
|
||||
|
||||
public Optional<String> getQuery(String key) {
|
||||
return Optional.ofNullable(medium.get(key));
|
||||
}
|
||||
|
||||
public void setMedium(Map<String, String> medium) {
|
||||
this.medium = medium;
|
||||
}
|
||||
|
||||
}
|
149
src/main/java/io/kamax/mxisd/config/rest/RestBackendConfig.java
Normal file
149
src/main/java/io/kamax/mxisd/config/rest/RestBackendConfig.java
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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.rest;
|
||||
|
||||
import io.kamax.mxisd.exception.ConfigurationException;
|
||||
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;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties("rest")
|
||||
public class RestBackendConfig {
|
||||
|
||||
public static class IdentityEndpoints {
|
||||
|
||||
private String single;
|
||||
private String bulk;
|
||||
|
||||
public String getSingle() {
|
||||
return single;
|
||||
}
|
||||
|
||||
public void setSingle(String single) {
|
||||
this.single = single;
|
||||
}
|
||||
|
||||
public String getBulk() {
|
||||
return bulk;
|
||||
}
|
||||
|
||||
public void setBulk(String bulk) {
|
||||
this.bulk = bulk;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Endpoints {
|
||||
|
||||
private IdentityEndpoints identity = new IdentityEndpoints();
|
||||
private String auth;
|
||||
|
||||
public IdentityEndpoints getIdentity() {
|
||||
return identity;
|
||||
}
|
||||
|
||||
public void setIdentity(IdentityEndpoints identity) {
|
||||
this.identity = identity;
|
||||
}
|
||||
|
||||
public String getAuth() {
|
||||
return auth;
|
||||
}
|
||||
|
||||
public void setAuth(String auth) {
|
||||
this.auth = auth;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(RestBackendConfig.class);
|
||||
|
||||
private boolean enabled;
|
||||
private String host;
|
||||
private Endpoints endpoints = new Endpoints();
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public Endpoints getEndpoints() {
|
||||
return endpoints;
|
||||
}
|
||||
|
||||
public void setEndpoints(Endpoints endpoints) {
|
||||
this.endpoints = endpoints;
|
||||
}
|
||||
|
||||
private String buildEndpointUrl(String endpoint) {
|
||||
if (StringUtils.startsWith(endpoint, "/")) {
|
||||
if (StringUtils.isBlank(getHost())) {
|
||||
throw new ConfigurationException("rest.host");
|
||||
}
|
||||
|
||||
try {
|
||||
new URL(getHost());
|
||||
} catch (MalformedURLException e) {
|
||||
throw new ConfigurationException("rest.host", e.getMessage());
|
||||
}
|
||||
|
||||
return getHost() + endpoint;
|
||||
} else {
|
||||
return endpoint;
|
||||
}
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void build() {
|
||||
log.info("--- REST backend config ---");
|
||||
log.info("Enabled: {}", isEnabled());
|
||||
|
||||
if (isEnabled()) {
|
||||
endpoints.setAuth(buildEndpointUrl(endpoints.getAuth()));
|
||||
endpoints.identity.setSingle(buildEndpointUrl(endpoints.identity.getSingle()));
|
||||
endpoints.identity.setBulk(buildEndpointUrl(endpoints.identity.getBulk()));
|
||||
|
||||
log.info("Host: {}", getHost());
|
||||
log.info("Auth endpoint: {}", endpoints.getAuth());
|
||||
log.info("Identity Single endpoint: {}", endpoints.identity.getSingle());
|
||||
log.info("Identity Bulk endpoint: {}", endpoints.identity.getBulk());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package io.kamax.mxisd.config.sql;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
// Unused
|
||||
@Configuration
|
||||
@ConfigurationProperties("sql.auth")
|
||||
public class SqlProviderAuthConfig {
|
||||
|
||||
private boolean enabled;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.sql;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
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("sql")
|
||||
public class SqlProviderConfig {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(SqlProviderConfig.class);
|
||||
|
||||
private boolean enabled;
|
||||
private String type;
|
||||
private String connection;
|
||||
private SqlProviderAuthConfig auth;
|
||||
private SqlProviderIdentityConfig identity;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getConnection() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
public void setConnection(String connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
public SqlProviderAuthConfig getAuth() {
|
||||
return auth;
|
||||
}
|
||||
|
||||
public void setAuth(SqlProviderAuthConfig auth) {
|
||||
this.auth = auth;
|
||||
}
|
||||
|
||||
public SqlProviderIdentityConfig getIdentity() {
|
||||
return identity;
|
||||
}
|
||||
|
||||
public void setIdentity(SqlProviderIdentityConfig identity) {
|
||||
this.identity = identity;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void postConstruct() {
|
||||
log.info("--- SQL Provider config ---");
|
||||
log.info("Enabled: {}", isEnabled());
|
||||
if (isEnabled()) {
|
||||
log.info("Type: {}", getType());
|
||||
log.info("Connection: {}", getConnection());
|
||||
log.info("Auth enabled: {}", getAuth().isEnabled());
|
||||
log.info("Identy type: {}", getIdentity().getType());
|
||||
log.info("Identity medium queries: {}", new Gson().toJson(getIdentity().getMedium()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.sql;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties("sql.identity")
|
||||
public class SqlProviderIdentityConfig {
|
||||
|
||||
private String type;
|
||||
private String query;
|
||||
private Map<String, String> medium = new HashMap<>();
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public void setQuery(String query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public Map<String, String> getMedium() {
|
||||
return medium;
|
||||
}
|
||||
|
||||
public void setMedium(Map<String, String> medium) {
|
||||
this.medium = medium;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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 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(prefix = "threepid.medium.email.connectors.smtp")
|
||||
public class EmailSmtpConfig {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(EmailSmtpConfig.class);
|
||||
|
||||
private String host;
|
||||
private int port;
|
||||
private int tls;
|
||||
private String login;
|
||||
private String password;
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public int getTls() {
|
||||
return tls;
|
||||
}
|
||||
|
||||
public void setTls(int tls) {
|
||||
this.tls = tls;
|
||||
}
|
||||
|
||||
public String getLogin() {
|
||||
return login;
|
||||
}
|
||||
|
||||
public void setLogin(String login) {
|
||||
this.login = login;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void build() {
|
||||
log.info("--- E-mail SMTP Connector config ---");
|
||||
log.info("Host: {}", getHost());
|
||||
log.info("Port: {}", getPort());
|
||||
log.info("TLS Mode: {}", getTls());
|
||||
log.info("Login: {}", getLogin());
|
||||
log.info("Has password: {}", StringUtils.isNotBlank(getPassword()));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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.medium;
|
||||
|
||||
import io.kamax.mxisd.config.MatrixConfig;
|
||||
import io.kamax.mxisd.exception.ConfigurationException;
|
||||
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.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties("threepid.medium.email")
|
||||
public class EmailConfig {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String generator;
|
||||
private String connector;
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(EmailConfig.class);
|
||||
|
||||
private MatrixConfig mxCfg;
|
||||
private Identity identity = new Identity();
|
||||
|
||||
@Autowired
|
||||
public EmailConfig(MatrixConfig mxCfg) {
|
||||
this.mxCfg = mxCfg;
|
||||
}
|
||||
|
||||
public Identity getIdentity() {
|
||||
return identity;
|
||||
}
|
||||
|
||||
public String getGenerator() {
|
||||
return generator;
|
||||
}
|
||||
|
||||
public void setGenerator(String generator) {
|
||||
this.generator = generator;
|
||||
}
|
||||
|
||||
public String getConnector() {
|
||||
return connector;
|
||||
}
|
||||
|
||||
public void setConnector(String connector) {
|
||||
this.connector = connector;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void build() {
|
||||
log.info("--- E-mail config ---");
|
||||
|
||||
if (StringUtils.isBlank(getGenerator())) {
|
||||
throw new ConfigurationException("generator");
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(getConnector())) {
|
||||
throw new ConfigurationException("connector");
|
||||
}
|
||||
|
||||
log.info("From: {}", identity.getFrom());
|
||||
|
||||
if (StringUtils.isBlank(identity.getName())) {
|
||||
identity.setName(WordUtils.capitalize(mxCfg.getDomain()) + " Identity Server");
|
||||
}
|
||||
log.info("Name: {}", identity.getName());
|
||||
log.info("Generator: {}", getGenerator());
|
||||
log.info("Connector: {}", getConnector());
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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.medium;
|
||||
|
||||
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("threepid.medium.email.generators.template")
|
||||
public class EmailTemplateConfig {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(EmailTemplateConfig.class);
|
||||
private static final String classpathPrefix = "classpath:";
|
||||
|
||||
private static String getName(String path) {
|
||||
if (StringUtils.startsWith(path, classpathPrefix)) {
|
||||
return "Built-in (" + path.substring(classpathPrefix.length()) + ")";
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public static class Session {
|
||||
|
||||
public static class SessionValidation {
|
||||
|
||||
private String local;
|
||||
private String remote;
|
||||
|
||||
public String getLocal() {
|
||||
return local;
|
||||
}
|
||||
|
||||
public void setLocal(String local) {
|
||||
this.local = local;
|
||||
}
|
||||
|
||||
public String getRemote() {
|
||||
return remote;
|
||||
}
|
||||
|
||||
public void setRemote(String remote) {
|
||||
this.remote = remote;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private SessionValidation validation;
|
||||
|
||||
public SessionValidation getValidation() {
|
||||
return validation;
|
||||
}
|
||||
|
||||
public void setValidation(SessionValidation validation) {
|
||||
this.validation = validation;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String invite;
|
||||
private Session session = new Session();
|
||||
|
||||
public String getInvite() {
|
||||
return invite;
|
||||
}
|
||||
|
||||
public void setInvite(String invite) {
|
||||
this.invite = invite;
|
||||
}
|
||||
|
||||
public Session getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void build() {
|
||||
log.info("--- E-mail Generator templates config ---");
|
||||
log.info("Invite: {}", getName(getInvite()));
|
||||
log.info("Session validation:");
|
||||
log.info("\tLocal: {}", getName(getSession().getValidation().getLocal()));
|
||||
log.info("\tRemote: {}", getName(getSession().getValidation().getRemote()));
|
||||
}
|
||||
|
||||
}
|
@@ -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.controller.v1;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import io.kamax.mxisd.auth.AuthManager;
|
||||
import io.kamax.mxisd.auth.UserAuthResult;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
@RestController
|
||||
@CrossOrigin
|
||||
@RequestMapping(produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public class AuthController {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(AuthController.class);
|
||||
|
||||
private Gson gson = new Gson();
|
||||
|
||||
@Autowired
|
||||
private AuthManager mgr;
|
||||
|
||||
@RequestMapping(value = "/_matrix-internal/identity/v1/check_credentials", method = RequestMethod.POST)
|
||||
public String checkCredentials(HttpServletRequest req) {
|
||||
try {
|
||||
JsonElement el = new JsonParser().parse(IOUtils.toString(req.getInputStream(), StandardCharsets.UTF_8));
|
||||
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")) {
|
||||
throw new IllegalArgumentException("Missing id or password keys");
|
||||
}
|
||||
|
||||
String id = authData.get("id").getAsString();
|
||||
log.info("Requested to check credentials for {}", id);
|
||||
String password = authData.get("password").getAsString();
|
||||
|
||||
UserAuthResult result = mgr.authenticate(id, password);
|
||||
|
||||
JsonObject authObj = new JsonObject();
|
||||
authObj.addProperty("success", result.isSuccess());
|
||||
if (result.isSuccess()) {
|
||||
authObj.addProperty("mxid", result.getMxid());
|
||||
authObj.addProperty("display_name", result.getDisplayName());
|
||||
}
|
||||
JsonObject obj = new JsonObject();
|
||||
|
||||
obj.add("authentication", authObj);
|
||||
return gson.toJson(obj);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* mxisd - Matrix Identity Server Daemon
|
||||
* Copyright (C) 2017 Maxime Dor
|
||||
*
|
||||
* https://max.kamax.io/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.kamax.mxisd.controller.v1;
|
||||
|
||||
import io.kamax.mxisd.lookup.ThreePidMapping;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class ClientBulkLookupAnswer {
|
||||
|
||||
private List<List<String>> threepids = new ArrayList<>();
|
||||
|
||||
public void addAll(Collection<ThreePidMapping> mappings) {
|
||||
for (ThreePidMapping mapping : mappings) {
|
||||
threepids.add(Arrays.asList(mapping.getMedium(), mapping.getValue(), mapping.getMxid()));
|
||||
}
|
||||
}
|
||||
|
||||
public List<List<String>> getThreepids() {
|
||||
return threepids;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* mxisd - Matrix Identity Server Daemon
|
||||
* Copyright (C) 2017 Maxime Dor
|
||||
*
|
||||
* https://max.kamax.io/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.kamax.mxisd.controller.v1;
|
||||
|
||||
import io.kamax.mxisd.lookup.ThreePidMapping;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ClientBulkLookupRequest {
|
||||
|
||||
private List<List<String>> threepids = new ArrayList<>();
|
||||
|
||||
public List<List<String>> getThreepids() {
|
||||
return threepids;
|
||||
}
|
||||
|
||||
public void setThreepids(List<List<String>> threepids) {
|
||||
this.threepids = threepids;
|
||||
}
|
||||
|
||||
public void setMappings(List<ThreePidMapping> mappings) {
|
||||
for (ThreePidMapping mapping : mappings) {
|
||||
List<String> threepid = new ArrayList<>();
|
||||
threepid.add(mapping.getMedium());
|
||||
threepid.add(mapping.getValue());
|
||||
threepids.add(threepid);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* mxisd - Matrix Identity Server Daemon
|
||||
* Copyright (C) 2017 Maxime Dor
|
||||
*
|
||||
* https://max.kamax.io/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.kamax.mxisd.controller.v1;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import io.kamax.mxisd.exception.BadRequestException;
|
||||
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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.MissingServletRequestParameterException;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.time.Instant;
|
||||
|
||||
@ControllerAdvice
|
||||
@ResponseBody
|
||||
@RequestMapping(produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public class DefaultExceptionHandler {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(DefaultExceptionHandler.class);
|
||||
|
||||
private static Gson gson = new Gson();
|
||||
|
||||
static String handle(String erroCode, String error) {
|
||||
JsonObject obj = new JsonObject();
|
||||
obj.addProperty("errcode", erroCode);
|
||||
obj.addProperty("error", error);
|
||||
return gson.toJson(obj);
|
||||
}
|
||||
|
||||
@ExceptionHandler(InternalServerError.class)
|
||||
public String handle(InternalServerError e, HttpServletResponse response) {
|
||||
if (StringUtils.isNotBlank(e.getInternalReason())) {
|
||||
log.error("Reference #{} - {}", e.getReference(), e.getInternalReason());
|
||||
} else {
|
||||
log.error("Reference #{}", e);
|
||||
}
|
||||
|
||||
return handleGeneric(e, response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(MatrixException.class)
|
||||
public String handleGeneric(MatrixException e, HttpServletResponse response) {
|
||||
response.setStatus(e.getStatus());
|
||||
return handle(e.getErrorCode(), e.getError());
|
||||
}
|
||||
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ExceptionHandler(MissingServletRequestParameterException.class)
|
||||
public String handle(MissingServletRequestParameterException e) {
|
||||
return handle("M_INVALID_BODY", e.getMessage());
|
||||
}
|
||||
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ExceptionHandler(MappingAlreadyExistsException.class)
|
||||
public String handle(MappingAlreadyExistsException e) {
|
||||
return handle("M_ALREADY_EXISTS", e.getMessage());
|
||||
}
|
||||
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ExceptionHandler(BadRequestException.class)
|
||||
public String handle(BadRequestException e) {
|
||||
return handle("M_BAD_REQUEST", e.getMessage());
|
||||
}
|
||||
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
@ExceptionHandler(RuntimeException.class)
|
||||
public String handle(HttpServletRequest req, RuntimeException e) {
|
||||
log.error("Unknown error when handling {}", req.getRequestURL(), e);
|
||||
return handle(
|
||||
"M_UNKNOWN",
|
||||
StringUtils.defaultIfBlank(
|
||||
e.getMessage(),
|
||||
"An internal server error occured. If this error persists, please contact support with reference #" +
|
||||
Instant.now().toEpochMilli()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* mxisd - Matrix Identity Server Daemon
|
||||
* Copyright (C) 2017 Maxime Dor
|
||||
*
|
||||
* https://max.kamax.io/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.kamax.mxisd.controller.v1;
|
||||
|
||||
public class IdentityAPIv1 {
|
||||
|
||||
public static final String BASE = "/_matrix/identity/api/v1";
|
||||
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* mxisd - Matrix Identity Server Daemon
|
||||
* Copyright (C) 2017 Maxime Dor
|
||||
*
|
||||
* https://max.kamax.io/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.kamax.mxisd.controller.v1;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import io.kamax.matrix.MatrixID;
|
||||
import io.kamax.mxisd.config.ServerConfig;
|
||||
import io.kamax.mxisd.controller.v1.io.ThreePidInviteReplyIO;
|
||||
import io.kamax.mxisd.invitation.IThreePidInvite;
|
||||
import io.kamax.mxisd.invitation.IThreePidInviteReply;
|
||||
import io.kamax.mxisd.invitation.InvitationManager;
|
||||
import io.kamax.mxisd.invitation.ThreePidInvite;
|
||||
import io.kamax.mxisd.key.KeyManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.POST;
|
||||
|
||||
@RestController
|
||||
@CrossOrigin
|
||||
@RequestMapping(path = IdentityAPIv1.BASE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
class InvitationController {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(InvitationController.class);
|
||||
|
||||
@Autowired
|
||||
private InvitationManager mgr;
|
||||
|
||||
@Autowired
|
||||
private KeyManager keyMgr;
|
||||
|
||||
@Autowired
|
||||
private ServerConfig srvCfg;
|
||||
|
||||
private Gson gson = new Gson();
|
||||
|
||||
@RequestMapping(value = "/store-invite", method = POST)
|
||||
String store(
|
||||
HttpServletRequest request,
|
||||
@RequestParam String sender,
|
||||
@RequestParam String medium,
|
||||
@RequestParam String address,
|
||||
@RequestParam("room_id") String roomId) {
|
||||
Map<String, String> parameters = new HashMap<>();
|
||||
for (String key : request.getParameterMap().keySet()) {
|
||||
parameters.put(key, request.getParameter(key));
|
||||
}
|
||||
IThreePidInvite invite = new ThreePidInvite(new MatrixID(sender), medium, address, roomId, parameters);
|
||||
IThreePidInviteReply reply = mgr.storeInvite(invite);
|
||||
|
||||
return gson.toJson(new ThreePidInviteReplyIO(reply, keyMgr.getPublicKeyBase64(keyMgr.getCurrentIndex()), srvCfg.getPublicUrl()));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* mxisd - Matrix Identity Server Daemon
|
||||
* Copyright (C) 2017 Maxime Dor
|
||||
*
|
||||
* https://max.kamax.io/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.kamax.mxisd.controller.v1;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import io.kamax.mxisd.controller.v1.io.KeyValidityJson;
|
||||
import io.kamax.mxisd.exception.BadRequestException;
|
||||
import io.kamax.mxisd.key.KeyManager;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.GET;
|
||||
|
||||
@RestController
|
||||
@CrossOrigin
|
||||
@RequestMapping(path = IdentityAPIv1.BASE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public class KeyController {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(KeyController.class);
|
||||
|
||||
@Autowired
|
||||
private KeyManager keyMgr;
|
||||
|
||||
private Gson gson = new Gson();
|
||||
private String validKey = gson.toJson(new KeyValidityJson(true));
|
||||
private String invalidKey = gson.toJson(new KeyValidityJson(false));
|
||||
|
||||
@RequestMapping(value = "/pubkey/{keyType}:{keyId}", method = GET)
|
||||
public String getKey(@PathVariable String keyType, @PathVariable int keyId) {
|
||||
if (!"ed25519".contentEquals(keyType)) {
|
||||
throw new BadRequestException("Invalid algorithm: " + keyType);
|
||||
}
|
||||
|
||||
log.info("Key {}:{} was requested", keyType, keyId);
|
||||
JsonObject obj = new JsonObject();
|
||||
obj.addProperty("public_key", keyMgr.getPublicKeyBase64(keyId));
|
||||
return gson.toJson(obj);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/pubkey/ephemeral/isvalid", method = GET)
|
||||
public String checkEphemeralKeyValidity(HttpServletRequest request) {
|
||||
log.warn("Ephemeral key was request but no ephemeral key are generated, replying not valid");
|
||||
|
||||
return invalidKey;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/pubkey/isvalid", method = GET)
|
||||
public String checkKeyValidity(HttpServletRequest request, @RequestParam("public_key") String pubKey) {
|
||||
log.info("Validating public key {}", pubKey);
|
||||
|
||||
// TODO do in manager
|
||||
boolean valid = StringUtils.equals(pubKey, keyMgr.getPublicKeyBase64(keyMgr.getCurrentIndex()));
|
||||
return valid ? validKey : invalidKey;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* mxisd - Matrix Identity Server Daemon
|
||||
* Copyright (C) 2017 Maxime Dor
|
||||
*
|
||||
* https://max.kamax.io/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.kamax.mxisd.controller.v1;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import io.kamax.mxisd.controller.v1.io.SingeLookupReplyJson;
|
||||
import io.kamax.mxisd.exception.InternalServerError;
|
||||
import io.kamax.mxisd.lookup.*;
|
||||
import io.kamax.mxisd.lookup.strategy.LookupStrategy;
|
||||
import io.kamax.mxisd.signature.SignatureManager;
|
||||
import io.kamax.mxisd.util.GsonParser;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.GET;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.POST;
|
||||
|
||||
@RestController
|
||||
@CrossOrigin
|
||||
@RequestMapping(path = IdentityAPIv1.BASE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public class MappingController {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(MappingController.class);
|
||||
private Gson gson = new Gson();
|
||||
private GsonParser parser = new GsonParser(gson);
|
||||
|
||||
@Autowired
|
||||
private LookupStrategy strategy;
|
||||
|
||||
@Autowired
|
||||
private SignatureManager signMgr;
|
||||
|
||||
private void setRequesterInfo(ALookupRequest lookupReq, HttpServletRequest req) {
|
||||
lookupReq.setRequester(req.getRemoteAddr());
|
||||
String xff = req.getHeader("X-FORWARDED-FOR");
|
||||
lookupReq.setRecursive(StringUtils.isNotBlank(xff));
|
||||
if (lookupReq.isRecursive()) {
|
||||
lookupReq.setRecurseHosts(Arrays.asList(xff.split(",")));
|
||||
}
|
||||
|
||||
lookupReq.setUserAgent(req.getHeader("USER-AGENT"));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/lookup", method = GET)
|
||||
String lookup(HttpServletRequest request, @RequestParam String medium, @RequestParam String address) {
|
||||
SingleLookupRequest lookupRequest = new SingleLookupRequest();
|
||||
setRequesterInfo(lookupRequest, request);
|
||||
lookupRequest.setType(medium);
|
||||
lookupRequest.setThreePid(address);
|
||||
|
||||
log.info("Got single lookup request from {} with client {} - Is recursive? {}", lookupRequest.getRequester(), lookupRequest.getUserAgent(), lookupRequest.isRecursive());
|
||||
|
||||
Optional<SingleLookupReply> lookupOpt = strategy.find(lookupRequest);
|
||||
if (!lookupOpt.isPresent()) {
|
||||
log.info("No mapping was found, return empty JSON object");
|
||||
return "{}";
|
||||
}
|
||||
|
||||
SingleLookupReply lookup = lookupOpt.get();
|
||||
if (lookup.isSigned()) {
|
||||
log.info("Lookup is already signed, sending as-is");
|
||||
return lookup.getBody();
|
||||
} else {
|
||||
log.info("Lookup is not signed, signing");
|
||||
JsonObject obj = gson.toJsonTree(new SingeLookupReplyJson(lookup)).getAsJsonObject();
|
||||
obj.add("signatures", signMgr.signMessageGson(gson.toJson(obj)));
|
||||
|
||||
return gson.toJson(obj);
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/bulk_lookup", method = POST)
|
||||
String bulkLookup(HttpServletRequest request) {
|
||||
BulkLookupRequest lookupRequest = new BulkLookupRequest();
|
||||
setRequesterInfo(lookupRequest, request);
|
||||
log.info("Got single lookup request from {} with client {} - Is recursive? {}", lookupRequest.getRequester(), lookupRequest.getUserAgent(), lookupRequest.isRecursive());
|
||||
|
||||
try {
|
||||
ClientBulkLookupRequest input = parser.parse(request, ClientBulkLookupRequest.class);
|
||||
List<ThreePidMapping> mappings = new ArrayList<>();
|
||||
for (List<String> mappingRaw : input.getThreepids()) {
|
||||
ThreePidMapping mapping = new ThreePidMapping();
|
||||
mapping.setMedium(mappingRaw.get(0));
|
||||
mapping.setValue(mappingRaw.get(1));
|
||||
mappings.add(mapping);
|
||||
}
|
||||
lookupRequest.setMappings(mappings);
|
||||
|
||||
ClientBulkLookupAnswer answer = new ClientBulkLookupAnswer();
|
||||
answer.addAll(strategy.find(lookupRequest));
|
||||
return gson.toJson(answer);
|
||||
} catch (IOException e) {
|
||||
throw new InternalServerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* mxisd - Matrix Identity Server Daemon
|
||||
* Copyright (C) 2017 Maxime Dor
|
||||
*
|
||||
* https://max.kamax.io/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.kamax.mxisd.controller.v1;
|
||||
|
||||
import io.kamax.mxisd.config.ServerConfig;
|
||||
import io.kamax.mxisd.config.ViewConfig;
|
||||
import io.kamax.mxisd.controller.v1.remote.RemoteIdentityAPIv1;
|
||||
import io.kamax.mxisd.exception.InternalServerError;
|
||||
import io.kamax.mxisd.session.SessionMananger;
|
||||
import io.kamax.mxisd.session.ValidationResult;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@Controller
|
||||
@RequestMapping(path = IdentityAPIv1.BASE)
|
||||
class SessionController {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(SessionController.class);
|
||||
|
||||
@Autowired
|
||||
private ServerConfig srvCfg;
|
||||
|
||||
@Autowired
|
||||
private SessionMananger mgr;
|
||||
|
||||
@Autowired
|
||||
private ViewConfig viewCfg;
|
||||
;
|
||||
|
||||
@RequestMapping(value = "/validate/{medium}/submitToken")
|
||||
public String validate(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@RequestParam String sid,
|
||||
@RequestParam("client_secret") String secret,
|
||||
@RequestParam String token,
|
||||
Model model
|
||||
) {
|
||||
log.info("Requested: {}?{}", request.getRequestURL(), request.getQueryString());
|
||||
|
||||
ValidationResult r = mgr.validate(sid, secret, token);
|
||||
log.info("Session {} was validated", sid);
|
||||
if (r.getNextUrl().isPresent()) {
|
||||
String url = srvCfg.getPublicUrl() + r.getNextUrl().get();
|
||||
log.info("Session {} validation: next URL is present, redirecting to {}", sid, url);
|
||||
try {
|
||||
response.sendRedirect(url);
|
||||
return "";
|
||||
} catch (IOException e) {
|
||||
log.warn("Unable to redirect user to {}", url);
|
||||
throw new InternalServerError(e);
|
||||
}
|
||||
} else {
|
||||
if (r.isCanRemote()) {
|
||||
String url = srvCfg.getPublicUrl() + RemoteIdentityAPIv1.getRequestToken(r.getSession().getId(), r.getSession().getSecret());
|
||||
model.addAttribute("remoteSessionLink", url);
|
||||
return viewCfg.getSession().getLocalRemote().getOnTokenSubmit().getSuccess();
|
||||
} else {
|
||||
return viewCfg.getSession().getLocal().getOnTokenSubmit().getSuccess();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* mxisd - Matrix Identity Server Daemon
|
||||
* Copyright (C) 2017 Maxime Dor
|
||||
*
|
||||
* https://max.kamax.io/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.kamax.mxisd.controller.v1;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import io.kamax.matrix.ThreePidMedium;
|
||||
import io.kamax.mxisd.ThreePid;
|
||||
import io.kamax.mxisd.config.ServerConfig;
|
||||
import io.kamax.mxisd.config.ViewConfig;
|
||||
import io.kamax.mxisd.controller.v1.io.SessionEmailTokenRequestJson;
|
||||
import io.kamax.mxisd.controller.v1.io.SessionPhoneTokenRequestJson;
|
||||
import io.kamax.mxisd.exception.BadRequestException;
|
||||
import io.kamax.mxisd.exception.SessionNotValidatedException;
|
||||
import io.kamax.mxisd.invitation.InvitationManager;
|
||||
import io.kamax.mxisd.lookup.ThreePidValidation;
|
||||
import io.kamax.mxisd.session.SessionMananger;
|
||||
import io.kamax.mxisd.util.GsonParser;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@RestController
|
||||
@CrossOrigin
|
||||
@RequestMapping(path = IdentityAPIv1.BASE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public class SessionRestController {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(SessionRestController.class);
|
||||
|
||||
private class Sid { // FIXME replace with RequestTokenResponse
|
||||
|
||||
private String sid;
|
||||
|
||||
public Sid(String sid) {
|
||||
setSid(sid);
|
||||
}
|
||||
|
||||
String getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
void setSid(String sid) {
|
||||
this.sid = sid;
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private ServerConfig srvCfg;
|
||||
|
||||
@Autowired
|
||||
private SessionMananger mgr;
|
||||
|
||||
@Autowired
|
||||
private InvitationManager invMgr;
|
||||
|
||||
@Autowired
|
||||
private ViewConfig viewCfg;
|
||||
|
||||
private Gson gson = new Gson();
|
||||
private GsonParser parser = new GsonParser(gson);
|
||||
|
||||
@RequestMapping(value = "/validate/{medium}/requestToken")
|
||||
String init(HttpServletRequest request, HttpServletResponse response, @PathVariable String medium) throws IOException {
|
||||
log.info("Request {}: {}", request.getMethod(), request.getRequestURL(), request.getQueryString());
|
||||
if (ThreePidMedium.Email.is(medium)) {
|
||||
SessionEmailTokenRequestJson req = parser.parse(request, SessionEmailTokenRequestJson.class);
|
||||
return gson.toJson(new Sid(mgr.create(
|
||||
request.getRemoteHost(),
|
||||
new ThreePid(req.getMedium(), req.getValue()),
|
||||
req.getSecret(),
|
||||
req.getAttempt(),
|
||||
req.getNextLink())));
|
||||
}
|
||||
|
||||
if (ThreePidMedium.PhoneNumber.is(medium)) {
|
||||
SessionPhoneTokenRequestJson req = parser.parse(request, SessionPhoneTokenRequestJson.class);
|
||||
return gson.toJson(new Sid(mgr.create(
|
||||
request.getRemoteHost(),
|
||||
new ThreePid(req.getMedium(), req.getValue()),
|
||||
req.getSecret(),
|
||||
req.getAttempt(),
|
||||
req.getNextLink())));
|
||||
}
|
||||
|
||||
JsonObject obj = new JsonObject();
|
||||
obj.addProperty("errcode", "M_INVALID_3PID_TYPE");
|
||||
obj.addProperty("error", medium + " is not supported as a 3PID type");
|
||||
response.setStatus(HttpStatus.SC_BAD_REQUEST);
|
||||
return gson.toJson(obj);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/3pid/getValidated3pid")
|
||||
String check(HttpServletRequest request, HttpServletResponse response,
|
||||
@RequestParam String sid, @RequestParam("client_secret") String secret) {
|
||||
log.info("Requested: {}", request.getRequestURL(), request.getQueryString());
|
||||
|
||||
try {
|
||||
ThreePidValidation pid = mgr.getValidated(sid, secret);
|
||||
|
||||
JsonObject obj = new JsonObject();
|
||||
obj.addProperty("medium", pid.getMedium());
|
||||
obj.addProperty("address", pid.getAddress());
|
||||
obj.addProperty("validated_at", pid.getValidation().toEpochMilli());
|
||||
|
||||
return gson.toJson(obj);
|
||||
} catch (SessionNotValidatedException e) {
|
||||
log.info("Session {} was requested but has not yet been validated", sid);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/3pid/bind")
|
||||
String bind(HttpServletRequest request, HttpServletResponse response,
|
||||
@RequestParam String sid, @RequestParam("client_secret") String secret, @RequestParam String mxid) {
|
||||
log.info("Requested: {}", request.getRequestURL(), request.getQueryString());
|
||||
try {
|
||||
mgr.bind(sid, secret, mxid);
|
||||
return "{}";
|
||||
} catch (BadRequestException e) {
|
||||
log.info("requested session was not validated");
|
||||
|
||||
JsonObject obj = new JsonObject();
|
||||
obj.addProperty("errcode", "M_SESSION_NOT_VALIDATED");
|
||||
obj.addProperty("error", e.getMessage());
|
||||
response.setStatus(HttpStatus.SC_BAD_REQUEST);
|
||||
return gson.toJson(obj);
|
||||
} finally {
|
||||
// If a user registers, there is no standard login event. Instead, this is the only way to trigger
|
||||
// resolution at an appropriate time. Meh at synapse/Riot!
|
||||
invMgr.lookupMappingsForInvites();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* mxisd - Matrix Identity Server Daemon
|
||||
* Copyright (C) 2017 Maxime Dor
|
||||
*
|
||||
* https://max.kamax.io/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.kamax.mxisd.controller.v1;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@CrossOrigin
|
||||
@RequestMapping(produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public class StatusController {
|
||||
|
||||
private Gson gson = new Gson();
|
||||
|
||||
@RequestMapping(value = "/_matrix/identity/status")
|
||||
public String getStatus() {
|
||||
// TODO link to backend
|
||||
JsonObject status = new JsonObject();
|
||||
status.addProperty("health", "OK");
|
||||
|
||||
JsonObject obj = new JsonObject();
|
||||
obj.add("status", status);
|
||||
|
||||
return gson.toJson(obj);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* mxisd - Matrix Identity Server Daemon
|
||||
* Copyright (C) 2017 Maxime Dor
|
||||
*
|
||||
* https://max.kamax.io/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.kamax.mxisd.controller.v1.io;
|
||||
|
||||
public abstract class GenericTokenRequestJson {
|
||||
|
||||
private String client_secret;
|
||||
private int send_attempt;
|
||||
private String next_link;
|
||||
|
||||
public String getSecret() {
|
||||
return client_secret;
|
||||
}
|
||||
|
||||
public int getAttempt() {
|
||||
return send_attempt;
|
||||
}
|
||||
|
||||
public String getNextLink() {
|
||||
return next_link;
|
||||
}
|
||||
|
||||
}
|
@@ -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.controller.v1.io;
|
||||
|
||||
public class KeyValidityJson {
|
||||
|
||||
private boolean valid;
|
||||
|
||||
public KeyValidityJson(boolean isValid) {
|
||||
this.valid = isValid;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* mxisd - Matrix Identity Server Daemon
|
||||
* Copyright (C) 2017 Maxime Dor
|
||||
*
|
||||
* https://max.kamax.io/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.kamax.mxisd.controller.v1.io;
|
||||
|
||||
public class RequestTokenResponse {
|
||||
|
||||
private String sid;
|
||||
|
||||
public String getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
}
|
@@ -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.controller.v1.io;
|
||||
|
||||
public class SessionEmailTokenRequestJson extends GenericTokenRequestJson {
|
||||
|
||||
private String email;
|
||||
|
||||
public String getMedium() {
|
||||
return "email";
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return email;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* mxisd - Matrix Identity Server Daemon
|
||||
* Copyright (C) 2017 Maxime Dor
|
||||
*
|
||||
* https://max.kamax.io/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.kamax.mxisd.controller.v1.io;
|
||||
|
||||
import com.google.i18n.phonenumbers.NumberParseException;
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
||||
import com.google.i18n.phonenumbers.Phonenumber;
|
||||
|
||||
public class SessionPhoneTokenRequestJson extends GenericTokenRequestJson {
|
||||
|
||||
private static PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
|
||||
|
||||
private String country;
|
||||
private String phone_number;
|
||||
|
||||
public String getMedium() {
|
||||
return "msisdn";
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
try {
|
||||
Phonenumber.PhoneNumber num = phoneUtil.parse(phone_number, country);
|
||||
return phoneUtil.format(num, PhoneNumberUtil.PhoneNumberFormat.E164).replace("+", "");
|
||||
} catch (NumberParseException e) {
|
||||
throw new IllegalArgumentException("Invalid phone number");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* mxisd - Matrix Identity Server Daemon
|
||||
* Copyright (C) 2017 Maxime Dor
|
||||
*
|
||||
* https://max.kamax.io/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.kamax.mxisd.controller.v1.io;
|
||||
|
||||
import io.kamax.mxisd.lookup.SingleLookupReply;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SingeLookupReplyJson {
|
||||
|
||||
private String address;
|
||||
private String medium;
|
||||
private String mxid;
|
||||
private long not_after;
|
||||
private long not_before;
|
||||
private long ts;
|
||||
private Map<String, Map<String, String>> signatures = new HashMap<>();
|
||||
|
||||
public SingeLookupReplyJson(SingleLookupReply reply) {
|
||||
this.address = reply.getRequest().getThreePid();
|
||||
this.medium = reply.getRequest().getType();
|
||||
this.mxid = reply.getMxid().getId();
|
||||
this.not_after = reply.getNotAfter().toEpochMilli();
|
||||
this.not_before = reply.getNotBefore().toEpochMilli();
|
||||
this.ts = reply.getTimestamp().toEpochMilli();
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public String getMedium() {
|
||||
return medium;
|
||||
}
|
||||
|
||||
public String getMxid() {
|
||||
return mxid;
|
||||
}
|
||||
|
||||
public long getNot_after() {
|
||||
return not_after;
|
||||
}
|
||||
|
||||
public long getNot_before() {
|
||||
return not_before;
|
||||
}
|
||||
|
||||
public long getTs() {
|
||||
return ts;
|
||||
}
|
||||
|
||||
public boolean isSigned() {
|
||||
return signatures != null && !signatures.isEmpty();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* mxisd - Matrix Identity Server Daemon
|
||||
* Copyright (C) 2017 Maxime Dor
|
||||
*
|
||||
* https://max.kamax.io/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.kamax.mxisd.controller.v1.io;
|
||||
|
||||
import io.kamax.mxisd.invitation.IThreePidInviteReply;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ThreePidInviteReplyIO {
|
||||
|
||||
private String token;
|
||||
private List<Key> public_keys;
|
||||
private String display_name;
|
||||
|
||||
public ThreePidInviteReplyIO(IThreePidInviteReply reply, String pubKey, String publicUrl) {
|
||||
this.token = reply.getToken();
|
||||
this.public_keys = Collections.singletonList(new Key(pubKey, publicUrl));
|
||||
this.display_name = reply.getDisplayName();
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public List<Key> getPublic_keys() {
|
||||
return public_keys;
|
||||
}
|
||||
|
||||
public String getDisplay_name() {
|
||||
return display_name;
|
||||
}
|
||||
|
||||
public class Key {
|
||||
private String key_validity_url;
|
||||
private String public_key;
|
||||
|
||||
public Key(String key, String publicUrl) {
|
||||
this.key_validity_url = publicUrl + "/_matrix/identity/api/v1/pubkey/isvalid";
|
||||
this.public_key = key;
|
||||
}
|
||||
|
||||
public String getKey_validity_url() {
|
||||
return key_validity_url;
|
||||
}
|
||||
|
||||
public String getPublic_key() {
|
||||
return public_key;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* mxisd - Matrix Identity Server Daemon
|
||||
* Copyright (C) 2017 Maxime Dor
|
||||
*
|
||||
* https://max.kamax.io/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.kamax.mxisd.controller.v1.remote;
|
||||
|
||||
public class RemoteIdentityAPIv1 {
|
||||
|
||||
public static final String BASE = "/_matrix/identity/remote/api/v1";
|
||||
public static final String SESSION_REQUEST_TOKEN = BASE + "/validate/requestToken";
|
||||
public static final String SESSION_CHECK = BASE + "/validate/check";
|
||||
|
||||
public static String getRequestToken(String id, String secret) {
|
||||
return SESSION_REQUEST_TOKEN + "?sid=" + id + "&client_secret=" + secret;
|
||||
}
|
||||
|
||||
public static String getSessionCheck(String id, String secret) {
|
||||
return SESSION_CHECK + "?sid=" + id + "&client_secret=" + secret;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
package io.kamax.mxisd.controller.v1.remote;
|
||||
|
||||
import io.kamax.mxisd.config.ViewConfig;
|
||||
import io.kamax.mxisd.exception.SessionNotValidatedException;
|
||||
import io.kamax.mxisd.session.SessionMananger;
|
||||
import io.kamax.mxisd.threepid.session.IThreePidSession;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import static io.kamax.mxisd.controller.v1.remote.RemoteIdentityAPIv1.SESSION_CHECK;
|
||||
import static io.kamax.mxisd.controller.v1.remote.RemoteIdentityAPIv1.SESSION_REQUEST_TOKEN;
|
||||
|
||||
@Controller
|
||||
public class RemoteSessionController {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(RemoteSessionController.class);
|
||||
|
||||
@Autowired
|
||||
private ViewConfig viewCfg;
|
||||
|
||||
@Autowired
|
||||
private SessionMananger mgr;
|
||||
|
||||
@RequestMapping(path = SESSION_REQUEST_TOKEN)
|
||||
public String requestToken(
|
||||
HttpServletRequest request,
|
||||
@RequestParam String sid,
|
||||
@RequestParam("client_secret") String secret,
|
||||
Model model
|
||||
) {
|
||||
log.info("Request {}: {}", request.getMethod(), request.getRequestURL());
|
||||
IThreePidSession session = mgr.createRemote(sid, secret);
|
||||
model.addAttribute("checkLink", RemoteIdentityAPIv1.getSessionCheck(session.getId(), session.getSecret()));
|
||||
return viewCfg.getSession().getRemote().getOnRequest().getSuccess();
|
||||
}
|
||||
|
||||
@RequestMapping(path = SESSION_CHECK)
|
||||
public String check(
|
||||
HttpServletRequest request,
|
||||
@RequestParam String sid,
|
||||
@RequestParam("client_secret") String secret) {
|
||||
log.info("Request {}: {}", request.getMethod(), request.getRequestURL());
|
||||
|
||||
try {
|
||||
mgr.validateRemote(sid, secret);
|
||||
return viewCfg.getSession().getRemote().getOnCheck().getSuccess();
|
||||
} catch (SessionNotValidatedException e) {
|
||||
return viewCfg.getSession().getRemote().getOnCheck().getFailure();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -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.exception;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
|
||||
public class BadRequestException extends RuntimeException {
|
||||
|
||||
public BadRequestException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.exception;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class ConfigurationException extends RuntimeException {
|
||||
|
||||
private String key;
|
||||
private String detailedMsg;
|
||||
|
||||
public ConfigurationException(String key) {
|
||||
super("Invalid or empty value for configuration key " + key);
|
||||
}
|
||||
|
||||
public ConfigurationException(Throwable t) {
|
||||
super(t.getMessage(), t);
|
||||
}
|
||||
|
||||
public ConfigurationException(String key, String detailedMsg) {
|
||||
this(key);
|
||||
this.detailedMsg = detailedMsg;
|
||||
}
|
||||
|
||||
public Optional<String> getDetailedMessage() {
|
||||
return Optional.ofNullable(detailedMsg);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.exception;
|
||||
|
||||
import org.apache.http.HttpStatus;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public class InternalServerError extends MatrixException {
|
||||
|
||||
private String reference = Long.toString(Instant.now().toEpochMilli());
|
||||
private String internalReason;
|
||||
|
||||
public InternalServerError() {
|
||||
super(
|
||||
HttpStatus.SC_INTERNAL_SERVER_ERROR,
|
||||
"M_UNKNOWN",
|
||||
"An internal server error occured. If this error persists, please contact support with reference #" +
|
||||
Instant.now().toEpochMilli()
|
||||
);
|
||||
}
|
||||
|
||||
public InternalServerError(String internalReason) {
|
||||
this();
|
||||
this.internalReason = internalReason;
|
||||
}
|
||||
|
||||
public InternalServerError(Throwable t) {
|
||||
this(t.getMessage());
|
||||
}
|
||||
|
||||
public String getReference() {
|
||||
return reference;
|
||||
}
|
||||
|
||||
public String getInternalReason() {
|
||||
return internalReason;
|
||||
}
|
||||
|
||||
}
|
@@ -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.exception;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
@ResponseStatus(value = HttpStatus.FORBIDDEN)
|
||||
public class InvalidCredentialsException extends RuntimeException {
|
||||
|
||||
public InvalidCredentialsException() {
|
||||
super("Supplied credentials are invalid");
|
||||
}
|
||||
|
||||
}
|
@@ -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.exception;
|
||||
|
||||
public class InvalidResponseJsonException extends RuntimeException {
|
||||
|
||||
public InvalidResponseJsonException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
}
|
@@ -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.exception;
|
||||
|
||||
public class JsonMemberNotFoundException extends RuntimeException {
|
||||
|
||||
public JsonMemberNotFoundException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
}
|
@@ -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.exception;
|
||||
|
||||
public class MappingAlreadyExistsException extends RuntimeException {
|
||||
|
||||
public MappingAlreadyExistsException() {
|
||||
super("A mapping already exists for this 3PID");
|
||||
}
|
||||
|
||||
}
|
47
src/main/java/io/kamax/mxisd/exception/MatrixException.java
Normal file
47
src/main/java/io/kamax/mxisd/exception/MatrixException.java
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.exception;
|
||||
|
||||
public abstract class MatrixException extends MxisdException {
|
||||
|
||||
private int status;
|
||||
private String errorCode;
|
||||
private String error;
|
||||
|
||||
public MatrixException(int status, String errorCode, String error) {
|
||||
this.status = status;
|
||||
this.errorCode = errorCode;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
}
|
24
src/main/java/io/kamax/mxisd/exception/MxisdException.java
Normal file
24
src/main/java/io/kamax/mxisd/exception/MxisdException.java
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.exception;
|
||||
|
||||
public class MxisdException extends RuntimeException {
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.exception;
|
||||
|
||||
|
||||
import org.apache.http.HttpStatus;
|
||||
|
||||
public class NotAllowedException extends MatrixException {
|
||||
|
||||
public NotAllowedException(String s) {
|
||||
super(HttpStatus.SC_FORBIDDEN, "M_FORBIDDEN", s);
|
||||
}
|
||||
|
||||
}
|
@@ -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.exception;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
@ResponseStatus(value = HttpStatus.NOT_IMPLEMENTED)
|
||||
public class NotImplementedException extends RuntimeException {
|
||||
|
||||
public NotImplementedException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
}
|
@@ -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.exception;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
@ResponseStatus(value = HttpStatus.NOT_FOUND)
|
||||
public class ObjectNotFoundException extends RuntimeException {
|
||||
|
||||
public ObjectNotFoundException(String type, String id) {
|
||||
super(type + " with ID " + id + " does not exist");
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.exception;
|
||||
|
||||
import org.apache.http.HttpStatus;
|
||||
|
||||
public class RemoteIdentityServerException extends MatrixException {
|
||||
|
||||
public RemoteIdentityServerException(String error) {
|
||||
super(HttpStatus.SC_SERVICE_UNAVAILABLE, "M_REMOTE_IS_ERROR", error);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.exception;
|
||||
|
||||
import org.apache.http.HttpStatus;
|
||||
|
||||
public class SessionNotValidatedException extends MatrixException {
|
||||
|
||||
public SessionNotValidatedException() {
|
||||
super(HttpStatus.SC_OK, "M_SESSION_NOT_VALIDATED", "This validation session has not yet been completed");
|
||||
}
|
||||
|
||||
}
|
@@ -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.exception;
|
||||
|
||||
public class SessionUnknownException extends MatrixException {
|
||||
|
||||
public SessionUnknownException() {
|
||||
this("No valid session was found matching that sid and client secret");
|
||||
}
|
||||
|
||||
public SessionUnknownException(String error) {
|
||||
super(200, "M_NO_VALID_SESSION", error);
|
||||
}
|
||||
|
||||
}
|
39
src/main/java/io/kamax/mxisd/invitation/IThreePidInvite.java
Normal file
39
src/main/java/io/kamax/mxisd/invitation/IThreePidInvite.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.invitation;
|
||||
|
||||
import io.kamax.matrix._MatrixID;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface IThreePidInvite {
|
||||
|
||||
_MatrixID getSender();
|
||||
|
||||
String getMedium();
|
||||
|
||||
String getAddress();
|
||||
|
||||
String getRoomId();
|
||||
|
||||
Map<String, String> getProperties();
|
||||
|
||||
}
|
@@ -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.invitation;
|
||||
|
||||
public interface IThreePidInviteReply {
|
||||
|
||||
String getId();
|
||||
|
||||
IThreePidInvite getInvite();
|
||||
|
||||
String getToken();
|
||||
|
||||
String getDisplayName();
|
||||
|
||||
}
|
338
src/main/java/io/kamax/mxisd/invitation/InvitationManager.java
Normal file
338
src/main/java/io/kamax/mxisd/invitation/InvitationManager.java
Normal file
@@ -0,0 +1,338 @@
|
||||
/*
|
||||
* 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.invitation;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import io.kamax.matrix.MatrixID;
|
||||
import io.kamax.mxisd.config.DnsOverwrite;
|
||||
import io.kamax.mxisd.config.DnsOverwriteEntry;
|
||||
import io.kamax.mxisd.exception.BadRequestException;
|
||||
import io.kamax.mxisd.exception.MappingAlreadyExistsException;
|
||||
import io.kamax.mxisd.lookup.SingleLookupReply;
|
||||
import io.kamax.mxisd.lookup.ThreePidMapping;
|
||||
import io.kamax.mxisd.lookup.strategy.LookupStrategy;
|
||||
import io.kamax.mxisd.notification.NotificationManager;
|
||||
import io.kamax.mxisd.signature.SignatureManager;
|
||||
import io.kamax.mxisd.storage.IStorage;
|
||||
import io.kamax.mxisd.storage.ormlite.ThreePidInviteIO;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.RandomStringUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.ssl.SSLContextBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.xbill.DNS.*;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Component
|
||||
public class InvitationManager {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(InvitationManager.class);
|
||||
|
||||
private Map<String, IThreePidInviteReply> invitations = new ConcurrentHashMap<>();
|
||||
|
||||
@Autowired
|
||||
private IStorage storage;
|
||||
|
||||
@Autowired
|
||||
private LookupStrategy lookupMgr;
|
||||
|
||||
@Autowired
|
||||
private SignatureManager signMgr;
|
||||
|
||||
@Autowired
|
||||
private DnsOverwrite dns;
|
||||
|
||||
private NotificationManager notifMgr;
|
||||
|
||||
private CloseableHttpClient client;
|
||||
private Gson gson;
|
||||
private Timer refreshTimer;
|
||||
|
||||
@Autowired
|
||||
public InvitationManager(NotificationManager notifMgr) {
|
||||
this.notifMgr = notifMgr;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void postConstruct() {
|
||||
gson = new Gson();
|
||||
|
||||
log.info("Loading saved invites");
|
||||
Collection<ThreePidInviteIO> ioList = storage.getInvites();
|
||||
ioList.forEach(io -> {
|
||||
log.info("Processing invite {}", gson.toJson(io));
|
||||
ThreePidInvite invite = new ThreePidInvite(
|
||||
new MatrixID(io.getSender()),
|
||||
io.getMedium(),
|
||||
io.getAddress(),
|
||||
io.getRoomId(),
|
||||
io.getProperties()
|
||||
);
|
||||
|
||||
ThreePidInviteReply reply = new ThreePidInviteReply(getId(invite), invite, io.getToken(), "");
|
||||
invitations.put(reply.getId(), reply);
|
||||
});
|
||||
|
||||
// FIXME export such madness into matrix-java-sdk with a nice wrapper to talk to a homeserver
|
||||
try {
|
||||
SSLContext sslContext = SSLContextBuilder.create().loadTrustMaterial(new TrustSelfSignedStrategy()).build();
|
||||
HostnameVerifier hostnameVerifier = new NoopHostnameVerifier();
|
||||
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
|
||||
client = HttpClients.custom().setSSLSocketFactory(sslSocketFactory).build();
|
||||
} catch (Exception e) {
|
||||
// FIXME do better...
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
log.info("Setting up invitation mapping refresh timer");
|
||||
refreshTimer = new Timer();
|
||||
refreshTimer.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
lookupMappingsForInvites();
|
||||
} catch (Throwable t) {
|
||||
log.error("Error when running background mapping refresh", t);
|
||||
}
|
||||
}
|
||||
}, 5000L, TimeUnit.MILLISECONDS.convert(1, TimeUnit.MINUTES)); // FIXME make configurable
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
private void preDestroy() {
|
||||
refreshTimer.cancel();
|
||||
ForkJoinPool.commonPool().awaitQuiescence(1, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
private String getId(IThreePidInvite invite) {
|
||||
return invite.getSender().getDomain().toLowerCase() + invite.getMedium().toLowerCase() + invite.getAddress().toLowerCase();
|
||||
}
|
||||
|
||||
private String getIdForLog(IThreePidInviteReply reply) {
|
||||
return reply.getInvite().getSender().getId() + ":" + reply.getInvite().getRoomId() + ":" + reply.getInvite().getMedium() + ":" + reply.getInvite().getAddress();
|
||||
}
|
||||
|
||||
private String getSrvRecordName(String domain) {
|
||||
return "_matrix._tcp." + domain;
|
||||
}
|
||||
|
||||
// TODO use caching mechanism
|
||||
// TODO export in matrix-java-sdk
|
||||
private String findHomeserverForDomain(String domain) {
|
||||
Optional<DnsOverwriteEntry> entryOpt = dns.findHost(domain);
|
||||
if (entryOpt.isPresent()) {
|
||||
DnsOverwriteEntry entry = entryOpt.get();
|
||||
log.info("Found DNS overwrite for {} to {}", entry.getName(), entry.getTarget());
|
||||
return "https://" + entry.getTarget();
|
||||
}
|
||||
|
||||
log.debug("Performing SRV lookup for {}", domain);
|
||||
String lookupDns = getSrvRecordName(domain);
|
||||
log.info("Lookup name: {}", lookupDns);
|
||||
|
||||
try {
|
||||
List<SRVRecord> srvRecords = new ArrayList<>();
|
||||
Record[] rawRecords = new Lookup(lookupDns, Type.SRV).run();
|
||||
if (rawRecords != null && rawRecords.length > 0) {
|
||||
for (Record record : rawRecords) {
|
||||
if (Type.SRV == record.getType()) {
|
||||
srvRecords.add((SRVRecord) record);
|
||||
} else {
|
||||
log.info("Got non-SRV record: {}", record.toString());
|
||||
}
|
||||
}
|
||||
|
||||
srvRecords.sort(Comparator.comparingInt(SRVRecord::getPriority));
|
||||
for (SRVRecord record : srvRecords) {
|
||||
log.info("Found SRV record: {}", record.toString());
|
||||
return "https://" + record.getTarget().toString(true) + ":" + record.getPort();
|
||||
}
|
||||
} else {
|
||||
log.info("No SRV record for {}", lookupDns);
|
||||
}
|
||||
} catch (TextParseException e) {
|
||||
log.warn("Unable to perform DNS SRV query for {}: {}", lookupDns, e.getMessage());
|
||||
}
|
||||
|
||||
log.info("Performing basic lookup using domain name {}", domain);
|
||||
return "https://" + domain + ":8448";
|
||||
}
|
||||
|
||||
public synchronized IThreePidInviteReply storeInvite(IThreePidInvite invitation) { // TODO better sync
|
||||
if (!notifMgr.isMediumSupported(invitation.getMedium())) {
|
||||
throw new BadRequestException("Medium type " + invitation.getMedium() + " is not supported");
|
||||
}
|
||||
|
||||
String invId = getId(invitation);
|
||||
log.info("Handling invite for {}:{} from {} in room {}", invitation.getMedium(), invitation.getAddress(), invitation.getSender(), invitation.getRoomId());
|
||||
if (invitations.containsKey(invId)) {
|
||||
log.info("Invite is already pending for {}:{}, returning data", invitation.getMedium(), invitation.getAddress());
|
||||
return invitations.get(invId);
|
||||
}
|
||||
|
||||
Optional<?> result = lookupMgr.find(invitation.getMedium(), invitation.getAddress(), true);
|
||||
if (result.isPresent()) {
|
||||
log.info("Mapping for {}:{} already exists, refusing to store invite", invitation.getMedium(), invitation.getAddress());
|
||||
throw new MappingAlreadyExistsException();
|
||||
}
|
||||
|
||||
String token = RandomStringUtils.randomAlphanumeric(64);
|
||||
String displayName = invitation.getAddress().substring(0, 3) + "...";
|
||||
|
||||
IThreePidInviteReply reply = new ThreePidInviteReply(invId, invitation, token, displayName);
|
||||
|
||||
log.info("Performing invite to {}:{}", invitation.getMedium(), invitation.getAddress());
|
||||
notifMgr.sendForInvite(reply);
|
||||
|
||||
log.info("Storing invite under ID {}", invId);
|
||||
storage.insertInvite(reply);
|
||||
invitations.put(invId, reply);
|
||||
log.info("A new invite has been created for {}:{} on HS {}", invitation.getMedium(), invitation.getAddress(), invitation.getSender().getDomain());
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
public void lookupMappingsForInvites() {
|
||||
if (!invitations.isEmpty()) {
|
||||
log.info("Checking for existing mapping for pending invites");
|
||||
for (IThreePidInviteReply reply : invitations.values()) {
|
||||
log.info("Processing invite {}", getIdForLog(reply));
|
||||
ForkJoinPool.commonPool().submit(new MappingChecker(reply));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void publishMappingIfInvited(ThreePidMapping threePid) {
|
||||
log.info("Looking up possible pending invites for {}:{}", threePid.getMedium(), threePid.getValue());
|
||||
for (IThreePidInviteReply reply : invitations.values()) {
|
||||
if (StringUtils.equalsIgnoreCase(reply.getInvite().getMedium(), threePid.getMedium()) && StringUtils.equalsIgnoreCase(reply.getInvite().getAddress(), threePid.getValue())) {
|
||||
log.info("{}:{} has an invite pending on HS {}, publishing mapping", threePid.getMedium(), threePid.getValue(), reply.getInvite().getSender().getDomain());
|
||||
publishMapping(reply, threePid.getMxid());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void publishMapping(IThreePidInviteReply reply, String mxid) {
|
||||
String medium = reply.getInvite().getMedium();
|
||||
String address = reply.getInvite().getAddress();
|
||||
String domain = reply.getInvite().getSender().getDomain();
|
||||
log.info("Discovering HS for domain {}", domain);
|
||||
String hsUrlOpt = findHomeserverForDomain(domain);
|
||||
|
||||
// TODO this is needed as this will block if called during authentication cycle due to synapse implementation
|
||||
new Thread(() -> { // FIXME need to make this retry-able and within a general background working pool
|
||||
HttpPost req = new HttpPost(hsUrlOpt + "/_matrix/federation/v1/3pid/onbind");
|
||||
// Expected body: https://matrix.to/#/!HUeDbmFUsWAhxHHvFG:matrix.org/$150469846739DCLWc:matrix.trancendances.fr
|
||||
JsonObject obj = new JsonObject();
|
||||
obj.addProperty("mxid", mxid);
|
||||
obj.addProperty("token", reply.getToken());
|
||||
obj.add("signatures", signMgr.signMessageGson(obj.toString()));
|
||||
|
||||
JsonObject objUp = new JsonObject();
|
||||
objUp.addProperty("mxid", mxid);
|
||||
objUp.addProperty("medium", medium);
|
||||
objUp.addProperty("address", address);
|
||||
objUp.addProperty("sender", reply.getInvite().getSender().getId());
|
||||
objUp.addProperty("room_id", reply.getInvite().getRoomId());
|
||||
objUp.add("signed", obj);
|
||||
|
||||
JsonObject content = new JsonObject();
|
||||
JsonArray invites = new JsonArray();
|
||||
invites.add(objUp);
|
||||
content.add("invites", invites);
|
||||
content.addProperty("medium", medium);
|
||||
content.addProperty("address", address);
|
||||
content.addProperty("mxid", mxid);
|
||||
|
||||
content.add("signatures", signMgr.signMessageGson(content.toString()));
|
||||
|
||||
StringEntity entity = new StringEntity(content.toString(), StandardCharsets.UTF_8);
|
||||
entity.setContentType("application/json");
|
||||
req.setEntity(entity);
|
||||
try {
|
||||
log.info("Posting onBind event to {}", req.getURI());
|
||||
CloseableHttpResponse response = client.execute(req);
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
log.info("Answer code: {}", statusCode);
|
||||
if (statusCode >= 300) {
|
||||
log.warn("Answer body: {}", IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8));
|
||||
} else {
|
||||
invitations.remove(getId(reply.getInvite()));
|
||||
storage.deleteInvite(reply.getId());
|
||||
log.info("Removed invite from internal store");
|
||||
}
|
||||
response.close();
|
||||
} catch (IOException e) {
|
||||
log.warn("Unable to tell HS {} about invite being mapped", domain, e);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private class MappingChecker implements Runnable {
|
||||
|
||||
private IThreePidInviteReply reply;
|
||||
|
||||
MappingChecker(IThreePidInviteReply reply) {
|
||||
this.reply = reply;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
log.info("Searching for mapping created since invite {} was created", getIdForLog(reply));
|
||||
Optional<SingleLookupReply> result = lookupMgr.find(reply.getInvite().getMedium(), reply.getInvite().getAddress(), true);
|
||||
if (result.isPresent()) {
|
||||
SingleLookupReply lookup = result.get();
|
||||
log.info("Found mapping for pending invite {}", getIdForLog(reply));
|
||||
publishMapping(reply, lookup.getMxid().getId());
|
||||
} else {
|
||||
log.info("No mapping for pending invite {}", getIdForLog(reply));
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
log.error("Unable to process invite", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
74
src/main/java/io/kamax/mxisd/invitation/ThreePidInvite.java
Normal file
74
src/main/java/io/kamax/mxisd/invitation/ThreePidInvite.java
Normal file
@@ -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.invitation;
|
||||
|
||||
import io.kamax.matrix._MatrixID;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ThreePidInvite implements IThreePidInvite {
|
||||
|
||||
private _MatrixID sender;
|
||||
private String medium;
|
||||
private String address;
|
||||
private String roomId;
|
||||
private Map<String, String> properties;
|
||||
|
||||
public ThreePidInvite(_MatrixID sender, String medium, String address, String roomId) {
|
||||
this.sender = sender;
|
||||
this.medium = medium;
|
||||
this.address = address;
|
||||
this.roomId = roomId;
|
||||
this.properties = new HashMap<>();
|
||||
}
|
||||
|
||||
public ThreePidInvite(_MatrixID sender, String medium, String address, String roomId, Map<String, String> properties) {
|
||||
this(sender, medium, address, roomId);
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public _MatrixID getSender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMedium() {
|
||||
return medium;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRoomId() {
|
||||
return roomId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
}
|
@@ -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.invitation;
|
||||
|
||||
public class ThreePidInviteReply implements IThreePidInviteReply {
|
||||
|
||||
private String id;
|
||||
private IThreePidInvite invite;
|
||||
private String token;
|
||||
private String displayName;
|
||||
|
||||
public ThreePidInviteReply(String id, IThreePidInvite invite, String token, String displayName) {
|
||||
this.id = id;
|
||||
this.invite = invite;
|
||||
this.token = token;
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IThreePidInvite getInvite() {
|
||||
return invite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
}
|
115
src/main/java/io/kamax/mxisd/key/KeyManager.java
Normal file
115
src/main/java/io/kamax/mxisd/key/KeyManager.java
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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.key;
|
||||
|
||||
import io.kamax.mxisd.config.KeyConfig;
|
||||
import net.i2p.crypto.eddsa.EdDSAEngine;
|
||||
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
|
||||
import net.i2p.crypto.eddsa.EdDSAPublicKey;
|
||||
import net.i2p.crypto.eddsa.KeyPairGenerator;
|
||||
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
|
||||
import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
|
||||
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
|
||||
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.KeyPair;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class KeyManager {
|
||||
|
||||
@Autowired
|
||||
private KeyConfig keyCfg;
|
||||
|
||||
private EdDSAParameterSpec keySpecs;
|
||||
private EdDSAEngine signEngine;
|
||||
private List<KeyPair> keys;
|
||||
|
||||
@PostConstruct
|
||||
public void build() {
|
||||
try {
|
||||
keySpecs = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512);
|
||||
signEngine = new EdDSAEngine(MessageDigest.getInstance(keySpecs.getHashAlgorithm()));
|
||||
keys = new ArrayList<>();
|
||||
|
||||
Path privKey = Paths.get(keyCfg.getPath());
|
||||
|
||||
if (!Files.exists(privKey)) {
|
||||
KeyPair pair = (new KeyPairGenerator()).generateKeyPair();
|
||||
String keyEncoded = Base64.getEncoder().encodeToString(pair.getPrivate().getEncoded());
|
||||
FileUtils.writeStringToFile(privKey.toFile(), keyEncoded, StandardCharsets.ISO_8859_1);
|
||||
keys.add(pair);
|
||||
} else {
|
||||
if (Files.isDirectory(privKey)) {
|
||||
throw new RuntimeException("Invalid path for private key: " + privKey.toString());
|
||||
}
|
||||
|
||||
if (Files.isReadable(privKey)) {
|
||||
byte[] seed = Base64.getDecoder().decode(FileUtils.readFileToString(privKey.toFile(), StandardCharsets.ISO_8859_1));
|
||||
EdDSAPrivateKeySpec privKeySpec = new EdDSAPrivateKeySpec(seed, keySpecs);
|
||||
EdDSAPublicKeySpec pubKeySpec = new EdDSAPublicKeySpec(privKeySpec.getA(), keySpecs);
|
||||
keys.add(new KeyPair(new EdDSAPublicKey(pubKeySpec), new EdDSAPrivateKey(privKeySpec)));
|
||||
}
|
||||
}
|
||||
} catch (NoSuchAlgorithmException | IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int getCurrentIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public KeyPair getKeys(int index) {
|
||||
return keys.get(index);
|
||||
}
|
||||
|
||||
public PrivateKey getPrivateKey(int index) {
|
||||
return getKeys(index).getPrivate();
|
||||
}
|
||||
|
||||
public EdDSAPublicKey getPublicKey(int index) {
|
||||
return (EdDSAPublicKey) getKeys(index).getPublic();
|
||||
}
|
||||
|
||||
public EdDSAParameterSpec getSpecs() {
|
||||
return keySpecs;
|
||||
}
|
||||
|
||||
public String getPublicKeyBase64(int index) {
|
||||
return Base64.getEncoder().encodeToString(getPublicKey(index).getAbyte());
|
||||
}
|
||||
|
||||
}
|
73
src/main/java/io/kamax/mxisd/lookup/ALookupRequest.java
Normal file
73
src/main/java/io/kamax/mxisd/lookup/ALookupRequest.java
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.lookup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ALookupRequest {
|
||||
|
||||
private String id;
|
||||
private String requester;
|
||||
private String userAgent;
|
||||
private boolean isRecursive;
|
||||
private List<String> recurseHosts;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getRequester() {
|
||||
return requester;
|
||||
}
|
||||
|
||||
public void setRequester(String requester) {
|
||||
this.requester = requester;
|
||||
}
|
||||
|
||||
public String getUserAgent() {
|
||||
return userAgent;
|
||||
}
|
||||
|
||||
public void setUserAgent(String userAgent) {
|
||||
this.userAgent = userAgent;
|
||||
}
|
||||
|
||||
public boolean isRecursive() {
|
||||
return isRecursive;
|
||||
}
|
||||
|
||||
public void setRecursive(boolean recursive) {
|
||||
isRecursive = recursive;
|
||||
}
|
||||
|
||||
public List<String> getRecurseHosts() {
|
||||
return recurseHosts;
|
||||
}
|
||||
|
||||
public void setRecurseHosts(List<String> recurseHosts) {
|
||||
this.recurseHosts = recurseHosts;
|
||||
}
|
||||
|
||||
}
|
37
src/main/java/io/kamax/mxisd/lookup/BulkLookupRequest.java
Normal file
37
src/main/java/io/kamax/mxisd/lookup/BulkLookupRequest.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.lookup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BulkLookupRequest extends ALookupRequest {
|
||||
|
||||
private List<ThreePidMapping> mappings;
|
||||
|
||||
public List<ThreePidMapping> getMappings() {
|
||||
return mappings;
|
||||
}
|
||||
|
||||
public void setMappings(List<ThreePidMapping> mappings) {
|
||||
this.mappings = mappings;
|
||||
}
|
||||
|
||||
}
|
116
src/main/java/io/kamax/mxisd/lookup/SingleLookupReply.java
Normal file
116
src/main/java/io/kamax/mxisd/lookup/SingleLookupReply.java
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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.lookup;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import io.kamax.matrix.MatrixID;
|
||||
import io.kamax.matrix._MatrixID;
|
||||
import io.kamax.mxisd.controller.v1.io.SingeLookupReplyJson;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public class SingleLookupReply {
|
||||
|
||||
private static Gson gson = new Gson();
|
||||
|
||||
private boolean isRecursive;
|
||||
private boolean isSigned;
|
||||
private String body;
|
||||
private SingleLookupRequest request;
|
||||
private _MatrixID mxid;
|
||||
private Instant notBefore;
|
||||
private Instant notAfter;
|
||||
private Instant timestamp;
|
||||
|
||||
public static SingleLookupReply fromRecursive(SingleLookupRequest request, String body) {
|
||||
SingleLookupReply reply = new SingleLookupReply();
|
||||
reply.isRecursive = true;
|
||||
reply.request = request;
|
||||
reply.body = body;
|
||||
|
||||
try {
|
||||
SingeLookupReplyJson json = gson.fromJson(body, SingeLookupReplyJson.class);
|
||||
reply.mxid = new MatrixID(json.getMxid());
|
||||
reply.notAfter = Instant.ofEpochMilli(json.getNot_after());
|
||||
reply.notBefore = Instant.ofEpochMilli(json.getNot_before());
|
||||
reply.timestamp = Instant.ofEpochMilli(json.getTs());
|
||||
reply.isSigned = json.isSigned();
|
||||
} catch (JsonSyntaxException e) {
|
||||
// stub - we only want to try, nothing more
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
private SingleLookupReply() {
|
||||
// stub
|
||||
}
|
||||
|
||||
public SingleLookupReply(SingleLookupRequest request, String mxid) {
|
||||
this(request, new MatrixID(mxid));
|
||||
}
|
||||
|
||||
public SingleLookupReply(SingleLookupRequest request, _MatrixID mxid) {
|
||||
this(request, mxid, Instant.now(), Instant.ofEpochMilli(0), Instant.ofEpochMilli(253402300799000L));
|
||||
}
|
||||
|
||||
public SingleLookupReply(SingleLookupRequest request, _MatrixID mxid, Instant timestamp, Instant notBefore, Instant notAfter) {
|
||||
this.request = request;
|
||||
this.mxid = mxid;
|
||||
this.timestamp = timestamp;
|
||||
this.notBefore = notBefore;
|
||||
this.notAfter = notAfter;
|
||||
}
|
||||
|
||||
public boolean isRecursive() {
|
||||
return isRecursive;
|
||||
}
|
||||
|
||||
public boolean isSigned() {
|
||||
return isSigned;
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public SingleLookupRequest getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
public _MatrixID getMxid() {
|
||||
return mxid;
|
||||
}
|
||||
|
||||
public Instant getNotBefore() {
|
||||
return notBefore;
|
||||
}
|
||||
|
||||
public Instant getNotAfter() {
|
||||
return notAfter;
|
||||
}
|
||||
|
||||
public Instant getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
}
|
44
src/main/java/io/kamax/mxisd/lookup/SingleLookupRequest.java
Normal file
44
src/main/java/io/kamax/mxisd/lookup/SingleLookupRequest.java
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.lookup;
|
||||
|
||||
public class SingleLookupRequest extends ALookupRequest {
|
||||
|
||||
private String type;
|
||||
private String threePid;
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getThreePid() {
|
||||
return threePid;
|
||||
}
|
||||
|
||||
public void setThreePid(String threePid) {
|
||||
this.threePid = threePid;
|
||||
}
|
||||
|
||||
}
|
95
src/main/java/io/kamax/mxisd/lookup/ThreePidMapping.java
Normal file
95
src/main/java/io/kamax/mxisd/lookup/ThreePidMapping.java
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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.lookup;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import io.kamax.mxisd.ThreePid;
|
||||
|
||||
public class ThreePidMapping {
|
||||
|
||||
private static Gson gson = new Gson();
|
||||
|
||||
private String medium;
|
||||
private String value;
|
||||
private String mxid;
|
||||
|
||||
public ThreePidMapping() {
|
||||
// stub
|
||||
}
|
||||
|
||||
public ThreePidMapping(ThreePid threePid, String mxid) {
|
||||
this(threePid.getMedium(), threePid.getAddress(), mxid);
|
||||
}
|
||||
|
||||
public ThreePidMapping(String medium, String value, String mxid) {
|
||||
setMedium(medium);
|
||||
setValue(value);
|
||||
setMxid(mxid);
|
||||
}
|
||||
|
||||
public String getMedium() {
|
||||
return medium;
|
||||
}
|
||||
|
||||
public void setMedium(String medium) {
|
||||
this.medium = medium;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getMxid() {
|
||||
return mxid;
|
||||
}
|
||||
|
||||
public void setMxid(String mxid) {
|
||||
this.mxid = mxid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ThreePidMapping that = (ThreePidMapping) o;
|
||||
|
||||
if (medium != null ? !medium.equals(that.medium) : that.medium != null) return false;
|
||||
return value != null ? value.equals(that.value) : that.value == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = medium != null ? medium.hashCode() : 0;
|
||||
result = 31 * result + (value != null ? value.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return gson.toJson(this);
|
||||
}
|
||||
|
||||
}
|
40
src/main/java/io/kamax/mxisd/lookup/ThreePidValidation.java
Normal file
40
src/main/java/io/kamax/mxisd/lookup/ThreePidValidation.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.lookup;
|
||||
|
||||
import io.kamax.mxisd.ThreePid;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public class ThreePidValidation extends ThreePid {
|
||||
|
||||
private Instant validation;
|
||||
|
||||
public ThreePidValidation(ThreePid tpid, Instant validation) {
|
||||
super(tpid);
|
||||
this.validation = validation;
|
||||
}
|
||||
|
||||
public Instant getValidation() {
|
||||
return validation;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.lookup.fetcher;
|
||||
|
||||
import io.kamax.mxisd.lookup.SingleLookupReply;
|
||||
import io.kamax.mxisd.lookup.SingleLookupRequest;
|
||||
import io.kamax.mxisd.lookup.ThreePidMapping;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface IBridgeFetcher {
|
||||
|
||||
Optional<SingleLookupReply> find(SingleLookupRequest request);
|
||||
|
||||
List<ThreePidMapping> populate(List<ThreePidMapping> mappings);
|
||||
|
||||
}
|
@@ -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.lookup.fetcher;
|
||||
|
||||
import io.kamax.mxisd.lookup.SingleLookupReply;
|
||||
import io.kamax.mxisd.lookup.SingleLookupRequest;
|
||||
import io.kamax.mxisd.lookup.ThreePidMapping;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface IRemoteIdentityServerFetcher {
|
||||
|
||||
boolean isUsable(String remote);
|
||||
|
||||
Optional<SingleLookupReply> find(String remote, SingleLookupRequest request);
|
||||
|
||||
List<ThreePidMapping> find(String remote, List<ThreePidMapping> mappings);
|
||||
|
||||
}
|
@@ -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.lookup.provider;
|
||||
|
||||
import io.kamax.mxisd.config.RecursiveLookupBridgeConfig;
|
||||
import io.kamax.mxisd.lookup.SingleLookupReply;
|
||||
import io.kamax.mxisd.lookup.SingleLookupRequest;
|
||||
import io.kamax.mxisd.lookup.ThreePidMapping;
|
||||
import io.kamax.mxisd.lookup.fetcher.IBridgeFetcher;
|
||||
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 java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class BridgeFetcher implements IBridgeFetcher {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(BridgeFetcher.class);
|
||||
|
||||
@Autowired
|
||||
private RecursiveLookupBridgeConfig cfg;
|
||||
|
||||
@Autowired
|
||||
private RemoteIdentityServerFetcher fetcher;
|
||||
|
||||
@Override
|
||||
public Optional<SingleLookupReply> find(SingleLookupRequest request) {
|
||||
Optional<String> mediumUrl = Optional.ofNullable(cfg.getMappings().get(request.getType()));
|
||||
if (mediumUrl.isPresent() && !StringUtils.isBlank(mediumUrl.get())) {
|
||||
log.info("Using specific medium bridge lookup URL {}", mediumUrl.get());
|
||||
|
||||
return fetcher.find(mediumUrl.get(), request);
|
||||
} else if (!StringUtils.isBlank(cfg.getServer())) {
|
||||
log.info("Using generic bridge lookup URL {}", cfg.getServer());
|
||||
|
||||
return fetcher.find(cfg.getServer(), request);
|
||||
} else {
|
||||
log.info("No bridge lookup URL found/configured, skipping");
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ThreePidMapping> populate(List<ThreePidMapping> mappings) {
|
||||
log.warn("Bulk lookup on bridge lookup requested, but not supported - returning empty list");
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* 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.lookup.provider;
|
||||
|
||||
import io.kamax.mxisd.config.MatrixConfig;
|
||||
import io.kamax.mxisd.lookup.SingleLookupReply;
|
||||
import io.kamax.mxisd.lookup.SingleLookupRequest;
|
||||
import io.kamax.mxisd.lookup.ThreePidMapping;
|
||||
import io.kamax.mxisd.lookup.fetcher.IRemoteIdentityServerFetcher;
|
||||
import io.kamax.mxisd.matrix.IdentityServerUtils;
|
||||
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 java.util.*;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.RecursiveTask;
|
||||
|
||||
@Component
|
||||
class DnsLookupProvider implements IThreePidProvider {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(DnsLookupProvider.class);
|
||||
|
||||
@Autowired
|
||||
private MatrixConfig mxCfg;
|
||||
|
||||
@Autowired
|
||||
private IRemoteIdentityServerFetcher fetcher;
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocal() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
private Optional<String> getDomain(String email) {
|
||||
int atIndex = email.lastIndexOf("@");
|
||||
if (atIndex == -1) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(email.substring(atIndex + 1));
|
||||
}
|
||||
|
||||
// TODO use caching mechanism
|
||||
private Optional<String> findIdentityServerForDomain(String domain) {
|
||||
if (StringUtils.equals(mxCfg.getDomain(), domain)) {
|
||||
log.info("We are authoritative for {}, no remote lookup", domain);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return IdentityServerUtils.findIsUrlForDomain(domain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<SingleLookupReply> find(SingleLookupRequest request) {
|
||||
if (!StringUtils.equals("email", request.getType())) { // TODO use enum
|
||||
log.info("Skipping unsupported type {} for {}", request.getType(), request.getThreePid());
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
log.info("Performing DNS lookup for {}", request.getThreePid());
|
||||
|
||||
String domain = request.getThreePid().substring(request.getThreePid().lastIndexOf("@") + 1);
|
||||
log.info("Domain name for {}: {}", request.getThreePid(), domain);
|
||||
Optional<String> baseUrl = findIdentityServerForDomain(domain);
|
||||
|
||||
if (baseUrl.isPresent()) {
|
||||
return fetcher.find(baseUrl.get(), request);
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ThreePidMapping> populate(List<ThreePidMapping> mappings) {
|
||||
Map<String, List<ThreePidMapping>> domains = new HashMap<>();
|
||||
|
||||
for (ThreePidMapping mapping : mappings) {
|
||||
if (!StringUtils.equals("email", mapping.getMedium())) {
|
||||
log.info("Skipping unsupported type {} for {}", mapping.getMedium(), mapping.getValue());
|
||||
continue;
|
||||
}
|
||||
|
||||
Optional<String> domainOpt = getDomain(mapping.getValue());
|
||||
if (!domainOpt.isPresent()) {
|
||||
log.warn("No domain for 3PID {}", mapping.getValue());
|
||||
continue;
|
||||
}
|
||||
|
||||
String domain = domainOpt.get();
|
||||
List<ThreePidMapping> domainMappings = domains.computeIfAbsent(domain, s -> new ArrayList<>());
|
||||
domainMappings.add(mapping);
|
||||
}
|
||||
|
||||
log.info("Looking mappings across {} domains", domains.keySet().size());
|
||||
ForkJoinPool pool = ForkJoinPool.commonPool();
|
||||
RecursiveTask<List<ThreePidMapping>> task = new RecursiveTask<List<ThreePidMapping>>() {
|
||||
|
||||
@Override
|
||||
protected List<ThreePidMapping> compute() {
|
||||
List<ThreePidMapping> mappingsFound = new ArrayList<>();
|
||||
List<DomainBulkLookupTask> tasks = new ArrayList<>();
|
||||
|
||||
for (String domain : domains.keySet()) {
|
||||
DomainBulkLookupTask domainTask = new DomainBulkLookupTask(domain, domains.get(domain));
|
||||
domainTask.fork();
|
||||
tasks.add(domainTask);
|
||||
}
|
||||
|
||||
for (DomainBulkLookupTask task : tasks) {
|
||||
mappingsFound.addAll(task.join());
|
||||
}
|
||||
|
||||
return mappingsFound;
|
||||
}
|
||||
};
|
||||
pool.submit(task);
|
||||
pool.shutdown();
|
||||
|
||||
List<ThreePidMapping> mappingsFound = task.join();
|
||||
log.info("Found {} mappings overall", mappingsFound.size());
|
||||
return mappingsFound;
|
||||
}
|
||||
|
||||
private class DomainBulkLookupTask extends RecursiveTask<List<ThreePidMapping>> {
|
||||
|
||||
private String domain;
|
||||
private List<ThreePidMapping> mappings;
|
||||
|
||||
DomainBulkLookupTask(String domain, List<ThreePidMapping> mappings) {
|
||||
this.domain = domain;
|
||||
this.mappings = mappings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ThreePidMapping> compute() {
|
||||
List<ThreePidMapping> domainMappings = new ArrayList<>();
|
||||
|
||||
Optional<String> baseUrl = findIdentityServerForDomain(domain);
|
||||
if (!baseUrl.isPresent()) {
|
||||
log.info("No usable Identity server for domain {}", domain);
|
||||
} else {
|
||||
domainMappings.addAll(fetcher.find(baseUrl.get(), mappings));
|
||||
log.info("Found {} mappings in domain {}", domainMappings.size(), domain);
|
||||
}
|
||||
|
||||
return domainMappings;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user