|
|
|
@ -12,18 +12,30 @@ import java.util.*;
@@ -12,18 +12,30 @@ import java.util.*;
|
|
|
|
|
|
|
|
|
|
import static de.srsoftware.widerhall.Constants.*; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @author Stephan Richter |
|
|
|
|
* This class embodies the ListMembers table |
|
|
|
|
*/ |
|
|
|
|
public class ListMember { |
|
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(ListMember.class); |
|
|
|
|
public static final String TABLE_NAME = "ListMembers"; |
|
|
|
|
public static final int STATE_OWNER = 1; |
|
|
|
|
public static final int STATE_SUBSCRIBER = 2; |
|
|
|
|
public static final int STATE_AWAITING_CONFIRMATION = 4; |
|
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(ListMember.class); |
|
|
|
|
private static final String LIST_EMAIL = "list_email"; |
|
|
|
|
private static final String USER_EMAIL = "user_email"; |
|
|
|
|
private static final String STATE = "state"; |
|
|
|
|
|
|
|
|
|
private final String listEmail,token,userEmail; |
|
|
|
|
private final int state; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* create a new list member object |
|
|
|
|
* @param listEmail |
|
|
|
|
* @param userEmail |
|
|
|
|
* @param state |
|
|
|
|
* @param token |
|
|
|
|
*/ |
|
|
|
|
public ListMember(String listEmail, String userEmail, int state, String token){ |
|
|
|
|
this.listEmail = listEmail; |
|
|
|
|
this.userEmail = userEmail; |
|
|
|
@ -31,10 +43,21 @@ public class ListMember {
@@ -31,10 +43,21 @@ public class ListMember {
|
|
|
|
|
this.token = token; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* tries to confirm the token: |
|
|
|
|
* This method loads the list member, that is assigned with the token. |
|
|
|
|
* If no db entry is found for the token, null is returned. |
|
|
|
|
* If an entry is found, the respective User object is loaded. |
|
|
|
|
* If no User object is assigned, null is returned. |
|
|
|
|
* If a matching User object is present, the member's state is altered from AWAITING_CONFIRMATION to SUBSCRIBER and the token is dropped. |
|
|
|
|
* @param token |
|
|
|
|
* @return |
|
|
|
|
* @throws SQLException |
|
|
|
|
*/ |
|
|
|
|
public static User confirm(String token) throws SQLException { |
|
|
|
|
var rs = Database.open().select(TABLE_NAME).where(TOKEN,token).compile().exec(); |
|
|
|
|
if (rs.next()){ |
|
|
|
|
var lm = new ListMember(rs.getString(LIST_EMAIL),rs.getString(USER_EMAIL),rs.getInt(STATE),rs.getString(TOKEN)); |
|
|
|
|
var lm = ListMember.from(rs); |
|
|
|
|
rs.close(); |
|
|
|
|
User user = User.loadAll(List.of(lm.userEmail)).stream().findAny().orElse(null); |
|
|
|
|
if (user != null){ |
|
|
|
@ -54,6 +77,15 @@ public class ListMember {
@@ -54,6 +77,15 @@ public class ListMember {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Create a new list member entry in the database. |
|
|
|
|
* If the member has the state AWAITING_CONFIRMATION, a token is assigned with the member, too. |
|
|
|
|
* @param list |
|
|
|
|
* @param user |
|
|
|
|
* @param state |
|
|
|
|
* @return |
|
|
|
|
* @throws SQLException |
|
|
|
|
*/ |
|
|
|
|
public static ListMember create(MailingList list, User user, int state) throws SQLException { |
|
|
|
|
String token = null; |
|
|
|
|
if ((state & STATE_AWAITING_CONFIRMATION) > 0){ |
|
|
|
@ -62,6 +94,10 @@ public class ListMember {
@@ -62,6 +94,10 @@ public class ListMember {
|
|
|
|
|
return new ListMember(list.email(),user.email(),state,token).save(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* create the table for ListMember objects |
|
|
|
|
* @throws SQLException |
|
|
|
|
*/ |
|
|
|
|
public static void createTable() throws SQLException { |
|
|
|
|
var sql = new StringBuilder() |
|
|
|
|
.append("CREATE TABLE ").append(TABLE_NAME) |
|
|
|
@ -74,11 +110,35 @@ public class ListMember {
@@ -74,11 +110,35 @@ public class ListMember {
|
|
|
|
|
Database.open().query(sql).compile().run(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* create a new ListMember object from a ResultSet |
|
|
|
|
* @param rs |
|
|
|
|
* @return |
|
|
|
|
* @throws SQLException |
|
|
|
|
*/ |
|
|
|
|
public static ListMember from(ResultSet rs) throws SQLException { |
|
|
|
|
return new ListMember( |
|
|
|
|
rs.getString(LIST_EMAIL), |
|
|
|
|
rs.getString(USER_EMAIL), |
|
|
|
|
rs.getInt(STATE), |
|
|
|
|
rs.getString(TOKEN)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* test, if the current object has a given state |
|
|
|
|
* @param testState |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
public boolean hasState(int testState) { |
|
|
|
|
return (state & testState) > 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* return a set of list emails of MailingLists owned by the given user |
|
|
|
|
* @param user |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
public static Set<String> listsOwnedBy(User user) { |
|
|
|
|
var list = new HashSet<String>(); |
|
|
|
|
try { |
|
|
|
@ -92,6 +152,13 @@ public class ListMember {
@@ -92,6 +152,13 @@ public class ListMember {
|
|
|
|
|
return list; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* load the list member specified by a MailingList and as User object |
|
|
|
|
* @param list |
|
|
|
|
* @param user |
|
|
|
|
* @return |
|
|
|
|
* @throws SQLException |
|
|
|
|
*/ |
|
|
|
|
public static ListMember load(MailingList list,User user) throws SQLException { |
|
|
|
|
var rs = Database |
|
|
|
|
.open() |
|
|
|
@ -101,19 +168,21 @@ public class ListMember {
@@ -101,19 +168,21 @@ public class ListMember {
|
|
|
|
|
.compile() |
|
|
|
|
.exec(); |
|
|
|
|
try { |
|
|
|
|
if (rs.next()) { |
|
|
|
|
return new ListMember(rs.getString(LIST_EMAIL), |
|
|
|
|
rs.getString(USER_EMAIL), |
|
|
|
|
rs.getInt(STATE), |
|
|
|
|
rs.getString(TOKEN)); |
|
|
|
|
} |
|
|
|
|
if (rs.next()) return ListMember.from(rs); |
|
|
|
|
} finally { |
|
|
|
|
rs.close(); |
|
|
|
|
} |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* return a map of User → State for a given MailingList |
|
|
|
|
* @param listEmail |
|
|
|
|
* @return |
|
|
|
|
* @throws SQLException |
|
|
|
|
*/ |
|
|
|
|
public static Map<User,Integer> of(String listEmail) throws SQLException { |
|
|
|
|
// Step 1: create mal USER_EMAIL → STATE for MailingList
|
|
|
|
|
var rs = Database.open() |
|
|
|
|
.select(TABLE_NAME) |
|
|
|
|
.where(LIST_EMAIL,listEmail) |
|
|
|
@ -121,6 +190,8 @@ public class ListMember {
@@ -121,6 +190,8 @@ public class ListMember {
|
|
|
|
|
.exec(); |
|
|
|
|
var temp = new HashMap<String,Integer>(); |
|
|
|
|
while (rs.next()) temp.put(rs.getString(USER_EMAIL),rs.getInt(STATE)); |
|
|
|
|
rs.close(); |
|
|
|
|
// Step 2: map user emails to users
|
|
|
|
|
var result = new HashMap<User,Integer>(); |
|
|
|
|
User.loadAll(temp.keySet()) |
|
|
|
|
.stream() |
|
|
|
@ -128,6 +199,27 @@ public class ListMember {
@@ -128,6 +199,27 @@ public class ListMember {
|
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Save the current ListMember object to the database |
|
|
|
|
* @return |
|
|
|
|
* @throws SQLException |
|
|
|
|
*/ |
|
|
|
|
private ListMember save() throws SQLException { |
|
|
|
|
var req = Database.open() |
|
|
|
|
.insertInto(TABLE_NAME) |
|
|
|
|
.set(LIST_EMAIL,listEmail) |
|
|
|
|
.set(USER_EMAIL,userEmail) |
|
|
|
|
.set(STATE,state); |
|
|
|
|
if (token != null) req.set(TOKEN,token); |
|
|
|
|
req.compile().run(); |
|
|
|
|
return this; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* convert state flag to readable text |
|
|
|
|
* @param state |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
public static String stateText(int state) { |
|
|
|
|
var words = new ArrayList<String>(); |
|
|
|
|
if ((state & STATE_OWNER) > 0) words.add("owner"); |
|
|
|
@ -136,20 +228,20 @@ public class ListMember {
@@ -136,20 +228,20 @@ public class ListMember {
|
|
|
|
|
return String.join(", ",words); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private ListMember save() throws SQLException { |
|
|
|
|
var vals = new HashMap<String,Object>(); |
|
|
|
|
vals.put(LIST_EMAIL,listEmail); |
|
|
|
|
vals.put(USER_EMAIL,userEmail); |
|
|
|
|
vals.put(STATE,state); |
|
|
|
|
if (token != null) vals.put(TOKEN,token); |
|
|
|
|
Database.open().insertInto(TABLE_NAME).values(vals).compile().run(); |
|
|
|
|
return this; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* get the token of the current list member |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
public String token() { |
|
|
|
|
return token; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* unsubscribe a list member |
|
|
|
|
* @param list |
|
|
|
|
* @param user |
|
|
|
|
* @throws SQLException |
|
|
|
|
*/ |
|
|
|
|
public static void unsubscribe(MailingList list, User user) throws SQLException { |
|
|
|
|
var db = Database.open(); |
|
|
|
|
var rs = db.select(TABLE_NAME) |
|
|
|
@ -158,21 +250,9 @@ public class ListMember {
@@ -158,21 +250,9 @@ public class ListMember {
|
|
|
|
|
.compile() |
|
|
|
|
.exec(); |
|
|
|
|
while (rs.next()){ |
|
|
|
|
int state = Util.unset(rs.getInt(STATE),STATE_SUBSCRIBER,STATE_AWAITING_CONFIRMATION); |
|
|
|
|
if (state < 1) { // drop entry
|
|
|
|
|
db.deleteFrom(TABLE_NAME) |
|
|
|
|
.where(LIST_EMAIL,list.email()) |
|
|
|
|
.where(USER_EMAIL,user.email()) |
|
|
|
|
.compile() |
|
|
|
|
.run(); |
|
|
|
|
} else { // update entry: whitdraw subscription
|
|
|
|
|
db.update(TABLE_NAME) |
|
|
|
|
.set(STATE,state) |
|
|
|
|
.where(LIST_EMAIL,list.email()) |
|
|
|
|
.where(USER_EMAIL,user.email()) |
|
|
|
|
.compile() |
|
|
|
|
.run(); |
|
|
|
|
} |
|
|
|
|
int state = Util.unset(rs.getInt(STATE),STATE_SUBSCRIBER,STATE_AWAITING_CONFIRMATION); // drop subscription and awaiting flags
|
|
|
|
|
var req = state < 1 ? db.deleteFrom(TABLE_NAME) : db.update(TABLE_NAME).set(STATE,state).set(TOKEN,null); |
|
|
|
|
req.where(LIST_EMAIL,list.email()).where(USER_EMAIL,user.email()).compile().run(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|