diff --git a/.gitignore b/.gitignore index e69dca0..564d771 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ target dependency-reduced-pom.xml .idea -*.iml \ No newline at end of file +*.iml +.env \ No newline at end of file diff --git a/README.md b/README.md index d1d04a0..3892cbe 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,6 @@ JWS Utilties org.javawebstack web-utils - 1.0.0 + 1.0.1 ``` diff --git a/pom.xml b/pom.xml index 0eb1b58..799ce50 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 8 8 - 1.0.0-SNAPSHOT + 1.0.1-SNAPSHOT org.javawebstack @@ -44,22 +44,17 @@ org.javawebstack orm - 1.0.1 + 1.0.2 org.javawebstack http-server - 1.0.1 - - - com.github.javafaker - javafaker 1.0.2 org.junit.jupiter junit-jupiter-engine - 5.8.1 + 5.9.0 test diff --git a/src/main/java/org/javawebstack/webutils/config/Config.java b/src/main/java/org/javawebstack/webutils/config/Config.java index 08b38b8..000e1d9 100644 --- a/src/main/java/org/javawebstack/webutils/config/Config.java +++ b/src/main/java/org/javawebstack/webutils/config/Config.java @@ -1,6 +1,12 @@ package org.javawebstack.webutils.config; +import org.javawebstack.abstractdata.AbstractElement; +import org.javawebstack.abstractdata.AbstractObject; + import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; public class Config { @@ -11,42 +17,41 @@ public Config set(String path, String key, String value) { return set(prefix + key.toLowerCase(Locale.ROOT), value); } - public Config add(String path, Map data, Map mapping) { + public Config add(String path, Map data, Function mapping) { data.forEach((key, value) -> { - if(mapping != null && mapping.containsKey(key)) - key = mapping.get(key); - set(path, key, value); + key = mapping.apply(key); + if(key != null) + set(path, key, value); }); return this; } - public Config add(Map data, Map mapping) { - return add(null, data, null); + public Config add(Map data, Function mapping) { + return add(null, data, mapping); } public Config add(String path, Map data) { - return add(path, data, null); + return add(path, data, k -> k); } public Config add(Map data) { - return add(null, data, null); + return add(null, data, k -> k); } - public Config add(String path, EnvFile envFile, Map mapping) { + public Config add(String path, EnvFile envFile, Function mapping) { return add(path, envFile.getValues(), mapping); } public Config add(String path, EnvFile envFile) { - return add(path, envFile, null); + return add(path, envFile, k -> k); } - public Config add(EnvFile envFile, Map mapping) { + public Config add(EnvFile envFile, Function mapping) { return add(null, envFile, mapping); - } public Config add(EnvFile envFile) { - return add(null, envFile, null); + return add(null, envFile, k -> k); } public Config set(String key, String value) { @@ -64,6 +69,21 @@ public String get(String key) { return get(key, null); } + public AbstractObject getObject(String key) { + String prefix = key.length() > 0 ? (key + ".") : ""; + Set s = config.keySet().stream().filter(k -> k.startsWith(prefix)).collect(Collectors.toSet()); + if(s.size() == 0) + return null; + return AbstractElement.fromTree(s.stream().collect(Collectors.toMap(k -> k.substring(prefix.length()).split("\\."), config::get))).object(); + } + + public Config set(String key, AbstractObject object) { + String prefix = key.length() > 0 ? (key + ".") : ""; + config.keySet().stream().filter(k -> k.startsWith(prefix)).forEach(config::remove); + object.toTree().forEach((k, v) -> config.put(prefix + String.join(".", k), v.toString())); + return this; + } + public int getInt(String key, int defaultValue) { String value = get(key); if (value == null) @@ -88,4 +108,12 @@ public boolean has(String key) { return config.containsKey(key); } + public Set keys() { + return config.keySet(); + } + + public static String basicEnvMapping(String k) { + return k.toLowerCase(Locale.ROOT).replace("_", "."); + } + } diff --git a/src/main/java/org/javawebstack/webutils/config/EnvAssocMapping.java b/src/main/java/org/javawebstack/webutils/config/EnvAssocMapping.java new file mode 100644 index 0000000..ce2bd6f --- /dev/null +++ b/src/main/java/org/javawebstack/webutils/config/EnvAssocMapping.java @@ -0,0 +1,28 @@ +package org.javawebstack.webutils.config; + +import java.util.Locale; +import java.util.function.Function; + +public class EnvAssocMapping implements Function { + + private final String prefix; + private final Function subMapping; + + public EnvAssocMapping(String prefix, Function subMapping) { + this.prefix = prefix; + this.subMapping = subMapping; + } + + public String apply(String s) { + if(!s.startsWith(prefix+ "_")) + return null; + String[] spl = s.substring(prefix.length() + 1).split("_", 2); + if(spl.length != 2) + return null; + String sk = subMapping.apply(spl[1]); + if(sk == null) + return null; + return prefix.toLowerCase(Locale.ROOT) + "." + spl[0].toLowerCase(Locale.ROOT) + "." + sk; + } + +} diff --git a/src/main/java/org/javawebstack/webutils/config/Mapping.java b/src/main/java/org/javawebstack/webutils/config/Mapping.java new file mode 100644 index 0000000..da8a1f0 --- /dev/null +++ b/src/main/java/org/javawebstack/webutils/config/Mapping.java @@ -0,0 +1,26 @@ +package org.javawebstack.webutils.config; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + +public class Mapping implements Function { + + private final Map mapping = new HashMap<>(); + private boolean failIfNotFound = false; + + public Mapping failIfNotFound(boolean failIfNotFound) { + this.failIfNotFound = failIfNotFound; + return this; + } + + public Mapping map(String from, String to) { + mapping.put(from, to); + return this; + } + + public String apply(String s) { + return mapping.getOrDefault(s, failIfNotFound ? null : s); + } + +} diff --git a/src/main/java/org/javawebstack/webutils/config/MappingPipeline.java b/src/main/java/org/javawebstack/webutils/config/MappingPipeline.java new file mode 100644 index 0000000..45a38e7 --- /dev/null +++ b/src/main/java/org/javawebstack/webutils/config/MappingPipeline.java @@ -0,0 +1,19 @@ +package org.javawebstack.webutils.config; + +import java.util.function.Function; + +public class MappingPipeline implements Function { + + private final Function[] pipeline; + + public MappingPipeline(Function... pipeline) { + this.pipeline = pipeline; + } + + public String apply(String s) { + String k = s; + for(Function mapping : pipeline) + k = mapping.apply(k); + return k == null ? s : k; + } +} diff --git a/src/main/java/org/javawebstack/webutils/config/MappingTryout.java b/src/main/java/org/javawebstack/webutils/config/MappingTryout.java new file mode 100644 index 0000000..f86f2b8 --- /dev/null +++ b/src/main/java/org/javawebstack/webutils/config/MappingTryout.java @@ -0,0 +1,28 @@ +package org.javawebstack.webutils.config; + +import java.util.function.Function; + +public class MappingTryout implements Function { + + private final Function[] tryout; + private boolean failIfEqual = true; + + public MappingTryout(Function... tryout) { + this.tryout = tryout; + } + + public MappingTryout failIfEqual(boolean failIfEqual) { + this.failIfEqual = failIfEqual; + return this; + } + + public String apply(String s) { + for(Function mapping : tryout) { + String k = mapping.apply(s); + if(k != null && (!failIfEqual || !k.equals(s))) + return k; + } + return null; + } + +} diff --git a/src/main/java/org/javawebstack/webutils/crypt/Crypt.java b/src/main/java/org/javawebstack/webutils/crypt/Crypt.java index 2a99d48..6e5f681 100644 --- a/src/main/java/org/javawebstack/webutils/crypt/Crypt.java +++ b/src/main/java/org/javawebstack/webutils/crypt/Crypt.java @@ -1,8 +1,7 @@ package org.javawebstack.webutils.crypt; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonObject; +import org.javawebstack.abstractdata.AbstractElement; +import org.javawebstack.abstractdata.AbstractObject; import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; @@ -84,11 +83,11 @@ public String encrypt(byte[] data) { cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec); byte[] value = cipher.doFinal(data); byte[] mac = mac(Base64.getEncoder().encode(iv), Base64.getEncoder().encode(value)); - Map cryptData = new HashMap<>(); - cryptData.put("iv", new String(Base64.getEncoder().encode(iv))); - cryptData.put("value", new String(Base64.getEncoder().encode(value))); - cryptData.put("mac", toHex(mac)); - return new String(Base64.getEncoder().encode(new GsonBuilder().disableHtmlEscaping().create().toJson(cryptData).getBytes(StandardCharsets.UTF_8))); + AbstractObject cryptData = new AbstractObject(); + cryptData.set("iv", new String(Base64.getEncoder().encode(iv))); + cryptData.set("value", new String(Base64.getEncoder().encode(value))); + cryptData.set("mac", toHex(mac)); + return new String(Base64.getEncoder().encode(cryptData.toJsonString().getBytes(StandardCharsets.UTF_8))); } catch (IllegalBlockSizeException | BadPaddingException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException ex) { throw new SecurityException(ex.getMessage()); } @@ -120,11 +119,11 @@ public String decryptString(String data) { public byte[] decrypt(String data) { try { - JsonObject json = new Gson().fromJson(new String(Base64.getDecoder().decode(data.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8), JsonObject.class); - if (!toHex(mac(json.get("iv").getAsString().getBytes(StandardCharsets.UTF_8), json.get("value").getAsString().getBytes(StandardCharsets.UTF_8))).equals(json.get("mac").getAsString())) + AbstractObject json = AbstractElement.fromJson(new String(Base64.getDecoder().decode(data.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)).object(); + if (!toHex(mac(json.string("iv").getBytes(StandardCharsets.UTF_8), json.string("value").getBytes(StandardCharsets.UTF_8))).equals(json.string("mac"))) throw new SecurityException("Invalid MAC"); - byte[] iv = Base64.getDecoder().decode(json.get("iv").getAsString().getBytes(StandardCharsets.UTF_8)); - byte[] value = Base64.getDecoder().decode(json.get("value").getAsString().getBytes(StandardCharsets.UTF_8)); + byte[] iv = Base64.getDecoder().decode(json.string("iv").getBytes(StandardCharsets.UTF_8)); + byte[] value = Base64.getDecoder().decode(json.string("value").getBytes(StandardCharsets.UTF_8)); SecretKeySpec secretKey = new SecretKeySpec(key, "AES"); IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); diff --git a/src/main/java/org/javawebstack/webutils/middleware/CORSPolicy.java b/src/main/java/org/javawebstack/webutils/middleware/CORSPolicy.java index ea71729..760fab9 100644 --- a/src/main/java/org/javawebstack/webutils/middleware/CORSPolicy.java +++ b/src/main/java/org/javawebstack/webutils/middleware/CORSPolicy.java @@ -1,8 +1,8 @@ package org.javawebstack.webutils.middleware; import org.javawebstack.httpserver.Exchange; +import org.javawebstack.httpserver.HTTPMethod; import org.javawebstack.httpserver.handler.RequestInterceptor; -import org.javawebstack.httpserver.helper.HttpMethod; public class CORSPolicy implements RequestInterceptor { private final String allowedOrigin; @@ -13,7 +13,7 @@ public CORSPolicy(String allowedOrigin) { public boolean intercept(Exchange exchange) { exchange.header("Access-Control-Allow-Origin", allowedOrigin); - if (exchange.getMethod() == HttpMethod.OPTIONS) { + if (exchange.getMethod() == HTTPMethod.OPTIONS) { exchange.header("Access-Control-Allow-Headers", "*"); exchange.header("Access-Control-Allow-Methods", "*"); return true; diff --git a/src/main/java/org/javawebstack/webutils/middleware/MultipartPolicy.java b/src/main/java/org/javawebstack/webutils/middleware/MultipartPolicy.java index 6c44094..7a76f22 100644 --- a/src/main/java/org/javawebstack/webutils/middleware/MultipartPolicy.java +++ b/src/main/java/org/javawebstack/webutils/middleware/MultipartPolicy.java @@ -12,8 +12,10 @@ public MultipartPolicy(String location) { } public boolean intercept(Exchange exchange) { + /* if (location != null) exchange.enableMultipart(location); + */ return false; } diff --git a/src/main/java/org/javawebstack/webutils/middlewares/RateLimitMiddleware.java b/src/main/java/org/javawebstack/webutils/middlewares/RateLimitMiddleware.java index 053fec4..43afd36 100644 --- a/src/main/java/org/javawebstack/webutils/middlewares/RateLimitMiddleware.java +++ b/src/main/java/org/javawebstack/webutils/middlewares/RateLimitMiddleware.java @@ -24,7 +24,7 @@ public RateLimitMiddleware(long millis){ } public Object handle(Exchange exchange) { - String ip = exchange.rawRequest().getRemoteAddr(); + String ip = exchange.socket().getRemoteAddress(); if (exchange.header("X-Forwarded-For") != null) ip = exchange.header("X-Forwarded-For"); RateLimit rateLimit = null;