Properly handle invites with LDAP backend

This commit is contained in:
Maxime Dor
2017-09-13 01:16:02 +02:00
parent 001de470ca
commit 548dace78c
17 changed files with 344 additions and 82 deletions

View File

@@ -25,6 +25,7 @@ import io.kamax.matrix.ThreePid;
import io.kamax.mxisd.exception.BadRequestException;
import io.kamax.mxisd.exception.MappingAlreadyExistsException;
import io.kamax.mxisd.invitation.sender.IInviteSender;
import io.kamax.mxisd.lookup.SingleLookupReply;
import io.kamax.mxisd.lookup.ThreePidMapping;
import io.kamax.mxisd.lookup.strategy.LookupStrategy;
import io.kamax.mxisd.signature.SignatureManager;
@@ -51,12 +52,15 @@ import org.xbill.DNS.TextParseException;
import org.xbill.DNS.Type;
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 {
@@ -92,6 +96,15 @@ public class InvitationManager {
}
}
@PreDestroy
private void preDestroy() {
ForkJoinPool.commonPool().awaitQuiescence(1, TimeUnit.MINUTES);
}
private String getId(IThreePidInviteReply reply) {
return reply.getInvite().getSender().getId() + ":" + reply.getInvite().getRoomId() + ":" + reply.getInvite().getMedium() + ":" + reply.getInvite().getAddress();
}
String getSrvRecordName(String domain) {
return "_matrix._tcp." + domain;
}
@@ -162,15 +175,28 @@ public class InvitationManager {
return reply;
}
public void lookupMappingsForInvites() {
log.info("Checking for existing mapping for pending invites");
for (IThreePidInviteReply reply : invitations.values()) {
log.info("Processing invite {}", getId(reply));
ForkJoinPool.commonPool().submit(new MappingChecker(reply));
}
}
public void publishMappingIfInvited(ThreePidMapping threePid) {
ThreePid key = new ThreePid(threePid.getMedium(), threePid.getValue());
IThreePidInviteReply reply = invitations.get(key);
if (reply == null) {
log.info("{}:{} does not have a pending invite, no mapping to publish", threePid.getMedium(), threePid.getValue());
return;
} else {
log.info("{}:{} has an invite pending, publishing mapping", threePid.getMedium(), threePid.getValue());
publishMapping(reply, threePid.getMxid());
}
}
log.info("{}:{} has an invite pending, publishing mapping", threePid.getMedium(), threePid.getValue());
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);
@@ -180,14 +206,14 @@ public class InvitationManager {
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(); // TODO use Gson instead
obj.put("mxid", threePid.getMxid());
obj.put("mxid", mxid);
obj.put("token", reply.getToken());
obj.put("signatures", signMgr.signMessageJson(obj.toString()));
JSONObject objUp = new JSONObject();
objUp.put("mxid", threePid.getMxid());
objUp.put("medium", threePid.getMedium());
objUp.put("address", threePid.getValue());
objUp.put("mxid", mxid);
objUp.put("medium", medium);
objUp.put("address", address);
objUp.put("sender", reply.getInvite().getSender().getId());
objUp.put("room_id", reply.getInvite().getRoomId());
objUp.put("signed", obj);
@@ -196,9 +222,9 @@ public class InvitationManager {
JSONArray invites = new JSONArray();
invites.put(objUp);
content.put("invites", invites);
content.put("medium", threePid.getMedium());
content.put("address", threePid.getValue());
content.put("mxid", threePid.getMxid());
content.put("medium", medium);
content.put("address", address);
content.put("mxid", mxid);
content.put("signatures", signMgr.signMessageJson(content.toString()));
@@ -217,8 +243,36 @@ public class InvitationManager {
} catch (IOException e) {
log.warn("Unable to tell HS {} about invite being mapped", domain, e);
}
invitations.remove(key);
invitations.remove(new ThreePid(medium, address));
log.info("Removed invite from internal store");
}).start();
}
private class MappingChecker implements Runnable {
private IThreePidInviteReply reply;
public MappingChecker(IThreePidInviteReply reply) {
this.reply = reply;
}
@Override
public void run() {
try {
log.info("Searching for mapping created since invite {} was created", getId(reply));
Optional<SingleLookupReply> result = lookupMgr.find(reply.getInvite().getMedium(), reply.getInvite().getAddress(), true);
log.info("Result: {}", result);
if (result.isPresent()) {
SingleLookupReply lookup = result.get();
log.info("Found mapping for pending invite {}", getId(reply));
publishMapping(reply, lookup.getMxid().getId());
} else {
log.info("No mapping for pending invite {}", getId(reply));
}
} catch (Throwable t) {
log.error("Unable to process invite", t);
}
}
}
}