diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte
index 00170ef..8ae9e23 100644
--- a/frontend/src/App.svelte
+++ b/frontend/src/App.svelte
@@ -17,11 +17,8 @@
function loadTheme(name){
if (!name) return;
- console.log({theme:name});
const url = `${location.protocol}//${location.host.replace('5173','8080')}/css/${name}.css`;
- fetch(url).then(resp => resp.text()).then(css => {
- document.getElementById('usercss').innerText = css;
- });
+ fetch(url).then(resp => resp.text()).then(css => document.getElementById('usercss').innerText = css);
}
$effect(() => loadTheme(user.theme));
diff --git a/frontend/src/routes/user/List.svelte b/frontend/src/routes/user/List.svelte
new file mode 100644
index 0000000..6392dc8
--- /dev/null
+++ b/frontend/src/routes/user/List.svelte
@@ -0,0 +1,44 @@
+
+
+
\ No newline at end of file
diff --git a/frontend/src/routes/user/User.svelte b/frontend/src/routes/user/User.svelte
index d743db4..a37e11c 100644
--- a/frontend/src/routes/user/User.svelte
+++ b/frontend/src/routes/user/User.svelte
@@ -4,6 +4,7 @@
import ClickInput from '../../Components/ClickInput.svelte';
import ClickSelect from '../../Components/ClickSelect.svelte';
import EditPassword from './EditPassword.svelte';
+ import UserList from './List.svelte';
let editPassword = false;
async function patch(changeset){
@@ -92,9 +93,6 @@
{#if user.permissions.includes('LIST_USERS')}
-
+
{/if}
diff --git a/frontend/src/translations.svelte.js b/frontend/src/translations.svelte.js
index f28b7dd..3652b1e 100644
--- a/frontend/src/translations.svelte.js
+++ b/frontend/src/translations.svelte.js
@@ -12,7 +12,7 @@ export function t(key,...args){
let keys = key.split('.');
for (let token of keys){
if (!set[token]){
- console.log('Missing translation for '+key);
+ console.warn('Missing translation for '+key);
return keys[keys.length-1].replaceAll('_',' ');
}
set = set[token];
diff --git a/frontend/src/user.svelte.js b/frontend/src/user.svelte.js
index 385aff8..c3844bb 100644
--- a/frontend/src/user.svelte.js
+++ b/frontend/src/user.svelte.js
@@ -4,7 +4,6 @@ export const user = $state({
})
export async function checkUser(){
- console.log('checkUser()');
const url = `${location.protocol}//${location.host.replace('5173','8080')}/api/user/whoami`;
const response = await fetch(url,{
credentials: 'include'
diff --git a/user/src/main/java/de/srsoftware/umbrella/user/UserModule.java b/user/src/main/java/de/srsoftware/umbrella/user/UserModule.java
index 0b9e0de..cce888b 100644
--- a/user/src/main/java/de/srsoftware/umbrella/user/UserModule.java
+++ b/user/src/main/java/de/srsoftware/umbrella/user/UserModule.java
@@ -3,13 +3,14 @@ package de.srsoftware.umbrella.user;
import static de.srsoftware.tools.Optionals.*;
import static de.srsoftware.umbrella.core.Constants.*;
+import static de.srsoftware.umbrella.core.Paths.LIST;
import static de.srsoftware.umbrella.core.Paths.LOGOUT;
import static de.srsoftware.umbrella.core.ResponseCode.*;
import static de.srsoftware.umbrella.user.Constants.*;
import static de.srsoftware.umbrella.user.Paths.LOGIN;
import static de.srsoftware.umbrella.user.Paths.WHOAMI;
+import static de.srsoftware.umbrella.user.model.DbUser.PERMISSION.LIST_USERS;
import static de.srsoftware.umbrella.user.model.DbUser.PERMISSION.UPDATE_USERS;
-import static java.lang.System.Logger.Level.DEBUG;
import static java.lang.System.Logger.Level.WARNING;
import static java.time.temporal.ChronoUnit.DAYS;
@@ -24,9 +25,9 @@ import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.util.List;
-import java.util.Set;
+import java.util.Optional;
+
import org.json.JSONObject;
-import org.sqlite.core.DB;
public class UserModule extends PathHandler {
@@ -63,12 +64,20 @@ public class UserModule extends PathHandler {
@Override
public boolean doGet(Path path, HttpExchange ex) throws IOException {
- var p = path.toString();
- switch (p){
- case LOGOUT: return logout(ex);
- case WHOAMI: return getUser(ex);
+ UmbrellaUser user = null;
+ var sessionToken = SessionToken.from(ex).map(Token::of);
+ if (sessionToken.isPresent()) try {
+ user = users.load(users.load(sessionToken.get()));
+ } catch (UmbrellaException e) {
+ LOG.log(WARNING,e);
}
- return super.doGet(path,ex);
+ addCors(ex);
+ return switch (path.toString()) {
+ case LIST -> getUserList(ex, user);
+ case LOGOUT -> logout(ex, sessionToken);
+ case WHOAMI -> getUser(ex, user);
+ default -> super.doGet(path, ex);
+ };
}
@Override
@@ -127,6 +136,19 @@ public class UserModule extends PathHandler {
}
}
+ private boolean getUserList(HttpExchange ex, UmbrellaUser user) throws IOException {
+
+ if (user instanceof DbUser dbUser && dbUser.permissions().contains(LIST_USERS)){
+ try {
+ var list = users.list(0, null).stream().map(UmbrellaUser::toMap).toList();
+ return sendContent(ex,list);
+ } catch (UmbrellaException e) {
+ return sendContent(ex,e.statusCode(),e.getMessage());
+ }
+ }
+ return sendContent(ex,FORBIDDEN,"You are not allowed to list users!");
+ }
+
private boolean patchPassword(HttpExchange ex, UmbrellaUser requestingUser) throws IOException {
if (!(requestingUser instanceof DbUser user)) return sendContent(ex,SERVER_ERROR,"DbUser expected");
JSONObject json;
@@ -160,22 +182,12 @@ public class UserModule extends PathHandler {
return super.doPost(path, ex);
}
- private boolean getUser(HttpExchange ex) throws IOException {
- addCors(ex);
- var sessionToken = SessionToken.from(ex);
- if (sessionToken.isEmpty()) return sendEmptyResponse(UNAUTHORIZED,ex);
- try {
- Session session = users.load(Token.of(sessionToken.get()));
- UmbrellaUser user = users.load(session);
- return sendContent(ex,OK,user);
- } catch (UmbrellaException e) {
- return sendContent(ex,e.statusCode(),e.getMessage());
- }
+ private boolean getUser(HttpExchange ex, UmbrellaUser user) throws IOException {
+ if (user != null) return sendContent(ex,OK,user);
+ return sendEmptyResponse(UNAUTHORIZED,ex);
}
- public boolean logout(HttpExchange ex) throws IOException {
- addCors(ex);
- var optToken = SessionToken.from(ex).map(Token::of);
+ public boolean logout(HttpExchange ex, Optional optToken) throws IOException {
if (optToken.isPresent()){
var token = optToken.get();
try {
diff --git a/web/src/main/resources/web/css/winter.css b/web/src/main/resources/web/css/winter.css
index 42f3553..cf43906 100644
--- a/web/src/main/resources/web/css/winter.css
+++ b/web/src/main/resources/web/css/winter.css
@@ -35,9 +35,14 @@ button{
border-color: darkgray black black darkgray;
}
footer {
- position: absolute;
+ position: sticky;
bottom: 0;
width: 100%;
text-align: center;
- margin: 5px;
+ padding: 5px;
+ margin-top: 5px;
+ background: white;
+ border-color: cyan;
+ border-style: dashed;
+ border-width: 1px 0 0;
}
\ No newline at end of file