preparing svelte login, mastered translations
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import { loadTranslation } from './translations.svelte.js'
|
||||
import { loadTranslation } from './translations.svelte.js';
|
||||
import { user } from './user.svelte.js';
|
||||
|
||||
let translations_ready = false;
|
||||
onMount(async () => {
|
||||
await loadTranslation('de','Login');
|
||||
@@ -12,10 +14,13 @@
|
||||
import Menu from "./Components/Menu.svelte";
|
||||
</script>
|
||||
|
||||
{#if translations_ready}
|
||||
{#if translations_ready }
|
||||
{#if user.username }
|
||||
<Menu />
|
||||
<Homepage />
|
||||
{:else}
|
||||
<Login />
|
||||
{/if}
|
||||
{:else}
|
||||
<p>Loading translations...</p>
|
||||
{/if}
|
||||
@@ -1 +1,5 @@
|
||||
<h1>Welcome</h1>
|
||||
<script>
|
||||
import { t } from '../translations.svelte.js';
|
||||
import { user } from '../user.svelte.js';
|
||||
</script>
|
||||
<h1>{t('home.Welcome')}, {user.username}</h1>
|
||||
@@ -1,5 +1,15 @@
|
||||
<script>
|
||||
import { t } from '../translations.svelte.js';
|
||||
import { tryLogin } from '../user.svelte.js';
|
||||
let credentials = { username : null, password : null }
|
||||
|
||||
function doLogin(ev){
|
||||
tryLogin(credentials);
|
||||
}
|
||||
|
||||
function init(element){
|
||||
element.focus();
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
label { display: block; margin: 5px; }
|
||||
@@ -14,21 +24,22 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
<form on:submit|preventDefault={doLogin}>
|
||||
<fieldset>
|
||||
<legend>{t('login.Login')}</legend>
|
||||
<label>
|
||||
<input type="text" bind:value={credentials.username} required use:init />
|
||||
<span>{t('login.Email_or_Username')}</span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="password" bind:value={credentials.password} required />
|
||||
<span>{t('login.Password')}</span>
|
||||
</label>
|
||||
<button>{t('login.do_login')}</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
<fieldset>
|
||||
<legend>{t('login.Login')}</legend>
|
||||
<label>
|
||||
<input type="text" />
|
||||
<span>Email/Username</span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="password" />
|
||||
<span>Password</span>
|
||||
</label>
|
||||
<button>Login</button>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend>OIDC Login</legend>
|
||||
<legend>{t('login.OIDC_Login')}</legend>
|
||||
<button>SRSoftware</button>
|
||||
<button>ORC ID</button>
|
||||
</fieldset>
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
<script>
|
||||
import { t } from '../translations.svelte.js';
|
||||
import { user } from '../user.svelte.js';
|
||||
|
||||
function logout(){
|
||||
user.username = null;
|
||||
}
|
||||
</script>
|
||||
<nav>
|
||||
<a href="/">Home</a>
|
||||
<a href="/">{t('nav.Home')}</a>
|
||||
<a href="https://svelte.dev/tutorial/svelte/state" target="_blank">{t('nav.Tutorial')}</a>
|
||||
<a href="#" on:click={logout}>Logout</a>
|
||||
</nav>
|
||||
@@ -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{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
20
frontend/src/user.svelte.js
Normal file
20
frontend/src/user.svelte.js
Normal file
@@ -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!");
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
rootProject.name = "Umbrella25"
|
||||
|
||||
include("backend")
|
||||
include("translations")
|
||||
include("user")
|
||||
include("web")
|
||||
include("translations")
|
||||
@@ -1,6 +1,5 @@
|
||||
description = "Umbrella : Translations"
|
||||
|
||||
dependencies{
|
||||
implementation("de.srsoftware:tools.http:6.0.0")
|
||||
implementation("org.json:json:20240303")
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
6
user/build.gradle.kts
Normal file
6
user/build.gradle.kts
Normal file
@@ -0,0 +1,6 @@
|
||||
description = "Umbrella : User"
|
||||
|
||||
dependencies{
|
||||
implementation("de.srsoftware:tools.mime:1.1.2")
|
||||
implementation("org.json:json:20240303")
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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") {
|
||||
|
||||
Reference in New Issue
Block a user