diff --git a/pom.xml b/pom.xml index a1ab163..04b7800 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.example Widerhall - 1.0.0 + 1.0.1 diff --git a/src/main/java/de/srsoftware/widerhall/Constants.java b/src/main/java/de/srsoftware/widerhall/Constants.java index fb9396b..cd57c4a 100644 --- a/src/main/java/de/srsoftware/widerhall/Constants.java +++ b/src/main/java/de/srsoftware/widerhall/Constants.java @@ -18,6 +18,8 @@ public class Constants { public static final String LIST = "list"; public static final String LOCATIONS = "locations"; public static final String NAME = "name"; + public static final String MESSAGE_ID = "message_id"; + public static final String MODERATOR = "moderator"; public static final String MONTH = "month"; public static final String NOTES = "notes"; public static final String PASSWORD = "password"; diff --git a/src/main/java/de/srsoftware/widerhall/data/Database.java b/src/main/java/de/srsoftware/widerhall/data/Database.java index b094c95..ae90a9b 100644 --- a/src/main/java/de/srsoftware/widerhall/data/Database.java +++ b/src/main/java/de/srsoftware/widerhall/data/Database.java @@ -169,8 +169,6 @@ public class Database { } } - - @Override protected Request clone() { Request clone = new Request(new StringBuilder(sql)); diff --git a/src/main/java/de/srsoftware/widerhall/data/MailingList.java b/src/main/java/de/srsoftware/widerhall/data/MailingList.java index 3e72621..ffe7afb 100644 --- a/src/main/java/de/srsoftware/widerhall/data/MailingList.java +++ b/src/main/java/de/srsoftware/widerhall/data/MailingList.java @@ -187,7 +187,7 @@ public class MailingList implements MessageHandler, ProblemListener { } private void forward(Message message, Stream members) throws MessagingException { - if (hasState(STATE_PUBLIC_ARCHIVE)) storeMessage(message); + if (hasPublicArchive()) storeMessage(message); String newSender = !hasState(STATE_FORWARD_FROM) ? email() : null; var receivers = members .map(ListMember::user) @@ -238,6 +238,10 @@ public class MailingList implements MessageHandler, ProblemListener { return ml; } + public boolean hasPublicArchive() { + return hasState(STATE_PUBLIC_ARCHIVE); + } + public boolean hasState(int test){ return (state & test) > 0; } @@ -327,6 +331,7 @@ public class MailingList implements MessageHandler, ProblemListener { } public boolean mayBeAlteredBy(User user) { + if (user == null) return false; if (user.hashPermission(PERMISSION_ADMIN)) return true; try { if (ListMember.load(this,user).isModerator()) return true; @@ -602,9 +607,9 @@ public class MailingList implements MessageHandler, ProblemListener { if (hasState(STATE_FORWARD_ATTACHED)) map.put(t("forward_attached"),HIDDEN); if (hasState(STATE_HIDE_RECEIVERS)) map.put(t("hide_receivers"),HIDDEN); if (hasState(STATE_REPLY_TO_LIST)) map.put(t("reply_to_list"),HIDDEN); - if (hasState(STATE_OPEN_FOR_GUESTS)) map.put(t("open_for_guests"),HIDDEN); - if (hasState(STATE_OPEN_FOR_SUBSCRIBERS)) map.put(t("open_for_subscribers"),HIDDEN); - if (hasState(STATE_PUBLIC_ARCHIVE)) map.put(t("archive"),VISIBLE); + if (isOpenForGuests()) map.put(t("open_for_guests"),HIDDEN); + if (isOpenForSubscribers()) map.put(t("open_for_subscribers"),HIDDEN); + if (hasPublicArchive()) map.put(t("archive"),VISIBLE); return map; } diff --git a/src/main/java/de/srsoftware/widerhall/data/Post.java b/src/main/java/de/srsoftware/widerhall/data/Post.java index deee9eb..282ac49 100644 --- a/src/main/java/de/srsoftware/widerhall/data/Post.java +++ b/src/main/java/de/srsoftware/widerhall/data/Post.java @@ -96,7 +96,7 @@ public class Post { return new File(filename); } - public static ArrayList find(MailingList list, String month, List allowedSenders) throws SQLException { + public static ArrayList find(MailingList list, String month, List allowedSenders) throws SQLException { var query = Database.open() .select(TABLE_NAME,"*","strftime('%Y-%m',date/1000,'unixepoch') as month") .where(LIST,list.email()) @@ -140,6 +140,10 @@ public class Post { return id; } + public MailingList list() { + return list; + } + public static Post load(String id) throws SQLException { var rs = Database.open().select(TABLE_NAME).where(ID,id).compile().exec(); try { @@ -160,6 +164,11 @@ public class Post { FILE,filename); } + public void remove() throws SQLException { + Database.open().deleteFrom(TABLE_NAME).where(ID,id).compile().run(); + file().delete(); + } + public Map safeMap() { return Map.of(ID,id, LIST,list.name(), @@ -188,5 +197,4 @@ public class Post { public long timestamp(){ return timestamp; } - } diff --git a/src/main/java/de/srsoftware/widerhall/web/Rest.java b/src/main/java/de/srsoftware/widerhall/web/Rest.java index b406a40..72bc6d4 100644 --- a/src/main/java/de/srsoftware/widerhall/web/Rest.java +++ b/src/main/java/de/srsoftware/widerhall/web/Rest.java @@ -13,6 +13,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.NotAllowedException; import java.io.IOException; import java.sql.SQLException; import java.time.Month; @@ -40,6 +41,7 @@ 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 MAIL_DROP = "mail/drop"; 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"; @@ -62,28 +64,30 @@ public class Rest extends HttpServlet { return Map.of(SUCCESS,"Nutzer-Berechtigungen aktualisiert"); } - private Map archive(MailingList list, String month, User requestingUser){ - if (list != null){ - try { - var allEmails = requestingUser != null || list.hasState(STATE_OPEN_FOR_SUBSCRIBERS) || list.hasState(STATE_OPEN_FOR_GUESTS); - var limitedSenders = allEmails ? null : list.moderators().map(ListMember::user).map(User::email).toList(); - if (month == null || month.isBlank()) { - return Map.of(LIST,list.email(),"summary",Post.summarize(list,limitedSenders)); - } else { - return Map.of(LIST,list.email(),"posts",Post.find(list,month,limitedSenders).stream().map(Post::safeMap).toList()); - } - } catch (SQLException e) { - e.printStackTrace(); - } - } - LOG.debug("list: {}",list.email()); - return Map.of(); + private Map archive(HttpServletRequest req, User user) throws SQLException { + var list = Util.getMailingList(req); + if (list == null) throw new IllegalArgumentException(t("You are trying to access a non-existing list!")); + var allowed = list.hasPublicArchive() || list.mayBeAlteredBy(user); + if (!allowed) throw new IllegalAccessError(t("You are not allowed to access the archive of this list!")); + + var allEmails = user != null || list.hasState(STATE_OPEN_FOR_SUBSCRIBERS) || list.hasState(STATE_OPEN_FOR_GUESTS); + var limitedSenders = allEmails ? null : list.moderators().map(ListMember::user).map(User::email).toList(); + + boolean userIsMod = list.mayBeAlteredBy(user); + String month = req.getParameter(MONTH); + if (month == null || month.isBlank()) return Map.of(LIST,list.email(),MODERATOR,userIsMod,"summary",Post.summarize(list,limitedSenders)); + return Map.of(LIST,list.email(),MODERATOR,userIsMod,"posts",Post.find(list,month,limitedSenders).stream().map(Post::safeMap).toList()); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - String error = handleGet(req, resp); + String error; + try { + error = handleGet(req, resp); + } catch (SQLException e) { + error = e.getMessage(); + } if (error != null) resp.sendError(400,error); } @@ -120,6 +124,21 @@ public class Rest extends HttpServlet { if (error != null) resp.sendError(400,error); } + private Map dropMail(String messageId,User user){ + try { + var message = Post.load(messageId); + if (message == null) return Map.of(ERROR,t("Cannot remove: unknown message id")); + var allowed = message.list().mayBeAlteredBy(user); + if (allowed){ + message.remove(); + return Map.of(SUCCESS,t("Message deleted")); + } + return Map.of(ERROR,t("You are not allowed to remove messages from this list!")); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + private Map dropPermission(String userEmail, String permissions) { if (userEmail == null || userEmail.isBlank()) return Map.of(ERROR,"Nutzer-Emailadresse fehlt!"); try { @@ -148,7 +167,7 @@ public class Rest extends HttpServlet { } } - public String handleGet(HttpServletRequest req, HttpServletResponse resp){ + public String handleGet(HttpServletRequest req, HttpServletResponse resp) throws SQLException { var user = Util.getUser(req); var path = Util.getPath(req); @@ -158,14 +177,7 @@ public class Rest extends HttpServlet { json.put(USER,user.safeMap()); switch (path) { case LIST_ARCHIVE: - var list = Util.getMailingList(req); - try { - var allowed = list.hasState(STATE_PUBLIC_ARCHIVE) || list.moderators().map(ListMember::user).anyMatch(mod -> user.equals(mod)); - if (!allowed) return t("Sie sind nicht berechtigt, das Archiv dieser Liste einzusehen!"); - json.put("archive",archive(list,req.getParameter(MONTH),user)); - } catch (SQLException sqle){ - return sqle.getMessage(); - } + json.put("archive",archive(req,user)); break; case USER_LIST: try { @@ -188,10 +200,7 @@ public class Rest extends HttpServlet { } else { switch (path) { case LIST_ARCHIVE: - var list = Util.getMailingList(req); - var allowed = list.hasState(STATE_PUBLIC_ARCHIVE); - if (!allowed) return t("Diese Liste hat kein öffentliches Archiv!"); - json.put("archive",archive(list,req.getParameter(MONTH),null)); + json.put("archive",archive(req,null)); break; case LIST_SUBSCRIBABLE: json.put("lists", MailingList.subscribable().stream().map(MailingList::minimalMap).toList()); @@ -257,6 +266,10 @@ public class Rest extends HttpServlet { case LIST_TEST: json.putAll(testList(list,user)); break; + case MAIL_DROP: + var messageId = req.getParameter(MESSAGE_ID); + json.putAll(dropMail(messageId,user)); + break; case USER_ADD_PERMISSION: if (user.hashPermission(User.PERMISSION_ADMIN)){ json.putAll(addPermission(userEmail,permissions)); @@ -319,7 +332,7 @@ public class Rest extends HttpServlet { if (list.hasState(MailingList.STATE_REPLY_TO_LIST)) map.put(KEY_REPLY_TO_LIST,true); if (list.isOpenForGuests()) map.put(KEY_OPEN_FOR_GUESTS,true); if (list.isOpenForSubscribers()) map.put(KEY_OPEN_FOR_SUBSCRIBERS,true); - if (list.hasState(MailingList.STATE_PUBLIC_ARCHIVE)) map.put(KEY_ARCHIVE,true); + if (list.hasPublicArchive()) map.put(KEY_ARCHIVE,true); if (list.hasState(STATE_MODS_CAN_EDIT_MODS)) map.put(KEY_MODS_CAN_EDIT_MODS,true); if (list.holdTime() != null) map.put(KEY_DELETE_MESSAGES,list.holdTime()); return map; diff --git a/src/main/java/de/srsoftware/widerhall/web/Web.java b/src/main/java/de/srsoftware/widerhall/web/Web.java index 2835f43..f6d9ec6 100644 --- a/src/main/java/de/srsoftware/widerhall/web/Web.java +++ b/src/main/java/de/srsoftware/widerhall/web/Web.java @@ -134,13 +134,20 @@ public class Web extends TemplateServlet { } } - private String archive(HttpServletRequest req, HttpServletResponse resp) { + private String archive(MailingList list, User user, HttpServletRequest req, HttpServletResponse resp) { + if (list == null) return t("The mailing list you are trying to view does not exist!"); + + var allowed = list.hasPublicArchive() || list.mayBeAlteredBy(user); + if (!allowed) return t("You are not allowed to access the archive of this list"); + var map = new HashMap(); - var list = Util.getMailingList(req); map.put(LIST,list.email()); var month = req.getParameter(MONTH); - if (month != null && !month.isBlank())map.put(MONTH,month); + if (month != null && !month.isBlank()){ + map.put(MONTH,month); + map.put(MODERATOR,list.mayBeAlteredBy(user)); + } return loadTemplate(ARCHIVE,map,resp); } @@ -279,10 +286,9 @@ public class Web extends TemplateServlet { if (user != null) data.put(USER,user.safeMap()); if (list != null) data.put(LIST,list.minimalMap()); - String notes = null; switch (path){ case ARCHIVE: - return archive(req,resp); + return archive(list,user,req,resp); case CONFIRM: return confirm(req,resp); case POST: diff --git a/static/templates/archive.st b/static/templates/archive.st index 7949e9e..66f5fc6 100644 --- a/static/templates/archive.st +++ b/static/templates/archive.st @@ -18,6 +18,9 @@ Datum Absender Betreff + «if (data.moderator)» + Aktionen + «endif»