Browse Source

implemented un-subscribe

drop_old_mail
Stephan Richter 3 years ago
parent
commit
6d73018247
  1. 134
      src/main/java/de/srsoftware/widerhall/data/Database.java
  2. 24
      src/main/java/de/srsoftware/widerhall/data/ListMember.java
  3. 72
      src/main/java/de/srsoftware/widerhall/web/Web.java
  4. 4
      static/templates/js.st
  5. 4
      static/templates/subscribe.st
  6. 30
      static/templates/unsubscribe.st

134
src/main/java/de/srsoftware/widerhall/data/Database.java

@ -30,56 +30,16 @@ public class Database { @@ -30,56 +30,16 @@ public class Database {
private final String sql;
private final HashMap<String, List<Object>> where = new HashMap<>();
private final HashMap<String,Object> values = new HashMap<>();
private final HashMap<String,Object> setValues = new HashMap<>();
public Request(String sql) {
this.sql = sql;
}
public Request where(String key, Object ... values) {
for (var val : values) where(key,val);
return this;
}
public Request where(String key, Collection<? extends Object> values) {
for (var val : values) where(key,val);
return this;
}
private Request where(String key, Object value) {
var list = where.get(key);
if (list == null) where.put(key,list = new ArrayList<>());
list.add(value);
return this;
}
public Request values(Map<String,Object> newValues) {
values.putAll(newValues);
return this;
}
public Request values(String key, Object value) {
values.put(key,value);
return this;
}
public void run() throws SQLException {
public ResultSet exec() throws SQLException {
var sb = new StringBuilder(sql);
var args = new ArrayList<>();
if (!values.isEmpty()){
var keys = new ArrayList<String>();
for (var entry : values.entrySet()) {
keys.add(entry.getKey());
args.add(entry.getValue());
}
sb.append("(")
.append(String.join(", ",keys))
.append(")")
.append(" VALUES ");
var arr = new String[args.size()];
Arrays.fill(arr,"?");
var marks = String.join(", ",arr);
sb.append("(").append(marks).append(")");
}
if (!where.isEmpty()){
var clauses = new ArrayList<String>();
sb.append(" WHERE ");
@ -97,19 +57,46 @@ public class Database { @@ -97,19 +57,46 @@ public class Database {
var sql = sb.toString();
LOG.debug(sql);
try {
var stmt = conn.prepareStatement(sql);
var stmt = Database.this.conn.prepareStatement(sql);
if (!args.isEmpty()) {
for (int i = 0; i < args.size(); i++) stmt.setObject(i+1, args.get(i));
}
stmt.execute();
return stmt.executeQuery();
} catch (SQLException sqle) {
throw new SQLException(t("Query '{}' failed:",sql),sqle);
}
}
public ResultSet exec() throws SQLException {
public void run() throws SQLException {
var sb = new StringBuilder(sql);
var args = new ArrayList<>();
if (!setValues.isEmpty()){
var keys = new ArrayList<String>();
var expressions = new ArrayList<String>();
for (var entry : setValues.entrySet()) {
expressions.add(" SET "+entry.getKey()+" = ?");
args.add(entry.getValue());
}
sb.append(String.join(", ",expressions));
}
if (!values.isEmpty()){
var keys = new ArrayList<String>();
for (var entry : values.entrySet()) {
keys.add(entry.getKey());
args.add(entry.getValue());
}
sb.append("(")
.append(String.join(", ",keys))
.append(")")
.append(" VALUES ");
var arr = new String[args.size()];
Arrays.fill(arr,"?");
var marks = String.join(", ",arr);
sb.append("(").append(marks).append(")");
}
if (!where.isEmpty()){
var clauses = new ArrayList<String>();
sb.append(" WHERE ");
@ -127,21 +114,61 @@ public class Database { @@ -127,21 +114,61 @@ public class Database {
var sql = sb.toString();
LOG.debug(sql);
try {
var stmt = Database.this.conn.prepareStatement(sql);
var stmt = conn.prepareStatement(sql);
if (!args.isEmpty()) {
for (int i = 0; i < args.size(); i++) stmt.setObject(i+1, args.get(i));
}
return stmt.executeQuery();
stmt.execute();
} catch (SQLException sqle) {
throw new SQLException(t("Query '{}' failed:",sql),sqle);
}
}
public Request set(String key, Object value) {
setValues.put(key,value);
return this;
}
public Request where(String key, Object ... values) {
for (var val : values) where(key,val);
return this;
}
public Request where(String key, Collection<? extends Object> values) {
for (var val : values) where(key,val);
return this;
}
private Request where(String key, Object value) {
var list = where.get(key);
if (list == null) where.put(key,list = new ArrayList<>());
list.add(value);
return this;
}
public Request values(Map<String,Object> newValues) {
values.putAll(newValues);
return this;
}
public Request values(String key, Object value) {
values.put(key,value);
return this;
}
}
public Database(Connection connection) {
this.conn = connection;
}
private Database assertTables() throws SQLException {
if (!tableExists(User.TABLE_NAME)) User.createTable();
if (!tableExists(MailingList.TABLE_NAME)) MailingList.createTable();
if (!tableExists(ListMember.TABLE_NAME)) ListMember.createTable();
return this;
}
public static Database open() {
if (singleton == null){
Configuration config = Configuration.instance();
@ -159,15 +186,10 @@ public class Database { @@ -159,15 +186,10 @@ public class Database {
return singleton;
}
private Database assertTables() throws SQLException {
if (!tableExists(User.TABLE_NAME)) User.createTable();
if (!tableExists(MailingList.TABLE_NAME)) MailingList.createTable();
if (!tableExists(ListMember.TABLE_NAME)) ListMember.createTable();
return this;
public Request query(String sql) {
return new Request(sql);
}
private boolean tableExists(String tbName) throws SQLException {
try {
ResultSet rs = query("SELECT EXISTS (SELECT name FROM sqlite_schema WHERE type='table' AND name='" + tbName + "')").exec();
@ -179,8 +201,4 @@ public class Database { @@ -179,8 +201,4 @@ public class Database {
throw new SQLException(t("Was not able to check existence of table {}!",tbName),e);
}
}
public Request query(String sql) {
return new Request(sql);
}
}

24
src/main/java/de/srsoftware/widerhall/data/ListMember.java

@ -3,6 +3,7 @@ package de.srsoftware.widerhall.data; @@ -3,6 +3,7 @@ package de.srsoftware.widerhall.data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.crypto.Data;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
@ -90,4 +91,27 @@ public class ListMember { @@ -90,4 +91,27 @@ public class ListMember {
.run();
return this;
}
public static void unsubscribe(String listEmail, User user) throws SQLException {
var db = Database.open();
var rs = db.query("SELECT * FROM "+TABLE_NAME)
.where(LIST_EMAIL,listEmail)
.where(USER_EMAIL,user.email())
.exec();
while (rs.next()){
int state = rs.getInt(STATE) ^ STATE_SUBSCRIBER;
if (state < 1) { // drop entry
db.query("DELETE FROM "+TABLE_NAME)
.where(LIST_EMAIL,listEmail)
.where(USER_EMAIL,user.email())
.run();
} else { // update entry: whitdraw subscription
db.query("UPDATE "+TABLE_NAME)
.set(STATE,state)
.where(LIST_EMAIL,listEmail)
.where(USER_EMAIL,user.email())
.run();
}
}
}
}

72
src/main/java/de/srsoftware/widerhall/web/Web.java

@ -32,8 +32,8 @@ public class Web extends HttpServlet { @@ -32,8 +32,8 @@ public class Web extends HttpServlet {
private static final String LOGOUT = "logout";
private static final String REGISTER = "register";
private static final String SUBSCRIBE = "subscribe";
private static final String UNSUBSCRIBE = "unsubscribe";
private static final String RELOAD = "reload";
private static final String INSPECT = "inspect";
private static final String IMAP_HOST = "imap_host";
private static final String IMAP_PORT = "imap_port";
private static final String IMAP_USER = "imap_user";
@ -140,6 +140,15 @@ public class Web extends HttpServlet { @@ -140,6 +140,15 @@ public class Web extends HttpServlet {
if (error != null) resp.sendError(400,error);
}
private SQLException getCausingException(SQLException sqle) {
Throwable cause = sqle.getCause();
while (cause instanceof SQLException){
sqle = (SQLException) cause;
cause = sqle.getCause();
}
return sqle;
}
private String handleGet(HttpServletRequest req, HttpServletResponse resp) {
var o = req.getSession().getAttribute("user");
User user = o instanceof User ? (User) o : null;
@ -148,6 +157,8 @@ public class Web extends HttpServlet { @@ -148,6 +157,8 @@ public class Web extends HttpServlet {
var path = req.getPathInfo();
path = (path == null || path.equals("/")) ? INDEX : path.substring(1);
String notes = null;
var list = req.getParameter(LIST);
if (list != null && !list.isBlank()) data.put(LIST,list);
switch (path){
case RELOAD:
loadTemplates();
@ -155,9 +166,9 @@ public class Web extends HttpServlet { @@ -155,9 +166,9 @@ public class Web extends HttpServlet {
path = INDEX;
case "css":
case INDEX:
case UNSUBSCRIBE:
return loadTemplate(path,data,resp);
case SUBSCRIBE:
var list = req.getParameter(LIST);
// TODO check permission
if (MailingList.isOpen(list)) {
data.put(LIST, list);
@ -183,9 +194,8 @@ public class Web extends HttpServlet { @@ -183,9 +194,8 @@ public class Web extends HttpServlet {
}
if (user != null){
var list = req.getParameter(LIST);
if (list != null) data.put(LIST,req.getParameter(LIST));
data.put(NOTES,notes);
//data.put(NOTES,notes);
return loadTemplate(path,data,resp);
}
return redirectTo(LOGIN,resp);
@ -225,6 +235,8 @@ public class Web extends HttpServlet { @@ -225,6 +235,8 @@ public class Web extends HttpServlet {
return registerUser(req,resp);
case SUBSCRIBE:
return subscribe(req,resp);
case UNSUBSCRIBE:
return unsubscribe(req,resp);
}
return t("No handler for path {}!",path);
@ -357,12 +369,52 @@ public class Web extends HttpServlet { @@ -357,12 +369,52 @@ public class Web extends HttpServlet {
}
}
private SQLException getCausingException(SQLException sqle) {
Throwable cause = sqle.getCause();
while (cause instanceof SQLException){
sqle = (SQLException) cause;
cause = sqle.getCause();
private String unsubscribe(HttpServletRequest req, HttpServletResponse resp) {
var data = new HashMap<String,Object>();
var user = getSessionUser(req);
var email = req.getParameter(EMAIL);
var pass = req.getParameter(PASSWORD);
var list = req.getParameter(LIST);
data.put(EMAIL,email);
data.put(LIST,list);
if (user != null) data.put(USER,user.safeMap());
if (list == null || list.isBlank()){
data.put(ERROR,"No list provided by form data!");
return loadTemplate(UNSUBSCRIBE,data,resp);
}
return sqle;
if (user == null) {
if (email == null || email.isBlank()) {
data.put(ERROR, "Email is required for list un-subscription!");
return loadTemplate(UNSUBSCRIBE, data, resp);
}
if (pass != null && pass.isBlank()) pass = null;
try {
user = User.load(email,pass);
req.getSession().setAttribute(USER,user);
data.put(USER,user.safeMap());
} catch (InvalidKeyException | SQLException e) {
data.put(ERROR,"Invalid email/password combination!");
return loadTemplate(UNSUBSCRIBE,data,resp);
}
}
// if we get here, we should have a valid user
try {
ListMember.unsubscribe(list,user);
data.put(NOTES,t("Sucessfully un-subscribed from '{}'.",list));
return loadTemplate(INDEX,data,resp);
} catch (SQLException e) {
LOG.warn("Problem during unscubsription of {} from {}:",user.email(),list,e);
data.put(ERROR,"Failed to unsubscribe!");
return loadTemplate(UNSUBSCRIBE,data,resp);
}
}
private User getSessionUser(HttpServletRequest req) {
return req.getSession().getAttribute(USER) instanceof User user ? user : null;
}
}

4
static/templates/js.st

@ -145,5 +145,9 @@ function subscribeTo(domain,prefix){ @@ -145,5 +145,9 @@ function subscribeTo(domain,prefix){
window.location.href='subscribe?list='+prefix+'@'+domain;
}
function unsubscribeFrom(domain,prefix){
window.location.href='unsubscribe?list='+prefix+'@'+domain;
}
$(start); // document.on ready

4
static/templates/subscribe.st

@ -16,11 +16,11 @@ @@ -16,11 +16,11 @@
<fieldset>
<legend>Suscribe to "«data.list»"</legend>
<label>
<input type="text" name="name" value="«if(data.user)»«data.user.name»«else»«data.name»«endif»">
<input type="text" name="name" value="«if(data.name)»«data.name»«else»«data.user.name»«endif»">
Name
</label>
<label>
<input type="text" name="email" value="«if(data.user)»«data.user.email»«else»«data.email»«endif»">
<input type="text" name="email" value="«if(data.email)»«data.email»«else»«data.user.email»«endif»">
Email
</label>
<label>

30
static/templates/unsubscribe.st

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="jquery"></script>
<script src="js"></script>
<link rel="stylesheet" href="css" />
</head>
<body id="login">
«navigation()»
«userinfo()»
«messages()»
<h1>Widerhall Subscription</h1>
<form method="POST">
<input type="hidden" name="list" value="«data.list»" />
<fieldset>
<legend>Un-subscribe from "«data.list»"</legend>
<label>
<input type="text" name="email" value="«if(data.email)»«data.email»«else»«data.user.email»«endif»">
Email
</label>
<label>
<input type="password" name="password">
Password (optional)
</label>
<button type="submit">Un-subscribe</button>
</fieldset>
</form>
</body>
</html>
Loading…
Cancel
Save