Add support for all features for Exec Identity Store

This commit is contained in:
Max Dor
2018-11-01 02:15:56 +01:00
parent b892d19023
commit ded5e3db5e
18 changed files with 875 additions and 122 deletions

View File

@@ -18,13 +18,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.kamax.mxisd.backend.exec.auth.input;
package io.kamax.mxisd.backend.exec;
import io.kamax.matrix.MatrixID;
import io.kamax.matrix._MatrixID;
import io.kamax.mxisd.UserIdType;
import io.kamax.mxisd.backend.exec.ExecAuthResult;
import io.kamax.mxisd.backend.exec.ExecAuthStore;
import io.kamax.mxisd.config.ExecConfig;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.Before;
@@ -35,7 +33,7 @@ import java.util.Collections;
import static org.junit.Assert.assertEquals;
public abstract class ExecAuthTest {
public abstract class ExecAuthStoreTest {
protected final ExecConfig cfg;
protected final ExecAuthStore p;
@@ -90,7 +88,7 @@ public abstract class ExecAuthTest {
cfg.getAuth().addEnv("REQ_PASS", requiredPass);
}
public ExecAuthTest() {
public ExecAuthStoreTest() {
cfg = new ExecConfig();
p = new ExecAuthStore(cfg);
}

View File

@@ -0,0 +1,128 @@
/*
* mxisd - Matrix Identity Server Daemon
* Copyright (C) 2018 Kamax Sarl
*
* https://www.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.exec;
import io.kamax.matrix.MatrixID;
import io.kamax.matrix.json.GsonUtil;
import io.kamax.mxisd.config.ExecConfig;
import io.kamax.mxisd.controller.directory.v1.io.UserDirectorySearchResult;
import io.kamax.mxisd.exception.InternalServerError;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import java.util.Collections;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
public class ExecDirectoryStoreTest extends ExecStoreTest {
public ExecDirectoryStoreTest() {
executables.put("byNameSuccessEmptyResult", () ->
make(0, () ->
GsonUtil.get().toJson(UserDirectorySearchResult.empty())
)
);
executables.put("byNameSuccessSingleResult", () -> make(0, () -> {
UserDirectorySearchResult.Result resultIo = new UserDirectorySearchResult.Result();
resultIo.setUserId(user1Localpart);
resultIo.setDisplayName(user1Name);
UserDirectorySearchResult io = new UserDirectorySearchResult();
io.setLimited(false);
io.setResults(Collections.singleton(resultIo));
return GsonUtil.get().toJson(io);
}));
}
private ExecConfig.Directory getCfg() {
ExecConfig.Directory cfg = new ExecConfig().compute().getDirectory();
assertFalse(cfg.isEnabled());
cfg.setEnabled(true);
assertTrue(cfg.isEnabled());
cfg.getSearch().getByName().getOutput().setType(ExecStore.JsonType);
return cfg;
}
private ExecDirectoryStore getStore(ExecConfig.Directory cfg) {
ExecDirectoryStore store = new ExecDirectoryStore(cfg, getMatrixCfg());
store.setExecutorSupplier(this::build);
assertTrue(store.isEnabled());
return store;
}
private ExecDirectoryStore getStore(String command) {
ExecConfig.Directory cfg = getCfg();
cfg.getSearch().getByName().setCommand(command);
cfg.getSearch().getByThreepid().setCommand(command);
return getStore(cfg);
}
@Test
public void byNameNoCommandDefined() {
ExecConfig.Directory cfg = getCfg();
assertTrue(StringUtils.isEmpty(cfg.getSearch().getByName().getCommand()));
ExecDirectoryStore store = getStore(cfg);
UserDirectorySearchResult result = store.searchByDisplayName("user");
assertFalse(result.isLimited());
assertTrue(result.getResults().isEmpty());
}
@Test
public void byNameSuccessNoOutput() {
UserDirectorySearchResult result = getStore(sno).searchByDisplayName("user");
assertFalse(result.isLimited());
assertTrue(result.getResults().isEmpty());
}
@Test
public void byNameSuccessEmptyResult() {
UserDirectorySearchResult output = getStore("byNameSuccessEmptyResult").searchByDisplayName("user");
assertFalse(output.isLimited());
assertTrue(output.getResults().isEmpty());
}
@Test
public void byNameSuccessSingleResult() {
UserDirectorySearchResult output = getStore("byNameSuccessSingleResult").searchByDisplayName("user");
assertFalse(output.isLimited());
assertEquals(1, output.getResults().size());
UserDirectorySearchResult.Result result = output.getResults().iterator().next();
assertEquals(MatrixID.from(user1Localpart, domain).acceptable().getId(), result.getUserId());
assertEquals(user1Name, result.getDisplayName());
}
@Test
public void byNameFailureNoOutput() {
UserDirectorySearchResult result = getStore(fno).searchByDisplayName("user");
assertFalse(result.isLimited());
assertTrue(result.getResults().isEmpty());
}
@Test(expected = InternalServerError.class)
public void byNameUnknownNoOutput() {
getStore(uno).searchByDisplayName("user");
}
}

View File

@@ -0,0 +1,129 @@
/*
* mxisd - Matrix Identity Server Daemon
* Copyright (C) 2018 Kamax Sarl
*
* https://www.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.exec;
import com.google.gson.JsonObject;
import io.kamax.matrix.MatrixID;
import io.kamax.matrix.ThreePidMedium;
import io.kamax.matrix.json.GsonUtil;
import io.kamax.mxisd.UserID;
import io.kamax.mxisd.UserIdType;
import io.kamax.mxisd.backend.rest.LookupSingleResponseJson;
import io.kamax.mxisd.config.ExecConfig;
import io.kamax.mxisd.exception.InternalServerError;
import io.kamax.mxisd.lookup.SingleLookupReply;
import io.kamax.mxisd.lookup.SingleLookupRequest;
import org.junit.Test;
import java.util.Optional;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
public class ExecIdentityStoreTest extends ExecStoreTest {
public ExecIdentityStoreTest() {
executables.put("singleSuccessEmpty", () -> make(0, () ->
GsonUtil.get().toJson(GsonUtil.makeObj("lookup", new JsonObject()))));
executables.put("singleSuccessData", () -> makeJson(0, () -> {
LookupSingleResponseJson json = new LookupSingleResponseJson();
json.setMedium(ThreePidMedium.Email);
json.setAddress(user1Email);
json.setId(new UserID(UserIdType.Localpart, user1Localpart));
return GsonUtil.makeObj("lookup", GsonUtil.get().toJsonTree(json));
}));
executables.put("singleSuccessEmptyFromInvalidOutput", () -> makeJson(0, () -> {
JsonObject lookup = new JsonObject();
lookup.addProperty("medium", "");
return GsonUtil.makeObj("lookup", lookup);
}));
}
private ExecConfig.Identity getCfg() {
ExecConfig.Identity cfg = new ExecConfig().compute().getIdentity();
assertFalse(cfg.isEnabled());
cfg.setEnabled(true);
assertTrue(cfg.isEnabled());
cfg.getLookup().getSingle().getOutput().setType(ExecStore.JsonType);
cfg.getLookup().getBulk().getOutput().setType(ExecStore.JsonType);
return cfg;
}
private ExecIdentityStore getStore(ExecConfig.Identity cfg) {
ExecIdentityStore store = new ExecIdentityStore(cfg, getMatrixCfg());
store.setExecutorSupplier(this::build);
assertTrue(store.isEnabled());
return store;
}
private ExecIdentityStore getStore(String command) {
ExecConfig.Identity cfg = getCfg();
cfg.getLookup().getSingle().setCommand(command);
cfg.getLookup().getBulk().setCommand(command);
return getStore(cfg);
}
@Test
public void singleSuccessNoOutput() {
ExecIdentityStore store = getStore(sno);
SingleLookupRequest req = new SingleLookupRequest();
req.setType(ThreePidMedium.Email.getId());
req.setThreePid(user1Email);
Optional<SingleLookupReply> lookup = store.find(req);
assertFalse(lookup.isPresent());
}
@Test
public void singleSuccessEmpty() {
ExecIdentityStore store = getStore("singleSuccessEmpty");
SingleLookupRequest req = new SingleLookupRequest();
req.setType(ThreePidMedium.Email.getId());
req.setThreePid(user1Email);
Optional<SingleLookupReply> lookup = store.find(req);
assertFalse(lookup.isPresent());
}
@Test
public void singleSuccessData() {
SingleLookupRequest req = new SingleLookupRequest();
req.setType(ThreePidMedium.Email.getId());
req.setThreePid(user1Email);
Optional<SingleLookupReply> lookup = getStore("singleSuccessData").find(req);
assertTrue(lookup.isPresent());
SingleLookupReply reply = lookup.get();
assertEquals(MatrixID.asAcceptable(user1Localpart, domain), reply.getMxid());
}
@Test(expected = InternalServerError.class)
public void singleSuccessEmptyFromInvalidOutput() {
SingleLookupRequest req = new SingleLookupRequest();
req.setType(ThreePidMedium.Email.getId());
req.setThreePid(user1Email);
getStore("singleSuccessEmptyFromInvalidOutput").find(req);
}
}

View File

@@ -0,0 +1,140 @@
/*
* mxisd - Matrix Identity Server Daemon
* Copyright (C) 2018 Kamax Sarl
*
* https://www.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.exec;
import com.google.gson.JsonObject;
import io.kamax.matrix.MatrixID;
import io.kamax.matrix.ThreePid;
import io.kamax.matrix.ThreePidMedium;
import io.kamax.matrix._ThreePid;
import io.kamax.matrix.json.GsonUtil;
import io.kamax.mxisd.UserIdType;
import io.kamax.mxisd.config.ExecConfig;
import io.kamax.mxisd.profile.JsonProfileResult;
import org.junit.Test;
import java.util.List;
import java.util.Optional;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
public class ExecProfileStoreTest extends ExecStoreTest {
private final String seo = "successEmptyOutput";
private final String sn = "successName";
private final String sst = "successSingleThreepid";
private final String smt = "successMultiThreepid";
private final String user1Msisdn = Long.toString(System.currentTimeMillis());
public ExecProfileStoreTest() {
executables.put(seo, () -> make(0, () -> "{}"));
executables.put(sn, () -> makeJson(0, () -> {
JsonObject profile = new JsonObject();
profile.addProperty("display_name", user1Name);
return GsonUtil.makeObj("profile", profile);
}));
executables.put(sst, () -> makeJson(0, () -> {
JsonProfileResult profile = new JsonProfileResult();
profile.addThreepid(new ThreePid(ThreePidMedium.Email.getId(), user1Email));
return GsonUtil.makeObj("profile", profile);
}));
executables.put(smt, () -> makeJson(0, () -> {
JsonProfileResult profile = new JsonProfileResult();
profile.addThreepid(new ThreePid(ThreePidMedium.Email.getId(), user1Email));
profile.addThreepid(new ThreePid(ThreePidMedium.PhoneNumber.getId(), user1Msisdn));
return GsonUtil.makeObj("profile", profile);
}));
}
private ExecConfig.Profile getCfg() {
ExecConfig.Profile cfg = new ExecConfig().compute().getProfile();
assertFalse(cfg.isEnabled());
cfg.setEnabled(true);
assertTrue(cfg.isEnabled());
cfg.getDisplayName().getOutput().setType(ExecStore.JsonType);
cfg.getThreePid().getOutput().setType(ExecStore.JsonType);
cfg.getRole().getOutput().setType(ExecStore.JsonType);
return cfg;
}
private ExecProfileStore getStore(ExecConfig.Profile cfg) {
ExecProfileStore store = new ExecProfileStore(cfg);
store.setExecutorSupplier(this::build);
assertTrue(store.isEnabled());
return store;
}
private ExecProfileStore getStore(String command) {
ExecConfig.Profile cfg = getCfg();
cfg.getDisplayName().setCommand(command);
cfg.getThreePid().setCommand(command);
cfg.getRole().setCommand(command);
return getStore(cfg);
}
@Test
public void getNameSuccessNoOutput() {
Optional<String> name = getStore(sno).getDisplayName(MatrixID.asAcceptable(user1Localpart, domain));
assertFalse(name.isPresent());
}
@Test
public void getNameSuccessEmptyOutput() {
Optional<String> name = getStore(seo).getDisplayName(MatrixID.asAcceptable(user1Localpart, domain));
assertFalse(name.isPresent());
}
@Test
public void getNameSuccess() {
Optional<String> name = getStore(sn).getDisplayName(user1Id);
assertTrue(name.isPresent());
assertEquals(user1Name, name.get());
}
@Test
public void getSingleThreePidSuccess() {
List<_ThreePid> tpids = getStore(sst).getThreepids(user1Id);
assertEquals(1, tpids.size());
_ThreePid tpid = tpids.get(0);
assertEquals(UserIdType.Email.getId(), tpid.getMedium());
assertEquals(user1Email, tpid.getAddress());
}
@Test
public void getMultiThreePidSuccess() {
List<_ThreePid> tpids = getStore(smt).getThreepids(user1Id);
assertEquals(2, tpids.size());
_ThreePid firstTpid = tpids.get(0);
assertEquals(ThreePidMedium.Email.getId(), firstTpid.getMedium());
assertEquals(user1Email, firstTpid.getAddress());
_ThreePid secondTpid = tpids.get(1);
assertEquals(ThreePidMedium.PhoneNumber.getId(), secondTpid.getMedium());
assertEquals(user1Msisdn, secondTpid.getAddress());
}
}

View File

@@ -0,0 +1,98 @@
/*
* mxisd - Matrix Identity Server Daemon
* Copyright (C) 2018 Kamax Sarl
*
* https://www.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.exec;
import io.kamax.matrix.MatrixID;
import io.kamax.matrix._MatrixID;
import io.kamax.matrix.json.GsonUtil;
import io.kamax.mxisd.config.MatrixConfig;
import org.zeroturnaround.exec.ProcessExecutor;
import org.zeroturnaround.exec.ProcessResult;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;
public class ExecStoreTest {
protected final String sno = "successNoOutput";
protected final String fno = "failureNoOutput";
protected final String uno = "unknownNoOutput";
protected final String domain = "domain.tld";
protected final String userLocalpart = "user";
protected final String user1Localpart = userLocalpart + "1";
protected final String user1Name = "User 1";
protected final String user2Localpart = userLocalpart + "2";
protected final String user2Name = "User 2";
protected final _MatrixID user1Id = MatrixID.asAcceptable(user1Localpart, domain);
protected final String user1Email = user1Localpart + "@" + domain;
protected Map<String, Supplier<ProcessResult>> executables = new HashMap<>();
public ExecStoreTest() {
executables.put(sno, () -> make(0, () -> ""));
executables.put(fno, () -> make(1, () -> ""));
executables.put(uno, () -> make(Integer.MAX_VALUE, () -> ""));
}
protected MatrixConfig getMatrixCfg() {
MatrixConfig mxCfg = new MatrixConfig();
mxCfg.setDomain(domain);
return mxCfg;
}
protected ProcessResult make(int exitCode, Supplier<String> supplier) {
return new ProcessResult(exitCode, null) {
@Override
public String outputUTF8() {
return supplier.get();
}
};
}
protected ProcessResult makeJson(int exitCode, Supplier<Object> supplier) {
return make(exitCode, () -> GsonUtil.get().toJson(supplier.get()));
}
protected ProcessExecutor build() {
return new ProcessExecutor() {
private Function<String, RuntimeException> notFound = command ->
new IllegalArgumentException("Command not found: " + command);
@Override
public ProcessResult execute() {
if (getCommand().size() == 0) throw new IllegalStateException();
String command = getCommand().get(0);
return executables.getOrDefault(command, () -> {
throw notFound.apply(command);
}).get();
}
};
}
}

View File

@@ -20,9 +20,11 @@
package io.kamax.mxisd.backend.exec.auth.input;
import io.kamax.mxisd.backend.exec.ExecAuthStoreTest;
import java.util.Arrays;
public class ExecAuthArgsTest extends ExecAuthTest {
public class ExecAuthArgsTest extends ExecAuthStoreTest {
@Override
protected void setValidCommand() {

View File

@@ -20,9 +20,11 @@
package io.kamax.mxisd.backend.exec.auth.input;
import io.kamax.mxisd.backend.exec.ExecAuthStoreTest;
import java.util.HashMap;
public class ExecAuthEnvTest extends ExecAuthTest {
public class ExecAuthEnvTest extends ExecAuthStoreTest {
private final String LocalpartEnv = "LOCALPART";
private final String DomainEnv = "DOMAIN";

View File

@@ -20,9 +20,10 @@
package io.kamax.mxisd.backend.exec.auth.input;
import io.kamax.mxisd.backend.exec.ExecAuthStoreTest;
import io.kamax.mxisd.backend.exec.ExecStore;
public class ExecAuthInputMultilinesTest extends ExecAuthTest {
public class ExecAuthInputMultilinesTest extends ExecAuthStoreTest {
@Override
protected void setValidCommand() {