From 7eca9dd08ebfa44afc51c165947223908c03a856 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Mon, 21 Jul 2025 23:47:28 +0200 Subject: [PATCH] working on Autocomplete field for member addition to projects --- .../umbrella/core/api/ProjectService.java | 1 - frontend/src/Components/Autocomplete.svelte | 47 +++++++++++++++++++ frontend/src/Components/MemberEditor.svelte | 31 +++++++++++- .../umbrella/project/ProjectModule.java | 12 ++--- .../srsoftware/umbrella/user/UserModule.java | 37 ++++++++------- .../srsoftware/umbrella/user/api/UserDb.java | 6 ++- .../umbrella/user/sqlite/SqliteDB.java | 17 +++++++ 7 files changed, 123 insertions(+), 28 deletions(-) create mode 100644 frontend/src/Components/Autocomplete.svelte diff --git a/core/src/main/java/de/srsoftware/umbrella/core/api/ProjectService.java b/core/src/main/java/de/srsoftware/umbrella/core/api/ProjectService.java index 231613a..846971c 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/api/ProjectService.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/api/ProjectService.java @@ -16,5 +16,4 @@ public interface ProjectService { loadMembers(List.of(project)); return project; } - Map> mapProjects(Map projects); } diff --git a/frontend/src/Components/Autocomplete.svelte b/frontend/src/Components/Autocomplete.svelte new file mode 100644 index 0000000..7f5ef56 --- /dev/null +++ b/frontend/src/Components/Autocomplete.svelte @@ -0,0 +1,47 @@ + + + + + diff --git a/frontend/src/Components/MemberEditor.svelte b/frontend/src/Components/MemberEditor.svelte index 9b8f945..b44dd10 100644 --- a/frontend/src/Components/MemberEditor.svelte +++ b/frontend/src/Components/MemberEditor.svelte @@ -1,6 +1,7 @@ @@ -41,7 +68,9 @@ {t('add_member')} - + + + \ No newline at end of file diff --git a/project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java b/project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java index ad8a986..d53c2c2 100644 --- a/project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java +++ b/project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java @@ -4,6 +4,7 @@ package de.srsoftware.umbrella.project; import static de.srsoftware.umbrella.core.ConnectionProvider.connect; import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.Paths.LIST; +import static de.srsoftware.umbrella.core.Util.mapValues; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; import static de.srsoftware.umbrella.core.model.Permission.EDIT; import static de.srsoftware.umbrella.core.model.Permission.OWNER; @@ -14,6 +15,7 @@ import static java.net.HttpURLConnection.HTTP_OK; import com.sun.net.httpserver.HttpExchange; import de.srsoftware.configuration.Configuration; +import de.srsoftware.tools.Mappable; import de.srsoftware.tools.Path; import de.srsoftware.tools.SessionToken; import de.srsoftware.umbrella.core.BaseHandler; @@ -130,7 +132,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { var company = companies.get(companyId); if (!companies.membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name()); var projects = listCompanyProjects(companyId,false); - return sendContent(ex,mapProjects(projects)); + return sendContent(ex,mapValues(projects)); } @Override @@ -142,7 +144,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { private boolean listUserProjects(HttpExchange ex, UmbrellaUser user, boolean showClosed) throws IOException, UmbrellaException { var projects = listUserProjects(user.id(),showClosed); - return sendContent(ex,mapProjects(projects)); + return sendContent(ex,mapValues(projects)); } @Override @@ -159,12 +161,6 @@ public class ProjectModule extends BaseHandler implements ProjectService { return projectList; } - @Override - public Map> mapProjects(Map projects) { - var mapped = new HashMap>(); - for (var entry : projects.entrySet()) mapped.put(entry.getKey(),entry.getValue().toMap()); - return mapped; - } private void patchMembers(Project project, JSONObject json) { var members = project.members(); 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 035005f..e19dafb 100644 --- a/user/src/main/java/de/srsoftware/umbrella/user/UserModule.java +++ b/user/src/main/java/de/srsoftware/umbrella/user/UserModule.java @@ -7,12 +7,11 @@ import static de.srsoftware.tools.Strings.uuid; import static de.srsoftware.umbrella.core.ConnectionProvider.connect; import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.Constants.CODE; -import static de.srsoftware.umbrella.core.Paths.LIST; -import static de.srsoftware.umbrella.core.Paths.LOGOUT; +import static de.srsoftware.umbrella.core.Constants.TOKEN; +import static de.srsoftware.umbrella.core.Paths.*; import static de.srsoftware.umbrella.core.ResponseCode.*; import static de.srsoftware.umbrella.core.ResponseCode.HTTP_SERVER_ERROR; -import static de.srsoftware.umbrella.core.Util.open; -import static de.srsoftware.umbrella.core.Util.request; +import static de.srsoftware.umbrella.core.Util.*; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; import static de.srsoftware.umbrella.user.Constants.*; import static de.srsoftware.umbrella.user.Paths.*; @@ -257,6 +256,7 @@ public class UserModule extends BaseHandler implements UserService { case OIDC -> postOIDC(ex, path); case IMPERSONATE -> impersonate(ex, targetId); case LOGIN -> postLogin(ex); + case SEARCH -> postSearch(ex); case RESET_PW -> postResetPassword(ex); case null, default -> super.doPost(path,ex); }; @@ -449,6 +449,17 @@ public class UserModule extends BaseHandler implements UserService { } } + private boolean patchService(HttpExchange ex, String serviceName, UmbrellaUser requestingUser) throws IOException, UmbrellaException { + if (!(requestingUser instanceof DbUser user && user.permissions().contains(MANAGE_LOGIN_SERVICES))) throw forbidden("You are not allowed to manage that service!"); + var json = json(ex); + if (!json.has(NAME) || !(json.get(NAME) instanceof String name) || name.isBlank()) throw missingFieldException(NAME); + if (!json.has(URL) || !(json.get(URL) instanceof String url) || url.isBlank()) throw missingFieldException(URL); + if (!json.has(CLIENT_ID) || !(json.get(CLIENT_ID) instanceof String clientId) || clientId.isBlank()) throw missingFieldException(CLIENT_ID); + if (!json.has(CLIENT_SECRET) || !(json.get(CLIENT_SECRET) instanceof String secret) || secret.isBlank()) throw missingFieldException(CLIENT_SECRET); + var service = logins.save(new LoginService(name,url,clientId,secret, DEFAULT_FIELD)); + return sendContent(ex,service.toMap()); + } + @Override public PostBox postBox() { return messages; @@ -496,17 +507,6 @@ public class UserModule extends BaseHandler implements UserService { return ok(ex); } - private boolean patchService(HttpExchange ex, String serviceName, UmbrellaUser requestingUser) throws IOException, UmbrellaException { - if (!(requestingUser instanceof DbUser user && user.permissions().contains(MANAGE_LOGIN_SERVICES))) throw forbidden("You are not allowed to manage that service!"); - var json = json(ex); - if (!json.has(NAME) || !(json.get(NAME) instanceof String name) || name.isBlank()) throw missingFieldException(NAME); - if (!json.has(URL) || !(json.get(URL) instanceof String url) || url.isBlank()) throw missingFieldException(URL); - if (!json.has(CLIENT_ID) || !(json.get(CLIENT_ID) instanceof String clientId) || clientId.isBlank()) throw missingFieldException(CLIENT_ID); - if (!json.has(CLIENT_SECRET) || !(json.get(CLIENT_SECRET) instanceof String secret) || secret.isBlank()) throw missingFieldException(CLIENT_SECRET); - var service = logins.save(new LoginService(name,url,clientId,secret, DEFAULT_FIELD)); - return sendContent(ex,service.toMap()); - } - private boolean postLogin(HttpExchange ex) throws IOException { var json = json(ex); if (!(json.has(USERNAME) && json.get(USERNAME) instanceof String username)) return sendContent(ex, HTTP_UNPROCESSABLE,"Username missing"); @@ -522,7 +522,12 @@ public class UserModule extends BaseHandler implements UserService { } } - + private boolean postSearch(HttpExchange ex) throws IOException { + var requestingUser = loadUser(ex); + if (!(requestingUser.isPresent() && requestingUser.get() instanceof DbUser dbUser)) return unauthorized(ex); + var key = body(ex); + return sendContent(ex,mapValues(users.search(key))); + } static int score(String password){ if (password == null) return 0; diff --git a/user/src/main/java/de/srsoftware/umbrella/user/api/UserDb.java b/user/src/main/java/de/srsoftware/umbrella/user/api/UserDb.java index f49b430..b7dada5 100644 --- a/user/src/main/java/de/srsoftware/umbrella/user/api/UserDb.java +++ b/user/src/main/java/de/srsoftware/umbrella/user/api/UserDb.java @@ -17,6 +17,8 @@ public interface UserDb { Boolean dropSession(Token token) throws UmbrellaException; + Session extend(Session session) throws UmbrellaException; + /** * Get a session for the provided user. * @param user @@ -24,8 +26,6 @@ public interface UserDb { */ Session getSession(UmbrellaUser user) throws UmbrellaException; - Session extend(Session session) throws UmbrellaException; - Map list(Integer start, Integer limit, Collection ids) throws UmbrellaException; Session load(Token token) throws UmbrellaException; @@ -39,4 +39,6 @@ public interface UserDb { UmbrellaUser load(String key, Password password) throws UmbrellaException; UmbrellaUser save(DbUser user) throws UmbrellaException; + + Map search(String key); } diff --git a/user/src/main/java/de/srsoftware/umbrella/user/sqlite/SqliteDB.java b/user/src/main/java/de/srsoftware/umbrella/user/sqlite/SqliteDB.java index b7f5ca6..607d4d9 100644 --- a/user/src/main/java/de/srsoftware/umbrella/user/sqlite/SqliteDB.java +++ b/user/src/main/java/de/srsoftware/umbrella/user/sqlite/SqliteDB.java @@ -5,6 +5,7 @@ import static de.srsoftware.tools.jdbc.Condition.*; import static de.srsoftware.tools.jdbc.Query.*; import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL; import static de.srsoftware.umbrella.core.Constants.*; +import static de.srsoftware.umbrella.core.ResponseCode.HTTP_SERVER_ERROR; import static de.srsoftware.umbrella.user.Constants.*; import static de.srsoftware.umbrella.user.model.DbUser.ADMIN_PERMISSIONS; import static java.lang.System.Logger.Level.*; @@ -499,6 +500,22 @@ CREATE TABLE IF NOT EXISTS {0} ( return user; } + @Override + public Map search(String key) { + try { + var rs = select(ALL).from(TABLE_USERS).where(LOGIN,like("%"+key+"%")).exec(db); + var users = new HashMap(); + while (rs.next()){ + var user = toUser(rs); + users.put(user.id(),user); + } + rs.close(); + return users; + } catch (SQLException e){ + throw new UmbrellaException(HTTP_SERVER_ERROR,"Failed to search for user by key = {0}",key); + } + } + public Instant then(){ return LocalDateTime.now().plus(DEFAULT_SESSION_DURATION).toInstant(ZoneOffset.UTC); }