Merge branch 'main' into lang_de
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<groupId>org.example</groupId>
|
<groupId>org.example</groupId>
|
||||||
<artifactId>Widerhall</artifactId>
|
<artifactId>Widerhall</artifactId>
|
||||||
<version>1.0.0</version>
|
<version>1.0.1</version>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ public class Constants {
|
|||||||
public static final String LIST = "list";
|
public static final String LIST = "list";
|
||||||
public static final String LOCATIONS = "locations";
|
public static final String LOCATIONS = "locations";
|
||||||
public static final String NAME = "name";
|
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 MONTH = "month";
|
||||||
public static final String NOTES = "notes";
|
public static final String NOTES = "notes";
|
||||||
public static final String PASSWORD = "password";
|
public static final String PASSWORD = "password";
|
||||||
|
|||||||
@@ -169,8 +169,6 @@ public class Database {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Request clone() {
|
protected Request clone() {
|
||||||
Request clone = new Request(new StringBuilder(sql));
|
Request clone = new Request(new StringBuilder(sql));
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ public class MailingList implements MessageHandler, ProblemListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void forward(Message message, Stream<ListMember> members) throws MessagingException {
|
private void forward(Message message, Stream<ListMember> members) throws MessagingException {
|
||||||
if (hasState(STATE_PUBLIC_ARCHIVE)) storeMessage(message);
|
if (hasPublicArchive()) storeMessage(message);
|
||||||
String newSender = !hasState(STATE_FORWARD_FROM) ? email() : null;
|
String newSender = !hasState(STATE_FORWARD_FROM) ? email() : null;
|
||||||
var receivers = members
|
var receivers = members
|
||||||
.map(ListMember::user)
|
.map(ListMember::user)
|
||||||
@@ -238,6 +238,10 @@ public class MailingList implements MessageHandler, ProblemListener {
|
|||||||
return ml;
|
return ml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasPublicArchive() {
|
||||||
|
return hasState(STATE_PUBLIC_ARCHIVE);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasState(int test){
|
public boolean hasState(int test){
|
||||||
return (state & test) > 0;
|
return (state & test) > 0;
|
||||||
}
|
}
|
||||||
@@ -327,6 +331,7 @@ public class MailingList implements MessageHandler, ProblemListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean mayBeAlteredBy(User user) {
|
public boolean mayBeAlteredBy(User user) {
|
||||||
|
if (user == null) return false;
|
||||||
if (user.hashPermission(PERMISSION_ADMIN)) return true;
|
if (user.hashPermission(PERMISSION_ADMIN)) return true;
|
||||||
try {
|
try {
|
||||||
if (ListMember.load(this,user).isModerator()) return true;
|
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_FORWARD_ATTACHED)) map.put(t("forward_attached"),HIDDEN);
|
||||||
if (hasState(STATE_HIDE_RECEIVERS)) map.put(t("hide_receivers"),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_REPLY_TO_LIST)) map.put(t("reply_to_list"),HIDDEN);
|
||||||
if (hasState(STATE_OPEN_FOR_GUESTS)) map.put(t("open_for_guests"),HIDDEN);
|
if (isOpenForGuests()) map.put(t("open_for_guests"),HIDDEN);
|
||||||
if (hasState(STATE_OPEN_FOR_SUBSCRIBERS)) map.put(t("open_for_subscribers"),HIDDEN);
|
if (isOpenForSubscribers()) map.put(t("open_for_subscribers"),HIDDEN);
|
||||||
if (hasState(STATE_PUBLIC_ARCHIVE)) map.put(t("archive"),VISIBLE);
|
if (hasPublicArchive()) map.put(t("archive"),VISIBLE);
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ public class Post {
|
|||||||
return new File(filename);
|
return new File(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayList<Post> find(MailingList list, String month, List<String> allowedSenders) throws SQLException {
|
public static ArrayList<Post> find(MailingList list, String month, List<String> allowedSenders) throws SQLException {
|
||||||
var query = Database.open()
|
var query = Database.open()
|
||||||
.select(TABLE_NAME,"*","strftime('%Y-%m',date/1000,'unixepoch') as month")
|
.select(TABLE_NAME,"*","strftime('%Y-%m',date/1000,'unixepoch') as month")
|
||||||
.where(LIST,list.email())
|
.where(LIST,list.email())
|
||||||
@@ -140,6 +140,10 @@ public class Post {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MailingList list() {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
public static Post load(String id) throws SQLException {
|
public static Post load(String id) throws SQLException {
|
||||||
var rs = Database.open().select(TABLE_NAME).where(ID,id).compile().exec();
|
var rs = Database.open().select(TABLE_NAME).where(ID,id).compile().exec();
|
||||||
try {
|
try {
|
||||||
@@ -160,6 +164,11 @@ public class Post {
|
|||||||
FILE,filename);
|
FILE,filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void remove() throws SQLException {
|
||||||
|
Database.open().deleteFrom(TABLE_NAME).where(ID,id).compile().run();
|
||||||
|
file().delete();
|
||||||
|
}
|
||||||
|
|
||||||
public Map<String,Object> safeMap() {
|
public Map<String,Object> safeMap() {
|
||||||
return Map.of(ID,id,
|
return Map.of(ID,id,
|
||||||
LIST,list.name(),
|
LIST,list.name(),
|
||||||
@@ -188,5 +197,4 @@ public class Post {
|
|||||||
public long timestamp(){
|
public long timestamp(){
|
||||||
return timestamp;
|
return timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import javax.servlet.ServletException;
|
|||||||
import javax.servlet.http.HttpServlet;
|
import javax.servlet.http.HttpServlet;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.ws.rs.NotAllowedException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.time.Month;
|
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_SHOW = "list/show";
|
||||||
private static final String LIST_TEST = "list/test";
|
private static final String LIST_TEST = "list/test";
|
||||||
private static final String LIST_SUBSCRIBABLE = "list/subscribable";
|
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_ADD_PERMISSION = "user/addpermission";
|
||||||
private static final String USER_DROP_PERMISSION = "user/droppermission";
|
private static final String USER_DROP_PERMISSION = "user/droppermission";
|
||||||
private static final String USER_LIST = "user/list";
|
private static final String USER_LIST = "user/list";
|
||||||
@@ -62,28 +64,30 @@ public class Rest extends HttpServlet {
|
|||||||
return Map.of(SUCCESS,"Nutzer-Berechtigungen aktualisiert");
|
return Map.of(SUCCESS,"Nutzer-Berechtigungen aktualisiert");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String,Object> 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()) {
|
private Map<String,Object> archive(HttpServletRequest req, User user) throws SQLException {
|
||||||
return Map.of(LIST,list.email(),"summary",Post.summarize(list,limitedSenders));
|
var list = Util.getMailingList(req);
|
||||||
} else {
|
if (list == null) throw new IllegalArgumentException(t("You are trying to access a non-existing list!"));
|
||||||
return Map.of(LIST,list.email(),"posts",Post.find(list,month,limitedSenders).stream().map(Post::safeMap).toList());
|
var allowed = list.hasPublicArchive() || list.mayBeAlteredBy(user);
|
||||||
}
|
if (!allowed) throw new IllegalAccessError(t("You are not allowed to access the archive of this list!"));
|
||||||
} catch (SQLException e) {
|
|
||||||
e.printStackTrace();
|
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();
|
||||||
}
|
|
||||||
LOG.debug("list: {}",list.email());
|
boolean userIsMod = list.mayBeAlteredBy(user);
|
||||||
return Map.of();
|
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
|
@Override
|
||||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
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);
|
if (error != null) resp.sendError(400,error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,6 +124,21 @@ public class Rest extends HttpServlet {
|
|||||||
if (error != null) resp.sendError(400,error);
|
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) {
|
private Map dropPermission(String userEmail, String permissions) {
|
||||||
if (userEmail == null || userEmail.isBlank()) return Map.of(ERROR,"Nutzer-Emailadresse fehlt!");
|
if (userEmail == null || userEmail.isBlank()) return Map.of(ERROR,"Nutzer-Emailadresse fehlt!");
|
||||||
try {
|
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 user = Util.getUser(req);
|
||||||
var path = Util.getPath(req);
|
var path = Util.getPath(req);
|
||||||
|
|
||||||
@@ -158,14 +177,7 @@ public class Rest extends HttpServlet {
|
|||||||
json.put(USER,user.safeMap());
|
json.put(USER,user.safeMap());
|
||||||
switch (path) {
|
switch (path) {
|
||||||
case LIST_ARCHIVE:
|
case LIST_ARCHIVE:
|
||||||
var list = Util.getMailingList(req);
|
json.put("archive",archive(req,user));
|
||||||
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();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case USER_LIST:
|
case USER_LIST:
|
||||||
try {
|
try {
|
||||||
@@ -188,10 +200,7 @@ public class Rest extends HttpServlet {
|
|||||||
} else {
|
} else {
|
||||||
switch (path) {
|
switch (path) {
|
||||||
case LIST_ARCHIVE:
|
case LIST_ARCHIVE:
|
||||||
var list = Util.getMailingList(req);
|
json.put("archive",archive(req,null));
|
||||||
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));
|
|
||||||
break;
|
break;
|
||||||
case LIST_SUBSCRIBABLE:
|
case LIST_SUBSCRIBABLE:
|
||||||
json.put("lists", MailingList.subscribable().stream().map(MailingList::minimalMap).toList());
|
json.put("lists", MailingList.subscribable().stream().map(MailingList::minimalMap).toList());
|
||||||
@@ -257,6 +266,10 @@ public class Rest extends HttpServlet {
|
|||||||
case LIST_TEST:
|
case LIST_TEST:
|
||||||
json.putAll(testList(list,user));
|
json.putAll(testList(list,user));
|
||||||
break;
|
break;
|
||||||
|
case MAIL_DROP:
|
||||||
|
var messageId = req.getParameter(MESSAGE_ID);
|
||||||
|
json.putAll(dropMail(messageId,user));
|
||||||
|
break;
|
||||||
case USER_ADD_PERMISSION:
|
case USER_ADD_PERMISSION:
|
||||||
if (user.hashPermission(User.PERMISSION_ADMIN)){
|
if (user.hashPermission(User.PERMISSION_ADMIN)){
|
||||||
json.putAll(addPermission(userEmail,permissions));
|
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.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.isOpenForGuests()) map.put(KEY_OPEN_FOR_GUESTS,true);
|
||||||
if (list.isOpenForSubscribers()) map.put(KEY_OPEN_FOR_SUBSCRIBERS,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.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());
|
if (list.holdTime() != null) map.put(KEY_DELETE_MESSAGES,list.holdTime());
|
||||||
return map;
|
return map;
|
||||||
|
|||||||
@@ -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<String,Object>();
|
var map = new HashMap<String,Object>();
|
||||||
var list = Util.getMailingList(req);
|
|
||||||
map.put(LIST,list.email());
|
map.put(LIST,list.email());
|
||||||
|
|
||||||
var month = req.getParameter(MONTH);
|
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);
|
return loadTemplate(ARCHIVE,map,resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,10 +286,9 @@ public class Web extends TemplateServlet {
|
|||||||
|
|
||||||
if (user != null) data.put(USER,user.safeMap());
|
if (user != null) data.put(USER,user.safeMap());
|
||||||
if (list != null) data.put(LIST,list.minimalMap());
|
if (list != null) data.put(LIST,list.minimalMap());
|
||||||
String notes = null;
|
|
||||||
switch (path){
|
switch (path){
|
||||||
case ARCHIVE:
|
case ARCHIVE:
|
||||||
return archive(req,resp);
|
return archive(list,user,req,resp);
|
||||||
case CONFIRM:
|
case CONFIRM:
|
||||||
return confirm(req,resp);
|
return confirm(req,resp);
|
||||||
case POST:
|
case POST:
|
||||||
|
|||||||
@@ -18,6 +18,9 @@
|
|||||||
<th>Datum</th>
|
<th>Datum</th>
|
||||||
<th>Absender</th>
|
<th>Absender</th>
|
||||||
<th>Betreff</th>
|
<th>Betreff</th>
|
||||||
|
«if (data.moderator)»
|
||||||
|
<th>Aktionen</th>
|
||||||
|
«endif»
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ function dropList(listEmail){
|
|||||||
$.post('/api/list/drop',{list:listEmail},showListResult,'json');
|
$.post('/api/list/drop',{list:listEmail},showListResult,'json');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function dropMail(mailId){
|
||||||
|
$.post('/api/mail/drop',{message_id:mailId},showListResult,'json');
|
||||||
|
}
|
||||||
|
|
||||||
function dropMember(userEmail,listEmail){
|
function dropMember(userEmail,listEmail){
|
||||||
$.post('/api/list/drop_member',{list:listEmail,email:userEmail},reload,'json');
|
$.post('/api/list/drop_member',{list:listEmail,email:userEmail},reload,'json');
|
||||||
}
|
}
|
||||||
@@ -78,6 +82,8 @@ function showList(listEmail){
|
|||||||
|
|
||||||
function showListArchive(data){
|
function showListArchive(data){
|
||||||
console.log(data);
|
console.log(data);
|
||||||
|
let moderator = data.archive.moderator;
|
||||||
|
console.log('moderator: ',moderator);
|
||||||
let posts = data.archive.posts;
|
let posts = data.archive.posts;
|
||||||
for (let time in posts){
|
for (let time in posts){
|
||||||
let post = posts[time];
|
let post = posts[time];
|
||||||
@@ -86,6 +92,9 @@ function showListArchive(data){
|
|||||||
$('<td/>').html('<a href="'+url+'">'+post.date+'</a>').appendTo(row);
|
$('<td/>').html('<a href="'+url+'">'+post.date+'</a>').appendTo(row);
|
||||||
$('<td/>').html('<a href="'+url+'">'+post.from_name+'</a>').appendTo(row);
|
$('<td/>').html('<a href="'+url+'">'+post.from_name+'</a>').appendTo(row);
|
||||||
$('<td/>').html('<a href="'+url+'">'+post.subject+'</a>').appendTo(row);
|
$('<td/>').html('<a href="'+url+'">'+post.subject+'</a>').appendTo(row);
|
||||||
|
if (moderator){
|
||||||
|
$('<button/>',{onclick:"dropMail('"+post.id+"');"}).text('Delete').appendTo($('<td/>')).appendTo(row);
|
||||||
|
}
|
||||||
row.appendTo($('#archive table'));
|
row.appendTo($('#archive table'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user