Skip to content

Commit

Permalink
Add HissPropertiesBuilder (#18)
Browse files Browse the repository at this point in the history
* Add HissPropertiesBuilder

* Fix javadoc errors
  • Loading branch information
mkay1375 authored Aug 20, 2024
1 parent a13bf44 commit d7518f1
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 182 deletions.
3 changes: 3 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@
</goals>
</execution>
</executions>
<configuration>
<doclint>none</doclint> <!-- Javadoc doesn't support lombok -->
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand Down
31 changes: 15 additions & 16 deletions src/main/java/io/github/tap30/hiss/HissFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import io.github.tap30.hiss.hasher.impl.TapsiHmacSha256Hasher;
import io.github.tap30.hiss.key.KeyHashGenerator;
import io.github.tap30.hiss.properties.HissProperties;
import io.github.tap30.hiss.properties.HissPropertiesProvider;
import io.github.tap30.hiss.properties.HissPropertiesValidator;
import org.jetbrains.annotations.NotNull;

Expand All @@ -27,14 +28,13 @@ public class HissFactory {
* Creates a Hiss instance with provided <code>HissProperties</code> and default encryptors and hashers.
*
* @param hissProperties the properties by which hiss will be instantiated;
* {@link io.github.tap30.hiss.properties.HissPropertiesFromEnv}
* or any custom implementation of
* {@link io.github.tap30.hiss.properties.HissProperties}
* can be used.
* use {@link HissProperties#fromEnv()}
* or {@link HissProperties#builder()}
* or {@link HissProperties#withProvider(HissPropertiesProvider)}
* @return {@link Hiss} instance.
* @throws IllegalArgumentException if the properties are not valid.
*/
public static Hiss createHiss(HissProperties hissProperties) {
public static Hiss createHiss(@NotNull HissProperties hissProperties) {
return createHiss(hissProperties, Set.of(), Set.of());
}

Expand All @@ -44,18 +44,17 @@ public static Hiss createHiss(HissProperties hissProperties) {
* Provided encryptors and hashers will be added alongside default ones.
*
* @param hissProperties the properties by which hiss will be instantiated;
* {@link io.github.tap30.hiss.properties.HissPropertiesFromEnv}
* or any custom implementation of
* {@link io.github.tap30.hiss.properties.HissProperties}
* can be used.
* @param encryptors custom {@link Encryptor} implementations. Can be empty but not null.
* @param hashers custom {@link Hasher} implementations. Can be empty but not null.
* use {@link HissProperties#fromEnv()}
* or {@link HissProperties#builder()}
* or {@link HissProperties#withProvider(HissPropertiesProvider)}
* @param encryptors custom {@link Encryptor} implementations. Can be empty but not null.
* @param hashers custom {@link Hasher} implementations. Can be empty but not null.
* @return {@link Hiss} instance.
* @throws IllegalArgumentException if the properties are not valid.
*/
public static Hiss createHiss(HissProperties hissProperties,
Set<Encryptor> encryptors,
Set<Hasher> hashers) {
public static Hiss createHiss(@NotNull HissProperties hissProperties,
@NotNull Set<Encryptor> encryptors,
@NotNull Set<Hasher> hashers) {
Objects.requireNonNull(hissProperties);
Objects.requireNonNull(encryptors);
Objects.requireNonNull(hashers);
Expand Down Expand Up @@ -109,8 +108,8 @@ public static Hiss createHiss(HissProperties hissProperties,
}

private static void logInitializingHiss(HissProperties hissProperties,
Map<String, Encryptor> encryptors,
Map<String, Hasher> hashers) {
Map<String, Encryptor> encryptors,
Map<String, Hasher> hashers) {
logger.log(Level.INFO, "Hiss initialized:\n" +
" Loaded Keys: {0}\n" +
" Default Encryption Key ID: {1}\n" +
Expand Down
103 changes: 51 additions & 52 deletions src/main/java/io/github/tap30/hiss/properties/HissProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,74 +2,73 @@

import io.github.tap30.hiss.key.Key;
import io.github.tap30.hiss.utils.StringUtils;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Value;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

public abstract class HissProperties {

private final Map<String, Object> properties = new HashMap<>();

public Map<String, Key> getKeys() {
return this.getProperty("Keys", this::loadKeys, HissProperties::keysAsMap);
}

public String getDefaultEncryptionKeyId() {
return this.getProperty("DefaultEncryptionKeyId",
this::loadDefaultEncryptionKeyId, StringUtils::toLowerCase);
}

public String getDefaultEncryptionAlgorithm() {
return this.getProperty("DefaultEncryptionAlgorithm",
this::loadDefaultEncryptionAlgorithm, StringUtils::toLowerCase);
}

public String getDefaultHashingKeyId() {
return this.getProperty("DefaultHashingKeyId",
this::loadDefaultHashingKeyId, StringUtils::toLowerCase);
}

public String getDefaultHashingAlgorithm() {
return this.getProperty("DefaultHashingAlgorithm",
this::loadDefaultHashingAlgorithm, StringUtils::toLowerCase);
@Builder
@Value
@AllArgsConstructor(access = AccessLevel.PACKAGE)
public class HissProperties {

Map<String, Key> keys;
String defaultEncryptionKeyId;
String defaultEncryptionAlgorithm;
String defaultHashingKeyId;
String defaultHashingAlgorithm;
boolean keyHashGenerationEnabled;

/**
* See {@link HissPropertiesFromEnvProvider}.
*/
public static HissProperties fromEnv() {
return withProvider(new HissPropertiesFromEnvProvider());
}

public boolean isKeyHashGenerationEnabled() {
return this.getProperty("KeyHashGenerationEnabled", this::loadKeyHashGenerationEnabled);
public static HissProperties withProvider(HissPropertiesProvider provider) {
return builder()
.keys(provider.getKeys())
.defaultEncryptionKeyId(provider.getDefaultEncryptionKeyId())
.defaultEncryptionAlgorithm(provider.getDefaultEncryptionAlgorithm())
.defaultHashingKeyId(provider.getDefaultHashingKeyId())
.defaultHashingAlgorithm(provider.getDefaultHashingAlgorithm())
.keyHashGenerationEnabled(provider.isKeyHashGenerationEnabled())
.build();
}

protected abstract Set<Key> loadKeys();

protected abstract String loadDefaultEncryptionKeyId();

protected abstract String loadDefaultEncryptionAlgorithm();

protected abstract String loadDefaultHashingKeyId();
public static class HissPropertiesBuilder {
public HissPropertiesBuilder keys(Set<Key> keys) {
this.keys = keys.stream()
.collect(Collectors.toMap(k -> StringUtils.toLowerCase(k.getId()), Function.identity()));
return this;
}

protected abstract String loadDefaultHashingAlgorithm();
public HissPropertiesBuilder defaultEncryptionKeyId(String defaultEncryptionKeyId) {
this.defaultEncryptionKeyId = StringUtils.toLowerCase(defaultEncryptionKeyId);
return this;
}

protected abstract boolean loadKeyHashGenerationEnabled();
public HissPropertiesBuilder defaultEncryptionAlgorithm(String defaultEncryptionAlgorithm) {
this.defaultEncryptionAlgorithm = StringUtils.toLowerCase(defaultEncryptionAlgorithm);
return this;
}

private <O> O getProperty(String key, Supplier<O> valueSupplier) {
return getProperty(key, valueSupplier, v -> v);
}
public HissPropertiesBuilder defaultHashingKeyId(String defaultHashingKeyId) {
this.defaultHashingKeyId = StringUtils.toLowerCase(defaultHashingKeyId);
return this;
}

@SuppressWarnings("unchecked")
private <I, O> O getProperty(String key, Supplier<I> valueSupplier, Function<I, O> mapper) {
if (this.properties.containsKey(key)) {
return (O) this.properties.get(key);
public HissPropertiesBuilder defaultHashingAlgorithm(String defaultHashingAlgorithm) {
this.defaultHashingAlgorithm = StringUtils.toLowerCase(defaultHashingAlgorithm);
return this;
}
var value = mapper.apply(valueSupplier.get());
this.properties.put(key, value);
return value;
}

private static Map<String, Key> keysAsMap(Set<Key> keys) {
return keys.stream().collect(Collectors.toMap(k -> StringUtils.toLowerCase(k.getId()), k -> k));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import java.util.Set;
import java.util.function.Supplier;

// Todo: import doc
// Todo: improve doc
/**
* Sample Envs:
* <br>
Expand All @@ -26,15 +26,15 @@
* HISS_DEFAULT_HASHING_ALGORITHM: hmac-sha256
* </code>
*/
public class HissPropertiesFromEnv extends HissProperties {
public class HissPropertiesFromEnvProvider implements HissPropertiesProvider {

private static final String KEY_ENV_PREFIX = "HISS_KEYS_";
private static final String KEY_HASH_ENV_POSTFIX = "___HASH";

private static final Supplier<Map<String, String>> ENV_PROVIDER = System::getenv;

@Override
public Set<Key> loadKeys() {
public Set<Key> getKeys() {
var keys = new HashSet<Key>();
ENV_PROVIDER.get().forEach((k, v) -> {
if (k.startsWith(KEY_ENV_PREFIX) && !k.endsWith(KEY_HASH_ENV_POSTFIX)) {
Expand All @@ -49,27 +49,28 @@ public Set<Key> loadKeys() {
}

@Override
public String loadDefaultEncryptionKeyId() {
public String getDefaultEncryptionKeyId() {
return ENV_PROVIDER.get().get("HISS_DEFAULT_ENCRYPTION_KEY_ID");
}

@Override
public String loadDefaultEncryptionAlgorithm() {
public String getDefaultEncryptionAlgorithm() {
return ENV_PROVIDER.get().get("HISS_DEFAULT_ENCRYPTION_ALGORITHM");
}

@Override
public String loadDefaultHashingKeyId() {
public String getDefaultHashingKeyId() {
return ENV_PROVIDER.get().get("HISS_DEFAULT_HASHING_KEY_ID");
}

@Override
public String loadDefaultHashingAlgorithm() {
public String getDefaultHashingAlgorithm() {
return ENV_PROVIDER.get().get("HISS_DEFAULT_HASHING_ALGORITHM");
}

@Override
protected boolean loadKeyHashGenerationEnabled() {
public boolean isKeyHashGenerationEnabled() {
return Boolean.parseBoolean(ENV_PROVIDER.get().get("HISS_KEY_HASH_GENERATION_ENABLED"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.github.tap30.hiss.properties;

import io.github.tap30.hiss.key.Key;

import java.util.Set;

public interface HissPropertiesProvider {
Set<Key> getKeys();
String getDefaultEncryptionKeyId();
String getDefaultEncryptionAlgorithm();
String getDefaultHashingKeyId();
String getDefaultHashingAlgorithm();
boolean isKeyHashGenerationEnabled();
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ private void validateDefaultEncryptionKeyAndAlgorithm(HissProperties hissPropert
if (!StringUtils.hasText(hissProperties.getDefaultEncryptionKeyId())) {
errors.add("Default encryption key ID is not defined");
}
if (!hissProperties.getKeys().containsKey(hissProperties.getDefaultEncryptionKeyId())) {
if (hissProperties.getKeys() != null
&& !hissProperties.getKeys().containsKey(hissProperties.getDefaultEncryptionKeyId())) {
errors.add("Default encryption key ID is not among provided keys: " + hissProperties.getKeys().keySet());
}
if (!StringUtils.hasText(hissProperties.getDefaultEncryptionAlgorithm())) {
Expand All @@ -67,7 +68,8 @@ private void validateDefaultHashingKeyAndAlgorithm(HissProperties hissProperties
if (!StringUtils.hasText(hissProperties.getDefaultHashingKeyId())) {
errors.add("Default hashing key ID is not defined");
}
if (!hissProperties.getKeys().containsKey(hissProperties.getDefaultHashingKeyId())) {
if (hissProperties.getKeys() != null
&& !hissProperties.getKeys().containsKey(hissProperties.getDefaultHashingKeyId())) {
errors.add("Default hashing key ID is not among provided keys: " + hissProperties.getKeys().keySet());
}
if (!StringUtils.hasText(hissProperties.getDefaultHashingAlgorithm())) {
Expand Down
5 changes: 2 additions & 3 deletions src/test/java/io/github/tap30/hiss/BaseHissTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.github.tap30.hiss;

import io.github.tap30.hiss.properties.HissPropertiesFromEnv;
import io.github.tap30.hiss.properties.HissProperties;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import uk.org.webcompere.systemstubs.environment.EnvironmentVariables;
Expand All @@ -24,8 +24,7 @@ public class BaseHissTest {

@BeforeEach
void setUpHiss() {
var hissPropertiesFromEnv = new HissPropertiesFromEnv();
hiss = HissFactory.createHiss(hissPropertiesFromEnv);
hiss = HissFactory.createHiss(HissProperties.fromEnv());
}

}
Loading

0 comments on commit d7518f1

Please sign in to comment.