Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
eb1326c56a | ||
|
10cdb4360e |
@@ -7,7 +7,7 @@ Default values:
|
|||||||
```.yaml
|
```.yaml
|
||||||
matrix:
|
matrix:
|
||||||
v1: true # deprecated
|
v1: true # deprecated
|
||||||
v2: true
|
v2: false
|
||||||
```
|
```
|
||||||
|
|
||||||
To disable change value to `false`.
|
To disable change value to `false`.
|
||||||
@@ -19,8 +19,14 @@ matrix:
|
|||||||
```
|
```
|
||||||
NOTE: Riot Web version 1.5.5 and below checks the v1 for backward compatibility.
|
NOTE: Riot Web version 1.5.5 and below checks the v1 for backward compatibility.
|
||||||
|
|
||||||
|
NOTE: v2 disabled by default in order to preserve backward compatibility.
|
||||||
|
|
||||||
## Terms
|
## Terms
|
||||||
|
|
||||||
|
###### Requires: No.
|
||||||
|
|
||||||
|
Administrator can omit terms configuration. In this case the terms checking will be disabled.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```.yaml
|
```.yaml
|
||||||
policy:
|
policy:
|
||||||
@@ -45,7 +51,7 @@ Where:
|
|||||||
- `version` -- the terms version.
|
- `version` -- the terms version.
|
||||||
- `lang` -- the term language.
|
- `lang` -- the term language.
|
||||||
- `name` -- the name of the term.
|
- `name` -- the name of the term.
|
||||||
- `url` -- the url of the term.
|
- `url` -- the url of the term. Might be any url (i.e. from another host) for a html page.
|
||||||
- `regexp` -- regexp patterns for API which should be available only after accepting the terms.
|
- `regexp` -- regexp patterns for API which should be available only after accepting the terms.
|
||||||
|
|
||||||
API will be checks for accepted terms only with authorization.
|
API will be checks for accepted terms only with authorization.
|
||||||
@@ -72,6 +78,10 @@ There is only one exception: [`POST /_matrix/identity/v2/terms`](https://matrix.
|
|||||||
|
|
||||||
Hashes and the pepper updates together according to the `rotationPolicy`.
|
Hashes and the pepper updates together according to the `rotationPolicy`.
|
||||||
|
|
||||||
|
###### Requires: No.
|
||||||
|
|
||||||
|
In case the `none` algorithms ma1sd will be lookup using the v1 bulk API.
|
||||||
|
|
||||||
```.yaml
|
```.yaml
|
||||||
hashing:
|
hashing:
|
||||||
enabled: true # enable or disable the hash lookup MSC2140 (default is false)
|
enabled: true # enable or disable the hash lookup MSC2140 (default is false)
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
matrix:
|
matrix:
|
||||||
domain: ''
|
domain: ''
|
||||||
v1: true # deprecated
|
v1: true # deprecated
|
||||||
v2: true # MSC2140 API v2
|
v2: false # MSC2140 API v2. Disabled by default in order to preserve backward compatibility.
|
||||||
|
|
||||||
|
|
||||||
################
|
################
|
||||||
@@ -115,16 +115,16 @@ threepid:
|
|||||||
|
|
||||||
#### MSC2134 (hash lookup)
|
#### MSC2134 (hash lookup)
|
||||||
|
|
||||||
hashing:
|
#hashing:
|
||||||
enabled: false # enable or disable the hash lookup MSC2140 (default is false)
|
# enabled: false # enable or disable the hash lookup MSC2140 (default is false)
|
||||||
pepperLength: 20 # length of the pepper value (default is 20)
|
# pepperLength: 20 # length of the pepper value (default is 20)
|
||||||
rotationPolicy: per_requests # or `per_seconds` how often the hashes will be updating
|
# rotationPolicy: per_requests # or `per_seconds` how often the hashes will be updating
|
||||||
hashStorageType: sql # or `in_memory` where the hashes will be stored
|
# hashStorageType: sql # or `in_memory` where the hashes will be stored
|
||||||
algorithms:
|
# algorithms:
|
||||||
- none # the same as v1 bulk lookup
|
# - none # the same as v1 bulk lookup
|
||||||
- sha256 # hash the 3PID and pepper.
|
# - sha256 # hash the 3PID and pepper.
|
||||||
delay: 2m # how often hashes will be updated if rotation policy = per_seconds (default is 10s)
|
# delay: 2m # how often hashes will be updated if rotation policy = per_seconds (default is 10s)
|
||||||
requests: 10 # how many lookup requests will be performed before updating hashes if rotation policy = per_requests (default is 10)
|
# requests: 10 # how many lookup requests will be performed before updating hashes if rotation policy = per_requests (default is 10)
|
||||||
|
|
||||||
### hash lookup for synapseSql provider.
|
### hash lookup for synapseSql provider.
|
||||||
# synapseSql:
|
# synapseSql:
|
||||||
@@ -132,19 +132,19 @@ hashing:
|
|||||||
# query: 'select user_id as mxid, medium, address from user_threepids' # query for retrive 3PIDs for hashes.
|
# query: 'select user_id as mxid, medium, address from user_threepids' # query for retrive 3PIDs for hashes.
|
||||||
|
|
||||||
#### MSC2140 (Terms)
|
#### MSC2140 (Terms)
|
||||||
policy:
|
#policy:
|
||||||
policies:
|
# policies:
|
||||||
term_name: # term name
|
# term_name: # term name
|
||||||
version: 1.0 # version
|
# version: 1.0 # version
|
||||||
terms:
|
# terms:
|
||||||
en: # lang
|
# en: # lang
|
||||||
name: term name en # localized name
|
# name: term name en # localized name
|
||||||
url: https://ma1sd.host.tld/term_en.html # localized url
|
# url: https://ma1sd.host.tld/term_en.html # localized url
|
||||||
fe: # lang
|
# fe: # lang
|
||||||
name: term name fr # localized name
|
# name: term name fr # localized name
|
||||||
url: https://ma1sd.host.tld/term_fr.html # localized url
|
# url: https://ma1sd.host.tld/term_fr.html # localized url
|
||||||
regexp:
|
# regexp:
|
||||||
- '/_matrix/identity/v2/account.*'
|
# - '/_matrix/identity/v2/account.*'
|
||||||
- '/_matrix/identity/v2/hash_details'
|
# - '/_matrix/identity/v2/hash_details'
|
||||||
- '/_matrix/identity/v2/lookup'
|
# - '/_matrix/identity/v2/lookup'
|
||||||
|
#
|
||||||
|
@@ -189,23 +189,32 @@ public class HttpMxisd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void accountEndpoints(RoutingHandler routingHandler) {
|
private void accountEndpoints(RoutingHandler routingHandler) {
|
||||||
routingHandler.post(AccountRegisterHandler.Path, SaneHandler.around(new AccountRegisterHandler(m.getAccMgr())));
|
MatrixConfig matrixConfig = m.getConfig().getMatrix();
|
||||||
wrapWithTokenAndAuthorizationHandlers(routingHandler, Methods.GET, sane(new AccountGetUserInfoHandler(m.getAccMgr())),
|
if (matrixConfig.isV2()) {
|
||||||
AccountGetUserInfoHandler.Path, true);
|
routingHandler.post(AccountRegisterHandler.Path, SaneHandler.around(new AccountRegisterHandler(m.getAccMgr())));
|
||||||
wrapWithTokenAndAuthorizationHandlers(routingHandler, Methods.GET, sane(new AccountLogoutHandler(m.getAccMgr())),
|
wrapWithTokenAndAuthorizationHandlers(routingHandler, Methods.GET, sane(new AccountGetUserInfoHandler(m.getAccMgr())),
|
||||||
AccountLogoutHandler.Path, true);
|
AccountGetUserInfoHandler.Path, true);
|
||||||
|
wrapWithTokenAndAuthorizationHandlers(routingHandler, Methods.GET, sane(new AccountLogoutHandler(m.getAccMgr())),
|
||||||
|
AccountLogoutHandler.Path, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void termsEndpoints(RoutingHandler routingHandler) {
|
private void termsEndpoints(RoutingHandler routingHandler) {
|
||||||
routingHandler.get(GetTermsHandler.PATH, new GetTermsHandler(m.getConfig().getPolicy()));
|
MatrixConfig matrixConfig = m.getConfig().getMatrix();
|
||||||
routingHandler.post(AcceptTermsHandler.PATH, sane(new AcceptTermsHandler(m.getAccMgr())));
|
if (matrixConfig.isV2()) {
|
||||||
|
routingHandler.get(GetTermsHandler.PATH, new GetTermsHandler(m.getConfig().getPolicy()));
|
||||||
|
routingHandler.post(AcceptTermsHandler.PATH, sane(new AcceptTermsHandler(m.getAccMgr())));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void hashEndpoints(RoutingHandler routingHandler) {
|
private void hashEndpoints(RoutingHandler routingHandler) {
|
||||||
wrapWithTokenAndAuthorizationHandlers(routingHandler, Methods.GET, sane(new HashDetailsHandler(m.getHashManager())),
|
MatrixConfig matrixConfig = m.getConfig().getMatrix();
|
||||||
HashDetailsHandler.PATH, true);
|
if (matrixConfig.isV2()) {
|
||||||
wrapWithTokenAndAuthorizationHandlers(routingHandler, Methods.POST,
|
wrapWithTokenAndAuthorizationHandlers(routingHandler, Methods.GET, sane(new HashDetailsHandler(m.getHashManager())),
|
||||||
sane(new HashLookupHandler(m.getIdentity(), m.getHashManager())), HashLookupHandler.Path, true);
|
HashDetailsHandler.PATH, true);
|
||||||
|
wrapWithTokenAndAuthorizationHandlers(routingHandler, Methods.POST,
|
||||||
|
sane(new HashLookupHandler(m.getIdentity(), m.getHashManager())), HashLookupHandler.Path, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addEndpoints(RoutingHandler routingHandler, HttpString method, boolean useAuthorization, ApiHandler... handlers) {
|
private void addEndpoints(RoutingHandler routingHandler, HttpString method, boolean useAuthorization, ApiHandler... handlers) {
|
||||||
|
@@ -10,6 +10,7 @@ import io.kamax.mxisd.exception.BadRequestException;
|
|||||||
import io.kamax.mxisd.exception.InvalidCredentialsException;
|
import io.kamax.mxisd.exception.InvalidCredentialsException;
|
||||||
import io.kamax.mxisd.exception.NotFoundException;
|
import io.kamax.mxisd.exception.NotFoundException;
|
||||||
import io.kamax.mxisd.matrix.HomeserverFederationResolver;
|
import io.kamax.mxisd.matrix.HomeserverFederationResolver;
|
||||||
|
import io.kamax.mxisd.matrix.HomeserverVerifier;
|
||||||
import io.kamax.mxisd.storage.IStorage;
|
import io.kamax.mxisd.storage.IStorage;
|
||||||
import io.kamax.mxisd.storage.ormlite.dao.AccountDao;
|
import io.kamax.mxisd.storage.ormlite.dao.AccountDao;
|
||||||
import org.apache.http.HttpStatus;
|
import org.apache.http.HttpStatus;
|
||||||
@@ -22,18 +23,10 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.cert.Certificate;
|
|
||||||
import java.security.cert.CertificateParsingException;
|
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import javax.net.ssl.HostnameVerifier;
|
|
||||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
|
||||||
import javax.net.ssl.SSLSession;
|
|
||||||
|
|
||||||
public class AccountManager {
|
public class AccountManager {
|
||||||
|
|
||||||
@@ -80,7 +73,7 @@ public class AccountManager {
|
|||||||
homeserverURL + "/_matrix/federation/v1/openid/userinfo?access_token=" + openIdToken.getAccessToken());
|
homeserverURL + "/_matrix/federation/v1/openid/userinfo?access_token=" + openIdToken.getAccessToken());
|
||||||
String userId;
|
String userId;
|
||||||
try (CloseableHttpClient httpClient = HttpClients.custom()
|
try (CloseableHttpClient httpClient = HttpClients.custom()
|
||||||
.setSSLHostnameVerifier(new MatrixHostnameVerifier(homeserverTarget.getDomain())).build()) {
|
.setSSLHostnameVerifier(new HomeserverVerifier(homeserverTarget.getDomain())).build()) {
|
||||||
try (CloseableHttpResponse response = httpClient.execute(getUserInfo)) {
|
try (CloseableHttpResponse response = httpClient.execute(getUserInfo)) {
|
||||||
int statusCode = response.getStatusLine().getStatusCode();
|
int statusCode = response.getStatusLine().getStatusCode();
|
||||||
if (statusCode == HttpStatus.SC_OK) {
|
if (statusCode == HttpStatus.SC_OK) {
|
||||||
@@ -170,74 +163,4 @@ public class AccountManager {
|
|||||||
public MatrixConfig getMatrixConfig() {
|
public MatrixConfig getMatrixConfig() {
|
||||||
return matrixConfig;
|
return matrixConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MatrixHostnameVerifier implements HostnameVerifier {
|
|
||||||
|
|
||||||
private static final String ALT_DNS_NAME_TYPE = "2";
|
|
||||||
private static final String ALT_IP_ADDRESS_TYPE = "7";
|
|
||||||
|
|
||||||
private final String matrixHostname;
|
|
||||||
|
|
||||||
public MatrixHostnameVerifier(String matrixHostname) {
|
|
||||||
this.matrixHostname = matrixHostname;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean verify(String hostname, SSLSession session) {
|
|
||||||
try {
|
|
||||||
Certificate peerCertificate = session.getPeerCertificates()[0];
|
|
||||||
if (peerCertificate instanceof X509Certificate) {
|
|
||||||
X509Certificate x509Certificate = (X509Certificate) peerCertificate;
|
|
||||||
if (x509Certificate.getSubjectAlternativeNames() == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (String altSubjectName : getAltSubjectNames(x509Certificate)) {
|
|
||||||
if (match(altSubjectName)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (SSLPeerUnverifiedException | CertificateParsingException e) {
|
|
||||||
LOGGER.error("Unable to check remote host", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> getAltSubjectNames(X509Certificate x509Certificate) {
|
|
||||||
List<String> subjectNames = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
for (List<?> subjectAlternativeNames : x509Certificate.getSubjectAlternativeNames()) {
|
|
||||||
if (subjectAlternativeNames == null
|
|
||||||
|| subjectAlternativeNames.size() < 2
|
|
||||||
|| subjectAlternativeNames.get(0) == null
|
|
||||||
|| subjectAlternativeNames.get(1) == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String subjectType = subjectAlternativeNames.get(0).toString();
|
|
||||||
switch (subjectType) {
|
|
||||||
case ALT_DNS_NAME_TYPE:
|
|
||||||
case ALT_IP_ADDRESS_TYPE:
|
|
||||||
subjectNames.add(subjectAlternativeNames.get(1).toString());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOGGER.trace("Unusable subject type: " + subjectType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (CertificateParsingException e) {
|
|
||||||
LOGGER.error("Unable to parse the certificate", e);
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
return subjectNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean match(String altSubjectName) {
|
|
||||||
if (altSubjectName.startsWith("*.")) {
|
|
||||||
return altSubjectName.toLowerCase().endsWith(matrixHostname.toLowerCase());
|
|
||||||
} else {
|
|
||||||
return matrixHostname.equalsIgnoreCase(altSubjectName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -64,7 +64,7 @@ public class MatrixConfig {
|
|||||||
private String domain;
|
private String domain;
|
||||||
private Identity identity = new Identity();
|
private Identity identity = new Identity();
|
||||||
private boolean v1 = true;
|
private boolean v1 = true;
|
||||||
private boolean v2 = true;
|
private boolean v2 = false;
|
||||||
|
|
||||||
public String getDomain() {
|
public String getDomain() {
|
||||||
return domain;
|
return domain;
|
||||||
|
@@ -48,7 +48,7 @@ public class AccountRegisterHandler extends BasicHttpHandler {
|
|||||||
|
|
||||||
if (LOGGER.isInfoEnabled()) {
|
if (LOGGER.isInfoEnabled()) {
|
||||||
LOGGER.info("Registration from domain: {}, expired at {}", openIdToken.getMatrixServerName(),
|
LOGGER.info("Registration from domain: {}, expired at {}", openIdToken.getMatrixServerName(),
|
||||||
new Date(openIdToken.getExpiresIn()));
|
new Date(System.currentTimeMillis() + openIdToken.getExpiresIn()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String token = accountManager.register(openIdToken);
|
String token = accountManager.register(openIdToken);
|
||||||
|
@@ -31,6 +31,8 @@ import io.kamax.mxisd.http.undertow.handler.ApiHandler;
|
|||||||
import io.kamax.mxisd.http.undertow.handler.identity.share.LookupHandler;
|
import io.kamax.mxisd.http.undertow.handler.identity.share.LookupHandler;
|
||||||
import io.kamax.mxisd.lookup.BulkLookupRequest;
|
import io.kamax.mxisd.lookup.BulkLookupRequest;
|
||||||
import io.kamax.mxisd.lookup.HashLookupRequest;
|
import io.kamax.mxisd.lookup.HashLookupRequest;
|
||||||
|
import io.kamax.mxisd.lookup.SingleLookupReply;
|
||||||
|
import io.kamax.mxisd.lookup.SingleLookupRequest;
|
||||||
import io.kamax.mxisd.lookup.ThreePidMapping;
|
import io.kamax.mxisd.lookup.ThreePidMapping;
|
||||||
import io.kamax.mxisd.lookup.strategy.LookupStrategy;
|
import io.kamax.mxisd.lookup.strategy.LookupStrategy;
|
||||||
import io.undertow.server.HttpServerExchange;
|
import io.undertow.server.HttpServerExchange;
|
||||||
@@ -40,6 +42,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class HashLookupHandler extends LookupHandler implements ApiHandler {
|
public class HashLookupHandler extends LookupHandler implements ApiHandler {
|
||||||
|
|
||||||
@@ -89,6 +92,18 @@ public class HashLookupHandler extends LookupHandler implements ApiHandler {
|
|||||||
throw new InvalidParamException();
|
throw new InvalidParamException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClientHashLookupAnswer answer = null;
|
||||||
|
if (input.getAddresses() != null && input.getAddresses().size() > 0) {
|
||||||
|
if (input.getAddresses().size() == 1) {
|
||||||
|
answer = noneSingleLookup(request, input);
|
||||||
|
} else {
|
||||||
|
answer = noneBulkLookup(request, input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
respondJson(exchange, answer != null ? answer : new ClientHashLookupAnswer());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ClientHashLookupAnswer noneBulkLookup(HashLookupRequest request, ClientHashLookupRequest input) throws Exception {
|
||||||
BulkLookupRequest bulkLookupRequest = new BulkLookupRequest();
|
BulkLookupRequest bulkLookupRequest = new BulkLookupRequest();
|
||||||
List<ThreePidMapping> mappings = new ArrayList<>();
|
List<ThreePidMapping> mappings = new ArrayList<>();
|
||||||
for (String address : input.getAddresses()) {
|
for (String address : input.getAddresses()) {
|
||||||
@@ -107,7 +122,26 @@ public class HashLookupHandler extends LookupHandler implements ApiHandler {
|
|||||||
}
|
}
|
||||||
log.info("Finished bulk lookup request from {}", request.getRequester());
|
log.info("Finished bulk lookup request from {}", request.getRequester());
|
||||||
|
|
||||||
respondJson(exchange, answer);
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ClientHashLookupAnswer noneSingleLookup(HashLookupRequest request, ClientHashLookupRequest input) {
|
||||||
|
SingleLookupRequest singleLookupRequest = new SingleLookupRequest();
|
||||||
|
String address = input.getAddresses().get(0);
|
||||||
|
String[] parts = address.split(" ");
|
||||||
|
singleLookupRequest.setThreePid(parts[0]);
|
||||||
|
singleLookupRequest.setType(parts[1]);
|
||||||
|
|
||||||
|
ClientHashLookupAnswer answer = new ClientHashLookupAnswer();
|
||||||
|
|
||||||
|
Optional<SingleLookupReply> singleLookupReply = strategy.find(singleLookupRequest);
|
||||||
|
if (singleLookupReply.isPresent()) {
|
||||||
|
SingleLookupReply reply = singleLookupReply.get();
|
||||||
|
answer.getMappings().put(address, reply.getMxid().toString());
|
||||||
|
}
|
||||||
|
log.info("Finished single lookup request from {}", request.getRequester());
|
||||||
|
|
||||||
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sha256Algorithm(HttpServerExchange exchange, HashLookupRequest request, ClientHashLookupRequest input) {
|
private void sha256Algorithm(HttpServerExchange exchange, HashLookupRequest request, ClientHashLookupRequest input) {
|
||||||
|
@@ -77,7 +77,8 @@ public class HomeserverVerifier implements HostnameVerifier {
|
|||||||
|
|
||||||
private boolean match(String altSubjectName) {
|
private boolean match(String altSubjectName) {
|
||||||
if (altSubjectName.startsWith("*.")) {
|
if (altSubjectName.startsWith("*.")) {
|
||||||
return altSubjectName.toLowerCase().endsWith(matrixHostname.toLowerCase());
|
String subjectNameWithoutMask = altSubjectName.substring(1); // remove wildcard
|
||||||
|
return matrixHostname.toLowerCase().endsWith(subjectNameWithoutMask.toLowerCase());
|
||||||
} else {
|
} else {
|
||||||
return matrixHostname.equalsIgnoreCase(altSubjectName);
|
return matrixHostname.equalsIgnoreCase(altSubjectName);
|
||||||
}
|
}
|
||||||
|
@@ -39,6 +39,7 @@ import io.kamax.mxisd.storage.IStorage;
|
|||||||
import io.kamax.mxisd.storage.dao.IThreePidSessionDao;
|
import io.kamax.mxisd.storage.dao.IThreePidSessionDao;
|
||||||
import io.kamax.mxisd.storage.ormlite.dao.ASTransactionDao;
|
import io.kamax.mxisd.storage.ormlite.dao.ASTransactionDao;
|
||||||
import io.kamax.mxisd.storage.ormlite.dao.AccountDao;
|
import io.kamax.mxisd.storage.ormlite.dao.AccountDao;
|
||||||
|
import io.kamax.mxisd.storage.ormlite.dao.ChangelogDao;
|
||||||
import io.kamax.mxisd.storage.ormlite.dao.HashDao;
|
import io.kamax.mxisd.storage.ormlite.dao.HashDao;
|
||||||
import io.kamax.mxisd.storage.ormlite.dao.HistoricalThreePidInviteIO;
|
import io.kamax.mxisd.storage.ormlite.dao.HistoricalThreePidInviteIO;
|
||||||
import io.kamax.mxisd.storage.ormlite.dao.AcceptedDao;
|
import io.kamax.mxisd.storage.ormlite.dao.AcceptedDao;
|
||||||
@@ -46,12 +47,15 @@ import io.kamax.mxisd.storage.ormlite.dao.ThreePidInviteIO;
|
|||||||
import io.kamax.mxisd.storage.ormlite.dao.ThreePidSessionDao;
|
import io.kamax.mxisd.storage.ormlite.dao.ThreePidSessionDao;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -59,6 +63,8 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
public class OrmLiteSqlStorage implements IStorage {
|
public class OrmLiteSqlStorage implements IStorage {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(OrmLiteSqlStorage.class);
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
private interface Getter<T> {
|
private interface Getter<T> {
|
||||||
|
|
||||||
@@ -73,13 +79,18 @@ public class OrmLiteSqlStorage implements IStorage {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Migrations {
|
||||||
|
public static final String FIX_ACCEPTED_DAO = "2019_12_09__2254__fix_accepted_dao";
|
||||||
|
}
|
||||||
|
|
||||||
private Dao<ThreePidInviteIO, String> invDao;
|
private Dao<ThreePidInviteIO, String> invDao;
|
||||||
private Dao<HistoricalThreePidInviteIO, String> expInvDao;
|
private Dao<HistoricalThreePidInviteIO, String> expInvDao;
|
||||||
private Dao<ThreePidSessionDao, String> sessionDao;
|
private Dao<ThreePidSessionDao, String> sessionDao;
|
||||||
private Dao<ASTransactionDao, String> asTxnDao;
|
private Dao<ASTransactionDao, String> asTxnDao;
|
||||||
private Dao<AccountDao, String> accountDao;
|
private Dao<AccountDao, String> accountDao;
|
||||||
private Dao<AcceptedDao, String> acceptedDao;
|
private Dao<AcceptedDao, Long> acceptedDao;
|
||||||
private Dao<HashDao, String> hashDao;
|
private Dao<HashDao, String> hashDao;
|
||||||
|
private Dao<ChangelogDao, String> changelogDao;
|
||||||
|
|
||||||
public OrmLiteSqlStorage(MxisdConfig cfg) {
|
public OrmLiteSqlStorage(MxisdConfig cfg) {
|
||||||
this(cfg.getStorage().getBackend(), cfg.getStorage().getProvider().getSqlite().getDatabase());
|
this(cfg.getStorage().getBackend(), cfg.getStorage().getProvider().getSqlite().getDatabase());
|
||||||
@@ -96,6 +107,7 @@ public class OrmLiteSqlStorage implements IStorage {
|
|||||||
|
|
||||||
withCatcher(() -> {
|
withCatcher(() -> {
|
||||||
ConnectionSource connPool = new JdbcConnectionSource("jdbc:" + backend + ":" + path);
|
ConnectionSource connPool = new JdbcConnectionSource("jdbc:" + backend + ":" + path);
|
||||||
|
changelogDao = createDaoAndTable(connPool, ChangelogDao.class);
|
||||||
invDao = createDaoAndTable(connPool, ThreePidInviteIO.class);
|
invDao = createDaoAndTable(connPool, ThreePidInviteIO.class);
|
||||||
expInvDao = createDaoAndTable(connPool, HistoricalThreePidInviteIO.class);
|
expInvDao = createDaoAndTable(connPool, HistoricalThreePidInviteIO.class);
|
||||||
sessionDao = createDaoAndTable(connPool, ThreePidSessionDao.class);
|
sessionDao = createDaoAndTable(connPool, ThreePidSessionDao.class);
|
||||||
@@ -103,10 +115,26 @@ public class OrmLiteSqlStorage implements IStorage {
|
|||||||
accountDao = createDaoAndTable(connPool, AccountDao.class);
|
accountDao = createDaoAndTable(connPool, AccountDao.class);
|
||||||
acceptedDao = createDaoAndTable(connPool, AcceptedDao.class);
|
acceptedDao = createDaoAndTable(connPool, AcceptedDao.class);
|
||||||
hashDao = createDaoAndTable(connPool, HashDao.class);
|
hashDao = createDaoAndTable(connPool, HashDao.class);
|
||||||
|
runMigration(connPool);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void runMigration(ConnectionSource connPol) throws SQLException {
|
||||||
|
ChangelogDao fixAcceptedDao = changelogDao.queryForId(Migrations.FIX_ACCEPTED_DAO);
|
||||||
|
if (fixAcceptedDao == null) {
|
||||||
|
fixAcceptedDao(connPol);
|
||||||
|
changelogDao.create(new ChangelogDao(Migrations.FIX_ACCEPTED_DAO, new Date(), "Recreate the accepted table."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fixAcceptedDao(ConnectionSource connPool) throws SQLException {
|
||||||
|
LOGGER.info("Migration: {}", Migrations.FIX_ACCEPTED_DAO);
|
||||||
|
TableUtils.dropTable(acceptedDao, true);
|
||||||
|
TableUtils.createTableIfNotExists(connPool, AcceptedDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
private <V, K> Dao<V, K> createDaoAndTable(ConnectionSource connPool, Class<V> c) throws SQLException {
|
private <V, K> Dao<V, K> createDaoAndTable(ConnectionSource connPool, Class<V> c) throws SQLException {
|
||||||
|
LOGGER.info("Create the dao: {}", c.getSimpleName());
|
||||||
Dao<V, K> dao = DaoManager.createDao(connPool, c);
|
Dao<V, K> dao = DaoManager.createDao(connPool, c);
|
||||||
TableUtils.createTableIfNotExists(connPool, c);
|
TableUtils.createTableIfNotExists(connPool, c);
|
||||||
return dao;
|
return dao;
|
||||||
|
@@ -26,7 +26,10 @@ import com.j256.ormlite.table.DatabaseTable;
|
|||||||
@DatabaseTable(tableName = "accepted")
|
@DatabaseTable(tableName = "accepted")
|
||||||
public class AcceptedDao {
|
public class AcceptedDao {
|
||||||
|
|
||||||
@DatabaseField(canBeNull = false, id = true)
|
@DatabaseField(generatedId = true)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@DatabaseField(canBeNull = false)
|
||||||
private String url;
|
private String url;
|
||||||
|
|
||||||
@DatabaseField(canBeNull = false)
|
@DatabaseField(canBeNull = false)
|
||||||
@@ -45,6 +48,14 @@ public class AcceptedDao {
|
|||||||
this.acceptedAt = acceptedAt;
|
this.acceptedAt = acceptedAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
public String getUrl() {
|
public String getUrl() {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,52 @@
|
|||||||
|
package io.kamax.mxisd.storage.ormlite.dao;
|
||||||
|
|
||||||
|
import com.j256.ormlite.field.DatabaseField;
|
||||||
|
import com.j256.ormlite.table.DatabaseTable;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@DatabaseTable(tableName = "changelog")
|
||||||
|
public class ChangelogDao {
|
||||||
|
|
||||||
|
@DatabaseField(id = true)
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@DatabaseField
|
||||||
|
private Date createdAt;
|
||||||
|
|
||||||
|
@DatabaseField
|
||||||
|
private String comment;
|
||||||
|
|
||||||
|
public ChangelogDao() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChangelogDao(String id, Date createdAt, String comment) {
|
||||||
|
this.id = id;
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedAt(Date createdAt) {
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getComment() {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComment(String comment) {
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user