diff --git a/external-sop/src/main/java/sop/external/operation/ListProfilesExternal.java b/external-sop/src/main/java/sop/external/operation/ListProfilesExternal.java index 1c6cdf3..b9df0f3 100644 --- a/external-sop/src/main/java/sop/external/operation/ListProfilesExternal.java +++ b/external-sop/src/main/java/sop/external/operation/ListProfilesExternal.java @@ -4,12 +4,12 @@ package sop.external.operation; +import sop.Profile; import sop.external.ExternalSOP; import sop.operation.ListProfiles; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Properties; @@ -25,23 +25,22 @@ public class ListProfilesExternal implements ListProfiles { } @Override - public List ofCommand(String command) { + public List subcommand(String command) { commandList.add(command); try { String output = new String(ExternalSOP.executeProducingOperation(Runtime.getRuntime(), commandList, envList).getBytes()); - return Arrays.asList(output.split("\n")); + return toProfiles(output); } catch (IOException e) { throw new RuntimeException(e); } } - @Override - public List global() { - try { - String output = new String(ExternalSOP.executeProducingOperation(Runtime.getRuntime(), commandList, envList).getBytes()); - return Arrays.asList(output.split("\n")); - } catch (IOException e) { - throw new RuntimeException(e); + private List toProfiles(String output) { + List profiles = new ArrayList<>(); + for (String line : output.split("\n")) { + String[] split = line.split(": "); + profiles.add(new Profile(split[0], split[1])); } + return profiles; } } diff --git a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/GenerateKeyCmd.java b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/GenerateKeyCmd.java index a592863..1d08b7c 100644 --- a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/GenerateKeyCmd.java +++ b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/GenerateKeyCmd.java @@ -31,7 +31,7 @@ public class GenerateKeyCmd extends AbstractSopCmd { String withKeyPassword; @CommandLine.Option(names = "--profile", - paramLabel = "PROFILE") + paramLabel = "PROFILE") String profile = "default"; @Override @@ -47,7 +47,12 @@ public class GenerateKeyCmd extends AbstractSopCmd { generateKey.noArmor(); } - generateKey.profile(profile); + try { + generateKey.profile(profile); + } catch (SOPGPException.UnsupportedProfile e) { + String errorMsg = getMsg("sop.error.usage.profile_not_supported", "generate-key", profile); + throw new SOPGPException.UnsupportedProfile(errorMsg, e); + } if (withKeyPassword != null) { try { diff --git a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/ListProfilesCmd.java b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/ListProfilesCmd.java index 14211c3..be271e6 100644 --- a/sop-java-picocli/src/main/java/sop/cli/picocli/commands/ListProfilesCmd.java +++ b/sop-java-picocli/src/main/java/sop/cli/picocli/commands/ListProfilesCmd.java @@ -5,7 +5,9 @@ package sop.cli.picocli.commands; import picocli.CommandLine; +import sop.Profile; import sop.cli.picocli.SopCLI; +import sop.exception.SOPGPException; import sop.operation.ListProfiles; @CommandLine.Command(name = "list-profiles", @@ -13,7 +15,7 @@ import sop.operation.ListProfiles; exitCodeOnInvalidInput = 37) public class ListProfilesCmd extends AbstractSopCmd { - @CommandLine.Parameters(paramLabel = "COMMAND", arity="0..1", descriptionKey = "subcommand") + @CommandLine.Parameters(paramLabel = "COMMAND", arity="1", descriptionKey = "subcommand") String subcommand; @Override @@ -21,19 +23,15 @@ public class ListProfilesCmd extends AbstractSopCmd { ListProfiles listProfiles = throwIfUnsupportedSubcommand( SopCLI.getSop().listProfiles(), "list-profiles"); - if (subcommand == null) { - for (String profile : listProfiles.global()) { + try { + for (Profile profile : listProfiles.subcommand(subcommand)) { // CHECKSTYLE:OFF System.out.println(profile); // CHECKSTYLE:ON } - return; - } - - for (String profile : listProfiles.ofCommand(subcommand)) { - // CHECKSTYLE:OFF - System.out.println(profile); - // CHECKSTYLE:ON + } catch (SOPGPException.UnsupportedProfile e) { + String errorMsg = getMsg("sop.error.feature_support.subcommand_does_not_support_profiles", subcommand); + throw new SOPGPException.UnsupportedProfile(errorMsg, e); } } } diff --git a/sop-java-picocli/src/main/resources/msg_generate-key.properties b/sop-java-picocli/src/main/resources/msg_generate-key.properties index 5744199..4647791 100644 --- a/sop-java-picocli/src/main/resources/msg_generate-key.properties +++ b/sop-java-picocli/src/main/resources/msg_generate-key.properties @@ -4,6 +4,7 @@ usage.header=Generate a secret key no-armor=ASCII armor the output USERID[0..*]=User-ID, e.g. "Alice " +profile=Profile identifier to switch between profiles with-key-password.0=Password to protect the private key with with-key-password.1=Is an INDIRECT data type (e.g. file, environment variable, file descriptor...). diff --git a/sop-java-picocli/src/main/resources/msg_generate-key_de.properties b/sop-java-picocli/src/main/resources/msg_generate-key_de.properties index b3cbf62..41a493b 100644 --- a/sop-java-picocli/src/main/resources/msg_generate-key_de.properties +++ b/sop-java-picocli/src/main/resources/msg_generate-key_de.properties @@ -4,6 +4,7 @@ usage.header=Generiere einen privaten Schlüssel no-armor=Schütze Ausgabe mit ASCII Armor USERID[0..*]=Nutzer-ID, z.B.. "Alice " +profile=Profil-Identifikator um zwischen Profilen zu wechseln with-key-password.0=Passwort zum Schutz des privaten Schlüssels with-key-password.1=Ist ein INDIREKTER Datentyp (z.B.. Datei, Umgebungsvariable, Dateideskriptor...). diff --git a/sop-java-picocli/src/main/resources/msg_sop.properties b/sop-java-picocli/src/main/resources/msg_sop.properties index 069b0ce..6ddcf9c 100644 --- a/sop-java-picocli/src/main/resources/msg_sop.properties +++ b/sop-java-picocli/src/main/resources/msg_sop.properties @@ -74,8 +74,10 @@ sop.error.runtime.cannot_decrypt_message=Message could not be decrypted. sop.error.usage.password_or_cert_required=At least one password file or cert file required for encryption. sop.error.usage.argument_required=Argument '%s' is required. sop.error.usage.parameter_required=Parameter '%s' is required. +sop.error.usage.profile_not_supported=Subcommand '%s' does not support profile '%s'. sop.error.usage.option_requires_other_option=Option '%s' is requested, but no option %s was provided. sop.error.usage.incompatible_options.clearsigned_no_armor=Options '--no-armor' and '--as=clearsigned' are incompatible. # Feature Support sop.error.feature_support.subcommand_not_supported=Subcommand '%s' is not supported. -sop.error.feature_support.option_not_supported=Option '%s' not supported. \ No newline at end of file +sop.error.feature_support.option_not_supported=Option '%s' not supported. +sop.error.feature_support.subcommand_does_not_support_profiles=Subcommand '%s' does not support any profiles. \ No newline at end of file diff --git a/sop-java-picocli/src/main/resources/msg_sop_de.properties b/sop-java-picocli/src/main/resources/msg_sop_de.properties index a8569e5..a20a11d 100644 --- a/sop-java-picocli/src/main/resources/msg_sop_de.properties +++ b/sop-java-picocli/src/main/resources/msg_sop_de.properties @@ -73,8 +73,10 @@ sop.error.runtime.cannot_decrypt_message=Nachricht konnte nicht entschl sop.error.usage.password_or_cert_required=Es wird mindestens ein Passwort und/oder Zertifikat zur Verschlüsselung benötigt. sop.error.usage.argument_required=Argument '%s' ist erforderlich. sop.error.usage.parameter_required=Parameter '%s' ist erforderlich. +sop.error.usage.profile_not_supported=Unterbefehl '%s' unterstützt Profil '%s' nicht. sop.error.usage.option_requires_other_option=Option '%s' wurde angegeben, jedoch kein Wert für %s. sop.error.usage.incompatible_options.clearsigned_no_armor=Optionen '--no-armor' und '--as=clearsigned' sind inkompatibel. # Feature Support sop.error.feature_support.subcommand_not_supported=Unterbefehl '%s' wird nicht unterstützt. -sop.error.feature_support.option_not_supported=Option '%s' wird nicht unterstützt. \ No newline at end of file +sop.error.feature_support.option_not_supported=Option '%s' wird nicht unterstützt. +sop.error.feature_support.subcommand_does_not_support_profiles=Unterbefehl '%s' unterstützt keine Profile. \ No newline at end of file diff --git a/sop-java/src/main/java/sop/exception/SOPGPException.java b/sop-java/src/main/java/sop/exception/SOPGPException.java index 04da74d..1618a58 100644 --- a/sop-java/src/main/java/sop/exception/SOPGPException.java +++ b/sop-java/src/main/java/sop/exception/SOPGPException.java @@ -401,12 +401,33 @@ public abstract class SOPGPException extends RuntimeException { public static final int EXIT_CODE = 89; - public UnsupportedProfile() { - super(); + private final String subcommand; + private final String profile; + + public UnsupportedProfile(String subcommand) { + super("Subcommand '" + subcommand + "' does not support any profiles."); + this.subcommand = subcommand; + this.profile = null; } - public UnsupportedProfile(String errorMessage) { - super(errorMessage); + public UnsupportedProfile(String subcommand, String profile) { + super("Subcommand '" + subcommand + "' does not support profile '" + profile + "'."); + this.subcommand = subcommand; + this.profile = profile; + } + + public UnsupportedProfile(String errorMsg, UnsupportedProfile e) { + super(errorMsg, e); + this.subcommand = e.getSubcommand(); + this.profile = e.getProfile(); + } + + public String getSubcommand() { + return subcommand; + } + + public String getProfile() { + return profile; } @Override diff --git a/sop-java/src/main/java/sop/operation/GenerateKey.java b/sop-java/src/main/java/sop/operation/GenerateKey.java index 1eb2620..27a3b19 100644 --- a/sop-java/src/main/java/sop/operation/GenerateKey.java +++ b/sop-java/src/main/java/sop/operation/GenerateKey.java @@ -6,8 +6,8 @@ package sop.operation; import java.io.IOException; import java.io.InputStream; -import java.util.List; +import sop.Profile; import sop.Ready; import sop.exception.SOPGPException; import sop.util.UTF8Util; @@ -57,11 +57,21 @@ public interface GenerateKey { return withKeyPassword(UTF8Util.decodeUTF8(password)); } + /** + * Pass in a profile. + * + * @param profile profile + * @return builder instance + */ + default GenerateKey profile(Profile profile) { + return profile(profile.getName()); + } + /** * Pass in a profile identifier. * * @param profile profile identifier - * @return this + * @return builder instance */ GenerateKey profile(String profile); diff --git a/sop-java/src/main/java/sop/operation/ListProfiles.java b/sop-java/src/main/java/sop/operation/ListProfiles.java index e27789f..87bb3b3 100644 --- a/sop-java/src/main/java/sop/operation/ListProfiles.java +++ b/sop-java/src/main/java/sop/operation/ListProfiles.java @@ -4,12 +4,12 @@ package sop.operation; +import sop.Profile; + import java.util.List; public interface ListProfiles { - List ofCommand(String command); - - List global(); + List subcommand(String command); } diff --git a/sop-java/src/testFixtures/java/sop/testsuite/operation/ListProfilesTest.java b/sop-java/src/testFixtures/java/sop/testsuite/operation/ListProfilesTest.java index 20f0590..e97dd39 100644 --- a/sop-java/src/testFixtures/java/sop/testsuite/operation/ListProfilesTest.java +++ b/sop-java/src/testFixtures/java/sop/testsuite/operation/ListProfilesTest.java @@ -7,6 +7,7 @@ package sop.testsuite.operation; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import sop.Profile; import sop.SOP; import java.io.IOException; @@ -21,19 +22,11 @@ public class ListProfilesTest extends AbstractSOPTest { return provideBackends(); } - @ParameterizedTest - @MethodSource("provideInstances") - public void listGlobalProfiles(SOP sop) throws IOException { - List profiles = sop.listProfiles() - .global(); - assertFalse(profiles.isEmpty()); - } - @ParameterizedTest @MethodSource("provideInstances") public void listGenerateKeyProfiles(SOP sop) throws IOException { - List profiles = sop.listProfiles() - .ofCommand("generate-key"); + List profiles = sop.listProfiles() + .subcommand("generate-key"); assertFalse(profiles.isEmpty()); }