Browse Source

implemented transfer of list ownership. this resolves #4

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
main
Stephan Richter 7 months ago
parent
commit
fa265f14b2
  1. 45
      src/main/java/de/srsoftware/widerhall/data/MailingList.java
  2. 5
      src/main/java/de/srsoftware/widerhall/data/User.java
  3. 8
      src/main/java/de/srsoftware/widerhall/web/Rest.java
  4. 25
      static/templates/js.st

45
src/main/java/de/srsoftware/widerhall/data/MailingList.java

@ -22,6 +22,7 @@ import java.util.stream.Stream;
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.ListMember.*;
import static de.srsoftware.widerhall.data.User.PERMISSION_ADMIN; import static de.srsoftware.widerhall.data.User.PERMISSION_ADMIN;
/** /**
@ -268,7 +269,7 @@ public class MailingList implements MessageHandler, ProblemListener {
if (user == null) return false; if (user == null) return false;
try { try {
var member = ListMember.load(this,user); var member = ListMember.load(this,user);
return member.hasState(ListMember.STATE_OWNER|ListMember.STATE_SUBSCRIBER); // owners may subscribe their own mailing lists return member.hasState(STATE_OWNER|STATE_SUBSCRIBER); // owners may subscribe their own mailing lists
} catch (SQLException e) { } catch (SQLException e) {
LOG.warn("Was not able to load ListMember:",e); LOG.warn("Was not able to load ListMember:",e);
return false; return false;
@ -283,6 +284,16 @@ public class MailingList implements MessageHandler, ProblemListener {
return hasState(STATE_OPEN_FOR_GUESTS|STATE_OPEN_FOR_SUBSCRIBERS); return hasState(STATE_OPEN_FOR_GUESTS|STATE_OPEN_FOR_SUBSCRIBERS);
} }
public boolean isOwnedBy(User user) {
if (user == null) return false;
try {
if (ListMember.load(this,user).isOwner()) return true;
} catch (SQLException e) {
LOG.debug("Error loading list member for ({}, {})",user.email(),email());
}
return false;
}
public static List<MailingList> listActive() { public static List<MailingList> listActive() {
try { try {
var list = new ArrayList<MailingList>(); var list = new ArrayList<MailingList>();
@ -505,10 +516,6 @@ public class MailingList implements MessageHandler, ProblemListener {
return list; return list;
} }
public Stream<ListMember> owners() throws SQLException {
return members().filter(ListMember::isOwner);
}
public MailingList replyToList(boolean on) throws SQLException { public MailingList replyToList(boolean on) throws SQLException {
return setFlag(STATE_REPLY_TO_LIST,on); return setFlag(STATE_REPLY_TO_LIST,on);
} }
@ -678,7 +685,7 @@ public class MailingList implements MessageHandler, ProblemListener {
* @throws MessagingException * @throws MessagingException
*/ */
public void requestSubscription(User user, boolean skipConfirmation, ST template) throws SQLException, MessagingException { public void requestSubscription(User user, boolean skipConfirmation, ST template) throws SQLException, MessagingException {
var state = skipConfirmation ? ListMember.STATE_SUBSCRIBER : ListMember.STATE_AWAITING_CONFIRMATION; var state = skipConfirmation ? STATE_SUBSCRIBER : STATE_AWAITING_CONFIRMATION;
var member = ListMember.create(this,user,state); var member = ListMember.create(this,user,state);
if (skipConfirmation) return; if (skipConfirmation) return;
try { try {
@ -742,6 +749,32 @@ public class MailingList implements MessageHandler, ProblemListener {
} }
} }
public String transfer(User owner, String newOwnerMail) {
User newOwner;
try {
newOwner = User.load(newOwnerMail);
} catch (SQLException e) {
return t("Failed to load user for address {}",newOwnerMail);
}
ListMember member;
try {
member = ListMember.load(this,newOwner);
} catch (SQLException e) {
return t("{} is not a member of {}",newOwner);
}
try {
member.setState(STATE_OWNER);
} catch (SQLException e) {
return t("Failed to transfer list ownership to {}",newOwner);
}
try {
ListMember.load(this,owner).setState(STATE_MODERATOR);
} catch (SQLException e) {
return t("Failed to withdraw ownership from {}",owner);
}
return null;
}
public void update(String name, String email, String imapHost, Integer imapPort, String imapUser, String imapPass, String inbox, String smtpHost, Integer smtpPort, String smtpUser, String smtpPass) throws SQLException { public void update(String name, String email, String imapHost, Integer imapPort, String imapUser, String imapPass, String inbox, String smtpHost, Integer smtpPort, String smtpUser, String smtpPass) throws SQLException {
imap.stop(); imap.stop();
Database.open() Database.open()

5
src/main/java/de/srsoftware/widerhall/data/User.java

@ -326,4 +326,9 @@ public class User {
public String token() { public String token() {
return token; return token;
} }
@Override
public String toString() {
return name == null ? email : name;
}
} }

8
src/main/java/de/srsoftware/widerhall/web/Rest.java

@ -18,6 +18,7 @@ import java.sql.SQLException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
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;
@ -40,6 +41,7 @@ public class Rest extends HttpServlet {
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 MAIL_DROP = "mail/drop";
private static final String TRANSFER = "list/transfer";
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";
@ -267,6 +269,11 @@ public class Rest extends HttpServlet {
var messageId = req.getParameter(MESSAGE_ID); var messageId = req.getParameter(MESSAGE_ID);
json.putAll(dropMail(messageId,user)); json.putAll(dropMail(messageId,user));
break; break;
case TRANSFER:
if (list.isOwnedBy(user)){
Optional.ofNullable(list.transfer(user,userEmail)).ifPresent(err -> json.put(ERROR,err));
} else json.put(ERROR,t("As you don't own this list, you may not transfer its ownership!"));
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));
@ -286,6 +293,7 @@ public class Rest extends HttpServlet {
} }
try { try {
resp.setContentType("application/json"); resp.setContentType("application/json");
if (json.containsKey(ERROR)) resp.setStatus(404);
resp.getWriter().println(json.toJSONString()); resp.getWriter().println(json.toJSONString());
return null; return null;
} catch (IOException e) { } catch (IOException e) {

25
static/templates/js.st

@ -211,6 +211,11 @@ function showListResult(result){
function showMembers(data){ function showMembers(data){
var list_mail = data.list.email.prefix+'@'+data.list.email.domain; var list_mail = data.list.email.prefix+'@'+data.list.email.domain;
console.log("data",data);
var owner = false;
for (let member of data.members){
if (member.email == data.user.email && member.state.includes("owner")) owner = member.email;
}
for (let i in data.members){ for (let i in data.members){
let member = data.members[i]; let member = data.members[i];
let row = $('<tr/>'); let row = $('<tr/>');
@ -218,11 +223,17 @@ function showMembers(data){
$('<td/>').text(member.email).appendTo(row); $('<td/>').text(member.email).appendTo(row);
$('<td/>').text(member.state).appendTo(row); $('<td/>').text(member.state).appendTo(row);
let col = $('<td/>'); let col = $('<td/>');
console.log("data",data);
if (member.state.includes("moderator")) { if (member.state.includes("moderator")) {
if (!member.state.includes("owner")) $('<button/>',{onclick:'dropMod("'+member.email+'","'+list_mail+'")'}).text("- moderator").appendTo(col); if (member.email != owner){
} else $('<button/>',{onclick:'addMod("'+member.email+'","'+list_mail+'")'}).text("+ moderator").appendTo(col); $('<button/>',{onclick:'dropMod("'+member.email+'","'+list_mail+'")'}).text("- moderator").appendTo(col);
if (!member.state.includes("owner")) $('<button/>',{onclick:'dropMember("'+member.email+'","'+list_mail+'")'}).text("remove").appendTo(col); if (data.user.email == owner) $('<button/>',{onclick:'transfer("'+member.email+'","'+list_mail+'")'}).text("transfer ownership").appendTo(col);
}
} else {
$('<button/>',{onclick:'addMod("'+member.email+'","'+list_mail+'")'}).text("+ moderator").appendTo(col);
}
if (!member.state.includes("owner")) {
$('<button/>',{onclick:'dropMember("'+member.email+'","'+list_mail+'")'}).text("remove").appendTo(col);
}
col.appendTo(row); col.appendTo(row);
row.appendTo('#memberlist'); row.appendTo('#memberlist');
@ -273,6 +284,12 @@ function testList(listEmail){
$.post('/api/list/test',{list:listEmail},showListResult,'json'); $.post('/api/list/test',{list:listEmail},showListResult,'json');
} }
function transfer(newOwner,listEmail){
if (confirm("Really transfer "+listEmail+" to "+newOwner+"?")){
$.post('/api/list/transfer',{email:newOwner,list:listEmail},reload,'json');
}
}
function unsubscribeFrom(listEmail){ function unsubscribeFrom(listEmail){
window.location.href='unsubscribe?list='+listEmail; window.location.href='unsubscribe?list='+listEmail;
} }

Loading…
Cancel
Save