diff --git a/src/main/java/io/kamax/mxisd/backend/exec/ExecAuthStore.java b/src/main/java/io/kamax/mxisd/backend/exec/ExecAuthStore.java index 537c1fa..997ee92 100644 --- a/src/main/java/io/kamax/mxisd/backend/exec/ExecAuthStore.java +++ b/src/main/java/io/kamax/mxisd/backend/exec/ExecAuthStore.java @@ -42,7 +42,7 @@ import java.util.Optional; @Component public class ExecAuthStore extends ExecStore implements AuthenticatorProvider { - private final transient Logger log = LoggerFactory.getLogger(ExecAuthStore.class); + private final Logger log = LoggerFactory.getLogger(ExecAuthStore.class); private ExecConfig.Auth cfg; @@ -66,43 +66,43 @@ public class ExecAuthStore extends ExecStore implements AuthenticatorProvider { ExecAuthResult result = new ExecAuthResult(); result.setId(new UserID(UserIdType.Localpart, uId.getLocalPart())); - Processor process = new Processor<>(); - process.withConfig(cfg); - process.addTokenMapper(cfg.getToken().getLocalpart(), uId::getLocalPart); - process.addTokenMapper(cfg.getToken().getDomain(), uId::getDomain); - process.addTokenMapper(cfg.getToken().getMxid(), uId::getId); - process.addTokenMapper(cfg.getToken().getPassword(), () -> password); + Processor p = new Processor<>(cfg); - process.addInputTemplate(JsonType, tokens -> { + p.addTokenMapper(cfg.getToken().getLocalpart(), uId::getLocalPart); + p.addTokenMapper(cfg.getToken().getDomain(), uId::getDomain); + p.addTokenMapper(cfg.getToken().getMxid(), uId::getId); + p.addTokenMapper(cfg.getToken().getPassword(), () -> password); + + p.addJsonInputTemplate(tokens -> { RestAuthRequestJson json = new RestAuthRequestJson(); json.setLocalpart(tokens.getLocalpart()); json.setDomain(tokens.getDomain()); json.setMxid(tokens.getMxid()); json.setPassword(tokens.getPassword()); - return GsonUtil.get().toJson(json); + return json; }); - process.addInputTemplate(MultilinesType, tokens -> tokens.getLocalpart() + System.lineSeparator() + + p.addInputTemplate(MultilinesType, tokens -> tokens.getLocalpart() + System.lineSeparator() + tokens.getDomain() + System.lineSeparator() + tokens.getMxid() + System.lineSeparator() + tokens.getPassword() + System.lineSeparator() ); - process.withExitHandler(pr -> result.setExitStatus(pr.getExitValue())); + p.withExitHandler(pr -> result.setExitStatus(pr.getExitValue())); - process.withSuccessHandler(pr -> result.setSuccess(true)); - process.withSuccessDefault(o -> result); - process.addSuccessMapper(JsonType, output -> { + p.withSuccessHandler(pr -> result.setSuccess(true)); + p.withSuccessDefault(o -> result); + p.addSuccessMapper(JsonType, output -> { JsonObject data = GsonUtil.getObj(GsonUtil.parseObj(output), "auth"); GsonUtil.findPrimitive(data, "success") .map(JsonPrimitive::getAsBoolean) .ifPresent(result::setSuccess); GsonUtil.findObj(data, "profile") - .flatMap(p -> GsonUtil.findString(p, "display_name")) + .flatMap(profile -> GsonUtil.findString(profile, "display_name")) .ifPresent(v -> result.getProfile().setDisplayName(v)); return result; }); - process.addSuccessMapper(MultilinesType, output -> { + p.addSuccessMapper(MultilinesType, output -> { String[] lines = output.split("\\R"); if (lines.length > 2) { throw new InternalServerError("Exec auth command returned more than 2 lines (" + lines.length + ")"); @@ -120,10 +120,10 @@ public class ExecAuthStore extends ExecStore implements AuthenticatorProvider { return result; }); - process.withFailureHandler(pr -> result.setSuccess(false)); - process.withFailureDefault(o -> result); + p.withFailureHandler(pr -> result.setSuccess(false)); + p.withFailureDefault(o -> result); - return process.execute(); + return p.execute(); } } diff --git a/src/main/java/io/kamax/mxisd/backend/exec/ExecDirectoryStore.java b/src/main/java/io/kamax/mxisd/backend/exec/ExecDirectoryStore.java index 71bd75e..4a0bb51 100644 --- a/src/main/java/io/kamax/mxisd/backend/exec/ExecDirectoryStore.java +++ b/src/main/java/io/kamax/mxisd/backend/exec/ExecDirectoryStore.java @@ -27,6 +27,7 @@ import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.controller.directory.v1.io.UserDirectorySearchRequest; import io.kamax.mxisd.controller.directory.v1.io.UserDirectorySearchResult; import io.kamax.mxisd.directory.IDirectoryProvider; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -38,7 +39,11 @@ public class ExecDirectoryStore extends ExecStore implements IDirectoryProvider @Autowired public ExecDirectoryStore(ExecConfig cfg, MatrixConfig mxCfg) { - this.cfg = cfg.getDirectory(); + this(cfg.getDirectory(), mxCfg); + } + + public ExecDirectoryStore(ExecConfig.Directory cfg, MatrixConfig mxCfg) { + this.cfg = cfg; this.mxCfg = mxCfg; } @@ -48,24 +53,32 @@ public class ExecDirectoryStore extends ExecStore implements IDirectoryProvider } private UserDirectorySearchResult search(ExecConfig.Process cfg, UserDirectorySearchRequest request) { - Processor processor = new Processor<>(); - processor.withConfig(cfg); - processor.addInputTemplate(JsonType, tokens -> GsonUtil.get().toJson(new UserDirectorySearchRequest(tokens.getType(), tokens.getQuery()))); - processor.addInputTemplate(MultilinesType, tokens -> tokens.getType() + System.lineSeparator() + tokens.getQuery()); + if (StringUtils.isEmpty(cfg.getCommand())) { + return UserDirectorySearchResult.empty(); + } - processor.addTokenMapper(cfg.getToken().getType(), request::getBy); - processor.addTokenMapper(cfg.getToken().getQuery(), request::getSearchTerm); + Processor p = new Processor<>(cfg); + + p.addJsonInputTemplate(tokens -> new UserDirectorySearchRequest(tokens.getType(), tokens.getQuery())); + p.addInputTemplate(MultilinesType, tokens -> tokens.getType() + System.lineSeparator() + tokens.getQuery()); + + p.addTokenMapper(cfg.getToken().getType(), request::getBy); + p.addTokenMapper(cfg.getToken().getQuery(), request::getSearchTerm); + + p.addSuccessMapper(JsonType, output -> { + if (StringUtils.isBlank(output)) { + return UserDirectorySearchResult.empty(); + } - processor.addSuccessMapper(JsonType, output -> { UserDirectorySearchResult response = GsonUtil.get().fromJson(output, UserDirectorySearchResult.class); for (UserDirectorySearchResult.Result result : response.getResults()) { result.setUserId(MatrixID.asAcceptable(result.getUserId(), mxCfg.getDomain()).getId()); } return response; }); - processor.withFailureDefault(output -> new UserDirectorySearchResult()); + p.withFailureDefault(output -> new UserDirectorySearchResult()); - return processor.execute(); + return p.execute(); } @Override diff --git a/src/main/java/io/kamax/mxisd/backend/exec/ExecIdentityStore.java b/src/main/java/io/kamax/mxisd/backend/exec/ExecIdentityStore.java index 5d866b7..8415745 100644 --- a/src/main/java/io/kamax/mxisd/backend/exec/ExecIdentityStore.java +++ b/src/main/java/io/kamax/mxisd/backend/exec/ExecIdentityStore.java @@ -21,12 +21,15 @@ package io.kamax.mxisd.backend.exec; import com.google.gson.JsonArray; -import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; import io.kamax.matrix.MatrixID; import io.kamax.matrix.ThreePid; +import io.kamax.matrix._MatrixID; import io.kamax.matrix.json.GsonUtil; +import io.kamax.mxisd.UserID; import io.kamax.mxisd.UserIdType; import io.kamax.mxisd.backend.rest.LookupBulkResponseJson; +import io.kamax.mxisd.backend.rest.LookupSingleResponseJson; import io.kamax.mxisd.config.ExecConfig; import io.kamax.mxisd.config.MatrixConfig; import io.kamax.mxisd.exception.InternalServerError; @@ -42,6 +45,7 @@ import org.springframework.stereotype.Component; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -55,7 +59,11 @@ public class ExecIdentityStore extends ExecStore implements IThreePidProvider { @Autowired public ExecIdentityStore(ExecConfig cfg, MatrixConfig mxCfg) { - this.cfg = cfg.getIdentity(); + this(cfg.getIdentity(), mxCfg); + } + + public ExecIdentityStore(ExecConfig.Identity cfg, MatrixConfig mxCfg) { + this.cfg = cfg; this.mxCfg = mxCfg; } @@ -78,46 +86,49 @@ public class ExecIdentityStore extends ExecStore implements IThreePidProvider { return cfg.getLookup().getSingle(); } + private _MatrixID getUserId(UserID id) { + if (Objects.isNull(id)) { + throw new JsonParseException("User id key is not present"); + } + + if (UserIdType.Localpart.is(id.getType())) { + return MatrixID.asAcceptable(id.getValue(), mxCfg.getDomain()); + } + + if (UserIdType.MatrixID.is(id.getType())) { + return MatrixID.asAcceptable(id.getValue()); + } + + throw new InternalServerError("Unknown user type: " + id.getType()); + } + @Override public Optional find(SingleLookupRequest request) { - Processor> processor = new Processor<>(); - processor.withConfig(cfg.getLookup().getSingle()); + Processor> p = new Processor<>(); + p.withConfig(cfg.getLookup().getSingle()); - processor.addTokenMapper(getSingleCfg().getToken().getMedium(), request::getType); - processor.addTokenMapper(getSingleCfg().getToken().getAddress(), request::getThreePid); + p.addTokenMapper(getSingleCfg().getToken().getMedium(), request::getType); + p.addTokenMapper(getSingleCfg().getToken().getAddress(), request::getThreePid); - processor.addInputTemplate(JsonType, tokens -> { - JsonObject json = new JsonObject(); - json.addProperty("medium", tokens.getMedium()); - json.addProperty("address", tokens.getAddress()); - return GsonUtil.get().toJson(json); - }); - processor.addInputTemplate(MultilinesType, tokens -> tokens.getMedium() + p.addJsonInputTemplate(tokens -> new ThreePid(tokens.getMedium(), tokens.getAddress())); + p.addInputTemplate(MultilinesType, tokens -> tokens.getMedium() + System.lineSeparator() + tokens.getAddress() ); - processor.addSuccessMapper(JsonType, output -> { + p.addSuccessMapper(JsonType, output -> { if (StringUtils.isBlank(output)) { return Optional.empty(); } - return GsonUtil.findObj(GsonUtil.parseObj(output), "lookup").map(lookup -> { - String type = GsonUtil.getStringOrThrow(lookup, "type"); - String value = GsonUtil.getStringOrThrow(lookup, "value"); - if (UserIdType.Localpart.is(type)) { - return MatrixID.asAcceptable(value, mxCfg.getDomain()); - } - - if (UserIdType.MatrixID.is(type)) { - return MatrixID.asAcceptable(value); - } - - throw new InternalServerError("Invalid user type: " + type); - }).map(mxId -> new SingleLookupReply(request, mxId)); + return GsonUtil.findObj(GsonUtil.parseObj(output), "lookup") + .filter(obj -> !obj.entrySet().isEmpty()) + .map(json -> GsonUtil.get().fromJson(json, LookupSingleResponseJson.class)) + .map(lookup -> getUserId(lookup.getId())) + .map(mxId -> new SingleLookupReply(request, mxId)); }); - processor.addSuccessMapper(MultilinesType, output -> { + p.addSuccessMapper(MultilinesType, output -> { String[] lines = output.split("\\R"); if (lines.length > 2) { throw new InternalServerError("Exec auth command returned more than 2 lines (" + lines.length + ")"); @@ -141,23 +152,23 @@ public class ExecIdentityStore extends ExecStore implements IThreePidProvider { throw new InternalServerError("Invalid user type: " + type); }); - processor.withFailureDefault(o -> Optional.empty()); + p.withFailureDefault(o -> Optional.empty()); - return processor.execute(); + return p.execute(); } @Override public List populate(List mappings) { - Processor> processor = new Processor<>(); - processor.withConfig(cfg.getLookup().getBulk()); + Processor> p = new Processor<>(); + p.withConfig(cfg.getLookup().getBulk()); - processor.addInput(JsonType, () -> { + p.addInput(JsonType, () -> { JsonArray tpids = GsonUtil.asArray(mappings.stream() .map(mapping -> GsonUtil.get().toJsonTree(new ThreePid(mapping.getMedium(), mapping.getValue()))) .collect(Collectors.toList())); return GsonUtil.get().toJson(GsonUtil.makeObj("lookup", tpids)); }); - processor.addInput(MultilinesType, () -> { + p.addInput(MultilinesType, () -> { StringBuilder input = new StringBuilder(); for (ThreePidMapping mapping : mappings) { input.append(mapping.getMedium()).append("\t").append(mapping.getValue()).append(System.lineSeparator()); @@ -165,7 +176,7 @@ public class ExecIdentityStore extends ExecStore implements IThreePidProvider { return input.toString(); }); - processor.addSuccessMapper(JsonType, output -> { + p.addSuccessMapper(JsonType, output -> { if (StringUtils.isBlank(output)) { return Collections.emptyList(); } @@ -190,9 +201,9 @@ public class ExecIdentityStore extends ExecStore implements IThreePidProvider { }).collect(Collectors.toList()); }); - processor.withFailureDefault(output -> Collections.emptyList()); + p.withFailureDefault(output -> Collections.emptyList()); - return processor.execute(); + return p.execute(); } } diff --git a/src/main/java/io/kamax/mxisd/backend/exec/ExecProfileStore.java b/src/main/java/io/kamax/mxisd/backend/exec/ExecProfileStore.java index 17a1e64..10007d3 100644 --- a/src/main/java/io/kamax/mxisd/backend/exec/ExecProfileStore.java +++ b/src/main/java/io/kamax/mxisd/backend/exec/ExecProfileStore.java @@ -22,12 +22,16 @@ package io.kamax.mxisd.backend.exec; import io.kamax.matrix._MatrixID; import io.kamax.matrix._ThreePid; +import io.kamax.matrix.json.GsonUtil; import io.kamax.mxisd.config.ExecConfig; -import io.kamax.mxisd.exception.NotImplementedException; +import io.kamax.mxisd.profile.JsonProfileRequest; +import io.kamax.mxisd.profile.JsonProfileResult; import io.kamax.mxisd.profile.ProfileProvider; +import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.Collections; import java.util.List; import java.util.Optional; @@ -38,7 +42,11 @@ public class ExecProfileStore extends ExecStore implements ProfileProvider { @Autowired public ExecProfileStore(ExecConfig cfg) { - this.cfg = cfg.getProfile(); + this(cfg.getProfile()); + } + + public ExecProfileStore(ExecConfig.Profile cfg) { + this.cfg = cfg; } @Override @@ -46,19 +54,50 @@ public class ExecProfileStore extends ExecStore implements ProfileProvider { return cfg.isEnabled(); } + private Optional getFull(_MatrixID userId, ExecConfig.Process cfg) { + Processor> p = new Processor<>(cfg); + + p.addJsonInputTemplate(tokens -> new JsonProfileRequest(tokens.getLocalpart(), tokens.getDomain(), tokens.getMxid())); + p.addInputTemplate(MultilinesType, tokens -> tokens.getLocalpart() + System.lineSeparator() + + tokens.getDomain() + System.lineSeparator() + + tokens.getMxid() + System.lineSeparator() + ); + + p.addTokenMapper(cfg.getToken().getLocalpart(), userId::getLocalPart); + p.addTokenMapper(cfg.getToken().getDomain(), userId::getDomain); + p.addTokenMapper(cfg.getToken().getMxid(), userId::getId); + + p.withFailureDefault(v -> Optional.empty()); + + p.addSuccessMapper(JsonType, output -> { + if (StringUtils.isBlank(output)) { + return Optional.empty(); + } + + return GsonUtil.findObj(GsonUtil.parseObj(output), "profile") + .map(obj -> GsonUtil.get().fromJson(obj, JsonProfileResult.class)); + }); + + return p.execute(); + } + @Override public Optional getDisplayName(_MatrixID userId) { - throw new NotImplementedException(this.getClass().getName()); + return getFull(userId, cfg.getDisplayName()).map(JsonProfileResult::getDisplayName); } @Override public List<_ThreePid> getThreepids(_MatrixID userId) { - throw new NotImplementedException(this.getClass().getName()); + return getFull(userId, cfg.getThreePid()) + .map(p -> Collections.<_ThreePid>unmodifiableList(p.getThreepids())) + .orElseGet(Collections::emptyList); } @Override public List getRoles(_MatrixID userId) { - throw new NotImplementedException(this.getClass().getName()); + return getFull(userId, cfg.getRole()) + .map(JsonProfileResult::getRoles) + .orElseGet(Collections::emptyList); } } diff --git a/src/main/java/io/kamax/mxisd/backend/exec/ExecStore.java b/src/main/java/io/kamax/mxisd/backend/exec/ExecStore.java index f5d6995..cd6dfc2 100644 --- a/src/main/java/io/kamax/mxisd/backend/exec/ExecStore.java +++ b/src/main/java/io/kamax/mxisd/backend/exec/ExecStore.java @@ -20,6 +20,7 @@ package io.kamax.mxisd.backend.exec; +import io.kamax.matrix.json.GsonUtil; import io.kamax.mxisd.config.ExecConfig; import io.kamax.mxisd.exception.InternalServerError; import org.apache.commons.io.IOUtils; @@ -42,8 +43,18 @@ public class ExecStore { public static final String JsonType = "json"; public static final String MultilinesType = "multilines"; + protected static String toJson(Object o) { + return GsonUtil.get().toJson(o); + } + private final Logger log = LoggerFactory.getLogger(ExecStore.class); + private Supplier executorSupplier = () -> new ProcessExecutor().readOutput(true); + + public void setExecutorSupplier(Supplier supplier) { + executorSupplier = supplier; + } + public class Processor { private ExecConfig.Process cfg; @@ -55,7 +66,6 @@ public class ExecStore { private Map> inputTypeTemplates; private Supplier inputTypeNoTemplateHandler; - private Map> inputTypeTokenizers; private Map> tokenMappers; private Function tokenHandler; @@ -70,17 +80,22 @@ public class ExecStore { private Map> unknownMappers; private Function unknownDefault; + public Processor(ExecConfig.Process cfg) { + this(); + withConfig(cfg); + } + public Processor() { tokenMappers = new HashMap<>(); inputTypeSuppliers = new HashMap<>(); inputTypeTemplates = new HashMap<>(); - tokenHandler = input -> { + withTokenHandler(tokenHandler = input -> { for (Map.Entry> entry : tokenMappers.entrySet()) { input = input.replace(entry.getKey(), entry.getValue().get()); } return input; - }; + }); inputTypeNoTemplateHandler = () -> cfg.getInput().getType() .map(type -> inputTypeTemplates.get(type).apply(cfg.getToken())) @@ -98,12 +113,12 @@ public class ExecStore { inputSupplier = () -> cfg.getInput().getType().map(type -> inputTypeMapper.apply(type)); - onExitHandler = pr -> { - }; + withExitHandler(pr -> { + }); - successMappers = new HashMap<>(); successHandler = pr -> { }; + successMappers = new HashMap<>(); successDefault = output -> { log.info("{} stdout: {}{}", cfg.getCommand(), System.lineSeparator(), output); throw new InternalServerError("Exec command has no success handler configured. This is a bug. Please report."); @@ -119,90 +134,80 @@ public class ExecStore { unknownHandler = pr -> log.warn("Unexpected exit status: {}", pr.getExitValue()); unknownMappers = new HashMap<>(); - unknownDefault = output -> { + withUnknownDefault(output -> { log.error("{} stdout:{}{}", cfg.getCommand(), System.lineSeparator(), output); throw new InternalServerError("Exec command returned with unexpected exit status"); - }; + }); } - public Processor withConfig(ExecConfig.Process cfg) { + public void withConfig(ExecConfig.Process cfg) { this.cfg = cfg; - return this; } - public Processor addTokenMapper(String token, Supplier data) { + public void addTokenMapper(String token, Supplier data) { tokenMappers.put(token, data); - return this; } - public Processor withTokenHandler(Function tokenHandler) { - this.tokenHandler = tokenHandler; - return this; + public void withTokenHandler(Function handler) { + tokenHandler = handler; } - public Processor addInput(String type, Supplier handler) { + public void addInput(String type, Supplier handler) { inputTypeSuppliers.put(type, handler); - return this; } - public Processor addInputTemplate(String type, Function template) { + protected void addInputTemplate(String type, Function template) { inputTypeTemplates.put(type, template); - return this; } - public Processor withExitHandler(Consumer handler) { + public void addJsonInputTemplate(Function template) { + inputTypeTemplates.put(JsonType, token -> GsonUtil.get().toJson(template.apply(token))); + } + + public void withExitHandler(Consumer handler) { onExitHandler = handler; - return this; } - public Processor withSuccessHandler(Consumer handler) { + public void withSuccessHandler(Consumer handler) { successHandler = handler; - return this; } - public Processor addSuccessMapper(String type, Function mapper) { + public void addSuccessMapper(String type, Function mapper) { successMappers.put(type, mapper); - return this; } - public Processor withSuccessDefault(Function mapper) { + public void withSuccessDefault(Function mapper) { successDefault = mapper; - return this; } - public Processor withFailureHandler(Consumer handler) { + public void withFailureHandler(Consumer handler) { failureHandler = handler; - return this; } - public Processor addFailureMapper(String type, Function mapper) { + public void addFailureMapper(String type, Function mapper) { failureMappers.put(type, mapper); - return this; } - public Processor withFailureDefault(Function mapper) { + public void withFailureDefault(Function mapper) { failureDefault = mapper; - return this; } - public Processor addUnknownMapper(String type, Function mapper) { + public void addUnknownMapper(String type, Function mapper) { unknownMappers.put(type, mapper); - return this; } - public Processor withUnknownDefault(Function mapper) { + public void withUnknownDefault(Function mapper) { unknownDefault = mapper; - return this; } - V execute() { + public V execute() { log.info("Executing {}", cfg.getCommand()); try { - ProcessExecutor psExec = new ProcessExecutor().readOutput(true); + ProcessExecutor psExec = executorSupplier.get(); List args = new ArrayList<>(); - args.add(cfg.getCommand()); + args.add(tokenHandler.apply(cfg.getCommand())); args.addAll(cfg.getArgs().stream().map(arg -> tokenHandler.apply(arg)).collect(Collectors.toList())); psExec.command(args); @@ -235,8 +240,9 @@ public class ExecStore { .map(type -> unknownMappers.getOrDefault(type, unknownDefault).apply(output)) .orElseGet(() -> unknownDefault.apply(output)); } - } catch (IOException | InterruptedException | TimeoutException e) { + } catch (RuntimeException | IOException | InterruptedException | TimeoutException e) { log.error("Failed to execute {}", cfg.getCommand()); + log.debug("Internal exception:", e); throw new InternalServerError(e); } } diff --git a/src/main/java/io/kamax/mxisd/backend/rest/LookupSingleResponseJson.java b/src/main/java/io/kamax/mxisd/backend/rest/LookupSingleResponseJson.java index 7bc9246..00ca014 100644 --- a/src/main/java/io/kamax/mxisd/backend/rest/LookupSingleResponseJson.java +++ b/src/main/java/io/kamax/mxisd/backend/rest/LookupSingleResponseJson.java @@ -20,6 +20,7 @@ package io.kamax.mxisd.backend.rest; +import io.kamax.matrix.ThreePidMedium; import io.kamax.mxisd.UserID; public class LookupSingleResponseJson { @@ -32,12 +33,28 @@ public class LookupSingleResponseJson { return medium; } + public void setMedium(String medium) { + this.medium = medium; + } + + public void setMedium(ThreePidMedium medium) { + setMedium(medium.getId()); + } + public String getAddress() { return address; } + public void setAddress(String address) { + this.address = address; + } + public UserID getId() { return id; } + public void setId(UserID id) { + this.id = id; + } + } diff --git a/src/main/java/io/kamax/mxisd/config/ExecConfig.java b/src/main/java/io/kamax/mxisd/config/ExecConfig.java index 128fecd..9fe9cab 100644 --- a/src/main/java/io/kamax/mxisd/config/ExecConfig.java +++ b/src/main/java/io/kamax/mxisd/config/ExecConfig.java @@ -420,9 +420,12 @@ public class ExecConfig { } - public class Profile extends Process { + public class Profile { private Boolean enabled; + private Process displayName = new Process(); + private Process threePid = new Process(); + private Process role = new Process(); public Boolean isEnabled() { return enabled; @@ -432,6 +435,30 @@ public class ExecConfig { this.enabled = enabled; } + public Process getDisplayName() { + return displayName; + } + + public void setDisplayName(Process displayName) { + this.displayName = displayName; + } + + public Process getThreePid() { + return threePid; + } + + public void setThreePid(Process threePid) { + this.threePid = threePid; + } + + public Process getRole() { + return role; + } + + public void setRoles(Process role) { + this.role = role; + } + } private boolean enabled; @@ -490,7 +517,7 @@ public class ExecConfig { } @PostConstruct - public void build() { + public ExecConfig compute() { if (Objects.isNull(getAuth().isEnabled())) { getAuth().setEnabled(isEnabled()); } @@ -506,6 +533,8 @@ public class ExecConfig { if (Objects.isNull(getProfile().isEnabled())) { getProfile().setEnabled(isEnabled()); } + + return this; } } diff --git a/src/main/java/io/kamax/mxisd/controller/directory/v1/io/UserDirectorySearchResult.java b/src/main/java/io/kamax/mxisd/controller/directory/v1/io/UserDirectorySearchResult.java index 42490ab..deffa3f 100644 --- a/src/main/java/io/kamax/mxisd/controller/directory/v1/io/UserDirectorySearchResult.java +++ b/src/main/java/io/kamax/mxisd/controller/directory/v1/io/UserDirectorySearchResult.java @@ -25,6 +25,10 @@ import java.util.Set; public class UserDirectorySearchResult { + public static UserDirectorySearchResult empty() { + return new UserDirectorySearchResult(); + } + public static class Result { private String displayName; diff --git a/src/main/java/io/kamax/mxisd/profile/JsonProfileRequest.java b/src/main/java/io/kamax/mxisd/profile/JsonProfileRequest.java new file mode 100644 index 0000000..adffc26 --- /dev/null +++ b/src/main/java/io/kamax/mxisd/profile/JsonProfileRequest.java @@ -0,0 +1,67 @@ +/* + * 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 . + */ + +package io.kamax.mxisd.profile; + +import io.kamax.matrix._MatrixID; + +public class JsonProfileRequest { + + private String localpart; + private String domain; + private String mxid; + + public JsonProfileRequest(_MatrixID mxId) { + this.localpart = mxId.getLocalPart(); + this.domain = mxId.getDomain(); + this.mxid = mxId.getId(); + } + + public JsonProfileRequest(String localpart, String domain, String mxId) { + this.localpart = localpart; + this.domain = domain; + 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 getMxid() { + return mxid; + } + + public void setMxid(String mxid) { + this.mxid = mxid; + } + +} diff --git a/src/main/java/io/kamax/mxisd/profile/JsonProfileResult.java b/src/main/java/io/kamax/mxisd/profile/JsonProfileResult.java new file mode 100644 index 0000000..b7d4e4a --- /dev/null +++ b/src/main/java/io/kamax/mxisd/profile/JsonProfileResult.java @@ -0,0 +1,69 @@ +/* + * 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 . + */ + +package io.kamax.mxisd.profile; + +import io.kamax.matrix.ThreePid; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class JsonProfileResult { + + private String displayName; + private List threepids; + private List roles; + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public List getThreepids() { + return threepids; + } + + public void setThreepids(List threepids) { + this.threepids = threepids; + } + + public void addThreepid(ThreePid threepid) { + if (Objects.isNull(threepids)) threepids = new ArrayList<>(); + threepids.add(threepid); + } + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } + + public void addRole(String role) { + if (Objects.isNull(roles)) roles = new ArrayList<>(); + roles.add(role); + } + +} diff --git a/src/test/java/io/kamax/mxisd/backend/exec/auth/input/ExecAuthTest.java b/src/test/java/io/kamax/mxisd/backend/exec/ExecAuthStoreTest.java similarity index 96% rename from src/test/java/io/kamax/mxisd/backend/exec/auth/input/ExecAuthTest.java rename to src/test/java/io/kamax/mxisd/backend/exec/ExecAuthStoreTest.java index e1a82bd..de26ae0 100644 --- a/src/test/java/io/kamax/mxisd/backend/exec/auth/input/ExecAuthTest.java +++ b/src/test/java/io/kamax/mxisd/backend/exec/ExecAuthStoreTest.java @@ -18,13 +18,11 @@ * along with this program. If not, see . */ -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); } diff --git a/src/test/java/io/kamax/mxisd/backend/exec/ExecDirectoryStoreTest.java b/src/test/java/io/kamax/mxisd/backend/exec/ExecDirectoryStoreTest.java new file mode 100644 index 0000000..46a2f02 --- /dev/null +++ b/src/test/java/io/kamax/mxisd/backend/exec/ExecDirectoryStoreTest.java @@ -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 . + */ + +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"); + } + +} diff --git a/src/test/java/io/kamax/mxisd/backend/exec/ExecIdentityStoreTest.java b/src/test/java/io/kamax/mxisd/backend/exec/ExecIdentityStoreTest.java new file mode 100644 index 0000000..16e258f --- /dev/null +++ b/src/test/java/io/kamax/mxisd/backend/exec/ExecIdentityStoreTest.java @@ -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 . + */ + +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 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 lookup = store.find(req); + assertFalse(lookup.isPresent()); + } + + @Test + public void singleSuccessData() { + SingleLookupRequest req = new SingleLookupRequest(); + req.setType(ThreePidMedium.Email.getId()); + req.setThreePid(user1Email); + + Optional 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); + } + +} diff --git a/src/test/java/io/kamax/mxisd/backend/exec/ExecProfileStoreTest.java b/src/test/java/io/kamax/mxisd/backend/exec/ExecProfileStoreTest.java new file mode 100644 index 0000000..ee5225d --- /dev/null +++ b/src/test/java/io/kamax/mxisd/backend/exec/ExecProfileStoreTest.java @@ -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 . + */ + +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 name = getStore(sno).getDisplayName(MatrixID.asAcceptable(user1Localpart, domain)); + assertFalse(name.isPresent()); + } + + @Test + public void getNameSuccessEmptyOutput() { + Optional name = getStore(seo).getDisplayName(MatrixID.asAcceptable(user1Localpart, domain)); + assertFalse(name.isPresent()); + } + + @Test + public void getNameSuccess() { + Optional 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()); + } + +} diff --git a/src/test/java/io/kamax/mxisd/backend/exec/ExecStoreTest.java b/src/test/java/io/kamax/mxisd/backend/exec/ExecStoreTest.java new file mode 100644 index 0000000..7806f21 --- /dev/null +++ b/src/test/java/io/kamax/mxisd/backend/exec/ExecStoreTest.java @@ -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 . + */ + +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> 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 supplier) { + return new ProcessResult(exitCode, null) { + + @Override + public String outputUTF8() { + return supplier.get(); + } + + }; + } + + protected ProcessResult makeJson(int exitCode, Supplier supplier) { + return make(exitCode, () -> GsonUtil.get().toJson(supplier.get())); + } + + protected ProcessExecutor build() { + return new ProcessExecutor() { + + private Function 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(); + } + + }; + } + +} diff --git a/src/test/java/io/kamax/mxisd/backend/exec/auth/input/ExecAuthArgsTest.java b/src/test/java/io/kamax/mxisd/backend/exec/auth/input/ExecAuthArgsTest.java index 1d7eb81..efaa897 100644 --- a/src/test/java/io/kamax/mxisd/backend/exec/auth/input/ExecAuthArgsTest.java +++ b/src/test/java/io/kamax/mxisd/backend/exec/auth/input/ExecAuthArgsTest.java @@ -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() { diff --git a/src/test/java/io/kamax/mxisd/backend/exec/auth/input/ExecAuthEnvTest.java b/src/test/java/io/kamax/mxisd/backend/exec/auth/input/ExecAuthEnvTest.java index 0f96239..fa153aa 100644 --- a/src/test/java/io/kamax/mxisd/backend/exec/auth/input/ExecAuthEnvTest.java +++ b/src/test/java/io/kamax/mxisd/backend/exec/auth/input/ExecAuthEnvTest.java @@ -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"; diff --git a/src/test/java/io/kamax/mxisd/backend/exec/auth/input/ExecAuthInputMultilinesTest.java b/src/test/java/io/kamax/mxisd/backend/exec/auth/input/ExecAuthInputMultilinesTest.java index 83ec388..1216e39 100644 --- a/src/test/java/io/kamax/mxisd/backend/exec/auth/input/ExecAuthInputMultilinesTest.java +++ b/src/test/java/io/kamax/mxisd/backend/exec/auth/input/ExecAuthInputMultilinesTest.java @@ -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() {