working on confirmed subscription

This commit is contained in:
2022-04-18 09:34:31 +02:00
parent e2bba174ee
commit 2b59c7ab96
9 changed files with 232 additions and 99 deletions

View File

@@ -1,9 +1,12 @@
package de.srsoftware.widerhall.data;
import de.srsoftware.widerhall.Configuration;
import de.srsoftware.widerhall.mail.SmtpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.crypto.Data;
import javax.mail.MessagingException;
import java.io.UnsupportedEncodingException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
@@ -11,6 +14,7 @@ import java.util.List;
import java.util.Map;
import static de.srsoftware.widerhall.Constants.*;
import static de.srsoftware.widerhall.Util.t;
public class MailingList {
private static final Logger LOG = LoggerFactory.getLogger(MailingList.class);
@@ -22,13 +26,17 @@ public class MailingList {
private static final String SMTP_PORT = "smtp_port";
private static final String SMTP_USER = "smtp_user";
private static final String SMTP_PASS = "smtp_pass";
private static final int ENABLED = 1;
private static final int PUBLIC = 2;
private static final int STATE_PENDING = 0;
private static final int STATE_ENABLED = 1;
private static final int STATE_PUBLIC = 2;
private final String name;
private final String email;
public static final String TABLE_NAME = "Lists";
private final String imapPass, smtpPass, imapHost, smtpHost, imapUser, smtpUser;
private final int imapPort, smtpPort, state;
private final String imapPass, imapHost, imapUser;
private final int imapPort, state;
private final SmtpClient smtp;
private static final HashMap<String,MailingList> lists = new HashMap<>();
public MailingList(String email, String name, String imapHost, int imapPort, String imapUser, String imapPass, String smtpHost, int smtpPort, String smtpUser, String smtpPass, int state) {
this.email = email;
@@ -37,15 +45,12 @@ public class MailingList {
this.imapPort = imapPort;
this.imapUser = imapUser;
this.imapPass = imapPass;
this.smtpHost = smtpHost;
this.smtpPort = smtpPort;
this.smtpUser = smtpUser;
this.smtpPass = smtpPass;
this.state = state;
this.smtp = new SmtpClient(smtpHost,smtpPort,smtpUser,smtpPass);
}
public static MailingList create(String email, String name, String imapHost, int imapPort, String imapUser, String imapPass, String smtpHost, int smtpPort, String smtpUser, String smtpPass) throws SQLException {
return new MailingList(email, name, imapHost, imapPort, imapUser, imapPass, smtpHost, smtpPort, smtpUser, smtpPass, ENABLED).save();
return new MailingList(email, name, imapHost, imapPort, imapUser, imapPass, smtpHost, smtpPort, smtpUser, smtpPass, STATE_PENDING).save();
}
public static void createTable() throws SQLException {
@@ -67,18 +72,28 @@ public class MailingList {
Database.open().query(sql).run();
}
public String email() {
return email;
}
public static void enable(String listEmail, boolean enable) throws SQLException {
// https://stackoverflow.com/questions/16440831/bitwise-xor-in-sqlite-bitwise-not-not-working-as-i-expect
String expression = enable ? "state = state | "+ENABLED : "state = (~(state & "+ENABLED+"))&(state|"+ENABLED+")";
String expression = enable ? "state = state | "+ STATE_ENABLED : "state = (~(state & "+ STATE_ENABLED +"))&(state|"+ STATE_ENABLED +")";
Database.open().update(TABLE_NAME,expression).where(EMAIL, listEmail).run();
}
public static void hide(String listEmail, boolean hide) throws SQLException {
// https://stackoverflow.com/questions/16440831/bitwise-xor-in-sqlite-bitwise-not-not-working-as-i-expect
String expression = hide ? "state = (~(state & "+PUBLIC+"))&(state|"+PUBLIC+")" : ("state = state | "+PUBLIC);
String expression = hide ? "state = (~(state & "+ STATE_PUBLIC +"))&(state|"+ STATE_PUBLIC +")" : ("state = state | "+ STATE_PUBLIC);
Database.open().update(TABLE_NAME,expression).where(EMAIL, listEmail).run();
}
public static boolean isOpen(String list) {
return openLists().stream().filter(ml -> ml.email.equals(list)).count() > 0;
}
public static List<MailingList> listsOf(User user) {
List<String> keys = (user.is(ADMIN)) ? null : ListMember.listsOwnedBy(user);
@@ -108,12 +123,44 @@ public class MailingList {
return list;
}
public static MailingList load(String listEmail) {
var ml = lists.get(listEmail);
if (ml == null) try {
var rs = Database.open()
.select(TABLE_NAME)
.where(EMAIL,listEmail)
.exec();
if (rs.next()){
ml = new MailingList(rs.getString(EMAIL),
rs.getString(NAME),
rs.getString(IMAP_HOST),
rs.getInt(IMAP_PORT),
rs.getString(IMAP_USER),
rs.getString(IMAP_PASS),
rs.getString(SMTP_HOST),
rs.getInt(SMTP_PORT),
rs.getString(SMTP_USER),
rs.getString(SMTP_PASS),
rs.getInt(STATE));
lists.put(listEmail,ml);
}
} catch (SQLException e) {
LOG.debug("Failed to load MailingList: ",e);
}
return ml;
}
public String name(){
return name;
}
public static List<MailingList> openLists() {
var list = new ArrayList<MailingList>();
try {
var rs = Database.open()
.select(TABLE_NAME,"*", "(" + STATE + " & " + PUBLIC + ") as test")
.where("test", PUBLIC)
.select(TABLE_NAME,"*", "(" + STATE + " & " + STATE_PUBLIC + ") as test")
.where("test", STATE_PUBLIC)
.exec();
while (rs.next()) {
var email = rs.getString(EMAIL);
@@ -127,34 +174,6 @@ public class MailingList {
return list;
}
public static boolean isOpen(String list) {
return openLists().stream().filter(ml -> ml.email.equals(list)).count() > 0;
}
public static MailingList load(String listEmail) {
try {
var rs = Database.open()
.select(TABLE_NAME)
.where(EMAIL,listEmail)
.exec();
if (rs.next()){
return new MailingList(rs.getString(EMAIL),
rs.getString(NAME),
rs.getString(IMAP_HOST),
rs.getInt(IMAP_PORT),
rs.getString(IMAP_USER),
rs.getString(IMAP_PASS),
rs.getString(SMTP_HOST),
rs.getInt(SMTP_PORT),
rs.getString(SMTP_USER),
rs.getString(SMTP_PASS),
rs.getInt(STATE));
}
} catch (SQLException e) {
LOG.debug("Failed to load MailingList: ",e);
}
return null;
}
public Map<String, Object> safeMap() {
var map = new HashMap<String,Object>();
@@ -164,19 +183,14 @@ public class MailingList {
if (imapHost != null) map.put(IMAP_HOST, imapHost);
if (imapPort != 0) map.put(IMAP_PORT, imapPort);
if (imapUser != null) map.put(IMAP_USER, imapUser);
if (smtpHost != null) map.put(SMTP_HOST, smtpHost);
if (smtpPort != 0) map.put(SMTP_PORT, smtpPort);
if (smtpUser != null) map.put(SMTP_USER, smtpUser);
if (smtp.host() != null) map.put(SMTP_HOST, smtp.host());
if (smtp.port() != 0) map.put(SMTP_PORT, smtp.port());
if (smtp.username() != null) map.put(SMTP_USER, smtp.username());
map.put(STATE, stateString(state));
return map;
}
private static String stateString(int state) {
var states = new ArrayList<String>();
states.add((state & ENABLED) == ENABLED ? "enabled" : "disabled");
states.add((state & PUBLIC) == PUBLIC ? "public" : "hidden");
return String.join(", ", states);
}
private MailingList save() throws SQLException {
Database.open().insertInto(TABLE_NAME)
@@ -187,16 +201,44 @@ public class MailingList {
Map.entry(IMAP_PORT, imapPort),
Map.entry(IMAP_USER, imapUser),
Map.entry(IMAP_PASS, imapPass),
Map.entry(SMTP_HOST, smtpHost),
Map.entry(SMTP_PORT, smtpPort),
Map.entry(SMTP_USER, smtpUser),
Map.entry(SMTP_PASS, smtpPass),
Map.entry(SMTP_HOST, smtp.host()),
Map.entry(SMTP_PORT, smtp.port()),
Map.entry(SMTP_USER, smtp.username()),
Map.entry(SMTP_PASS, smtp.password()),
Map.entry(STATE, state)))
.run();
return this;
}
public String email() {
return email;
private void sendConfirmationRequest(User user, String token) throws MessagingException, UnsupportedEncodingException {
var subject = t("Please confirm your list subscription");
var config = Configuration.instance();
var url = new StringBuilder(config.baseUrl()).append("/confirm?token=").append(token);
var text = t("Please go to {} in order to complete your list subscription!",url);
smtp.login().send(email(),name(),user.email(),subject,text);
}
private static String stateString(int state) {
var states = new ArrayList<String>();
states.add((state & STATE_ENABLED) == STATE_ENABLED ? "enabled" : "disabled");
states.add((state & STATE_PUBLIC) == STATE_PUBLIC ? "public" : "hidden");
return String.join(", ", states);
}
public void requestSubscription(User user) throws SQLException, MessagingException {
var member = ListMember.create(this,user,ListMember.STATE_AWAITING_CONFIRMATION);
var token = member.token();
try {
sendConfirmationRequest(user, token);
} catch (UnsupportedEncodingException e) {
throw new MessagingException("Failed to send email to "+user.email(),e);
}
}
public void test(User user) throws MessagingException, UnsupportedEncodingException {
var subject = t("{}: test mail",name());
var text = t("If you received this mail, the SMTP settings of your mailing list are correct.");
smtp.login().send(email(),name(),user.email(),subject,text);
}
}