Bye bye Groovy, you won't be missed :(

This commit is contained in:
Maxime Dor
2017-09-25 02:31:31 +02:00
parent af19fed6e7
commit 33263d3cff
140 changed files with 1711 additions and 1678 deletions

View 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.storage;
import io.kamax.mxisd.ThreePid;
import io.kamax.mxisd.invitation.IThreePidInviteReply;
import io.kamax.mxisd.storage.dao.IThreePidSessionDao;
import io.kamax.mxisd.storage.ormlite.ThreePidInviteIO;
import java.util.Collection;
import java.util.Optional;
public interface IStorage {
Collection<ThreePidInviteIO> getInvites();
void insertInvite(IThreePidInviteReply data);
void deleteInvite(String id);
Optional<IThreePidSessionDao> getThreePidSession(String sid);
Optional<IThreePidSessionDao> findThreePidSession(ThreePid tpid, String secret);
void insertThreePidSession(IThreePidSessionDao session);
void updateThreePidSession(IThreePidSessionDao session);
}

View File

@@ -0,0 +1,59 @@
/*
* 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.storage.dao;
public interface IThreePidSessionDao {
String getId();
long getCreationTime();
String getServer();
String getMedium();
String getAddress();
String getSecret();
int getAttempt();
String getNextLink();
String getToken();
boolean getValidated();
long getValidationTime();
boolean isRemote();
String getRemoteServer();
String getRemoteId();
String getRemoteSecret();
int getRemoteAttempt();
boolean isRemoteValidated();
}

View File

@@ -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.storage.ormlite;
import com.j256.ormlite.dao.CloseableWrappedIterable;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.DaoManager;
import com.j256.ormlite.jdbc.JdbcConnectionSource;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
import io.kamax.mxisd.ThreePid;
import io.kamax.mxisd.exception.InternalServerError;
import io.kamax.mxisd.invitation.IThreePidInviteReply;
import io.kamax.mxisd.storage.IStorage;
import io.kamax.mxisd.storage.dao.IThreePidSessionDao;
import io.kamax.mxisd.storage.ormlite.dao.ThreePidSessionDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
public class OrmLiteSqliteStorage implements IStorage {
private Logger log = LoggerFactory.getLogger(OrmLiteSqliteStorage.class);
@FunctionalInterface
private interface Getter<T> {
T get() throws SQLException, IOException;
}
@FunctionalInterface
private interface Doer {
void run() throws SQLException, IOException;
}
private Dao<ThreePidInviteIO, String> invDao;
private Dao<ThreePidSessionDao, String> sessionDao;
OrmLiteSqliteStorage(String path) {
withCatcher(() -> {
File parent = new File(path).getParentFile();
if (!parent.mkdirs() && !parent.isDirectory()) {
throw new RuntimeException("Unable to create DB parent directory: " + parent);
}
ConnectionSource connPool = new JdbcConnectionSource("jdbc:sqlite:" + path);
invDao = createDaoAndTable(connPool, ThreePidInviteIO.class);
sessionDao = createDaoAndTable(connPool, ThreePidSessionDao.class);
});
}
private <V, K> Dao<V, K> createDaoAndTable(ConnectionSource connPool, Class<V> c) throws SQLException {
Dao<V, K> dao = DaoManager.createDao(connPool, c);
TableUtils.createTableIfNotExists(connPool, c);
return dao;
}
private <T> T withCatcher(Getter<T> g) {
try {
return g.get();
} catch (SQLException | IOException e) {
throw new RuntimeException(e); // FIXME do better
}
}
private void withCatcher(Doer d) {
try {
d.run();
} catch (SQLException | IOException e) {
throw new RuntimeException(e); // FIXME do better
}
}
private <T> List<T> forIterable(CloseableWrappedIterable<? extends T> t) {
return withCatcher(() -> {
try {
List<T> ioList = new ArrayList<>();
t.forEach(ioList::add);
return ioList;
} finally {
t.close();
}
});
}
@Override
public Collection<ThreePidInviteIO> getInvites() {
return forIterable(invDao.getWrappedIterable());
}
@Override
public void insertInvite(IThreePidInviteReply data) {
withCatcher(() -> {
int updated = invDao.create(new ThreePidInviteIO(data));
if (updated != 1) {
throw new RuntimeException("Unexpected row count after DB action: " + updated);
}
});
}
@Override
public void deleteInvite(String id) {
withCatcher(() -> {
int updated = invDao.deleteById(id);
if (updated != 1) {
throw new RuntimeException("Unexpected row count after DB action: " + updated);
}
});
}
@Override
public Optional<IThreePidSessionDao> getThreePidSession(String sid) {
return withCatcher(() -> Optional.ofNullable(sessionDao.queryForId(sid)));
}
@Override
public Optional<IThreePidSessionDao> findThreePidSession(ThreePid tpid, String secret) {
return withCatcher(() -> {
List<ThreePidSessionDao> daoList = sessionDao.queryForMatchingArgs(new ThreePidSessionDao(tpid, secret));
if (daoList.size() > 1) {
log.error("Lookup for 3PID Session {}:{} returned more than one result");
throw new InternalServerError();
}
if (daoList.isEmpty()) {
return Optional.empty();
}
return Optional.of(daoList.get(0));
});
}
@Override
public void insertThreePidSession(IThreePidSessionDao session) {
withCatcher(() -> {
int updated = sessionDao.create(new ThreePidSessionDao(session));
if (updated != 1) {
throw new RuntimeException("Unexpected row count after DB action: " + updated);
}
});
}
@Override
public void updateThreePidSession(IThreePidSessionDao session) {
withCatcher(() -> {
int updated = sessionDao.update(new ThreePidSessionDao(session));
if (updated != 1) {
throw new RuntimeException("Unexpected row count after DB action: " + updated);
}
});
}
}

View File

@@ -0,0 +1,76 @@
/*
* 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.storage.ormlite;
import io.kamax.mxisd.config.SQLiteStorageConfig;
import io.kamax.mxisd.config.StorageConfig;
import io.kamax.mxisd.exception.ConfigurationException;
import io.kamax.mxisd.storage.IStorage;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.FactoryBeanNotInitializedException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class OrmLiteSqliteStorageBeanFactory implements FactoryBean<IStorage> {
@Autowired
private StorageConfig storagecfg;
@Autowired
private SQLiteStorageConfig cfg;
private OrmLiteSqliteStorage storage;
@PostConstruct
private void postConstruct() {
if (StringUtils.equals("sqlite", storagecfg.getBackend())) {
if (StringUtils.isBlank(cfg.getDatabase())) {
throw new ConfigurationException("storage.provider.sqlite.database");
}
storage = new OrmLiteSqliteStorage(cfg.getDatabase());
}
}
@Override
public IStorage getObject() throws Exception {
if (storage == null) {
throw new FactoryBeanNotInitializedException();
}
return storage;
}
@Override
public Class<?> getObjectType() {
return OrmLiteSqliteStorage.class;
}
@Override
public boolean isSingleton() {
return true;
}
}

View File

@@ -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.storage.ormlite;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import io.kamax.mxisd.invitation.IThreePidInviteReply;
import org.apache.commons.lang.StringUtils;
import java.util.HashMap;
import java.util.Map;
@DatabaseTable(tableName = "invite_3pid")
public class ThreePidInviteIO {
private static Gson gson = new Gson();
@DatabaseField(id = true)
private String id;
@DatabaseField(canBeNull = false)
private String token;
@DatabaseField(canBeNull = false)
private String sender;
@DatabaseField(canBeNull = false)
private String medium;
@DatabaseField(canBeNull = false)
private String address;
@DatabaseField(canBeNull = false)
private String roomId;
@DatabaseField
private String properties;
public ThreePidInviteIO() {
// needed for ORMlite
}
public ThreePidInviteIO(IThreePidInviteReply data) {
this.id = data.getId();
this.token = data.getToken();
this.sender = data.getInvite().getSender().getId();
this.medium = data.getInvite().getMedium();
this.address = data.getInvite().getAddress();
this.roomId = data.getInvite().getRoomId();
this.properties = gson.toJson(data.getInvite().getProperties());
}
public String getId() {
return id;
}
public String getToken() {
return token;
}
public String getSender() {
return sender;
}
public String getMedium() {
return medium;
}
public String getAddress() {
return address;
}
public String getRoomId() {
return roomId;
}
public Map<String, String> getProperties() {
if (StringUtils.isBlank(properties)) {
return new HashMap<>();
}
return gson.fromJson(properties, new TypeToken<Map<String, String>>() {
}.getType());
}
}

View File

@@ -0,0 +1,264 @@
/*
* 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.storage.ormlite.dao;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import io.kamax.mxisd.ThreePid;
import io.kamax.mxisd.storage.dao.IThreePidSessionDao;
@DatabaseTable(tableName = "session_3pid")
public class ThreePidSessionDao implements IThreePidSessionDao {
@DatabaseField(id = true)
private String id;
@DatabaseField(canBeNull = false)
private long creationTime;
@DatabaseField(canBeNull = false)
private String server;
@DatabaseField(canBeNull = false)
private String medium;
@DatabaseField(canBeNull = false)
private String address;
@DatabaseField(canBeNull = false)
private String secret;
@DatabaseField(canBeNull = false)
private int attempt;
@DatabaseField
private String nextLink;
@DatabaseField(canBeNull = false)
private String token;
@DatabaseField
private boolean validated;
@DatabaseField
private long validationTime;
@DatabaseField(canBeNull = false)
private boolean isRemote;
@DatabaseField
private String remoteServer;
@DatabaseField
private String remoteId;
@DatabaseField
private String remoteSecret;
@DatabaseField
private Integer remoteAttempt;
@DatabaseField(canBeNull = false)
private boolean isRemoteValidated;
public ThreePidSessionDao() {
// stub for ORMLite
}
public ThreePidSessionDao(IThreePidSessionDao session) {
setId(session.getId());
setCreationTime(session.getCreationTime());
setServer(session.getServer());
setMedium(session.getMedium());
setAddress(session.getAddress());
setSecret(session.getSecret());
setAttempt(session.getAttempt());
setNextLink(session.getNextLink());
setToken(session.getToken());
setValidated(session.getValidated());
setValidationTime(session.getValidationTime());
setRemote(session.isRemote());
setRemoteServer(session.getRemoteServer());
setRemoteId(session.getRemoteId());
setRemoteSecret(session.getRemoteSecret());
setRemoteAttempt(session.getRemoteAttempt());
setRemoteValidated(session.isRemoteValidated());
}
public ThreePidSessionDao(ThreePid tpid, String secret) {
setMedium(tpid.getMedium());
setAddress(tpid.getAddress());
setSecret(secret);
}
@Override
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public long getCreationTime() {
return creationTime;
}
public void setCreationTime(long creationTime) {
this.creationTime = creationTime;
}
@Override
public String getServer() {
return server;
}
public void setServer(String server) {
this.server = server;
}
@Override
public String getMedium() {
return medium;
}
public void setMedium(String medium) {
this.medium = medium;
}
@Override
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
@Override
public int getAttempt() {
return attempt;
}
public void setAttempt(int attempt) {
this.attempt = attempt;
}
@Override
public String getNextLink() {
return nextLink;
}
public void setNextLink(String nextLink) {
this.nextLink = nextLink;
}
@Override
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public boolean getValidated() {
return validated;
}
public void setValidated(boolean validated) {
this.validated = validated;
}
@Override
public long getValidationTime() {
return validationTime;
}
@Override
public boolean isRemote() {
return isRemote;
}
public void setRemote(boolean remote) {
isRemote = remote;
}
@Override
public String getRemoteServer() {
return remoteServer;
}
public void setRemoteServer(String remoteServer) {
this.remoteServer = remoteServer;
}
@Override
public String getRemoteId() {
return remoteId;
}
public void setRemoteId(String remoteId) {
this.remoteId = remoteId;
}
@Override
public String getRemoteSecret() {
return remoteSecret;
}
public void setRemoteSecret(String remoteSecret) {
this.remoteSecret = remoteSecret;
}
@Override
public int getRemoteAttempt() {
return remoteAttempt;
}
@Override
public boolean isRemoteValidated() {
return isRemoteValidated;
}
public void setRemoteValidated(boolean remoteValidated) {
isRemoteValidated = remoteValidated;
}
public void setRemoteAttempt(int remoteAttempt) {
this.remoteAttempt = remoteAttempt;
}
public void setValidationTime(long validationTime) {
this.validationTime = validationTime;
}
}