Stephan Richter
2 months ago
60 changed files with 187 additions and 963 deletions
@ -1,36 +0,0 @@ |
|||||||
plugins { |
|
||||||
id 'java' |
|
||||||
id "com.diffplug.spotless" version "6.25.0" |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
group = 'de.srsoftware' |
|
||||||
version = '1.0.1' |
|
||||||
|
|
||||||
jar.enabled = false |
|
||||||
build.enabled = false |
|
||||||
|
|
||||||
repositories { |
|
||||||
mavenCentral() |
|
||||||
} |
|
||||||
|
|
||||||
dependencies { |
|
||||||
testImplementation platform('org.junit:junit-bom:5.10.0') |
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter' |
|
||||||
} |
|
||||||
|
|
||||||
test { |
|
||||||
useJUnitPlatform() |
|
||||||
} |
|
||||||
|
|
||||||
spotless { |
|
||||||
java { |
|
||||||
target '*/src/*/java/**/*.java' |
|
||||||
removeUnusedImports() |
|
||||||
importOrder() |
|
||||||
clangFormat('18.1.8').style('file:config/clang-format') |
|
||||||
licenseHeader '/* © SRSoftware $YEAR */' // or licenseHeaderFile |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
compileJava.dependsOn 'spotlessApply' |
|
@ -0,0 +1,50 @@ |
|||||||
|
plugins { |
||||||
|
id("com.diffplug.spotless") version "latest.release" |
||||||
|
} |
||||||
|
|
||||||
|
repositories { |
||||||
|
mavenCentral() |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
spotless { |
||||||
|
java { |
||||||
|
target("**/src/**/java/**/*.java") |
||||||
|
removeUnusedImports() |
||||||
|
importOrder() |
||||||
|
clangFormat("18.1.8").style("file:config/clang-format") |
||||||
|
licenseHeader("/* © SRSoftware 2024 */") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
subprojects { |
||||||
|
group = "de.srsoftware" |
||||||
|
version = "1.0-SNAPSHOT" |
||||||
|
|
||||||
|
apply(plugin = "java") |
||||||
|
apply(plugin = "maven-publish") |
||||||
|
apply(plugin = "com.diffplug.spotless") |
||||||
|
|
||||||
|
repositories { |
||||||
|
mavenLocal() |
||||||
|
mavenCentral() |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
val implementation by configurations |
||||||
|
val compileOnly by configurations |
||||||
|
val testImplementation by configurations |
||||||
|
val testRuntimeOnly by configurations |
||||||
|
|
||||||
|
|
||||||
|
dependencies { |
||||||
|
testImplementation(platform("org.junit:junit-bom:5.10.0")) |
||||||
|
testImplementation("org.junit.jupiter:junit-jupiter") |
||||||
|
} |
||||||
|
|
||||||
|
tasks.withType<Test>() { |
||||||
|
useJUnitPlatform() |
||||||
|
} |
||||||
|
} |
@ -1,21 +0,0 @@ |
|||||||
plugins { |
|
||||||
id 'java' |
|
||||||
} |
|
||||||
|
|
||||||
group = 'de.srsoftware' |
|
||||||
version = '1.0-SNAPSHOT' |
|
||||||
|
|
||||||
repositories { |
|
||||||
mavenCentral() |
|
||||||
} |
|
||||||
|
|
||||||
dependencies { |
|
||||||
testImplementation platform('org.junit:junit-bom:5.10.0') |
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter' |
|
||||||
implementation 'org.json:json:20240303' |
|
||||||
implementation project(':de.srsoftware.utils') |
|
||||||
} |
|
||||||
|
|
||||||
test { |
|
||||||
useJUnitPlatform() |
|
||||||
} |
|
@ -1,53 +0,0 @@ |
|||||||
/* © SRSoftware 2024 */ |
|
||||||
package de.srsoftware.http; |
|
||||||
|
|
||||||
import static de.srsoftware.utils.Optionals.nullable; |
|
||||||
import static java.lang.System.Logger.Level.*; |
|
||||||
|
|
||||||
import com.sun.net.httpserver.Headers; |
|
||||||
import com.sun.net.httpserver.HttpExchange; |
|
||||||
import java.util.Arrays; |
|
||||||
import java.util.List; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
public abstract class Cookie implements Map.Entry<String, String> { |
|
||||||
static final System.Logger LOG = System.getLogger(SessionToken.class.getSimpleName()); |
|
||||||
private final String key; |
|
||||||
private String value = null; |
|
||||||
|
|
||||||
Cookie(String key, String value) { |
|
||||||
this.key = key; |
|
||||||
setValue(value); |
|
||||||
} |
|
||||||
|
|
||||||
public <T extends Cookie> T addTo(Headers headers) { |
|
||||||
LOG.log(INFO, "sending cookie {0}={1}", key, value); |
|
||||||
headers.add("Set-Cookie", "%s=%s".formatted(key, value)); |
|
||||||
return (T)this; |
|
||||||
} |
|
||||||
|
|
||||||
public <T extends Cookie> T addTo(HttpExchange ex) { |
|
||||||
return this.addTo(ex.getResponseHeaders()); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String getKey() { |
|
||||||
return key; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String getValue() { |
|
||||||
return value; |
|
||||||
} |
|
||||||
|
|
||||||
protected static List<String> of(HttpExchange ex) { |
|
||||||
return nullable(ex.getRequestHeaders().get("Cookie")).stream().flatMap(List::stream).flatMap(s -> Arrays.stream(s.split(";"))).map(String::trim).peek(cookie -> LOG.log(INFO, "received cookie {0}", cookie)).toList(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String setValue(String s) { |
|
||||||
var oldVal = value; |
|
||||||
value = s; |
|
||||||
return oldVal; |
|
||||||
} |
|
||||||
} |
|
@ -1,202 +0,0 @@ |
|||||||
/* © SRSoftware 2024 */ |
|
||||||
package de.srsoftware.http; |
|
||||||
|
|
||||||
|
|
||||||
import static de.srsoftware.utils.Optionals.nullable; |
|
||||||
import static java.lang.System.Logger.Level.*; |
|
||||||
import static java.net.HttpURLConnection.*; |
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8; |
|
||||||
|
|
||||||
import com.sun.net.httpserver.HttpExchange; |
|
||||||
import com.sun.net.httpserver.HttpHandler; |
|
||||||
import com.sun.net.httpserver.HttpServer; |
|
||||||
import com.sun.net.httpserver.HttpsExchange; |
|
||||||
import de.srsoftware.utils.Error; |
|
||||||
import java.io.IOException; |
|
||||||
import java.util.*; |
|
||||||
import java.util.stream.Collectors; |
|
||||||
import java.util.stream.Stream; |
|
||||||
import org.json.JSONArray; |
|
||||||
import org.json.JSONObject; |
|
||||||
|
|
||||||
public abstract class PathHandler implements HttpHandler { |
|
||||||
public static final String AUTHORIZATION = "Authorization"; |
|
||||||
public static final String CONTENT_TYPE = "Content-Type"; |
|
||||||
public static final String DEFAULT_LANGUAGE = "en"; |
|
||||||
public static final String DELETE = "DELETE"; |
|
||||||
private static final String FORWARDED_HOST = "x-forwarded-host"; |
|
||||||
public static final String GET = "GET"; |
|
||||||
public static final String HOST = "host"; |
|
||||||
public static final String JSON = "application/json"; |
|
||||||
public static System.Logger LOG = System.getLogger(PathHandler.class.getSimpleName()); |
|
||||||
public static final String POST = "POST"; |
|
||||||
|
|
||||||
private String[] paths; |
|
||||||
|
|
||||||
public record BasicAuth(String userId, String pass) { |
|
||||||
} |
|
||||||
|
|
||||||
public class Bond { |
|
||||||
Bond(String[] paths) { |
|
||||||
PathHandler.this.paths = paths; |
|
||||||
} |
|
||||||
public PathHandler on(HttpServer server) { |
|
||||||
for (var path : paths) server.createContext(path, PathHandler.this); |
|
||||||
return PathHandler.this; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static boolean badRequest(HttpExchange ex, byte[] bytes) throws IOException { |
|
||||||
return sendContent(ex, HTTP_BAD_REQUEST, bytes); |
|
||||||
} |
|
||||||
|
|
||||||
public static boolean badRequest(HttpExchange ex, Object o) throws IOException { |
|
||||||
return sendContent(ex, HTTP_BAD_REQUEST, o); |
|
||||||
} |
|
||||||
|
|
||||||
public Bond bindPath(String... path) { |
|
||||||
return new Bond(path); |
|
||||||
} |
|
||||||
|
|
||||||
public boolean doDelete(String path, HttpExchange ex) throws IOException { |
|
||||||
return notFound(ex); |
|
||||||
} |
|
||||||
|
|
||||||
public boolean doGet(String path, HttpExchange ex) throws IOException { |
|
||||||
return notFound(ex); |
|
||||||
} |
|
||||||
|
|
||||||
public boolean doPost(String path, HttpExchange ex) throws IOException { |
|
||||||
return notFound(ex); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void handle(HttpExchange ex) throws IOException { |
|
||||||
String path = relativePath(ex); |
|
||||||
String method = ex.getRequestMethod(); |
|
||||||
LOG.log(INFO, "{0} {1}", method, path); |
|
||||||
boolean ignored = switch (method) { |
|
||||||
case DELETE -> doDelete(path,ex); |
|
||||||
case GET -> doGet(path,ex); |
|
||||||
case POST -> doPost(path,ex); |
|
||||||
default -> false; |
|
||||||
}; |
|
||||||
ex.getResponseBody().close(); |
|
||||||
} |
|
||||||
|
|
||||||
public String relativePath(HttpExchange ex) { |
|
||||||
var requestPath = ex.getRequestURI().toString(); |
|
||||||
for (var path : paths){ |
|
||||||
if (requestPath.startsWith(path)) { |
|
||||||
requestPath = requestPath.substring(path.length()); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
if (!requestPath.startsWith("/")) requestPath = "/" + requestPath; |
|
||||||
var pos = requestPath.indexOf("?"); |
|
||||||
if (pos >= 0) requestPath = requestPath.substring(0, pos); |
|
||||||
return requestPath; |
|
||||||
} |
|
||||||
|
|
||||||
/******* begin of static methods *************/ |
|
||||||
|
|
||||||
public static String body(HttpExchange ex) throws IOException { |
|
||||||
return new String(ex.getRequestBody().readAllBytes(), UTF_8); |
|
||||||
} |
|
||||||
|
|
||||||
public static Optional<String> getAuthToken(HttpExchange ex) { |
|
||||||
return getHeader(ex, AUTHORIZATION); |
|
||||||
} |
|
||||||
|
|
||||||
public static Optional<BasicAuth> getBasicAuth(HttpExchange ex) { |
|
||||||
return getAuthToken(ex) |
|
||||||
.filter(token -> token.startsWith("Basic ")) //
|
|
||||||
.map(token -> token.substring(6)) |
|
||||||
.map(Base64.getDecoder()::decode) |
|
||||||
.map(bytes -> new String(bytes, UTF_8)) |
|
||||||
.map(token -> token.split(":", 2)) |
|
||||||
.map(arr -> new BasicAuth(arr[0], arr[1])); |
|
||||||
} |
|
||||||
|
|
||||||
public static Optional<String> getBearer(HttpExchange ex) { |
|
||||||
return getAuthToken(ex).filter(token -> token.startsWith("Bearer ")).map(token -> token.substring(7)); |
|
||||||
} |
|
||||||
|
|
||||||
public static Optional<String> getHeader(HttpExchange ex, String key) { |
|
||||||
return nullable(ex.getRequestHeaders().get(key)).map(List::stream).flatMap(Stream::findFirst); |
|
||||||
} |
|
||||||
|
|
||||||
public static String hostname(HttpExchange ex) { |
|
||||||
var headers = ex.getRequestHeaders(); |
|
||||||
var host = headers.getFirst(FORWARDED_HOST); |
|
||||||
if (host == null) host = headers.getFirst(HOST); |
|
||||||
var proto = nullable(headers.getFirst("X-forwarded-proto")).orElseGet(() -> ex instanceof HttpsExchange ? "https" : "http"); |
|
||||||
return host == null ? null : proto + "://" + host; |
|
||||||
} |
|
||||||
|
|
||||||
public static JSONObject json(HttpExchange ex) throws IOException { |
|
||||||
return new JSONObject(body(ex)); |
|
||||||
} |
|
||||||
|
|
||||||
public static String language(HttpExchange ex) { |
|
||||||
return getHeader(ex, "Accept-Language") //
|
|
||||||
.map(s -> Arrays.stream(s.split(","))) |
|
||||||
.flatMap(Stream::findFirst) |
|
||||||
.orElse(DEFAULT_LANGUAGE); |
|
||||||
} |
|
||||||
|
|
||||||
public static boolean notFound(HttpExchange ex) throws IOException { |
|
||||||
LOG.log(ERROR, "not implemented"); |
|
||||||
return sendEmptyResponse(HTTP_NOT_FOUND, ex); |
|
||||||
} |
|
||||||
|
|
||||||
public Map<String, String> queryParam(HttpExchange ex) { |
|
||||||
return Arrays |
|
||||||
.stream(ex.getRequestURI().getQuery().split("&")) //
|
|
||||||
.map(s -> s.split("=", 2)) |
|
||||||
.collect(Collectors.toMap(arr -> arr[0], arr -> arr[1])); |
|
||||||
} |
|
||||||
|
|
||||||
public static boolean sendEmptyResponse(int statusCode, HttpExchange ex) throws IOException { |
|
||||||
ex.sendResponseHeaders(statusCode, 0); |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
public static boolean sendRedirect(HttpExchange ex, String url) throws IOException { |
|
||||||
ex.getResponseHeaders().add("Location", url); |
|
||||||
return sendEmptyResponse(HTTP_MOVED_TEMP, ex); |
|
||||||
} |
|
||||||
|
|
||||||
public static boolean sendContent(HttpExchange ex, int status, byte[] bytes) throws IOException { |
|
||||||
LOG.log(DEBUG, "sending {0} response…", status); |
|
||||||
ex.sendResponseHeaders(status, bytes.length); |
|
||||||
ex.getResponseBody().write(bytes); |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
public static boolean sendContent(HttpExchange ex, int status, Object o) throws IOException { |
|
||||||
if (o instanceof List<?> list) o = new JSONArray(list); |
|
||||||
if (o instanceof Map<?, ?> map) o = new JSONObject(map); |
|
||||||
if (o instanceof Error<?> error) o = error.json(); |
|
||||||
if (o instanceof JSONObject) ex.getResponseHeaders().add(CONTENT_TYPE, JSON); |
|
||||||
return sendContent(ex, status, o.toString().getBytes(UTF_8)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public static boolean sendContent(HttpExchange ex, byte[] bytes) throws IOException { |
|
||||||
return sendContent(ex, HTTP_OK, bytes); |
|
||||||
} |
|
||||||
|
|
||||||
public static boolean sendContent(HttpExchange ex, Object o) throws IOException { |
|
||||||
return sendContent(ex, HTTP_OK, o); |
|
||||||
} |
|
||||||
|
|
||||||
public static boolean serverError(HttpExchange ex, Object o) throws IOException { |
|
||||||
sendContent(ex, HTTP_INTERNAL_ERROR, o); |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
public static String url(HttpExchange ex) { |
|
||||||
return hostname(ex) + ex.getRequestURI(); |
|
||||||
} |
|
||||||
} |
|
@ -1,51 +0,0 @@ |
|||||||
/* © SRSoftware 2024 */ |
|
||||||
package de.srsoftware.http; |
|
||||||
|
|
||||||
|
|
||||||
import com.sun.net.httpserver.Headers; |
|
||||||
import com.sun.net.httpserver.HttpExchange; |
|
||||||
import java.time.Instant; |
|
||||||
import java.time.ZoneOffset; |
|
||||||
import java.time.format.DateTimeFormatter; |
|
||||||
import java.util.Optional; |
|
||||||
|
|
||||||
|
|
||||||
public class SessionToken extends Cookie { |
|
||||||
private final String sessionId; |
|
||||||
private static final DateTimeFormatter FORMAT = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss O"); |
|
||||||
|
|
||||||
public SessionToken(String sessionId, Instant expiration, boolean trust) { |
|
||||||
super("sessionToken", sessionToken(sessionId, expiration, trust)); |
|
||||||
this.sessionId = sessionId; |
|
||||||
} |
|
||||||
|
|
||||||
private static String sessionToken(String sessionId, Instant expiration, boolean trust) { |
|
||||||
if (trust) return "%s; Path=/api; Expires=%s".formatted(sessionId, FORMAT.format(expiration.atZone(ZoneOffset.UTC))); |
|
||||||
return "%s; Path=/api".formatted(sessionId); |
|
||||||
} |
|
||||||
|
|
||||||
public SessionToken(String sessionId) { |
|
||||||
super("sessionToken", sessionId + "; Path=/api"); |
|
||||||
this.sessionId = sessionId; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public <T extends Cookie> T addTo(Headers headers) { |
|
||||||
headers.add("session", getValue()); |
|
||||||
return super.addTo(headers); |
|
||||||
} |
|
||||||
|
|
||||||
public static Optional<SessionToken> from(HttpExchange ex) { |
|
||||||
return Cookie.of(ex) |
|
||||||
.stream() |
|
||||||
.filter(cookie -> cookie.startsWith("sessionToken=")) |
|
||||||
|
|
||||||
.map(cookie -> cookie.split("=", 2)[1]) |
|
||||||
.map(id -> new SessionToken(id)) |
|
||||||
.findAny(); |
|
||||||
} |
|
||||||
|
|
||||||
public String sessionId() { |
|
||||||
return sessionId; |
|
||||||
} |
|
||||||
} |
|
@ -1,19 +0,0 @@ |
|||||||
plugins { |
|
||||||
id 'java' |
|
||||||
} |
|
||||||
|
|
||||||
group = 'de.srsoftware' |
|
||||||
version = '1.0-SNAPSHOT' |
|
||||||
|
|
||||||
repositories { |
|
||||||
mavenCentral() |
|
||||||
} |
|
||||||
|
|
||||||
dependencies { |
|
||||||
testImplementation platform('org.junit:junit-bom:5.10.0') |
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter' |
|
||||||
} |
|
||||||
|
|
||||||
test { |
|
||||||
useJUnitPlatform() |
|
||||||
} |
|
@ -1,65 +0,0 @@ |
|||||||
/* © SRSoftware 2024 */ |
|
||||||
package de.srsoftware.logging; |
|
||||||
|
|
||||||
import static de.srsoftware.logging.ConsoleColors.*; |
|
||||||
import static java.lang.System.Logger.Level.*; |
|
||||||
|
|
||||||
import java.text.DateFormat; |
|
||||||
import java.text.MessageFormat; |
|
||||||
import java.text.SimpleDateFormat; |
|
||||||
import java.util.Date; |
|
||||||
import java.util.ResourceBundle; |
|
||||||
|
|
||||||
public class ColorLogger implements System.Logger { |
|
||||||
private final String name; |
|
||||||
private static int rootLevel = INFO.getSeverity(); |
|
||||||
private static DateFormat TIME = new SimpleDateFormat("hh:mm:ss.SSS"); |
|
||||||
private static DateFormat DATE = new SimpleDateFormat("yyyy-MM-dd"); |
|
||||||
private static String lastDate = null; |
|
||||||
|
|
||||||
public ColorLogger(String name) { |
|
||||||
this.name = name; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String getName() { |
|
||||||
return name; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isLoggable(Level level) { |
|
||||||
return level.getSeverity() >= rootLevel; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void log(Level level, ResourceBundle bundle, String msg, Throwable thrown) { |
|
||||||
if (isLoggable(level)) { |
|
||||||
System.out.println(colorize(msg, level.getSeverity())); |
|
||||||
thrown.printStackTrace(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void log(Level level, ResourceBundle bundle, String format, Object... params) { |
|
||||||
if (isLoggable(level)) { |
|
||||||
System.out.println(colorize(MessageFormat.format(format, params), level.getSeverity())); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public ColorLogger setLogLevel(Level level) { |
|
||||||
rootLevel = level.getSeverity(); |
|
||||||
return this; |
|
||||||
} |
|
||||||
|
|
||||||
private static String colorize(String message, int severity) { |
|
||||||
var color = severity >= ERROR.getSeverity() ? RED : severity >= WARNING.getSeverity() ? YELLOW : severity >= INFO.getSeverity() ? WHITE_BRIGHT : WHITE; |
|
||||||
var date = new Date(); |
|
||||||
var day = DATE.format(date); |
|
||||||
StringBuilder sb = new StringBuilder(); |
|
||||||
if (!day.equals(lastDate)) { |
|
||||||
lastDate = day; |
|
||||||
sb.append(WHITE).append(day).append("\n"); |
|
||||||
} |
|
||||||
return sb.append(WHITE).append(TIME.format(date)).append(" ").append(color).append(message).append(RESET).toString(); |
|
||||||
} |
|
||||||
} |
|
@ -1,14 +0,0 @@ |
|||||||
/* © SRSoftware 2024 */ |
|
||||||
package de.srsoftware.logging; |
|
||||||
|
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
public class ColorLoggerFinder extends System.LoggerFinder { |
|
||||||
private static final Map<String, ColorLogger> LOGGERS = new HashMap<>(); |
|
||||||
|
|
||||||
@Override |
|
||||||
public System.Logger getLogger(String name, Module module) { |
|
||||||
return LOGGERS.computeIfAbsent(name, ColorLogger::new); |
|
||||||
} |
|
||||||
} |
|
@ -1,77 +0,0 @@ |
|||||||
/* © SRSoftware 2024 */ |
|
||||||
package de.srsoftware.logging; |
|
||||||
|
|
||||||
public class ConsoleColors { |
|
||||||
// Reset
|
|
||||||
public static final String RESET = "\033[0m"; // Text Reset
|
|
||||||
|
|
||||||
// Regular Colors
|
|
||||||
public static final String BLACK = "\033[0;30m"; // BLACK
|
|
||||||
public static final String RED = "\033[0;31m"; // RED
|
|
||||||
public static final String GREEN = "\033[0;32m"; // GREEN
|
|
||||||
public static final String YELLOW = "\033[0;33m"; // YELLOW
|
|
||||||
public static final String BLUE = "\033[0;34m"; // BLUE
|
|
||||||
public static final String PURPLE = "\033[0;35m"; // PURPLE
|
|
||||||
public static final String CYAN = "\033[0;36m"; // CYAN
|
|
||||||
public static final String WHITE = "\033[0;37m"; // WHITE
|
|
||||||
|
|
||||||
// Bold
|
|
||||||
public static final String BLACK_BOLD = "\033[1;30m"; // BLACK
|
|
||||||
public static final String RED_BOLD = "\033[1;31m"; // RED
|
|
||||||
public static final String GREEN_BOLD = "\033[1;32m"; // GREEN
|
|
||||||
public static final String YELLOW_BOLD = "\033[1;33m"; // YELLOW
|
|
||||||
public static final String BLUE_BOLD = "\033[1;34m"; // BLUE
|
|
||||||
public static final String PURPLE_BOLD = "\033[1;35m"; // PURPLE
|
|
||||||
public static final String CYAN_BOLD = "\033[1;36m"; // CYAN
|
|
||||||
public static final String WHITE_BOLD = "\033[1;37m"; // WHITE
|
|
||||||
|
|
||||||
// Underline
|
|
||||||
public static final String BLACK_UNDERLINED = "\033[4;30m"; // BLACK
|
|
||||||
public static final String RED_UNDERLINED = "\033[4;31m"; // RED
|
|
||||||
public static final String GREEN_UNDERLINED = "\033[4;32m"; // GREEN
|
|
||||||
public static final String YELLOW_UNDERLINED = "\033[4;33m"; // YELLOW
|
|
||||||
public static final String BLUE_UNDERLINED = "\033[4;34m"; // BLUE
|
|
||||||
public static final String PURPLE_UNDERLINED = "\033[4;35m"; // PURPLE
|
|
||||||
public static final String CYAN_UNDERLINED = "\033[4;36m"; // CYAN
|
|
||||||
public static final String WHITE_UNDERLINED = "\033[4;37m"; // WHITE
|
|
||||||
|
|
||||||
// Background
|
|
||||||
public static final String BLACK_BACKGROUND = "\033[40m"; // BLACK
|
|
||||||
public static final String RED_BACKGROUND = "\033[41m"; // RED
|
|
||||||
public static final String GREEN_BACKGROUND = "\033[42m"; // GREEN
|
|
||||||
public static final String YELLOW_BACKGROUND = "\033[43m"; // YELLOW
|
|
||||||
public static final String BLUE_BACKGROUND = "\033[44m"; // BLUE
|
|
||||||
public static final String PURPLE_BACKGROUND = "\033[45m"; // PURPLE
|
|
||||||
public static final String CYAN_BACKGROUND = "\033[46m"; // CYAN
|
|
||||||
public static final String WHITE_BACKGROUND = "\033[47m"; // WHITE
|
|
||||||
|
|
||||||
// High Intensity
|
|
||||||
public static final String BLACK_BRIGHT = "\033[0;90m"; // BLACK
|
|
||||||
public static final String RED_BRIGHT = "\033[0;91m"; // RED
|
|
||||||
public static final String GREEN_BRIGHT = "\033[0;92m"; // GREEN
|
|
||||||
public static final String YELLOW_BRIGHT = "\033[0;93m"; // YELLOW
|
|
||||||
public static final String BLUE_BRIGHT = "\033[0;94m"; // BLUE
|
|
||||||
public static final String PURPLE_BRIGHT = "\033[0;95m"; // PURPLE
|
|
||||||
public static final String CYAN_BRIGHT = "\033[0;96m"; // CYAN
|
|
||||||
public static final String WHITE_BRIGHT = "\033[0;97m"; // WHITE
|
|
||||||
|
|
||||||
// Bold High Intensity
|
|
||||||
public static final String BLACK_BOLD_BRIGHT = "\033[1;90m"; // BLACK
|
|
||||||
public static final String RED_BOLD_BRIGHT = "\033[1;91m"; // RED
|
|
||||||
public static final String GREEN_BOLD_BRIGHT = "\033[1;92m"; // GREEN
|
|
||||||
public static final String YELLOW_BOLD_BRIGHT = "\033[1;93m"; // YELLOW
|
|
||||||
public static final String BLUE_BOLD_BRIGHT = "\033[1;94m"; // BLUE
|
|
||||||
public static final String PURPLE_BOLD_BRIGHT = "\033[1;95m"; // PURPLE
|
|
||||||
public static final String CYAN_BOLD_BRIGHT = "\033[1;96m"; // CYAN
|
|
||||||
public static final String WHITE_BOLD_BRIGHT = "\033[1;97m"; // WHITE
|
|
||||||
|
|
||||||
// High Intensity backgrounds
|
|
||||||
public static final String BLACK_BACKGROUND_BRIGHT = "\033[0;100m"; // BLACK
|
|
||||||
public static final String RED_BACKGROUND_BRIGHT = "\033[0;101m"; // RED
|
|
||||||
public static final String GREEN_BACKGROUND_BRIGHT = "\033[0;102m"; // GREEN
|
|
||||||
public static final String YELLOW_BACKGROUND_BRIGHT = "\033[0;103m"; // YELLOW
|
|
||||||
public static final String BLUE_BACKGROUND_BRIGHT = "\033[0;104m"; // BLUE
|
|
||||||
public static final String PURPLE_BACKGROUND_BRIGHT = "\033[0;105m"; // PURPLE
|
|
||||||
public static final String CYAN_BACKGROUND_BRIGHT = "\033[0;106m"; // CYAN
|
|
||||||
public static final String WHITE_BACKGROUND_BRIGHT = "\033[0;107m"; // WHITE
|
|
||||||
} |
|
@ -1 +0,0 @@ |
|||||||
de.srsoftware.logging.ColorLoggerFinder |
|
@ -1,47 +0,0 @@ |
|||||||
plugins { |
|
||||||
id 'java' |
|
||||||
} |
|
||||||
|
|
||||||
group = 'de.srsoftware' |
|
||||||
version = '1.0-SNAPSHOT' |
|
||||||
|
|
||||||
repositories { |
|
||||||
mavenCentral() |
|
||||||
} |
|
||||||
|
|
||||||
dependencies { |
|
||||||
testImplementation platform('org.junit:junit-bom:5.10.0') |
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter' |
|
||||||
implementation project(':de.srsoftware.http') |
|
||||||
implementation project(':de.srsoftware.logging') |
|
||||||
implementation project(':de.srsoftware.oidc.api') |
|
||||||
implementation project(':de.srsoftware.oidc.backend') |
|
||||||
implementation project(':de.srsoftware.oidc.datastore.encrypted') |
|
||||||
implementation project(':de.srsoftware.oidc.datastore.file') |
|
||||||
implementation project(':de.srsoftware.oidc.web') |
|
||||||
implementation project(':de.srsoftware.utils') |
|
||||||
implementation 'org.json:json:20240303' |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
test { |
|
||||||
useJUnitPlatform() |
|
||||||
} |
|
||||||
|
|
||||||
task run(type: JavaExec) { |
|
||||||
group = "application" |
|
||||||
description = "Run the main class with JavaExecTask" |
|
||||||
classpath = sourceSets.main.runtimeClasspath |
|
||||||
mainClass = 'de.srsoftware.oidc.app.Application' |
|
||||||
args = ['--base','/home/srichter/workspace/LightOIDC/de.srsoftware.oidc.web/src/main/resources'] |
|
||||||
} |
|
||||||
|
|
||||||
jar { |
|
||||||
manifest { |
|
||||||
attributes "Main-Class": "de.srsoftware.oidc.app.Application" |
|
||||||
} |
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE |
|
||||||
from { |
|
||||||
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,14 @@ |
|||||||
|
description = "SRSoftware OIDC: app" |
||||||
|
|
||||||
|
dependencies{ |
||||||
|
implementation("org.json:json:20240303") |
||||||
|
implementation("de.srsoftware:tools.http:1.0.0") |
||||||
|
implementation("de.srsoftware:tools.logging:1.0.0") |
||||||
|
implementation("de.srsoftware:tools.optionals:1.0.0") |
||||||
|
implementation("de.srsoftware:tools.util:1.0.2") |
||||||
|
implementation(project(":de.srsoftware.oidc.api")) |
||||||
|
implementation(project(":de.srsoftware.oidc.backend")) |
||||||
|
implementation(project(":de.srsoftware.oidc.datastore.encrypted")) |
||||||
|
implementation(project(":de.srsoftware.oidc.datastore.file")) |
||||||
|
implementation(project(":de.srsoftware.oidc.web")) |
||||||
|
} |
@ -1,27 +0,0 @@ |
|||||||
plugins { |
|
||||||
id 'java' |
|
||||||
} |
|
||||||
|
|
||||||
group = 'de.srsoftware' |
|
||||||
version = '1.0-SNAPSHOT' |
|
||||||
|
|
||||||
repositories { |
|
||||||
mavenCentral() |
|
||||||
} |
|
||||||
|
|
||||||
dependencies { |
|
||||||
testImplementation platform('org.junit:junit-bom:5.10.0') |
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter' |
|
||||||
implementation project(':de.srsoftware.http') |
|
||||||
implementation project(':de.srsoftware.logging') |
|
||||||
implementation project(':de.srsoftware.oidc.api') |
|
||||||
implementation project(':de.srsoftware.utils') |
|
||||||
implementation 'org.json:json:20240303' |
|
||||||
implementation 'org.bitbucket.b_c:jose4j:0.9.6' |
|
||||||
implementation 'com.sun.mail:jakarta.mail:2.0.1' |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
test { |
|
||||||
useJUnitPlatform() |
|
||||||
} |
|
@ -0,0 +1,13 @@ |
|||||||
|
description = "SRSoftware OIDC: backend" |
||||||
|
|
||||||
|
dependencies{ |
||||||
|
implementation("com.sun.mail:jakarta.mail:2.0.1") |
||||||
|
implementation("de.srsoftware:tools.http:1.0.0") |
||||||
|
implementation("de.srsoftware:tools.optionals:1.0.0") |
||||||
|
implementation("de.srsoftware:tools.util:1.0.2") |
||||||
|
implementation("org.bitbucket.b_c:jose4j:0.9.6") |
||||||
|
implementation("org.json:json:20240303") |
||||||
|
|
||||||
|
implementation(project(":de.srsoftware.oidc.api")) |
||||||
|
} |
||||||
|
|
@ -1,24 +0,0 @@ |
|||||||
plugins { |
|
||||||
id 'java' |
|
||||||
} |
|
||||||
|
|
||||||
group = 'de.srsoftware' |
|
||||||
version = '1.0-SNAPSHOT' |
|
||||||
|
|
||||||
repositories { |
|
||||||
mavenCentral() |
|
||||||
} |
|
||||||
|
|
||||||
dependencies { |
|
||||||
testImplementation platform('org.junit:junit-bom:5.10.0') |
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter' |
|
||||||
testImplementation project(path: ':de.srsoftware.oidc.api', configuration: "testBundle") |
|
||||||
implementation project(':de.srsoftware.oidc.api') |
|
||||||
implementation project(':de.srsoftware.utils') |
|
||||||
implementation 'com.sun.mail:jakarta.mail:2.0.1' |
|
||||||
implementation 'org.bitbucket.b_c:jose4j:0.9.6' |
|
||||||
} |
|
||||||
|
|
||||||
test { |
|
||||||
useJUnitPlatform() |
|
||||||
} |
|
@ -0,0 +1,11 @@ |
|||||||
|
description = "SRSoftware OIDC: encrypted datastore module" |
||||||
|
|
||||||
|
dependencies{ |
||||||
|
implementation("com.sun.mail:jakarta.mail:2.0.1") |
||||||
|
implementation("de.srsoftware:tools.optionals:1.0.0") |
||||||
|
implementation("de.srsoftware:tools.util:1.0.2") |
||||||
|
|
||||||
|
implementation(project(":de.srsoftware.oidc.api")) |
||||||
|
testImplementation(project(":de.srsoftware.oidc.api","testBundle")) |
||||||
|
} |
||||||
|
|
@ -1,11 +1,11 @@ |
|||||||
/* © SRSoftware 2024 */ |
/* © SRSoftware 2024 */ |
||||||
import static de.srsoftware.utils.Optionals.nullable; |
package de.srsoftware.oidc.datastore.encrypted; /* © SRSoftware 2024 */ |
||||||
import static de.srsoftware.utils.Strings.uuid; |
import static de.srsoftware.tools.Optionals.nullable; |
||||||
|
import static de.srsoftware.tools.Strings.uuid; |
||||||
|
|
||||||
import de.srsoftware.oidc.api.ClientService; |
import de.srsoftware.oidc.api.ClientService; |
||||||
import de.srsoftware.oidc.api.ClientServiceTest; |
import de.srsoftware.oidc.api.ClientServiceTest; |
||||||
import de.srsoftware.oidc.api.data.Client; |
import de.srsoftware.oidc.api.data.Client; |
||||||
import de.srsoftware.oidc.datastore.encrypted.EncryptedClientService; |
|
||||||
import java.sql.SQLException; |
import java.sql.SQLException; |
||||||
import java.util.HashMap; |
import java.util.HashMap; |
||||||
import java.util.List; |
import java.util.List; |
@ -1,8 +1,8 @@ |
|||||||
/* © SRSoftware 2024 */ |
/* © SRSoftware 2024 */ |
||||||
import static de.srsoftware.utils.Strings.uuid; |
package de.srsoftware.oidc.datastore.encrypted; /* © SRSoftware 2024 */ |
||||||
|
import static de.srsoftware.tools.Strings.uuid; |
||||||
import static org.junit.jupiter.api.Assertions.assertEquals; |
import static org.junit.jupiter.api.Assertions.assertEquals; |
||||||
|
|
||||||
import de.srsoftware.oidc.datastore.encrypted.EncryptedConfig; |
|
||||||
import org.junit.jupiter.api.Test; |
import org.junit.jupiter.api.Test; |
||||||
|
|
||||||
public class EncryptedConfigTest { |
public class EncryptedConfigTest { |
@ -1,9 +1,9 @@ |
|||||||
/* © SRSoftware 2024 */ |
/* © SRSoftware 2024 */ |
||||||
import static de.srsoftware.utils.Strings.uuid; |
package de.srsoftware.oidc.datastore.encrypted; /* © SRSoftware 2024 */ |
||||||
|
import static de.srsoftware.tools.Strings.uuid; |
||||||
|
|
||||||
import de.srsoftware.oidc.api.KeyStorage; |
import de.srsoftware.oidc.api.KeyStorage; |
||||||
import de.srsoftware.oidc.api.KeyStoreTest; |
import de.srsoftware.oidc.api.KeyStoreTest; |
||||||
import de.srsoftware.oidc.datastore.encrypted.EncryptedKeyStore; |
|
||||||
import java.io.IOException; |
import java.io.IOException; |
||||||
import java.sql.SQLException; |
import java.sql.SQLException; |
||||||
import java.util.HashMap; |
import java.util.HashMap; |
@ -1,9 +1,9 @@ |
|||||||
/* © SRSoftware 2024 */ |
/* © SRSoftware 2024 */ |
||||||
import static de.srsoftware.utils.Strings.uuid; |
package de.srsoftware.oidc.datastore.encrypted; /* © SRSoftware 2024 */ |
||||||
|
import static de.srsoftware.tools.Strings.uuid; |
||||||
import static org.junit.jupiter.api.Assertions.*; |
import static org.junit.jupiter.api.Assertions.*; |
||||||
|
|
||||||
import de.srsoftware.oidc.api.MailConfig; |
import de.srsoftware.oidc.api.MailConfig; |
||||||
import de.srsoftware.oidc.datastore.encrypted.EncryptedMailConfig; |
|
||||||
import jakarta.mail.Authenticator; |
import jakarta.mail.Authenticator; |
||||||
import java.util.Map; |
import java.util.Map; |
||||||
import java.util.Properties; |
import java.util.Properties; |
@ -1,17 +1,17 @@ |
|||||||
/* © SRSoftware 2024 */ |
/* © SRSoftware 2024 */ |
||||||
|
package de.srsoftware.oidc.datastore.encrypted; /* © SRSoftware 2024 */ |
||||||
import static de.srsoftware.oidc.api.Constants.*; |
import static de.srsoftware.oidc.api.Constants.*; |
||||||
import static de.srsoftware.utils.Optionals.nullable; |
import static de.srsoftware.tools.Optionals.nullable; |
||||||
import static de.srsoftware.utils.Strings.uuid; |
import static de.srsoftware.tools.Strings.uuid; |
||||||
import static java.lang.System.Logger.Level.WARNING; |
import static java.lang.System.Logger.Level.WARNING; |
||||||
|
|
||||||
import de.srsoftware.oidc.api.*; |
import de.srsoftware.oidc.api.*; |
||||||
import de.srsoftware.oidc.api.data.AccessToken; |
import de.srsoftware.oidc.api.data.AccessToken; |
||||||
import de.srsoftware.oidc.api.data.User; |
import de.srsoftware.oidc.api.data.User; |
||||||
import de.srsoftware.oidc.datastore.encrypted.EncryptedUserService; |
import de.srsoftware.tools.Error; |
||||||
import de.srsoftware.utils.Error; |
import de.srsoftware.tools.PasswordHasher; |
||||||
import de.srsoftware.utils.PasswordHasher; |
import de.srsoftware.tools.Payload; |
||||||
import de.srsoftware.utils.Payload; |
import de.srsoftware.tools.Result; |
||||||
import de.srsoftware.utils.Result; |
|
||||||
import java.io.File; |
import java.io.File; |
||||||
import java.util.*; |
import java.util.*; |
||||||
import java.util.stream.Collectors; |
import java.util.stream.Collectors; |
@ -1,26 +0,0 @@ |
|||||||
plugins { |
|
||||||
id 'java' |
|
||||||
} |
|
||||||
|
|
||||||
group = 'de.srsoftware' |
|
||||||
version = '1.0-SNAPSHOT' |
|
||||||
|
|
||||||
repositories { |
|
||||||
mavenCentral() |
|
||||||
} |
|
||||||
|
|
||||||
dependencies { |
|
||||||
testImplementation platform('org.junit:junit-bom:5.10.0') |
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter' |
|
||||||
testImplementation project(path: ':de.srsoftware.oidc.api', configuration: "testBundle") |
|
||||||
implementation project(':de.srsoftware.oidc.api') |
|
||||||
implementation project(':de.srsoftware.utils') |
|
||||||
implementation 'org.json:json:20240303' |
|
||||||
implementation 'org.bitbucket.b_c:jose4j:0.9.6' |
|
||||||
implementation 'com.sun.mail:jakarta.mail:2.0.1' |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
test { |
|
||||||
useJUnitPlatform() |
|
||||||
} |
|
@ -0,0 +1,13 @@ |
|||||||
|
description = "SRSoftware OIDC: file datastore module" |
||||||
|
|
||||||
|
dependencies{ |
||||||
|
implementation("com.sun.mail:jakarta.mail:2.0.1") |
||||||
|
implementation("de.srsoftware:tools.optionals:1.0.0") |
||||||
|
implementation("de.srsoftware:tools.util:1.0.2") |
||||||
|
implementation("org.json:json:20240303") |
||||||
|
|
||||||
|
implementation(project(":de.srsoftware.oidc.api")) |
||||||
|
implementation(project(":de.srsoftware.oidc.web")) |
||||||
|
testImplementation(project(":de.srsoftware.oidc.api","testBundle")) |
||||||
|
} |
||||||
|
|
@ -1,21 +0,0 @@ |
|||||||
plugins { |
|
||||||
id 'java' |
|
||||||
} |
|
||||||
|
|
||||||
group = 'de.srsoftware' |
|
||||||
version = '1.0-SNAPSHOT' |
|
||||||
|
|
||||||
repositories { |
|
||||||
mavenCentral() |
|
||||||
} |
|
||||||
|
|
||||||
dependencies { |
|
||||||
testImplementation platform('org.junit:junit-bom:5.10.0') |
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter' |
|
||||||
implementation project(':de.srsoftware.oidc.api') |
|
||||||
implementation project(':de.srsoftware.http') |
|
||||||
} |
|
||||||
|
|
||||||
test { |
|
||||||
useJUnitPlatform() |
|
||||||
} |
|
@ -0,0 +1,8 @@ |
|||||||
|
description = "SRSoftware OIDC: web module" |
||||||
|
|
||||||
|
dependencies{ |
||||||
|
implementation("de.srsoftware:tools.http:1.0.0") |
||||||
|
|
||||||
|
implementation(project(":de.srsoftware.oidc.api")) |
||||||
|
} |
||||||
|
|
@ -1,20 +0,0 @@ |
|||||||
plugins { |
|
||||||
id 'java' |
|
||||||
} |
|
||||||
|
|
||||||
group = 'de.srsoftware' |
|
||||||
version = '1.0-SNAPSHOT' |
|
||||||
|
|
||||||
repositories { |
|
||||||
mavenCentral() |
|
||||||
} |
|
||||||
|
|
||||||
dependencies { |
|
||||||
testImplementation platform('org.junit:junit-bom:5.10.0') |
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter' |
|
||||||
implementation 'org.json:json:20240303' |
|
||||||
} |
|
||||||
|
|
||||||
test { |
|
||||||
useJUnitPlatform() |
|
||||||
} |
|
@ -1,40 +0,0 @@ |
|||||||
/* © SRSoftware 2024 */ |
|
||||||
package de.srsoftware.utils; |
|
||||||
|
|
||||||
|
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
import org.json.JSONObject; |
|
||||||
|
|
||||||
public class Error<T> implements Result<T> { |
|
||||||
private final String cause; |
|
||||||
private Map<String, Object> metadata; |
|
||||||
|
|
||||||
public Error(String cause) { |
|
||||||
this.cause = cause; |
|
||||||
} |
|
||||||
|
|
||||||
public String cause() { |
|
||||||
return cause; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isError() { |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
public static <T> Error<T> message(String cause, Object... tokens) { |
|
||||||
var err = new Error<T>(cause); |
|
||||||
err.metadata = new HashMap<>(); |
|
||||||
for (int i = 0; i < tokens.length - 1; i += 2) { |
|
||||||
err.metadata.put(tokens[i].toString(), tokens[i + 1]); |
|
||||||
} |
|
||||||
return err; |
|
||||||
} |
|
||||||
|
|
||||||
public JSONObject json() { |
|
||||||
var json = new JSONObject(Map.of("error", cause)); |
|
||||||
if (metadata != null) json.put("metadata", metadata); |
|
||||||
return json; |
|
||||||
} |
|
||||||
} |
|
@ -1,15 +0,0 @@ |
|||||||
/* © SRSoftware 2024 */ |
|
||||||
package de.srsoftware.utils; |
|
||||||
import static java.util.Optional.empty; |
|
||||||
|
|
||||||
import java.util.Optional; |
|
||||||
|
|
||||||
public class Optionals { |
|
||||||
public static <T> Optional<T> nullable(T val) { |
|
||||||
return Optional.ofNullable(val); |
|
||||||
} |
|
||||||
|
|
||||||
public static Optional<String> emptyIfBlank(String text) { |
|
||||||
return text == null || text.isBlank() ? empty() : nullable(text.trim()); |
|
||||||
} |
|
||||||
} |
|
@ -1,11 +0,0 @@ |
|||||||
/* © SRSoftware 2024 */ |
|
||||||
package de.srsoftware.utils; |
|
||||||
|
|
||||||
public interface PasswordHasher<T> { |
|
||||||
public String hash(String password, String salt); |
|
||||||
public String salt(String hashedPassword); |
|
||||||
|
|
||||||
public default boolean matches(String plaintextPassword, String hashedPassword) { |
|
||||||
return hash(plaintextPassword, salt(hashedPassword)).equals(hashedPassword); |
|
||||||
} |
|
||||||
} |
|
@ -1,25 +0,0 @@ |
|||||||
/* © SRSoftware 2024 */ |
|
||||||
package de.srsoftware.utils; |
|
||||||
|
|
||||||
import java.io.File; |
|
||||||
import java.nio.file.Path; |
|
||||||
|
|
||||||
public class Paths { |
|
||||||
public static Path configDir(String applicationName) { |
|
||||||
String home = System.getProperty("user.home"); |
|
||||||
return Path.of(home, ".config", applicationName); |
|
||||||
} |
|
||||||
|
|
||||||
public static Path configDir(Class clazz) { |
|
||||||
return configDir(clazz.getSimpleName()); |
|
||||||
} |
|
||||||
|
|
||||||
public static Path configDir(Object clazz) { |
|
||||||
return configDir(clazz.getClass()); |
|
||||||
} |
|
||||||
|
|
||||||
public static String extension(File file) { |
|
||||||
var parts = file.getName().split("\\."); |
|
||||||
return parts.length == 1 ? "" : parts[parts.length - 1]; |
|
||||||
} |
|
||||||
} |
|
@ -1,24 +0,0 @@ |
|||||||
/* © SRSoftware 2024 */ |
|
||||||
package de.srsoftware.utils; |
|
||||||
|
|
||||||
|
|
||||||
public class Payload<T> implements Result<T> { |
|
||||||
private final T object; |
|
||||||
|
|
||||||
public Payload(T object) { |
|
||||||
this.object = object; |
|
||||||
} |
|
||||||
|
|
||||||
public static <T> Payload<T> of(T object) { |
|
||||||
return new Payload<>(object); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isError() { |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
public T get() { |
|
||||||
return object; |
|
||||||
} |
|
||||||
} |
|
@ -1,6 +0,0 @@ |
|||||||
/* © SRSoftware 2024 */ |
|
||||||
package de.srsoftware.utils; |
|
||||||
|
|
||||||
public interface Result<T> { |
|
||||||
public boolean isError(); |
|
||||||
} |
|
@ -1,10 +0,0 @@ |
|||||||
/* © SRSoftware 2024 */ |
|
||||||
package de.srsoftware.utils; |
|
||||||
|
|
||||||
import java.util.UUID; |
|
||||||
|
|
||||||
public class Strings { |
|
||||||
public static String uuid() { |
|
||||||
return UUID.randomUUID().toString(); |
|
||||||
} |
|
||||||
} |
|
@ -1,38 +0,0 @@ |
|||||||
/* © SRSoftware 2024 */ |
|
||||||
package de.srsoftware.utils; |
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8; |
|
||||||
|
|
||||||
import java.security.MessageDigest; |
|
||||||
import java.security.NoSuchAlgorithmException; |
|
||||||
|
|
||||||
|
|
||||||
public class UuidHasher implements PasswordHasher<String> { |
|
||||||
private static final String SHA256 = "SHA-256"; |
|
||||||
|
|
||||||
private final MessageDigest digest; |
|
||||||
|
|
||||||
public UuidHasher() throws NoSuchAlgorithmException { |
|
||||||
digest = MessageDigest.getInstance(SHA256); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String hash(String password, String uuid) { |
|
||||||
var salt = uuid; |
|
||||||
var saltedPass = "%s %s".formatted(salt, password); |
|
||||||
var bytes = digest.digest(saltedPass.getBytes(UTF_8)); |
|
||||||
|
|
||||||
return "%s@%s".formatted(hex(bytes), salt); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String salt(String hashedPassword) { |
|
||||||
return hashedPassword.split("@", 2)[1]; |
|
||||||
} |
|
||||||
|
|
||||||
public static String hex(byte[] bytes) { |
|
||||||
StringBuilder sb = new StringBuilder(bytes.length * 2); |
|
||||||
for (byte b : bytes) sb.append(String.format("%02x", b)); |
|
||||||
return sb.toString(); |
|
||||||
} |
|
||||||
} |
|
@ -1,11 +0,0 @@ |
|||||||
rootProject.name = 'LightOIDC' |
|
||||||
include 'de.srsoftware.http' |
|
||||||
include 'de.srsoftware.logging' |
|
||||||
include 'de.srsoftware.oidc.api' |
|
||||||
include 'de.srsoftware.oidc.app' |
|
||||||
include 'de.srsoftware.oidc.backend' |
|
||||||
include 'de.srsoftware.oidc.datastore.encrypted' |
|
||||||
include 'de.srsoftware.oidc.datastore.file' |
|
||||||
include 'de.srsoftware.oidc.web' |
|
||||||
include 'de.srsoftware.utils' |
|
||||||
|
|
@ -0,0 +1,8 @@ |
|||||||
|
rootProject.name = "LightOIDC" |
||||||
|
include("de.srsoftware.oidc.api") |
||||||
|
include("de.srsoftware.oidc.app") |
||||||
|
include("de.srsoftware.oidc.backend") |
||||||
|
include("de.srsoftware.oidc.datastore.encrypted") |
||||||
|
include("de.srsoftware.oidc.datastore.file") |
||||||
|
include("de.srsoftware.oidc.web") |
||||||
|
|
Loading…
Reference in new issue