added new state bits to MailingList, implemented form for editing those
This commit is contained in:
@@ -1,16 +0,0 @@
|
|||||||
<configuration scan="true" scanPeriod="30 seconds" debug="true">
|
|
||||||
<!-- scan="true" enables automatic updates if config file changes, see http://logback.qos.ch/manual/configuration.html -->
|
|
||||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
|
||||||
<encoder>
|
|
||||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{5}: %msg%n
|
|
||||||
</pattern>
|
|
||||||
</encoder>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<root level="WARN">
|
|
||||||
<appender-ref ref="STDOUT" />
|
|
||||||
</root>
|
|
||||||
|
|
||||||
<logger name="de.srsoftware" level="DEBUG" />
|
|
||||||
|
|
||||||
</configuration>
|
|
||||||
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>0.2.13</version>
|
<version>0.2.14</version>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
|||||||
@@ -28,6 +28,13 @@ import static de.srsoftware.widerhall.data.User.PERMISSION_ADMIN;
|
|||||||
* this class encapsulates a MailingList db object
|
* this class encapsulates a MailingList db object
|
||||||
*/
|
*/
|
||||||
public class MailingList implements MessageHandler {
|
public class MailingList implements MessageHandler {
|
||||||
|
public static final String KEY_FORWARD_FROM = "forward_from";
|
||||||
|
public static final String KEY_FORWARD_ATTACHED = "forward_attached";
|
||||||
|
public static final String KEY_HIDE_RECEIVERS = "hide_receivers";
|
||||||
|
public static final String KEY_REPLY_TO_LIST = "reply_to_list";
|
||||||
|
public static final String KEY_OPEN_FOR_GUESTS = "open_for_guests";
|
||||||
|
public static final String KEY_OPEN_FOR_SUBSCRIBERS = "open_for_subscribers";
|
||||||
|
public static final String KEY_ARCHIVE = "archive";
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(MailingList.class);
|
private static final Logger LOG = LoggerFactory.getLogger(MailingList.class);
|
||||||
private static final String IMAP_HOST = "imap_host";
|
private static final String IMAP_HOST = "imap_host";
|
||||||
private static final String IMAP_PORT = "imap_port";
|
private static final String IMAP_PORT = "imap_port";
|
||||||
@@ -47,10 +54,11 @@ public class MailingList implements MessageHandler {
|
|||||||
public static final int STATE_REPLY_TO_LIST = 32; // set REPLY TO field to list address?
|
public static final int STATE_REPLY_TO_LIST = 32; // set REPLY TO field to list address?
|
||||||
public static final int STATE_OPEN_FOR_GUESTS = 64; // allow anyone to send via this list?
|
public static final int STATE_OPEN_FOR_GUESTS = 64; // allow anyone to send via this list?
|
||||||
public static final int STATE_PUBLIC_ARCHIVE = 128; // save received messages in archive?
|
public static final int STATE_PUBLIC_ARCHIVE = 128; // save received messages in archive?
|
||||||
public static final int STATE_OPEN_FOR_MODS = 256; // allow mods to send via this list?
|
public static final int STATE_OPEN_FOR_SUBSCRIBERS = 256; // allow mods to send via this list?
|
||||||
|
public static final int STATE_MODS_CAN_CREATE_MODS = 512; // allow mods to make subscribers to mods?
|
||||||
private static final int VISIBLE = 1;
|
private static final int VISIBLE = 1;
|
||||||
private static final int HIDDEN = 0;
|
private static final int HIDDEN = 0;
|
||||||
private static final int DEFAULT_STATE = STATE_PENDING|STATE_HIDE_RECEIVERS|STATE_PUBLIC_ARCHIVE|STATE_OPEN_FOR_MODS;
|
private static final int DEFAULT_STATE = STATE_PENDING|STATE_HIDE_RECEIVERS|STATE_PUBLIC_ARCHIVE;
|
||||||
private static final String RETAINED_FOLDER = "retained";
|
private static final String RETAINED_FOLDER = "retained";
|
||||||
private final String name;
|
private final String name;
|
||||||
private final String email;
|
private final String email;
|
||||||
@@ -227,6 +235,20 @@ public class MailingList implements MessageHandler {
|
|||||||
return setFlag(STATE_HIDE_RECEIVERS,hide);
|
return setFlag(STATE_HIDE_RECEIVERS,hide);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAllowedSender(String senderEmail){
|
||||||
|
if (senderEmail == null || senderEmail.isBlank()) return false;
|
||||||
|
try {
|
||||||
|
var user = User.load(senderEmail);
|
||||||
|
if (user == null) return this.isOpenForGuests();
|
||||||
|
var member = ListMember.load(this,user);
|
||||||
|
if (member == null) return this.isOpenForGuests();
|
||||||
|
if (member.isModerator()) return true;
|
||||||
|
if (member.isSubscriber()) return this.isOpenForSubscribers();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
LOG.warn("Failed to load User for {}",senderEmail,e);
|
||||||
|
}
|
||||||
|
return this.isOpenForGuests();
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* test, whether the current ML is subscribable by a given user
|
* test, whether the current ML is subscribable by a given user
|
||||||
* @param user
|
* @param user
|
||||||
@@ -244,6 +266,14 @@ public class MailingList implements MessageHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isOpenForGuests(){
|
||||||
|
return hasState(STATE_OPEN_FOR_GUESTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOpenForSubscribers(){
|
||||||
|
return hasState(STATE_OPEN_FOR_GUESTS|STATE_OPEN_FOR_SUBSCRIBERS);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a ML object by it's identifying email address.
|
* Load a ML object by it's identifying email address.
|
||||||
* This is a cached method: if the ML has been loaded before, the already-loaded object will be returned.
|
* This is a cached method: if the ML has been loaded before, the already-loaded object will be returned.
|
||||||
@@ -334,7 +364,7 @@ public class MailingList implements MessageHandler {
|
|||||||
Address from = message.getFrom()[0];
|
Address from = message.getFrom()[0];
|
||||||
if (from instanceof InternetAddress internetAddress){
|
if (from instanceof InternetAddress internetAddress){
|
||||||
var senderEmail = ((InternetAddress) from).getAddress();
|
var senderEmail = ((InternetAddress) from).getAddress();
|
||||||
if (!hasState(STATE_OPEN_FOR_GUESTS) && !this.hashMember(senderEmail)){
|
if (!isAllowedSender(senderEmail)) {
|
||||||
retainMessage(message);
|
retainMessage(message);
|
||||||
sentRetentionNotification(senderEmail);
|
sentRetentionNotification(senderEmail);
|
||||||
return;
|
return;
|
||||||
@@ -344,10 +374,14 @@ public class MailingList implements MessageHandler {
|
|||||||
forward(message);
|
forward(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MailingList open(boolean open) throws SQLException {
|
public MailingList openForGuests(boolean open) throws SQLException {
|
||||||
return setFlag(STATE_OPEN_FOR_GUESTS,open);
|
return setFlag(STATE_OPEN_FOR_GUESTS,open);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MailingList openForSubscribers(boolean open) throws SQLException {
|
||||||
|
return setFlag(STATE_OPEN_FOR_SUBSCRIBERS,open);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* provide the set of mailing lists that are publicy open to subscriptions
|
* provide the set of mailing lists that are publicy open to subscriptions
|
||||||
* @return
|
* @return
|
||||||
@@ -490,7 +524,8 @@ public class MailingList implements MessageHandler {
|
|||||||
if (hasState(STATE_FORWARD_ATTACHED)) map.put("forward_attached",HIDDEN);
|
if (hasState(STATE_FORWARD_ATTACHED)) map.put("forward_attached",HIDDEN);
|
||||||
if (hasState(STATE_HIDE_RECEIVERS)) map.put("hide_receivers",HIDDEN);
|
if (hasState(STATE_HIDE_RECEIVERS)) map.put("hide_receivers",HIDDEN);
|
||||||
if (hasState(STATE_REPLY_TO_LIST)) map.put("reply_to_list",HIDDEN);
|
if (hasState(STATE_REPLY_TO_LIST)) map.put("reply_to_list",HIDDEN);
|
||||||
if (hasState(STATE_OPEN_FOR_GUESTS)) map.put("open",VISIBLE);
|
if (hasState(STATE_OPEN_FOR_GUESTS)) map.put("open_for_guests",HIDDEN);
|
||||||
|
if (hasState(STATE_OPEN_FOR_SUBSCRIBERS)) map.put("open_for_subscribers",HIDDEN);
|
||||||
if (hasState(STATE_PUBLIC_ARCHIVE)) map.put("archive",VISIBLE);
|
if (hasState(STATE_PUBLIC_ARCHIVE)) map.put("archive",VISIBLE);
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import static de.srsoftware.widerhall.Constants.*;
|
import static de.srsoftware.widerhall.Constants.*;
|
||||||
import static de.srsoftware.widerhall.Util.t;
|
import static de.srsoftware.widerhall.Util.t;
|
||||||
|
import static de.srsoftware.widerhall.data.MailingList.*;
|
||||||
|
|
||||||
public class Rest extends HttpServlet {
|
public class Rest extends HttpServlet {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Rest.class);
|
private static final Logger LOG = LoggerFactory.getLogger(Rest.class);
|
||||||
@@ -56,6 +57,19 @@ public class Rest extends HttpServlet {
|
|||||||
return Map.of(SUCCESS,"Updated user permissions");
|
return Map.of(SUCCESS,"Updated user permissions");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<? extends Object> archive(HttpServletRequest req) {
|
||||||
|
var list = Util.getMailingList(req);
|
||||||
|
if (list != null){
|
||||||
|
try {
|
||||||
|
return Post.find(list).stream().map(Post::safeMap).toList();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG.debug("list: {}",list.email());
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
@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 = handleGet(req, resp);
|
||||||
@@ -144,18 +158,7 @@ public class Rest extends HttpServlet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<? extends Object> archive(HttpServletRequest req) {
|
|
||||||
var list = Util.getMailingList(req);
|
|
||||||
if (list != null){
|
|
||||||
try {
|
|
||||||
return Post.find(list).stream().map(Post::safeMap).toList();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG.debug("list: {}",list.email());
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String handlePost(HttpServletRequest req, HttpServletResponse resp){
|
public String handlePost(HttpServletRequest req, HttpServletResponse resp){
|
||||||
|
|
||||||
@@ -232,12 +235,13 @@ public class Rest extends HttpServlet {
|
|||||||
private Map listDetail(MailingList list, User user) {
|
private Map listDetail(MailingList list, User user) {
|
||||||
if (list == null) return Map.of(ERROR,"no list email provided!");
|
if (list == null) return Map.of(ERROR,"no list email provided!");
|
||||||
var map = new HashMap<>();
|
var map = new HashMap<>();
|
||||||
if (list.hasState(MailingList.STATE_FORWARD_FROM)) map.put("forward_from",true);
|
if (list.hasState(MailingList.STATE_FORWARD_FROM)) map.put(KEY_FORWARD_FROM,true);
|
||||||
if (list.hasState(MailingList.STATE_FORWARD_ATTACHED)) map.put("forward_attached",true);
|
if (list.hasState(MailingList.STATE_FORWARD_ATTACHED)) map.put(KEY_FORWARD_ATTACHED,true);
|
||||||
if (list.hasState(MailingList.STATE_HIDE_RECEIVERS)) map.put("hide_receivers",true);
|
if (list.hasState(MailingList.STATE_HIDE_RECEIVERS)) map.put(KEY_HIDE_RECEIVERS,true);
|
||||||
if (list.hasState(MailingList.STATE_REPLY_TO_LIST)) map.put("reply_to_list",true);
|
if (list.hasState(MailingList.STATE_REPLY_TO_LIST)) map.put(KEY_REPLY_TO_LIST,true);
|
||||||
if (list.hasState(MailingList.STATE_OPEN_FOR_GUESTS)) map.put("open",true);
|
if (list.isOpenForGuests()) map.put(KEY_OPEN_FOR_GUESTS,true);
|
||||||
if (list.hasState(MailingList.STATE_PUBLIC_ARCHIVE)) map.put("archive",true);
|
if (list.isOpenForSubscribers()) map.put(KEY_OPEN_FOR_SUBSCRIBERS,true);
|
||||||
|
if (list.hasState(MailingList.STATE_PUBLIC_ARCHIVE)) map.put(KEY_ARCHIVE,true);
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import static de.srsoftware.widerhall.Constants.*;
|
import static de.srsoftware.widerhall.Constants.*;
|
||||||
import static de.srsoftware.widerhall.Util.t;
|
import static de.srsoftware.widerhall.Util.t;
|
||||||
|
import static de.srsoftware.widerhall.data.MailingList.*;
|
||||||
|
|
||||||
public class Web extends TemplateServlet {
|
public class Web extends TemplateServlet {
|
||||||
public static final String WEB_ROOT = "/web";
|
public static final String WEB_ROOT = "/web";
|
||||||
@@ -300,12 +301,13 @@ public class Web extends TemplateServlet {
|
|||||||
|
|
||||||
if (!error){
|
if (!error){
|
||||||
try {
|
try {
|
||||||
list.forwardFrom(Util.getCheckbox(req, "forward_from"))
|
list.forwardFrom(Util.getCheckbox(req, KEY_FORWARD_FROM))
|
||||||
.forwardAttached(Util.getCheckbox(req, "forward_attached"))
|
.forwardAttached(Util.getCheckbox(req, KEY_FORWARD_ATTACHED))
|
||||||
.hideReceivers(Util.getCheckbox(req, "hide_receivers"))
|
.hideReceivers(Util.getCheckbox(req, KEY_HIDE_RECEIVERS))
|
||||||
.replyToList(Util.getCheckbox(req, "reply_to_list"))
|
.replyToList(Util.getCheckbox(req, KEY_REPLY_TO_LIST))
|
||||||
.open(Util.getCheckbox(req,"open"))
|
.openForGuests(Util.getCheckbox(req,KEY_OPEN_FOR_GUESTS))
|
||||||
.archive(Util.getCheckbox(req,"archive"));
|
.openForSubscribers(Util.getCheckbox(req,KEY_OPEN_FOR_SUBSCRIBERS))
|
||||||
|
.archive(Util.getCheckbox(req,KEY_ARCHIVE));
|
||||||
data.put(NOTES,t("Sucessfully updated MailingList!"));
|
data.put(NOTES,t("Sucessfully updated MailingList!"));
|
||||||
} catch (SQLException e){
|
} catch (SQLException e){
|
||||||
LOG.warn("Failed to update MailingList:",e);
|
LOG.warn("Failed to update MailingList:",e);
|
||||||
|
|||||||
@@ -11,6 +11,6 @@
|
|||||||
<appender-ref ref="STDOUT" />
|
<appender-ref ref="STDOUT" />
|
||||||
</root>
|
</root>
|
||||||
|
|
||||||
<logger name="de.srsoftware" level="INFO" />
|
<logger name="de.srsoftware" level="DEBUG" />
|
||||||
|
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -11,37 +11,54 @@
|
|||||||
«userinfo()»
|
«userinfo()»
|
||||||
«messages()»
|
«messages()»
|
||||||
<h1>Widerhall '«data.list»' Details</h1>
|
<h1>Widerhall '«data.list»' Details</h1>
|
||||||
«listmembers()»
|
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Options for «data.list»</legend>
|
<legend>Settings</legend>
|
||||||
<label>
|
<fieldset>
|
||||||
<input type="checkbox" name="forward_from">
|
<legend>Forward permissions</legend>
|
||||||
Forward using original sender
|
<p>
|
||||||
</label>
|
Who is allowed to distribute mails via «data.list»?
|
||||||
<label>
|
</p>
|
||||||
<input type="checkbox" name="reply_to_list">
|
✓ Oweners and Moderators
|
||||||
Set list adddress in "ReplyTo" header
|
<label>
|
||||||
</label>
|
<input type="checkbox" name="open_for_subscribers">
|
||||||
<label>
|
All subscribers
|
||||||
<input type="checkbox" name="open">
|
</label>
|
||||||
Allow non-members to send mails via list (Danger!)
|
<label>
|
||||||
</label>
|
<input type="checkbox" name="open_for_guests">
|
||||||
<label>
|
Everyone (i.e. non members, DANGER!)
|
||||||
<input type="checkbox" name="forward_attached">
|
</label>
|
||||||
Append original message as attachment
|
</fieldset>
|
||||||
</label>
|
<fieldset>
|
||||||
<label>
|
<legend>Forward options</legend>
|
||||||
<input type="checkbox" name="hide_receivers">
|
<label>
|
||||||
Hide receivers (using BCC)
|
<input type="checkbox" name="forward_from">
|
||||||
</label>
|
Forward using original sender
|
||||||
<label>
|
</label>
|
||||||
<input type="checkbox" name="archive">
|
<label>
|
||||||
Collect messages in public archive
|
<input type="checkbox" name="reply_to_list">
|
||||||
</label>
|
Set list adddress in "ReplyTo" header
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="forward_attached">
|
||||||
|
Append original message as attachment
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="hide_receivers">
|
||||||
|
Hide receivers (using BCC)
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Archive options</legend>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="archive">
|
||||||
|
Collect messages in public archive
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
<button type="submit">Save</button>
|
<button type="submit">Save</button>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
|
«listmembers()»
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
loadListDetail('«data.list»');
|
loadListDetail('«data.list»');
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -74,12 +74,11 @@ function showListArchive(data){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function showListDetail(data){
|
function showListDetail(data){
|
||||||
if (data.forward_from) $('input[name="forward_from"]').prop('checked',true);
|
var options = ['forward_from','forward_attached','hide_receivers','reply_to_list','open_for_guests','open_for_subscribers','archive'];
|
||||||
if (data.forward_attached) $('input[name="forward_attached"]').prop('checked',true);
|
options.forEach(function(option,index,array){
|
||||||
if (data.hide_receivers) $('input[name="hide_receivers"]').prop('checked',true);
|
console.log(option,'→',data[option]);
|
||||||
if (data.reply_to_list) $('input[name="reply_to_list"]').prop('checked',true);
|
if (data[option]) $('input[name="'+option+'"]').prop('checked',true);
|
||||||
if (data.open) $('input[name="open"]').prop('checked',true);
|
});
|
||||||
if (data.archive) $('input[name="archive"]').prop('checked',true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function showListOfEditableLists(data){
|
function showListOfEditableLists(data){
|
||||||
|
|||||||
Reference in New Issue
Block a user