From fccfea671ae6c8b81771a83b4466d03ca8d9b1c4 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Mon, 18 Apr 2022 17:15:24 +0200 Subject: [PATCH] working on permissions --- .../srsoftware/widerhall/data/ListMember.java | 6 ++- .../de/srsoftware/widerhall/data/User.java | 7 ++- .../de/srsoftware/widerhall/web/Rest.java | 54 +++++++++++++++++-- .../java/de/srsoftware/widerhall/web/Web.java | 11 ++-- static/templates/js.st | 34 ++++++++++-- static/templates/userlist.st | 1 + 6 files changed, 100 insertions(+), 13 deletions(-) diff --git a/src/main/java/de/srsoftware/widerhall/data/ListMember.java b/src/main/java/de/srsoftware/widerhall/data/ListMember.java index 916b9f7..908eb8f 100644 --- a/src/main/java/de/srsoftware/widerhall/data/ListMember.java +++ b/src/main/java/de/srsoftware/widerhall/data/ListMember.java @@ -1,6 +1,7 @@ package de.srsoftware.widerhall.data; import de.srsoftware.widerhall.Util; +import org.antlr.runtime.MismatchedTokenException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.stringtemplate.v4.ST; @@ -32,14 +33,15 @@ public class ListMember { public static User confirm(String token) throws SQLException { var rs = Database.open().select(TABLE_NAME).where(TOKEN,token).exec(); - while (rs.next()){ + if (rs.next()){ var lm = new ListMember(rs.getString(LIST_EMAIL),rs.getString(USER_EMAIL),rs.getInt(STATE),rs.getString(TOKEN)); + rs.close(); User user = User.loadAll(List.of(lm.userEmail)).stream().findAny().orElse(null); if (user != null){ int newState = lm.state ^ STATE_AWAITING_CONFIRMATION | STATE_SUBSCRIBER; Database.open() .update(TABLE_NAME) - .set(TOKEN,"NULL") + .set(TOKEN,null) .set(STATE, newState) //drop confirmation state, set subscriber state .where(LIST_EMAIL,lm.listEmail) .where(USER_EMAIL,lm.userEmail) diff --git a/src/main/java/de/srsoftware/widerhall/data/User.java b/src/main/java/de/srsoftware/widerhall/data/User.java index 5797683..7c333ca 100644 --- a/src/main/java/de/srsoftware/widerhall/data/User.java +++ b/src/main/java/de/srsoftware/widerhall/data/User.java @@ -56,7 +56,7 @@ public class User { public void addPermission(int newPermission) throws SQLException { permissions |= newPermission; - Database.open().update(TABLE_NAME).set(PERMISSIONS,permissions).run(); + Database.open().update(TABLE_NAME).set(PERMISSIONS,permissions).where(EMAIL,email()).run(); } @@ -84,6 +84,11 @@ public class User { Database.open().query(sql).run(); } + public void dropPermission(int newPermission) throws SQLException { + permissions ^= (permissions & newPermission); + Database.open().update(TABLE_NAME).set(PERMISSIONS,permissions).run(); + } + public boolean hashPermission(int permission){ return (permissions & permission) > 0; } diff --git a/src/main/java/de/srsoftware/widerhall/web/Rest.java b/src/main/java/de/srsoftware/widerhall/web/Rest.java index 81882d2..1d9e059 100644 --- a/src/main/java/de/srsoftware/widerhall/web/Rest.java +++ b/src/main/java/de/srsoftware/widerhall/web/Rest.java @@ -33,10 +33,28 @@ public class Rest extends HttpServlet { private static final String LIST_SHOW = "list/show"; private static final String LIST_TEST = "list/test"; private static final String LIST_SUBSCRIBABLE = "list/subscribable"; + private static final String USER_ADD_PERMISSION = "user/addpermission"; + private static final String USER_DROP_PERMISSION = "user/droppermission"; private static final String USER_LIST = "user/list"; private static final String MEMBERS = "members"; private static final String SUCCESS = "success"; + private Map addPermission(String userEmail, String permissions) { + if (userEmail == null || userEmail.isBlank()) return Map.of(ERROR,"missing user email address!"); + try { + int perm = Integer.parseInt(permissions); + var user = User.loadAll(List.of(userEmail)).stream().findAny().orElse(null); + if (user == null) return Map.of(ERROR,t("Failed to load user for address {}",userEmail)); + user.addPermission(perm); + } catch (NumberFormatException nfe){ + return Map.of(ERROR,"no valid permissions provided!"); + } catch (SQLException e) { + LOG.debug("Failed to load user for address {}",userEmail,e); + return Map.of(ERROR,t("Failed to load user for address {}",userEmail)); + } + return Map.of(SUCCESS,"Updated user permissions"); + } + @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String error = handleGet(req, resp); @@ -49,6 +67,22 @@ public class Rest extends HttpServlet { if (error != null) resp.sendError(400,error); } + private Map dropPermission(String userEmail, String permissions) { + if (userEmail == null || userEmail.isBlank()) return Map.of(ERROR,"missing user email address!"); + try { + int perm = Integer.parseInt(permissions); + var user = User.loadAll(List.of(userEmail)).stream().findAny().orElse(null); + if (user == null) return Map.of(ERROR,t("Failed to load user for address {}",userEmail)); + user.dropPermission(perm); + } catch (NumberFormatException nfe){ + return Map.of(ERROR,"no valid permissions provided!"); + } catch (SQLException e) { + LOG.debug("Failed to load user for address {}",userEmail,e); + return Map.of(ERROR,t("Failed to load user for address {}",userEmail)); + } + return Map.of(SUCCESS,"Updated user permissions"); + } + public String handleGet(HttpServletRequest req, HttpServletResponse resp){ Object o = req.getSession().getAttribute(USER); JSONObject json = new JSONObject(); @@ -102,9 +136,9 @@ public class Rest extends HttpServlet { json.put(USER,user.safeMap()); var listEmail = req.getParameter(LIST); - if (listEmail == null || listEmail.isBlank()) { - json.putAll(Map.of(ERROR,"no list email provided!")); - } else switch (path) { + var userEmail = req.getParameter(EMAIL); + var permissions = req.getParameter(PERMISSIONS); + switch (path) { case LIST_DISABLE: json.putAll(enableList(listEmail,user,false)); break; @@ -123,6 +157,16 @@ public class Rest extends HttpServlet { case LIST_TEST: json.putAll(testList(listEmail,user)); break; + case USER_ADD_PERMISSION: + if (user.hashPermission(User.PERMISSION_ADMIN)){ + json.putAll(addPermission(userEmail,permissions)); + } else json.put(ERROR,"You are not allowed to alter user permissions!"); + break; + case USER_DROP_PERMISSION: + if (user.hashPermission(User.PERMISSION_ADMIN)){ + json.putAll(dropPermission(userEmail,permissions)); + } else json.put(ERROR,"You are not allowed to alter user permissions!"); + break; default: json.put(ERROR,t("No handler for path '{}'!",path)); break; @@ -140,6 +184,7 @@ public class Rest extends HttpServlet { } private Map listMembers(String listEmail, User user) { + if (listEmail == null || listEmail.isBlank()) return Map.of(ERROR,"no list email provided!"); if (user.hashPermission(User.PERMISSION_ADMIN) || ListMember.listsOwnedBy(user).contains(listEmail)) { try { var members = ListMember.of(listEmail) @@ -161,6 +206,7 @@ public class Rest extends HttpServlet { } private Map enableList(String listEmail, User user, boolean enable) { + if (listEmail == null || listEmail.isBlank()) return Map.of(ERROR,"no list email provided!"); if (user.hashPermission(User.PERMISSION_ADMIN) || ListMember.listsOwnedBy(user).contains(listEmail)){ try { MailingList.load(listEmail).enable(enable); @@ -174,6 +220,7 @@ public class Rest extends HttpServlet { } private Map hideList(String listEmail, User user, boolean hide) { + if (listEmail == null || listEmail.isBlank()) return Map.of(ERROR,"no list email provided!"); if (user.hashPermission(User.PERMISSION_ADMIN) || ListMember.listsOwnedBy(user).contains(listEmail)){ try { MailingList.load(listEmail).hide(hide); @@ -188,6 +235,7 @@ public class Rest extends HttpServlet { } private Map testList(String listEmail, User user) { + if (listEmail == null || listEmail.isBlank()) return Map.of(ERROR,"no list email provided!"); try { MailingList.load(listEmail).test(user); return Map.of(SUCCESS,t("Sent test email to {}",user.email())); diff --git a/src/main/java/de/srsoftware/widerhall/web/Web.java b/src/main/java/de/srsoftware/widerhall/web/Web.java index 9f77722..41ddbf2 100644 --- a/src/main/java/de/srsoftware/widerhall/web/Web.java +++ b/src/main/java/de/srsoftware/widerhall/web/Web.java @@ -6,6 +6,7 @@ import de.srsoftware.widerhall.Util; import de.srsoftware.widerhall.data.ListMember; import de.srsoftware.widerhall.data.MailingList; import de.srsoftware.widerhall.data.User; +import org.antlr.runtime.MismatchedTokenException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.stringtemplate.v4.STGroup; @@ -146,8 +147,8 @@ public class Web extends HttpServlet { if (token== null || token.isBlank()) return t("Invalid or missing token!"); var user = ListMember.confirm(token); if (user != null) return loadTemplate(INDEX,Map.of(USER,user.safeMap(),NOTES,"Confirmed list subscription!"),resp); - return t("Unknown user"); - } catch (SQLException e) { + return t("Unknown user or token"); + } catch (Exception e) { LOG.debug("Failed to confirm list membership:",e); return t("Confirmation of list membership failed!"); } @@ -400,7 +401,11 @@ public class Web extends HttpServlet { try { list.requestSubscription(user,skipConfirmation); - data.put(NOTES,t("Successfully subscribed '{}' to '{}'.",user.email(),list.email())); + if (skipConfirmation) { + data.put(NOTES, t("Successfully subscribed '{}' to '{}'.", user.email(), list.email())); + } else { + data.put(NOTES, t("Sent confirmation mail to '{}.", user.email())); + } return loadTemplate(INDEX,data,resp); } catch (SQLException sqle) { LOG.debug("List subscription failed: ",sqle); diff --git a/static/templates/js.st b/static/templates/js.st index 0334c63..2f3a2b1 100644 --- a/static/templates/js.st +++ b/static/templates/js.st @@ -1,3 +1,9 @@ +function addPermission(userEmail,permission){ + if (confirm("Really give permission to "+userEmail+"?")){ + $.post('/api/user/addpermission',{email:userEmail,permissions:permission},reload,'json'); + } +} + function disableList(listEmail){ $.post('/api/list/disable',{list:listEmail},showListResult,'json'); } @@ -6,6 +12,13 @@ function dropList(listEmail){ console.log('dopList('+listEmail+')'); } +function dropPermission(userEmail,permission){ + if (confirm("Really withdraw permission from "+userEmail+"?")){ + $.post('/api/user/droppermission',{email:userEmail,permissions:permission},reload,'json'); + } +} + + function enableList(listEmail){ $.post('/api/list/enable',{list:listEmail},showListResult,'json'); } @@ -55,7 +68,7 @@ function showListOfEditableLists(data){ let select = $('