Skip to content

Commit eae95a3

Browse files
committed
Final touches
1 parent 6aac500 commit eae95a3

File tree

10 files changed

+198
-60
lines changed

10 files changed

+198
-60
lines changed

src/main/java/org/codehaus/plexus/components/secdispatcher/Meta.java renamed to src/main/java/org/codehaus/plexus/components/secdispatcher/DispatcherMeta.java

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,68 @@
11
package org.codehaus.plexus.components.secdispatcher;
22

33
import java.util.Collection;
4+
import java.util.List;
45
import java.util.Optional;
56

67
import static java.util.Objects.requireNonNull;
78

89
/**
910
* Meta description of dispatcher.
1011
*/
11-
public interface Meta {
12+
public interface DispatcherMeta {
1213
class Field {
1314
private final String key;
1415
private final boolean optional;
1516
private final String defaultValue;
1617
private final String description;
18+
private final List<Field> options;
1719

18-
private Field(String key, boolean optional, String defaultValue, String description) {
20+
private Field(String key, boolean optional, String defaultValue, String description, List<Field> options) {
1921
this.key = requireNonNull(key);
2022
this.optional = optional;
2123
this.defaultValue = defaultValue;
2224
this.description = requireNonNull(description);
25+
this.options = options;
2326
}
2427

28+
/**
29+
* The key to be used in configuration map for field.
30+
*/
2531
public String getKey() {
2632
return key;
2733
}
2834

35+
/**
36+
* Is configuration optional?
37+
*/
2938
public boolean isOptional() {
3039
return optional;
3140
}
3241

42+
/**
43+
* Optional default value of the configuration.
44+
*/
3345
public Optional<String> getDefaultValue() {
3446
return Optional.ofNullable(defaultValue);
3547
}
3648

49+
/**
50+
* The human description of the configuration.
51+
*/
3752
public String getDescription() {
3853
return description;
3954
}
4055

56+
/**
57+
* Optional list of options, if this configuration accepts limited values. Each option is represented
58+
* as field, where {@link #getKey()} represents the value to be used, and {@link #displayName()} represents
59+
* the description of option. The {@link #getDefaultValue()}, if present represents the value to be used
60+
* instead of {@link #getKey()}.
61+
*/
62+
public Optional<List<Field>> getOptions() {
63+
return Optional.ofNullable(options);
64+
}
65+
4166
public static Builder builder(String key) {
4267
return new Builder(key);
4368
}
@@ -47,6 +72,7 @@ public static class Builder {
4772
private boolean optional;
4873
private String defaultValue;
4974
private String description;
75+
private List<Field> options;
5076

5177
private Builder(String key) {
5278
this.key = requireNonNull(key);
@@ -67,24 +93,29 @@ public Builder description(String description) {
6793
return this;
6894
}
6995

96+
public Builder options(List<Field> options) {
97+
this.options = requireNonNull(options);
98+
return this;
99+
}
100+
70101
public Field build() {
71-
return new Field(key, optional, defaultValue, description);
102+
return new Field(key, optional, defaultValue, description, options);
72103
}
73104
}
74105
}
75106

76107
/**
77-
* The key of the item.
108+
* The name of the dispatcher.
78109
*/
79110
String name();
80111

81112
/**
82-
* Returns the display (human) name of the item.
113+
* Returns the display (human) name of the dispatcher.
83114
*/
84115
String displayName();
85116

86117
/**
87-
* Returns the configuration fields of the item.
118+
* Returns the configuration fields of the dispatcher.
88119
*/
89120
Collection<Field> fields();
90121
}

src/main/java/org/codehaus/plexus/components/secdispatcher/SecDispatcher.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public interface SecDispatcher {
4848
/**
4949
* Returns the set of available dispatcher metadata, never {@code null}.
5050
*/
51-
Set<Meta> availableDispatchers();
51+
Set<DispatcherMeta> availableDispatchers();
5252

5353
/**
5454
* Encrypt given plaintext string.

src/main/java/org/codehaus/plexus/components/secdispatcher/internal/DefaultSecDispatcher.java

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,14 @@
2222
import java.nio.file.Paths;
2323
import java.util.HashMap;
2424
import java.util.Map;
25+
import java.util.Objects;
2526
import java.util.Set;
2627
import java.util.StringTokenizer;
2728
import java.util.stream.Collectors;
2829

2930
import org.codehaus.plexus.components.cipher.PlexusCipher;
3031
import org.codehaus.plexus.components.cipher.PlexusCipherException;
31-
import org.codehaus.plexus.components.secdispatcher.Meta;
32+
import org.codehaus.plexus.components.secdispatcher.DispatcherMeta;
3233
import org.codehaus.plexus.components.secdispatcher.SecDispatcher;
3334
import org.codehaus.plexus.components.secdispatcher.SecDispatcherException;
3435
import org.codehaus.plexus.components.secdispatcher.model.SettingsSecurity;
@@ -59,7 +60,7 @@ public DefaultSecDispatcher(
5960
}
6061

6162
@Override
62-
public Set<Meta> availableDispatchers() {
63+
public Set<DispatcherMeta> availableDispatchers() {
6364
return Set.copyOf(dispatchers.values().stream().map(Dispatcher::meta).collect(Collectors.toSet()));
6465
}
6566

@@ -74,17 +75,25 @@ public String encrypt(String str, Map<String, String> attr) throws SecDispatcher
7475
attr = new HashMap<>(attr);
7576
}
7677
if (attr.get(DISPATCHER_NAME_ATTR) == null) {
77-
attr.put(DISPATCHER_NAME_ATTR, getConfiguration().getDefaultDispatcher());
78+
attr.put(
79+
DISPATCHER_NAME_ATTR,
80+
requireNonNull(
81+
getConfiguration().getDefaultDispatcher(),
82+
"no default dispatcher set in configuration"));
7883
}
7984
String name = attr.get(DISPATCHER_NAME_ATTR);
8085
Dispatcher dispatcher = dispatchers.get(name);
8186
if (dispatcher == null) throw new SecDispatcherException("no dispatcher for name " + name);
87+
Dispatcher.EncryptPayload payload = dispatcher.encrypt(str, attr, prepareDispatcherConfig(name));
88+
if (!Objects.equals(payload.getAttributes().get(DISPATCHER_NAME_ATTR), name)) {
89+
throw new SecDispatcherException("Dispatcher " + name + " bug: mismatched name attribute");
90+
}
8291
String res = ATTR_START
83-
+ attr.entrySet().stream()
92+
+ payload.getAttributes().entrySet().stream()
8493
.map(e -> e.getKey() + "=" + e.getValue())
8594
.collect(Collectors.joining(","))
8695
+ ATTR_STOP;
87-
res += dispatcher.encrypt(str, attr, prepareDispatcherConfig(name));
96+
res += payload.getEncrypted();
8897
return cipher.decorate(res);
8998
} catch (PlexusCipherException e) {
9099
throw new SecDispatcherException(e.getMessage(), e);
@@ -96,9 +105,9 @@ public String decrypt(String str) throws SecDispatcherException {
96105
if (!isEncryptedString(str)) return str;
97106
try {
98107
String bare = cipher.unDecorate(str);
99-
Map<String, String> attr = stripAttributes(bare);
108+
Map<String, String> attr = requireNonNull(stripAttributes(bare));
100109
if (attr.get(DISPATCHER_NAME_ATTR) == null) {
101-
attr.put(DISPATCHER_NAME_ATTR, getConfiguration().getDefaultDispatcher());
110+
throw new SecDispatcherException("malformed password: no attribute with name");
102111
}
103112
String name = attr.get(DISPATCHER_NAME_ATTR);
104113
Dispatcher dispatcher = dispatchers.get(name);

src/main/java/org/codehaus/plexus/components/secdispatcher/internal/Dispatcher.java

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515

1616
import java.util.Map;
1717

18-
import org.codehaus.plexus.components.secdispatcher.Meta;
18+
import org.codehaus.plexus.components.secdispatcher.DispatcherMeta;
1919
import org.codehaus.plexus.components.secdispatcher.SecDispatcherException;
2020

21+
import static java.util.Objects.requireNonNull;
22+
2123
/**
2224
* Dispatcher.
2325
*
@@ -26,26 +28,48 @@
2628
*
2729
*/
2830
public interface Dispatcher {
31+
/**
32+
* The "encrypt payload" prepared by dispatcher.
33+
*/
34+
final class EncryptPayload {
35+
private final Map<String, String> attributes;
36+
private final String encrypted;
37+
38+
public EncryptPayload(Map<String, String> attributes, String encrypted) {
39+
this.attributes = requireNonNull(attributes);
40+
this.encrypted = requireNonNull(encrypted);
41+
}
42+
43+
public Map<String, String> getAttributes() {
44+
return attributes;
45+
}
46+
47+
public String getEncrypted() {
48+
return encrypted;
49+
}
50+
}
51+
2952
/**
3053
* The metadata of this dispatcher.
3154
*/
32-
Meta meta();
55+
DispatcherMeta meta();
3356

3457
/**
35-
* encrypt given plaintext string
58+
* Encrypt given plaintext string. Implementation must return at least same attributes it got, but may add more
59+
* attributes to returned payload.
3660
*
37-
* @param str string to encrypt
61+
* @param str string to encrypt, never {@code null}
3862
* @param attributes attributes, never {@code null}
3963
* @param config configuration from settings-security.xml, never {@code null}
40-
* @return encrypted string
64+
* @return encrypted string and attributes in {@link EncryptPayload}
4165
*/
42-
String encrypt(String str, Map<String, String> attributes, Map<String, String> config)
66+
EncryptPayload encrypt(String str, Map<String, String> attributes, Map<String, String> config)
4367
throws SecDispatcherException;
4468

4569
/**
46-
* decrypt given encrypted string
70+
* Decrypt given encrypted string.
4771
*
48-
* @param str string to decrypt
72+
* @param str string to decrypt, never {@code null}
4973
* @param attributes attributes, never {@code null}
5074
* @param config configuration from settings-security.xml, never {@code null}
5175
* @return decrypted string

src/main/java/org/codehaus/plexus/components/secdispatcher/internal/MasterSource.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,36 @@
1313

1414
package org.codehaus.plexus.components.secdispatcher.internal;
1515

16+
import java.util.Optional;
17+
1618
import org.codehaus.plexus.components.secdispatcher.SecDispatcherException;
1719

1820
/**
1921
* Source of master password.
2022
*/
2123
public interface MasterSource {
2224
/**
23-
* Handles the URI to get master password. Implementation may do one of the following things:
25+
* String describing what this source does.
26+
*/
27+
String description();
28+
29+
/**
30+
* Optional "config template" that may serve as basis to configure this master source. The template cannot be
31+
* "reused" as is as configuration.
32+
*/
33+
Optional<String> configTemplate();
34+
35+
/**
36+
* Handles the config to get master password. Implementation may do one of the following things:
2437
* <ul>
25-
* <li>if the URI cannot be handled by given source, return {@code null}</li>
26-
* <li>if master password retrieval was attempted, but failed throw {@link SecDispatcherException}</li>
38+
* <li>if the config cannot be handled by given source, return {@code null}</li>
39+
* <li>otherwise, if master password retrieval based on config was attempted but failed, throw {@link SecDispatcherException}</li>
2740
* <li>happy path: return the master password.</li>
2841
* </ul>
2942
*
30-
* @param masterSource the source of master password, and opaque string.
31-
* @return the master password, or {@code null} if implementation does not handle this masterSource
32-
* @throws SecDispatcherException If implementation does handle this masterSource, but cannot obtain it
43+
* @param config the source of master password, and opaque string.
44+
* @return the master password, or {@code null} if implementation does not handle this config
45+
* @throws SecDispatcherException If implementation does handle this masterSource, but cannot obtain master password
3346
*/
34-
String handle(String masterSource) throws SecDispatcherException;
47+
String handle(String config) throws SecDispatcherException;
3548
}

0 commit comments

Comments
 (0)