From 71cf6ec96dedad2eed2b7f43941d669a3ba7c184 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Sat, 28 Jun 2025 00:23:37 +0200 Subject: [PATCH] preparing svelte login, mastered translations --- backend/build.gradle.kts | 2 +- .../umbrella/backend/Application.java | 2 + build.gradle.kts | 2 +- frontend/src/App.svelte | 9 +++- frontend/src/Components/Homepage.svelte | 6 ++- frontend/src/Components/Login.svelte | 39 +++++++++----- frontend/src/Components/Menu.svelte | 12 ++++- frontend/src/app.css | 4 ++ frontend/src/translations.svelte.js | 7 ++- frontend/src/user.svelte.js | 20 +++++++ settings.gradle.kts | 3 +- translations/build.gradle.kts | 1 - .../umbrella/translations/Translations.java | 7 +-- translations/src/main/resources/de.json | 11 +++- user/build.gradle.kts | 6 +++ .../srsoftware/umbrella/user/UserModule.java | 54 +++++++++++++++++++ web/build.gradle.kts | 4 -- 17 files changed, 151 insertions(+), 38 deletions(-) create mode 100644 frontend/src/user.svelte.js create mode 100644 user/build.gradle.kts create mode 100644 user/src/main/java/de/srsoftware/umbrella/user/UserModule.java diff --git a/backend/build.gradle.kts b/backend/build.gradle.kts index 3fd1243..4eaa3bf 100644 --- a/backend/build.gradle.kts +++ b/backend/build.gradle.kts @@ -13,8 +13,8 @@ application{ dependencies{ implementation(project(":translations")) + implementation(project(":user")) implementation(project(":web")) - implementation("de.srsoftware:tools.http:6.0.0") } tasks.jar { diff --git a/backend/src/main/java/de/srsoftware/umbrella/backend/Application.java b/backend/src/main/java/de/srsoftware/umbrella/backend/Application.java index 546dd29..f44e6e9 100644 --- a/backend/src/main/java/de/srsoftware/umbrella/backend/Application.java +++ b/backend/src/main/java/de/srsoftware/umbrella/backend/Application.java @@ -7,6 +7,7 @@ import static java.lang.System.Logger.Level.INFO; import com.sun.net.httpserver.HttpServer; import de.srsoftware.tools.ColorLogger; import de.srsoftware.umbrella.translations.Translations; +import de.srsoftware.umbrella.user.UserModule; import de.srsoftware.umbrella.web.WebHandler; import java.io.IOException; import java.net.InetSocketAddress; @@ -22,6 +23,7 @@ public class Application { HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); server.setExecutor(Executors.newFixedThreadPool(threads)); new WebHandler().bindPath("/").on(server); + new UserModule().bindPath("/api/user").on(server); new Translations().bindPath("/api/translations").on(server); LOG.log(INFO,"Started web server at {0}",port); server.start(); diff --git a/build.gradle.kts b/build.gradle.kts index 8709c33..d868971 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -40,7 +40,7 @@ subprojects { dependencies { testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") - + implementation("de.srsoftware:tools.http:6.0.2") implementation("de.srsoftware:tools.logging:1.3.2") } diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index 64780fe..7f8d333 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -1,6 +1,8 @@ -{#if translations_ready} +{#if translations_ready } +{#if user.username } +{:else} +{/if} {:else}

Loading translations...

{/if} \ No newline at end of file diff --git a/frontend/src/Components/Homepage.svelte b/frontend/src/Components/Homepage.svelte index f47aba5..24cce90 100644 --- a/frontend/src/Components/Homepage.svelte +++ b/frontend/src/Components/Homepage.svelte @@ -1 +1,5 @@ -

Welcome

\ No newline at end of file + +

{t('home.Welcome')}, {user.username}

\ No newline at end of file diff --git a/frontend/src/Components/Login.svelte b/frontend/src/Components/Login.svelte index d20f186..cd66614 100644 --- a/frontend/src/Components/Login.svelte +++ b/frontend/src/Components/Login.svelte @@ -1,5 +1,15 @@ +
+
+ {t('login.Login')} + + + +
+
- {t('login.Login')} - - - -
- -
- OIDC Login + {t('login.OIDC_Login')}
diff --git a/frontend/src/Components/Menu.svelte b/frontend/src/Components/Menu.svelte index de5b32b..3ffce07 100644 --- a/frontend/src/Components/Menu.svelte +++ b/frontend/src/Components/Menu.svelte @@ -1,3 +1,13 @@ + \ No newline at end of file diff --git a/frontend/src/app.css b/frontend/src/app.css index afcfe68..5298a0b 100644 --- a/frontend/src/app.css +++ b/frontend/src/app.css @@ -1,3 +1,6 @@ +a { + color: orange; +} body { background: black; color: orange; @@ -14,6 +17,7 @@ input{ border-radius: 4px; padding: 3px; margin: 3px; + color: orange; } button{ diff --git a/frontend/src/translations.svelte.js b/frontend/src/translations.svelte.js index 41bb40d..405192e 100644 --- a/frontend/src/translations.svelte.js +++ b/frontend/src/translations.svelte.js @@ -8,12 +8,11 @@ export async function loadTranslation(lang){ } export function t(key){ - var keys = key.split('.'); let set = translations.values; + var keys = key.split('.'); for (let key of keys){ - if (set[key]) { - set = set[key]; - } else return key; + if (!set[key]) return keys[keys.length-1]; + set = set[key]; } return set; } \ No newline at end of file diff --git a/frontend/src/user.svelte.js b/frontend/src/user.svelte.js new file mode 100644 index 0000000..3f016fd --- /dev/null +++ b/frontend/src/user.svelte.js @@ -0,0 +1,20 @@ +export const user = $state({ + name : null +}) + +export async function tryLogin(credentials){ + var url = `${location.protocol}//${location.host.replace('5173','8080')}/api/user/login`; + let response = await fetch(url,{ + headers: { + 'Content-Type':'application/json' + }, + method: 'POST', + body: JSON.stringify(credentials) + }); + if (response.ok){ + const json = await response.json(); + for (var key of Object.keys(json)) user[key] = json[key]; + } else { + alert("Login failed!"); + } +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index cfacc5e..1e4f564 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,6 @@ rootProject.name = "Umbrella25" include("backend") +include("translations") +include("user") include("web") -include("translations") \ No newline at end of file diff --git a/translations/build.gradle.kts b/translations/build.gradle.kts index 42cfea2..cb99751 100644 --- a/translations/build.gradle.kts +++ b/translations/build.gradle.kts @@ -1,6 +1,5 @@ description = "Umbrella : Translations" dependencies{ - implementation("de.srsoftware:tools.http:6.0.0") implementation("org.json:json:20240303") } \ No newline at end of file diff --git a/translations/src/main/java/de/srsoftware/umbrella/translations/Translations.java b/translations/src/main/java/de/srsoftware/umbrella/translations/Translations.java index e2ebc6c..8aa47ce 100644 --- a/translations/src/main/java/de/srsoftware/umbrella/translations/Translations.java +++ b/translations/src/main/java/de/srsoftware/umbrella/translations/Translations.java @@ -1,21 +1,17 @@ /* © SRSoftware 2025 */ package de.srsoftware.umbrella.translations; -import static java.lang.System.Logger.Level.INFO; import static java.lang.System.Logger.Level.WARNING; import static java.nio.charset.StandardCharsets.UTF_8; import com.sun.net.httpserver.HttpExchange; import de.srsoftware.tools.Path; import de.srsoftware.tools.PathHandler; -import org.json.JSONObject; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URL; -import java.nio.charset.StandardCharsets; import java.util.HashMap; -import java.util.Map; +import org.json.JSONObject; public class Translations extends PathHandler { private static final System.Logger LOG = System.getLogger("Translations"); @@ -24,7 +20,6 @@ public class Translations extends PathHandler { @Override public boolean doGet(Path path, HttpExchange ex) throws IOException { - LOG.log(INFO,"doGet({0},ex)",path); allowOrigin(ex,"*"); if (path.empty())return sendContent(ex,501,"Language missing"); var lang = path.pop(); diff --git a/translations/src/main/resources/de.json b/translations/src/main/resources/de.json index 79f1143..8e13952 100644 --- a/translations/src/main/resources/de.json +++ b/translations/src/main/resources/de.json @@ -1,5 +1,12 @@ { - 'login' : { - 'Login' : "Mist!" + "home" : { + "Welcome" : "Willkommen" + }, + "login" : { + "do_login" : "anmelden", + "Email_or_Username": "Email oder Nutzername", + "Login" : "Anmeldung", + "OIDC_Login" : "Anmeldung mit OIDC", + "Password" : "Passwort" } } \ No newline at end of file diff --git a/user/build.gradle.kts b/user/build.gradle.kts new file mode 100644 index 0000000..e21ca3b --- /dev/null +++ b/user/build.gradle.kts @@ -0,0 +1,6 @@ +description = "Umbrella : User" + +dependencies{ + implementation("de.srsoftware:tools.mime:1.1.2") + implementation("org.json:json:20240303") +} \ No newline at end of file diff --git a/user/src/main/java/de/srsoftware/umbrella/user/UserModule.java b/user/src/main/java/de/srsoftware/umbrella/user/UserModule.java new file mode 100644 index 0000000..2c7f736 --- /dev/null +++ b/user/src/main/java/de/srsoftware/umbrella/user/UserModule.java @@ -0,0 +1,54 @@ +/* © SRSoftware 2025 */ +package de.srsoftware.umbrella.user; + +import com.sun.net.httpserver.HttpExchange; +import de.srsoftware.tools.MimeType; +import de.srsoftware.tools.Path; +import de.srsoftware.tools.PathHandler; +import de.srsoftware.tools.SessionToken; +import org.json.JSONObject; + +import java.io.IOException; +import java.util.Map; +import java.util.UUID; + +import static de.srsoftware.tools.MimeType.MIME_JSON; + + +public class UserModule extends PathHandler { + + private HttpExchange addCors(HttpExchange ex){ + var headers = ex.getResponseHeaders(); + headers.add("Allow-Origin","*"); + headers.add("Access-Control-Allow-Origin","*"); + headers.add("Access-Control-Allow-Headers","Content-Type"); + return ex; + } + + @Override + public boolean doOptions(Path path, HttpExchange ex) throws IOException { + return sendEmptyResponse(200,addCors(ex)); + } + + @Override + public boolean doPost(Path path, HttpExchange ex) throws IOException { + addCors(ex); + var p = path.toString(); + switch (p){ + case "login": return postLogin(ex); + } + return super.doPost(path, ex); + } + + private boolean postLogin(HttpExchange ex) throws IOException { + var json = json(ex); + if (!(json.has("username") && json.get("username") instanceof String username)) return sendContent(ex,402,"Username missing"); + if (!(json.has("password") && json.get("password") instanceof String password)) return sendContent(ex,402,"Password missing"); + + if (!username.equals(password)) return sendContent(ex,401,"Login failed"); + var sessionId = UUID.randomUUID().toString(); + new SessionToken(sessionId).addTo(ex); + ex.getResponseHeaders().add("Content-Type", MIME_JSON); + return sendContent(ex,200,new JSONObject(Map.of("username",username)).toString()); + } +} diff --git a/web/build.gradle.kts b/web/build.gradle.kts index c2870d9..dae15cf 100644 --- a/web/build.gradle.kts +++ b/web/build.gradle.kts @@ -1,9 +1,5 @@ description = "Umbrella : Web" -dependencies{ - implementation("de.srsoftware:tools.http:6.0.0") -} - tasks.processResources { System.out.println("Copying from dist…") from("../frontend/dist") {