Merge branch 'main' into lang_de
This commit is contained in:
@@ -21,8 +21,10 @@ public class Constants {
|
|||||||
public static final String MESSAGE_ID = "message_id";
|
public static final String MESSAGE_ID = "message_id";
|
||||||
public static final String MODERATOR = "moderator";
|
public static final String MODERATOR = "moderator";
|
||||||
public static final String MONTH = "month";
|
public static final String MONTH = "month";
|
||||||
|
public static final String NEW_PASSWORD_FORM = "new_password_form";
|
||||||
public static final String NOTES = "notes";
|
public static final String NOTES = "notes";
|
||||||
public static final String PASSWORD = "password";
|
public static final String PASSWORD = "password";
|
||||||
|
public static final String PASSWORD_REPEAT = "password-repeat";
|
||||||
public static final String PERMISSIONS = "permissions";
|
public static final String PERMISSIONS = "permissions";
|
||||||
public static final Object PORT = "port";
|
public static final Object PORT = "port";
|
||||||
public static final String PREFIX = "prefix";
|
public static final String PREFIX = "prefix";
|
||||||
|
|||||||
@@ -4,12 +4,9 @@ import de.srsoftware.tools.translations.Translation;
|
|||||||
import de.srsoftware.widerhall.data.MailingList;
|
import de.srsoftware.widerhall.data.MailingList;
|
||||||
import de.srsoftware.widerhall.data.User;
|
import de.srsoftware.widerhall.data.User;
|
||||||
|
|
||||||
import javax.mail.Message;
|
|
||||||
import javax.mail.MessagingException;
|
import javax.mail.MessagingException;
|
||||||
import javax.mail.Multipart;
|
import javax.mail.Multipart;
|
||||||
import javax.mail.Part;
|
import javax.mail.Part;
|
||||||
import javax.mail.internet.AddressException;
|
|
||||||
import javax.mail.internet.InternetAddress;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
@@ -19,6 +16,7 @@ import java.security.NoSuchAlgorithmException;
|
|||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static de.srsoftware.widerhall.Constants.*;
|
import static de.srsoftware.widerhall.Constants.*;
|
||||||
@@ -28,6 +26,14 @@ public class Util {
|
|||||||
private static final MessageDigest SHA256 = getSha256();
|
private static final MessageDigest SHA256 = getSha256();
|
||||||
private static final String EMAIL_PATTERN = "^[a-zA-Z0-9_!#$%&'*+/=?`{|}~^-]+(?:\\.[a-zA-Z0-9_!#$%&'*+/=?`{|}~^-]+)*@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$";
|
private static final String EMAIL_PATTERN = "^[a-zA-Z0-9_!#$%&'*+/=?`{|}~^-]+(?:\\.[a-zA-Z0-9_!#$%&'*+/=?`{|}~^-]+)*@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$";
|
||||||
|
|
||||||
|
public static char boundedChar(int i) {
|
||||||
|
i = (i<0 ? -i : i) % 62;
|
||||||
|
i += '0';
|
||||||
|
if (i>57) i+=7;
|
||||||
|
if (i>90) i+=6;
|
||||||
|
return (char) i;
|
||||||
|
}
|
||||||
|
|
||||||
public static String dropEmail(String tx) {
|
public static String dropEmail(String tx) {
|
||||||
return tx.replaceAll( "[.\\-\\w]+@[.\\-\\w]+", "[email_removed]");
|
return tx.replaceAll( "[.\\-\\w]+@[.\\-\\w]+", "[email_removed]");
|
||||||
}
|
}
|
||||||
@@ -119,6 +125,18 @@ public class Util {
|
|||||||
return email.matches(EMAIL_PATTERN);
|
return email.matches(EMAIL_PATTERN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String randomString(int length) {
|
||||||
|
Random rand = new Random();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i=0; i<length; i++) {
|
||||||
|
int k = rand.nextInt();
|
||||||
|
char c = boundedChar(k);
|
||||||
|
System.out.println("adding '"+c+"'…");
|
||||||
|
sb.append(c);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
public static String sha256(String s) {
|
public static String sha256(String s) {
|
||||||
byte[] bytes = SHA256.digest(s.getBytes(StandardCharsets.UTF_8));
|
byte[] bytes = SHA256.digest(s.getBytes(StandardCharsets.UTF_8));
|
||||||
return hex(bytes);
|
return hex(bytes);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import java.sql.ResultSet;
|
|||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
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.HOLD_TIME;
|
import static de.srsoftware.widerhall.data.MailingList.HOLD_TIME;
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ import static de.srsoftware.widerhall.data.MailingList.HOLD_TIME;
|
|||||||
*/
|
*/
|
||||||
public class Database {
|
public class Database {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Database.class);
|
private static final Logger LOG = LoggerFactory.getLogger(Database.class);
|
||||||
|
private static final String DB_VERSION = "db_version";
|
||||||
private static Database singleton = null; // we only need one db handle ever. This will be it.
|
private static Database singleton = null; // we only need one db handle ever. This will be it.
|
||||||
private final Connection conn; // the actual db connection handle within the singleton
|
private final Connection conn; // the actual db connection handle within the singleton
|
||||||
|
|
||||||
@@ -295,6 +297,14 @@ public class Database {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createVersionTable() throws SQLException {
|
||||||
|
var sql = "CREATE TABLE %s (%s %s NOT NULL PRIMARY KEY);".formatted(DB_VERSION,DB_VERSION,INT);
|
||||||
|
var db = Database.open();
|
||||||
|
db.query(sql).compile().run();
|
||||||
|
sql = "INSERT INTO %s VALUES (1)".formatted(DB_VERSION);
|
||||||
|
db.query(sql).compile().run();
|
||||||
|
}
|
||||||
|
|
||||||
private boolean columnExists(String tableName, String columnName) throws SQLException {
|
private boolean columnExists(String tableName, String columnName) throws SQLException {
|
||||||
var rs = Database.open().select("pragma_table_info('"+tableName+"')","COUNT(*) AS num").where("name",columnName).compile().exec();
|
var rs = Database.open().select("pragma_table_info('"+tableName+"')","COUNT(*) AS num").where("name",columnName).compile().exec();
|
||||||
try {
|
try {
|
||||||
@@ -357,6 +367,7 @@ public class Database {
|
|||||||
try {
|
try {
|
||||||
singleton = new Database(DriverManager.getConnection(url));
|
singleton = new Database(DriverManager.getConnection(url));
|
||||||
singleton.assertTables(); // must not be concatenated to exception above (assertTables accesses singleton)!
|
singleton.assertTables(); // must not be concatenated to exception above (assertTables accesses singleton)!
|
||||||
|
singleton.update202405();
|
||||||
} catch (SQLException sqle) {
|
} catch (SQLException sqle) {
|
||||||
sqle.printStackTrace();
|
sqle.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -373,6 +384,10 @@ public class Database {
|
|||||||
return new Request(sql);
|
return new Request(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Request query(String sql) {
|
||||||
|
return new Request(new StringBuilder(sql));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* create a SELECT [flields] FROM [table] request.
|
* create a SELECT [flields] FROM [table] request.
|
||||||
* If no fields are supplied, a request in the form SELECT * FROM [table] will be generated.
|
* If no fields are supplied, a request in the form SELECT * FROM [table] will be generated.
|
||||||
@@ -390,7 +405,6 @@ public class Database {
|
|||||||
return new Request(sql.append(" FROM ").append(tableName));
|
return new Request(sql.append(" FROM ").append(tableName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* check, whether a table with the provided name exists
|
* check, whether a table with the provided name exists
|
||||||
* @param tbName
|
* @param tbName
|
||||||
@@ -420,4 +434,12 @@ public class Database {
|
|||||||
public Request update(String tableName) {
|
public Request update(String tableName) {
|
||||||
return new Request(new StringBuilder("UPDATE ").append(tableName));
|
return new Request(new StringBuilder("UPDATE ").append(tableName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Database update202405() throws SQLException {
|
||||||
|
if (!tableExists(Database.DB_VERSION)) {
|
||||||
|
createVersionTable();
|
||||||
|
User.addTokenColumn();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ public class MailingList implements MessageHandler, ProblemListener {
|
|||||||
private static final String SMTP_PASS = "smtp_pass";
|
private static final String SMTP_PASS = "smtp_pass";
|
||||||
public static final String TABLE_NAME = "Lists";
|
public static final String TABLE_NAME = "Lists";
|
||||||
private static final int STATE_PENDING = 0;
|
private static final int STATE_PENDING = 0;
|
||||||
private static final int STATE_ENABLED = 1; // do we process incoming messages?
|
public static final int STATE_ENABLED = 1; // do we process incoming messages?
|
||||||
private static final int STATE_PUBLIC = 2; // can guests see this ML?
|
public static final int STATE_PUBLIC = 2; // can guests see this ML?
|
||||||
public static final int STATE_FORWARD_FROM = 4; // set original sender as FROM when forwarding?
|
public static final int STATE_FORWARD_FROM = 4; // set original sender as FROM when forwarding?
|
||||||
public static final int STATE_FORWARD_ATTACHED = 8; // forward messages as attachment?
|
public static final int STATE_FORWARD_ATTACHED = 8; // forward messages as attachment?
|
||||||
public static final int STATE_HIDE_RECEIVERS = 16; // send using BCC receivers
|
public static final int STATE_HIDE_RECEIVERS = 16; // send using BCC receivers
|
||||||
@@ -283,6 +283,18 @@ 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 static List<MailingList> listActive() {
|
||||||
|
try {
|
||||||
|
var list = new ArrayList<MailingList>();
|
||||||
|
var rs = Database.open().select(TABLE_NAME).where(STATE+" % 2",1).compile().exec();
|
||||||
|
while (rs.next()) list.add(MailingList.from(rs));
|
||||||
|
return list;
|
||||||
|
} catch (SQLException e){
|
||||||
|
LOG.debug("Failed to load active MailingLists");
|
||||||
|
}
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
@@ -308,6 +320,7 @@ public class MailingList implements MessageHandler, ProblemListener {
|
|||||||
return ml;
|
return ml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
@@ -679,6 +692,10 @@ public class MailingList implements MessageHandler, ProblemListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sendPasswordReset(String email, String subject,String text) throws MessagingException, UnsupportedEncodingException {
|
||||||
|
smtp.send(email(),name(),email,subject,text);
|
||||||
|
}
|
||||||
|
|
||||||
protected SmtpClient smtp(){
|
protected SmtpClient smtp(){
|
||||||
return smtp;
|
return smtp;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import java.security.InvalidKeyException;
|
|||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static de.srsoftware.widerhall.Constants.*;
|
import static de.srsoftware.widerhall.Constants.*;
|
||||||
@@ -20,10 +21,11 @@ public class User {
|
|||||||
public static final int PERMISSION_ADMIN = 1;
|
public static final int PERMISSION_ADMIN = 1;
|
||||||
public static final int PERMISSION_CREATE_LISTS = 2;
|
public static final int PERMISSION_CREATE_LISTS = 2;
|
||||||
public static final String HASHED_PASS = "hashedPassword";
|
public static final String HASHED_PASS = "hashedPassword";
|
||||||
|
public static final String RESET_TOKEN = "resetToken";
|
||||||
public static final String SALT = "salt";
|
public static final String SALT = "salt";
|
||||||
private static final HashMap<String,User> users = new HashMap<>();
|
private static final HashMap<String,User> users = new HashMap<>();
|
||||||
|
|
||||||
private String email, salt, hashedPass, name;
|
private String email, salt, hashedPass, name, token;
|
||||||
private int permissions;
|
private int permissions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,11 +36,12 @@ public class User {
|
|||||||
* @param hashedPass
|
* @param hashedPass
|
||||||
* @param permissions
|
* @param permissions
|
||||||
*/
|
*/
|
||||||
public User(String email, String name, String salt, String hashedPass, int permissions) {
|
public User(String email, String name, String salt, String hashedPass, String token, int permissions) {
|
||||||
this.email = email.toLowerCase();
|
this.email = email.toLowerCase();
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.salt = salt;
|
this.salt = salt;
|
||||||
this.hashedPass = hashedPass;
|
this.hashedPass = hashedPass;
|
||||||
|
this.token = token;
|
||||||
this.permissions = permissions;
|
this.permissions = permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,6 +84,21 @@ public class User {
|
|||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void addTokenColumn() throws SQLException {
|
||||||
|
String sql = "ALTER TABLE %s ADD COLUMN %s %s;".formatted(TABLE_NAME,RESET_TOKEN,VARCHAR);
|
||||||
|
Database.open().query(sql).compile().run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static User byToken(String token) throws SQLException {
|
||||||
|
if (token == null || token.isBlank()) return null;
|
||||||
|
var rs = Database.open().select(TABLE_NAME).where(RESET_TOKEN,token).compile().exec();
|
||||||
|
try {
|
||||||
|
if (rs.next()) return User.from(rs);
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
rs.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new user object by hashing it's password and storing user data, salt and hashed password to the db.
|
* Create a new user object by hashing it's password and storing user data, salt and hashed password to the db.
|
||||||
@@ -96,10 +114,10 @@ public class User {
|
|||||||
String salt = null;
|
String salt = null;
|
||||||
String hashedPass = null;
|
String hashedPass = null;
|
||||||
if (password != null) {
|
if (password != null) {
|
||||||
salt = Util.sha256(email + name + LocalDate.now());
|
salt = Util.sha256(email + LocalDateTime.now() + name);
|
||||||
hashedPass = Util.sha256(password + salt);
|
hashedPass = Util.sha256(password + salt);
|
||||||
}
|
}
|
||||||
return new User(email,name,salt,hashedPass,0).save();
|
return new User(email,name,salt,hashedPass,null,0).save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -115,7 +133,6 @@ public class User {
|
|||||||
.append(PERMISSIONS).append(" ").append(INT).append(", ")
|
.append(PERMISSIONS).append(" ").append(INT).append(", ")
|
||||||
.append(SALT).append(" ").append(VARCHAR).append(", ")
|
.append(SALT).append(" ").append(VARCHAR).append(", ")
|
||||||
.append(HASHED_PASS).append(" ").append(VARCHAR)
|
.append(HASHED_PASS).append(" ").append(VARCHAR)
|
||||||
|
|
||||||
.append(");");
|
.append(");");
|
||||||
Database.open().query(sql).compile().run();
|
Database.open().query(sql).compile().run();
|
||||||
}
|
}
|
||||||
@@ -195,10 +212,16 @@ public class User {
|
|||||||
rs.getString(NAME),
|
rs.getString(NAME),
|
||||||
rs.getString(SALT),
|
rs.getString(SALT),
|
||||||
rs.getString(HASHED_PASS),
|
rs.getString(HASHED_PASS),
|
||||||
|
rs.getString(RESET_TOKEN),
|
||||||
rs.getInt(PERMISSIONS)));
|
rs.getInt(PERMISSIONS)));
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String generateToken() throws SQLException {
|
||||||
|
token = Util.randomString(64);
|
||||||
|
Database.open().update(TABLE_NAME).set(RESET_TOKEN,token).where(EMAIL,this.email).compile().run();
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the user identified by it's email, but only if the provided password matches.
|
* Loads the user identified by it's email, but only if the provided password matches.
|
||||||
@@ -284,4 +307,18 @@ public class User {
|
|||||||
req.compile().run();
|
req.compile().run();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPassword(String newPassword) throws SQLException {
|
||||||
|
if (newPassword != null) {
|
||||||
|
String newSalt = Util.sha256(email + LocalDateTime.now() + name);
|
||||||
|
String newHashedPass = Util.sha256(newPassword + newSalt);
|
||||||
|
Database.open().update(TABLE_NAME).set(HASHED_PASS,newHashedPass).set(SALT,newSalt).where(EMAIL,email).compile().run();
|
||||||
|
hashedPass = newHashedPass;
|
||||||
|
salt = newSalt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String token() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,7 @@ import java.io.IOException;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
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;
|
||||||
@@ -37,6 +36,7 @@ public class Web extends TemplateServlet {
|
|||||||
private static final String POST = "post";
|
private static final String POST = "post";
|
||||||
private static final String REGISTER = "register";
|
private static final String REGISTER = "register";
|
||||||
private static final String RELOAD = "reload";
|
private static final String RELOAD = "reload";
|
||||||
|
private static final String RESET_PASSWORD = "reset-pw";
|
||||||
private static final String SUBSCRIBE = "subscribe";
|
private static final String SUBSCRIBE = "subscribe";
|
||||||
private static final String UNSUBSCRIBE = "unsubscribe";
|
private static final String UNSUBSCRIBE = "unsubscribe";
|
||||||
private static final String IMAP_HOST = "imap_host";
|
private static final String IMAP_HOST = "imap_host";
|
||||||
@@ -49,7 +49,7 @@ public class Web extends TemplateServlet {
|
|||||||
private static final String SMTP_PASS = "smtp_pass";
|
private static final String SMTP_PASS = "smtp_pass";
|
||||||
private static final int PRIMARY_KEY_CONSTRAINT = 19;
|
private static final int PRIMARY_KEY_CONSTRAINT = 19;
|
||||||
|
|
||||||
private String addList(HttpServletRequest req, HttpServletResponse resp) {
|
private String addList(HttpServletRequest req, HttpServletResponse resp, boolean isGet) {
|
||||||
var user = Util.getUser(req);
|
var user = Util.getUser(req);
|
||||||
if (user == null) return redirectTo(LOGIN,resp);
|
if (user == null) return redirectTo(LOGIN,resp);
|
||||||
var data = new HashMap<String, Object>();
|
var data = new HashMap<String, Object>();
|
||||||
@@ -88,7 +88,7 @@ public class Web extends TemplateServlet {
|
|||||||
data.put(SMTP_PORT, smtpPort);
|
data.put(SMTP_PORT, smtpPort);
|
||||||
|
|
||||||
if (name == null || name.isBlank() || email == null || email.isBlank()) {
|
if (name == null || name.isBlank() || email == null || email.isBlank()) {
|
||||||
data.put(ERROR, "List name and address are required!");
|
data.put(ERROR, t("List name and address are required!"));
|
||||||
return loadTemplate(ADD_LIST, data, resp);
|
return loadTemplate(ADD_LIST, data, resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ public class Web extends TemplateServlet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (imapHost == null || imapHost.isBlank() || imapUser == null || imapUser.isBlank() || imapPass == null || imapPass.isBlank()) {
|
if (imapHost == null || imapHost.isBlank() || imapUser == null || imapUser.isBlank() || imapPass == null || imapPass.isBlank()) {
|
||||||
data.put(ERROR, "IMAP credentials are required!");
|
data.put(ERROR, t("IMAP credentials are required!"));
|
||||||
return loadTemplate(ADD_LIST, data, resp);
|
return loadTemplate(ADD_LIST, data, resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ public class Web extends TemplateServlet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (smtpHost == null || smtpHost.isBlank() || smtpUser == null || smtpUser.isBlank() || smtpPass == null || smtpPass.isBlank()) {
|
if (smtpHost == null || smtpHost.isBlank() || smtpUser == null || smtpUser.isBlank() || smtpPass == null || smtpPass.isBlank()) {
|
||||||
data.put(ERROR, "SMTP credentials are required!");
|
data.put(ERROR, t("SMTP credentials are required!"));
|
||||||
return loadTemplate(ADD_LIST, data, resp);
|
return loadTemplate(ADD_LIST, data, resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,15 +139,16 @@ public class Web extends TemplateServlet {
|
|||||||
var allowed = list.hasPublicArchive() || list.mayBeAlteredBy(user);
|
var allowed = list.hasPublicArchive() || list.mayBeAlteredBy(user);
|
||||||
if (!allowed) return t("You are not allowed to access the archive of this list");
|
if (!allowed) return t("You are not allowed to access the archive of this list");
|
||||||
|
|
||||||
var map = new HashMap<String,Object>();
|
var data = new HashMap<String,Object>();
|
||||||
map.put(LIST,list.email());
|
if (user != null) data.put(USER,user);
|
||||||
|
data.put(LIST,list.email());
|
||||||
|
|
||||||
var month = req.getParameter(MONTH);
|
var month = req.getParameter(MONTH);
|
||||||
if (month != null && !month.isBlank()){
|
if (month != null && !month.isBlank()){
|
||||||
map.put(MONTH,month);
|
data.put(MONTH,month);
|
||||||
map.put(MODERATOR,list.mayBeAlteredBy(user));
|
data.put(MODERATOR,list.mayBeAlteredBy(user));
|
||||||
}
|
}
|
||||||
return loadTemplate(ARCHIVE,map,resp);
|
return loadTemplate(ARCHIVE,data,resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String confirm(HttpServletRequest req, HttpServletResponse resp) {
|
private String confirm(HttpServletRequest req, HttpServletResponse resp) {
|
||||||
@@ -158,7 +159,7 @@ public class Web extends TemplateServlet {
|
|||||||
if (listMember != null) {
|
if (listMember != null) {
|
||||||
listMember.sendConfirmationMail(getTemplate("confirmation_mail"));
|
listMember.sendConfirmationMail(getTemplate("confirmation_mail"));
|
||||||
|
|
||||||
return loadTemplate(INDEX,Map.of(USER,listMember.user().safeMap(),NOTES,"Confirmed list subscription!"),resp);
|
return loadTemplate(INDEX,Map.of(USER,listMember.user().safeMap(),NOTES,t("Confirmed list subscription!")),resp);
|
||||||
}
|
}
|
||||||
return t("Unknown user or token!");
|
return t("Unknown user or token!");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -169,17 +170,17 @@ public class Web extends TemplateServlet {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||||
String error = handleGet(req, resp);
|
String error = handleRequest(req, resp, true);
|
||||||
if (error != null) resp.sendError(400,error);
|
if (error != null) resp.sendError(400,error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||||
String error = handlePost(req, resp);
|
String error = handleRequest(req, resp, false);
|
||||||
if (error != null) resp.sendError(400,error);
|
if (error != null) resp.sendError(400,error);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String editList(HttpServletRequest req, HttpServletResponse resp) {
|
public String editList(HttpServletRequest req, HttpServletResponse resp, boolean isGet) {
|
||||||
var user = Util.getUser(req);
|
var user = Util.getUser(req);
|
||||||
if (user == null) return redirectTo(LOGIN,resp);
|
if (user == null) return redirectTo(LOGIN,resp);
|
||||||
|
|
||||||
@@ -188,6 +189,7 @@ public class Web extends TemplateServlet {
|
|||||||
|
|
||||||
var list = Util.getMailingList(req);
|
var list = Util.getMailingList(req);
|
||||||
data.put(LIST,list.safeMap());
|
data.put(LIST,list.safeMap());
|
||||||
|
if (isGet) return loadTemplate(EDIT_LIST,data,resp);
|
||||||
try {
|
try {
|
||||||
var allowed = user.hashPermission(PERMISSION_ADMIN) || ListMember.load(list,user).isOwner();
|
var allowed = user.hashPermission(PERMISSION_ADMIN) || ListMember.load(list,user).isOwner();
|
||||||
if (!allowed) return loadTemplate(ADMIN,data,resp);
|
if (!allowed) return loadTemplate(ADMIN,data,resp);
|
||||||
@@ -220,7 +222,7 @@ public class Web extends TemplateServlet {
|
|||||||
data.put(SMTP_PORT, smtpPort);
|
data.put(SMTP_PORT, smtpPort);
|
||||||
|
|
||||||
if (name == null || name.isBlank() || email == null || email.isBlank()) {
|
if (name == null || name.isBlank() || email == null || email.isBlank()) {
|
||||||
data.put(ERROR, "List name and address are required!");
|
data.put(ERROR, t("List name and address are required!"));
|
||||||
return loadTemplate(EDIT_LIST, data, resp);
|
return loadTemplate(EDIT_LIST, data, resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,7 +232,7 @@ public class Web extends TemplateServlet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (imapHost == null || imapHost.isBlank() || imapUser == null || imapUser.isBlank() || imapPass == null || imapPass.isBlank()) {
|
if (imapHost == null || imapHost.isBlank() || imapUser == null || imapUser.isBlank() || imapPass == null || imapPass.isBlank()) {
|
||||||
data.put(ERROR, "IMAP credentials are required!");
|
data.put(ERROR, t("IMAP credentials are required!"));
|
||||||
return loadTemplate(EDIT_LIST, data, resp);
|
return loadTemplate(EDIT_LIST, data, resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,7 +246,7 @@ public class Web extends TemplateServlet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (smtpHost == null || smtpHost.isBlank() || smtpUser == null || smtpUser.isBlank() || smtpPass == null || smtpPass.isBlank()) {
|
if (smtpHost == null || smtpHost.isBlank() || smtpUser == null || smtpUser.isBlank() || smtpPass == null || smtpPass.isBlank()) {
|
||||||
data.put(ERROR, "SMTP credentials are required!");
|
data.put(ERROR, t("SMTP credentials are required!"));
|
||||||
return loadTemplate(EDIT_LIST, data, resp);
|
return loadTemplate(EDIT_LIST, data, resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +261,7 @@ public class Web extends TemplateServlet {
|
|||||||
list.update(name,email,imapHost,imapPort,imapUser,imapPass,inbox,smtpHost,smtpPort,smtpUser,smtpPass);
|
list.update(name,email,imapHost,imapPort,imapUser,imapPass,inbox,smtpHost,smtpPort,smtpUser,smtpPass);
|
||||||
return loadTemplate(ADMIN,data,resp);
|
return loadTemplate(ADMIN,data,resp);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
LOG.warn("Editing list {} by {} failed",list.email(),user.email(),e);
|
LOG.warn("Editing list {} by {} failed!",list.email(),user.email(),e);
|
||||||
return t("Editing list {} by {} failed!",list.email(),user.email());
|
return t("Editing list {} by {} failed!",list.email(),user.email());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -273,81 +275,12 @@ public class Web extends TemplateServlet {
|
|||||||
return sqle;
|
return sqle;
|
||||||
}
|
}
|
||||||
|
|
||||||
private User getSessionUser(HttpServletRequest req) {
|
private String handleLogin(HttpServletRequest req, HttpServletResponse resp,boolean isGet) {
|
||||||
return req.getSession().getAttribute(USER) instanceof User user ? user : null;
|
if (isGet) return loadTemplate(LOGIN,null,resp);
|
||||||
}
|
|
||||||
|
|
||||||
private String handleGet(HttpServletRequest req, HttpServletResponse resp) {
|
|
||||||
var path = Util.getPath(req);
|
|
||||||
var user = Util.getUser(req);
|
|
||||||
var data = new HashMap<String,Object>();
|
|
||||||
var list = Util.getMailingList(req);
|
|
||||||
|
|
||||||
if (user != null) data.put(USER,user.safeMap());
|
|
||||||
if (list != null) data.put(LIST,list.minimalMap());
|
|
||||||
switch (path){
|
|
||||||
case ARCHIVE:
|
|
||||||
return archive(list,user,req,resp);
|
|
||||||
case CONFIRM:
|
|
||||||
return confirm(req,resp);
|
|
||||||
case POST:
|
|
||||||
return post(req,resp);
|
|
||||||
case RELOAD:
|
|
||||||
loadTemplates();
|
|
||||||
data.put(NOTES,t("Templates have been reloaded!"));
|
|
||||||
path = INDEX;
|
|
||||||
case CSS:
|
|
||||||
case INDEX:
|
|
||||||
return loadTemplate(path,data,resp);
|
|
||||||
case SUBSCRIBE:
|
|
||||||
if (list.isOpenFor(user)) {
|
|
||||||
data.put(LIST,list.email());
|
|
||||||
return loadTemplate(path, data, resp);
|
|
||||||
}
|
|
||||||
return t("You are not allowed to subscribe to '{}'!",list.email());
|
|
||||||
case "js":
|
|
||||||
resp.setContentType("text/javascript");
|
|
||||||
return loadTemplate(path,data,resp);
|
|
||||||
case LOGIN:
|
|
||||||
try {
|
|
||||||
if (User.noUsers()) return loadTemplate(REGISTER, Map.of(NOTES,t("User database is empty. Create admin user first:")), resp);
|
|
||||||
return loadTemplate(path,null,resp);
|
|
||||||
} catch (SQLException e) {
|
|
||||||
return "Error reading user database!";
|
|
||||||
}
|
|
||||||
case LOGOUT:
|
|
||||||
req.getSession().invalidate();
|
|
||||||
return redirectTo(INDEX,resp);
|
|
||||||
case "jquery":
|
|
||||||
resp.setContentType("text/javascript");
|
|
||||||
return loadFile("jquery-3.6.0.min.js",resp);
|
|
||||||
case "OpenSans-Regular.woff":
|
|
||||||
resp.setContentType("font/woff");
|
|
||||||
return loadFile("OpenSans-Regular.woff",resp);
|
|
||||||
case "Bhineka.ttf":
|
|
||||||
resp.setContentType("font/ttf");
|
|
||||||
return loadFile("Bhineka.ttf",resp); case UNSUBSCRIBE:
|
|
||||||
data.put(LIST,list.email());
|
|
||||||
return loadTemplate(path,data,resp);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user != null){
|
|
||||||
if (list != null) data.put(LIST,req.getParameter(LIST));
|
|
||||||
switch (path){
|
|
||||||
case EDIT_LIST:
|
|
||||||
return editList(req,resp);
|
|
||||||
}
|
|
||||||
return loadTemplate(path,data,resp);
|
|
||||||
}
|
|
||||||
return redirectTo(LOGIN,resp);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String handleLogin(HttpServletRequest req, HttpServletResponse resp) {
|
|
||||||
var email = req.getParameter("email");
|
var email = req.getParameter("email");
|
||||||
var pass = req.getParameter("pass");
|
var pass = req.getParameter("pass");
|
||||||
if (email == null || pass == null) return loadTemplate("login", Map.of("error",t("Missing username or password!")), resp);
|
if (email == null || pass == null) return loadTemplate(LOGIN, Map.of("error",t("Missing username or password!")), resp);
|
||||||
if (!Util.isEmail(email)) return loadTemplate("login", Map.of("error",t("'{}' is not a valid email address!",email)), resp);
|
if (!Util.isEmail(email)) return loadTemplate(LOGIN, Map.of("error",t("'{}' is not a valid email address!",email)), resp);
|
||||||
try {
|
try {
|
||||||
var user = User.loadUser(email,pass);
|
var user = User.loadUser(email,pass);
|
||||||
req.getSession().setAttribute("user",user);
|
req.getSession().setAttribute("user",user);
|
||||||
@@ -364,34 +297,131 @@ public class Web extends TemplateServlet {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String handlePost(HttpServletRequest req, HttpServletResponse resp) {
|
private String handleNewPassword(HttpServletRequest req, HttpServletResponse resp, boolean isGet) {
|
||||||
final var path = Util.getPath(req);
|
var user = Util.getUser(req);
|
||||||
|
if (user == null) return redirectTo(LOGIN,resp);
|
||||||
switch (path){
|
var data = new HashMap<String,Object>();
|
||||||
case ADD_LIST:
|
data.put(USER,user.safeMap());
|
||||||
return addList(req,resp);
|
if (!isGet) {
|
||||||
case EDIT_LIST:
|
var pass = req.getParameter(PASSWORD);
|
||||||
return editList(req,resp);
|
var repeat = req.getParameter(PASSWORD_REPEAT);
|
||||||
case INSPECT:
|
if (pass == null || pass.isBlank()) {
|
||||||
return inspect(req,resp);
|
data.put(ERROR, t("Please set a password!"));
|
||||||
case LOGIN:
|
} else if (!pass.equals(repeat)) {
|
||||||
return handleLogin(req,resp);
|
data.put(ERROR, t("Passwords do not match!"));
|
||||||
case REGISTER:
|
} else if (Util.simplePassword(pass)) {
|
||||||
return registerUser(req,resp);
|
data.put(ERROR, t("Your password is to simple!"));
|
||||||
case SUBSCRIBE:
|
} else {
|
||||||
return subscribe(req,resp);
|
try {
|
||||||
case UNSUBSCRIBE:
|
user.setPassword(pass);
|
||||||
return unsubscribe(req,resp);
|
data.put(NOTES,t("Your password has been updated!"));
|
||||||
|
return loadTemplate(ADMIN,data,resp);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
data.put(ERROR,t("Failed to update password in database!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return loadTemplate(NEW_PASSWORD_FORM,data,resp);
|
||||||
return t("No handler for path {}!",path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String inspect(HttpServletRequest req, HttpServletResponse resp) {
|
private String handleRequest(HttpServletRequest req, HttpServletResponse resp, boolean isGet){
|
||||||
|
var path = Util.getPath(req);
|
||||||
|
var user = Util.getUser(req);
|
||||||
|
var data = new HashMap<String,Object>();
|
||||||
|
var list = Util.getMailingList(req);
|
||||||
|
|
||||||
|
if (user != null) data.put(USER,user.safeMap());
|
||||||
|
if (list != null) data.put(LIST,list.minimalMap());
|
||||||
|
var interesting = !Set.of("js","jquery","css","OpenSans-Regular.woff","Bhineka.ttf").contains(path);
|
||||||
|
LOG.debug("{}",interesting?"interesting":"boring");
|
||||||
|
if (user != null){
|
||||||
|
switch (path){
|
||||||
|
case ADD_LIST:
|
||||||
|
return addList(req,resp,isGet);
|
||||||
|
case ADMIN:
|
||||||
|
return loadTemplate(path,data,resp);
|
||||||
|
case EDIT_LIST:
|
||||||
|
return editList(req,resp,isGet);
|
||||||
|
case INSPECT:
|
||||||
|
return inspect(req,resp,isGet);
|
||||||
|
case NEW_PASSWORD_FORM:
|
||||||
|
return handleNewPassword(req,resp,isGet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (path){
|
||||||
|
case ARCHIVE:
|
||||||
|
return archive(list,user,req,resp);
|
||||||
|
case CSS:
|
||||||
|
case INDEX:
|
||||||
|
return loadTemplate(path,data,resp);
|
||||||
|
case CONFIRM:
|
||||||
|
return confirm(req,resp);
|
||||||
|
case LOGIN:
|
||||||
|
return handleLogin(req,resp,isGet);
|
||||||
|
case LOGOUT:
|
||||||
|
req.getSession().invalidate();
|
||||||
|
return redirectTo(INDEX,resp);
|
||||||
|
case POST:
|
||||||
|
return post(req,resp);
|
||||||
|
case REGISTER:
|
||||||
|
return registerUser(req,resp,isGet);
|
||||||
|
case RELOAD:
|
||||||
|
loadTemplates();
|
||||||
|
data.put(NOTES,t("Templates have been reloaded!"));
|
||||||
|
return loadTemplate(INDEX,data,resp);
|
||||||
|
case RESET_PASSWORD:
|
||||||
|
if (!isGet) return resetPassword(req,resp);
|
||||||
|
// TODO: move following code into resetPassword method
|
||||||
|
try {
|
||||||
|
user = User.byToken(req.getParameter(TOKEN));
|
||||||
|
if (user != null) {
|
||||||
|
req.getSession().setAttribute("user",user);
|
||||||
|
return redirectTo(NEW_PASSWORD_FORM,resp);
|
||||||
|
}
|
||||||
|
} catch (SQLException sqle){
|
||||||
|
return loadTemplate(path,Map.of(ERROR,t("Failed to find user for token!")),resp);
|
||||||
|
}
|
||||||
|
var email = req.getParameter(EMAIL);
|
||||||
|
return loadTemplate(path,email == null ? null : Map.of(EMAIL,email),resp);
|
||||||
|
|
||||||
|
case SUBSCRIBE:
|
||||||
|
if (!isGet) {
|
||||||
|
return subscribe(req, resp);
|
||||||
|
} // TODO: Code für GET-Request mit in subscribe-Methode verschieben
|
||||||
|
if (list.isOpenFor(user)) {
|
||||||
|
data.put(LIST,list.email());
|
||||||
|
return loadTemplate(path, data, resp);
|
||||||
|
}
|
||||||
|
return t("You are not allowed to subscribe to '{}'!",list.email());
|
||||||
|
case UNSUBSCRIBE:
|
||||||
|
return unsubscribe(req,resp,isGet);
|
||||||
|
}
|
||||||
|
/* uninteresting paths */
|
||||||
|
switch (path){
|
||||||
|
case "js":
|
||||||
|
resp.setContentType("text/javascript");
|
||||||
|
return loadTemplate(path,data,resp);
|
||||||
|
case "jquery":
|
||||||
|
resp.setContentType("text/javascript");
|
||||||
|
return loadFile("jquery-3.6.0.min.js",resp);
|
||||||
|
case "OpenSans-Regular.woff":
|
||||||
|
resp.setContentType("font/woff");
|
||||||
|
return loadFile("OpenSans-Regular.woff",resp);
|
||||||
|
case "Bhineka.ttf":
|
||||||
|
resp.setContentType("font/ttf");
|
||||||
|
return loadFile("Bhineka.ttf",resp); case UNSUBSCRIBE:
|
||||||
|
data.put(LIST,list.email());
|
||||||
|
return loadTemplate(path,data,resp);
|
||||||
|
}
|
||||||
|
return redirectTo(LOGIN,resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String inspect(HttpServletRequest req, HttpServletResponse resp, boolean isGet) {
|
||||||
var user = Util.getUser(req);
|
var user = Util.getUser(req);
|
||||||
if (user == null) return redirectTo(LOGIN,resp);
|
if (user == null) return redirectTo(LOGIN,resp);
|
||||||
|
|
||||||
var data = new HashMap<String,Object>();
|
var data = new HashMap<String,Object>();
|
||||||
|
data.put(USER,user);
|
||||||
var error = false;
|
var error = false;
|
||||||
|
|
||||||
var list = Util.getMailingList(req);
|
var list = Util.getMailingList(req);
|
||||||
@@ -399,6 +429,7 @@ public class Web extends TemplateServlet {
|
|||||||
error = true;
|
error = true;
|
||||||
data.put(ERROR, t("No valid mailing list provided!"));
|
data.put(ERROR, t("No valid mailing list provided!"));
|
||||||
} else data.put(LIST, list.email());
|
} else data.put(LIST, list.email());
|
||||||
|
if (isGet) return loadTemplate(INSPECT,data,resp);
|
||||||
|
|
||||||
if (!error && !list.mayBeAlteredBy(user)) {
|
if (!error && !list.mayBeAlteredBy(user)) {
|
||||||
error = true;
|
error = true;
|
||||||
@@ -428,7 +459,7 @@ public class Web extends TemplateServlet {
|
|||||||
|
|
||||||
private String post(HttpServletRequest req, HttpServletResponse resp) {
|
private String post(HttpServletRequest req, HttpServletResponse resp) {
|
||||||
var id = req.getParameter(ID);
|
var id = req.getParameter(ID);
|
||||||
if (id == null) return t("Could not find email with id!");
|
if (id == null) return t("Could not find email: missing id!");
|
||||||
try {
|
try {
|
||||||
var post = Post.load(id);
|
var post = Post.load(id);
|
||||||
var map = new HashMap<String,Object>();
|
var map = new HashMap<String,Object>();
|
||||||
@@ -451,10 +482,8 @@ public class Web extends TemplateServlet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String registerUser(HttpServletRequest req, HttpServletResponse resp, boolean isGet) {
|
||||||
|
if (isGet) return loadTemplate(REGISTER,null,resp);
|
||||||
private String registerUser(HttpServletRequest req, HttpServletResponse resp) {
|
|
||||||
|
|
||||||
var email = req.getParameter("email");
|
var email = req.getParameter("email");
|
||||||
var pass = req.getParameter("pass");
|
var pass = req.getParameter("pass");
|
||||||
var pass_repeat = req.getParameter("pass_repeat");
|
var pass_repeat = req.getParameter("pass_repeat");
|
||||||
@@ -463,9 +492,9 @@ public class Web extends TemplateServlet {
|
|||||||
if (email == null || email.isBlank() ||
|
if (email == null || email.isBlank() ||
|
||||||
name == null || name.isBlank() ||
|
name == null || name.isBlank() ||
|
||||||
pass == null || pass.isBlank() ||
|
pass == null || pass.isBlank() ||
|
||||||
pass_repeat == null || pass_repeat.isBlank()) return loadTemplate(REGISTER,Map.of(ERROR,t("Fill all fields, please!"),NAME,name,EMAIL,email),resp);
|
pass_repeat == null || pass_repeat.isBlank()) return loadTemplate(REGISTER,Map.of(ERROR,t("Fill all fields, please!"),NAME,name,EMAIL,email),resp);
|
||||||
if (!pass.equals(pass_repeat)) return loadTemplate(REGISTER,Map.of(ERROR,t("Passwords do not match!"),NAME,name,EMAIL,email),resp);
|
if (!pass.equals(pass_repeat)) return loadTemplate(REGISTER,Map.of(ERROR,t("Passwords do not match!"),NAME,name,EMAIL,email),resp);
|
||||||
if (Util.simplePassword(pass)) return loadTemplate(REGISTER,Map.of(ERROR,t("Password to short or to simple!"),NAME,name,EMAIL,email),resp);
|
if (Util.simplePassword(pass)) return loadTemplate(REGISTER,Map.of(ERROR,t("Password to short or to simple!"),NAME,name,EMAIL,email),resp);
|
||||||
|
|
||||||
var firstUser = false;
|
var firstUser = false;
|
||||||
try {
|
try {
|
||||||
@@ -474,7 +503,6 @@ public class Web extends TemplateServlet {
|
|||||||
return t("Failed to access user database: {}",e.getMessage());
|
return t("Failed to access user database: {}",e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var user = User.create(email, name, pass);
|
var user = User.create(email, name, pass);
|
||||||
if (firstUser) user.addPermission(PERMISSION_ADMIN|User.PERMISSION_CREATE_LISTS);
|
if (firstUser) user.addPermission(PERMISSION_ADMIN|User.PERMISSION_CREATE_LISTS);
|
||||||
@@ -486,6 +514,39 @@ public class Web extends TemplateServlet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String resetPassword(HttpServletRequest req, HttpServletResponse resp) {
|
||||||
|
var email = req.getParameter("email");
|
||||||
|
if (email == null) return loadTemplate("login", Map.of("error",t("Missing email address!")), resp);
|
||||||
|
if (!Util.isEmail(email)) return loadTemplate("login", Map.of("error",t("'{}' is not a valid email address!",email)), resp);
|
||||||
|
|
||||||
|
try {
|
||||||
|
var user = User.load(email);
|
||||||
|
if (user != null) {
|
||||||
|
MailingList list = ListMember.listsOf(user).stream().map(ListMember::list).filter(ml -> ml.hasState(STATE_ENABLED)).findAny().orElse(null);
|
||||||
|
if (list == null) list = MailingList.listActive().stream().findAny().orElse(null);
|
||||||
|
if (list == null) throw new NullPointerException(t("no active List found!"));
|
||||||
|
String token = user.generateToken();
|
||||||
|
var host = Arrays.stream(req.getRequestURL().toString().split("/")).filter(s -> !s.isEmpty() && !s.startsWith("http")).findFirst().orElse("unknwon host");
|
||||||
|
|
||||||
|
var link = req.getRequestURL().toString()+"?token="+token;
|
||||||
|
var subject = t("Reset your password at {}",host);
|
||||||
|
var text = t("Somebody asked to reset your account password at {}.",host)+
|
||||||
|
"\n\n"+
|
||||||
|
t("If that was you, please open the following link in your web browser:")
|
||||||
|
+"\n\n"
|
||||||
|
+link+
|
||||||
|
"\n\n"+
|
||||||
|
t("If you did not expect this email, please ignore it.");
|
||||||
|
|
||||||
|
list.sendPasswordReset(email,subject,text);
|
||||||
|
return loadTemplate("reset_link_sent",null,resp);
|
||||||
|
}
|
||||||
|
} catch (Exception e){
|
||||||
|
return loadTemplate(Util.getPath(req),Map.of(EMAIL,email,ERROR,t("Failed to send reset email:")+e.getMessage()),resp);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private String subscribe(HttpServletRequest req, HttpServletResponse resp) {
|
private String subscribe(HttpServletRequest req, HttpServletResponse resp) {
|
||||||
var name = req.getParameter(NAME);
|
var name = req.getParameter(NAME);
|
||||||
var email = req.getParameter(EMAIL);
|
var email = req.getParameter(EMAIL);
|
||||||
@@ -499,12 +560,12 @@ public class Web extends TemplateServlet {
|
|||||||
|
|
||||||
|
|
||||||
if (list == null){
|
if (list == null){
|
||||||
data.put(ERROR,"No list provided by form data!");
|
data.put(ERROR,t("No list provided by form data!"));
|
||||||
return loadTemplate(SUBSCRIBE,data,resp);
|
return loadTemplate(SUBSCRIBE,data,resp);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (name == null || name.isBlank() || email == null || email.isBlank()){
|
if (name == null || name.isBlank() || email == null || email.isBlank()){
|
||||||
data.put(ERROR,"Name and email are required fields for list subscription!");
|
data.put(ERROR,t("Name and email are required fields for list subscription!"));
|
||||||
return loadTemplate(SUBSCRIBE,data,resp);
|
return loadTemplate(SUBSCRIBE,data,resp);
|
||||||
}
|
}
|
||||||
if (pass != null && pass.isBlank()) pass = null;
|
if (pass != null && pass.isBlank()) pass = null;
|
||||||
@@ -517,6 +578,7 @@ public class Web extends TemplateServlet {
|
|||||||
int code = cause.getErrorCode();
|
int code = cause.getErrorCode();
|
||||||
if (code == PRIMARY_KEY_CONSTRAINT) try {// user already exists
|
if (code == PRIMARY_KEY_CONSTRAINT) try {// user already exists
|
||||||
user = User.loadUser(email,pass);
|
user = User.loadUser(email,pass);
|
||||||
|
req.getSession().setAttribute("user",user);
|
||||||
skipConfirmation = pass != null; // subscription with email address already known to database
|
skipConfirmation = pass != null; // subscription with email address already known to database
|
||||||
// success → subscribe
|
// success → subscribe
|
||||||
} catch (InvalidKeyException | SQLException e) {
|
} catch (InvalidKeyException | SQLException e) {
|
||||||
@@ -555,11 +617,9 @@ public class Web extends TemplateServlet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String unsubscribe(HttpServletRequest req, HttpServletResponse resp, boolean isGet) {
|
||||||
|
|
||||||
private String unsubscribe(HttpServletRequest req, HttpServletResponse resp) {
|
|
||||||
var data = new HashMap<String,Object>();
|
var data = new HashMap<String,Object>();
|
||||||
var user = getSessionUser(req);
|
var user = Util.getUser(req);
|
||||||
var email = req.getParameter(EMAIL);
|
var email = req.getParameter(EMAIL);
|
||||||
var list = Util.getMailingList(req);
|
var list = Util.getMailingList(req);
|
||||||
data.put(EMAIL,email);
|
data.put(EMAIL,email);
|
||||||
@@ -568,6 +628,7 @@ public class Web extends TemplateServlet {
|
|||||||
data.put(ERROR,t("No list provided by form data!"));
|
data.put(ERROR,t("No list provided by form data!"));
|
||||||
return loadTemplate(UNSUBSCRIBE,data,resp);
|
return loadTemplate(UNSUBSCRIBE,data,resp);
|
||||||
} else data.put(LIST,list.email());
|
} else data.put(LIST,list.email());
|
||||||
|
if (isGet) return loadTemplate(UNSUBSCRIBE,data,resp);
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
if (email == null || email.isBlank()) {
|
if (email == null || email.isBlank()) {
|
||||||
data.put(ERROR, t("Email is required for list un-subscription!"));
|
data.put(ERROR, t("Email is required for list un-subscription!"));
|
||||||
@@ -605,9 +666,8 @@ public class Web extends TemplateServlet {
|
|||||||
return loadTemplate(INDEX,data,resp);
|
return loadTemplate(INDEX,data,resp);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
LOG.warn("Problem during unscubsription of {} from {}:",user.email(),list.email(),e);
|
LOG.warn("Problem during unscubsription of {} from {}:",user.email(),list.email(),e);
|
||||||
data.put(ERROR,"Failed to unsubscribe!");
|
data.put(ERROR,t("Failed to unsubscribe!"));
|
||||||
return loadTemplate(UNSUBSCRIBE,data,resp);
|
return loadTemplate(UNSUBSCRIBE,data,resp);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,14 +11,16 @@ archive : Archiv
|
|||||||
awaiting confirmation : erwartet Bestätigung
|
awaiting confirmation : erwartet Bestätigung
|
||||||
Confirmation of list membership failed! : Bestätigung des Listen-Abonnements fehlgeschlagen!
|
Confirmation of list membership failed! : Bestätigung des Listen-Abonnements fehlgeschlagen!
|
||||||
Confirmed list subscription! : Listen-Mitgliedschaft bestätigt!
|
Confirmed list subscription! : Listen-Mitgliedschaft bestätigt!
|
||||||
|
Could not find email: missing id! : Konnte Email nicht finden: ID fehlt!
|
||||||
enabled : aktiviert
|
enabled : aktiviert
|
||||||
disabled : deaktiviert
|
disabled : deaktiviert
|
||||||
Editing list {} by {} failed : Bearbeiten der Liste {} durch {} fehlgeschlagen!
|
Editing list {} by {} failed! : Bearbeiten der Liste {} durch {} fehlgeschlagen!
|
||||||
Email is required for list un-subscription! : Für das Abbestellen ist eine E-Mail-Adresse erforderlich!
|
Email is required for list un-subscription! : Für das Abbestellen ist eine E-Mail-Adresse erforderlich!
|
||||||
Error reading user database! : Fehler beim Lesen der Nutzer-Datenbank!
|
Error reading user database! : Fehler beim Lesen der Nutzer-Datenbank!
|
||||||
Failed to access user database\: {} : Fehler beim Zugriff auf die Nutzer-Datenbank: {}
|
Failed to access user database\: {} : Fehler beim Zugriff auf die Nutzer-Datenbank: {}
|
||||||
Failed to create list '{}'\: {} : Erzeugen der Liste '{}' fehlgeschlagen: {}
|
Failed to create list '{}'\: {} : Erzeugen der Liste '{}' fehlgeschlagen: {}
|
||||||
Failed to create new user\: {} : Erzeugen des neuen Nutzers fehlgeschlagen: {}
|
Failed to create new user\: {} : Erzeugen des neuen Nutzers fehlgeschlagen: {}
|
||||||
|
Failed to find user for token! : Konnte keinen Nutzer zum Token finden!
|
||||||
Failed to handle request\: {} : Konnte Anfrage nicht verarbeiten: {}
|
Failed to handle request\: {} : Konnte Anfrage nicht verarbeiten: {}
|
||||||
Failed to load file '{}'! : Laden der Datei '{}' fehlgeschlagen!
|
Failed to load file '{}'! : Laden der Datei '{}' fehlgeschlagen!
|
||||||
Failed to load list member for {}/{} : Laden der Mitgliedschaft zu {}/{} fehlgeschlagen!
|
Failed to load list member for {}/{} : Laden der Mitgliedschaft zu {}/{} fehlgeschlagen!
|
||||||
@@ -29,6 +31,7 @@ Failed to load user for {} : Laden des Nutzers zu {} fehlgeschlagen!
|
|||||||
Failed to load user for address {} : Laden des Nutzers für die Adresse {} fehlgeschlagen!
|
Failed to load user for address {} : Laden des Nutzers für die Adresse {} fehlgeschlagen!
|
||||||
Failed to make {} a moderator of {} : Ernennen von {} zum Moderator von {} fehlgeschlagen!
|
Failed to make {} a moderator of {} : Ernennen von {} zum Moderator von {} fehlgeschlagen!
|
||||||
Failed to make {} a subscriber of {} : Ernennen von {} zum regulären Abonnenten von {} fehlgeschlagen!
|
Failed to make {} a subscriber of {} : Ernennen von {} zum regulären Abonnenten von {} fehlgeschlagen!
|
||||||
|
Failed to send reset email\: Versenden der Passwort-Zurücksetzen-Mail fehlgeschlagen:
|
||||||
Failed to send email to {} : Senden der Email an {} fehlgeschlagen!
|
Failed to send email to {} : Senden der Email an {} fehlgeschlagen!
|
||||||
Failed to send request confirmation email\: {} : Senden der Bestätigungs-Email fehlgeschlagen: {}
|
Failed to send request confirmation email\: {} : Senden der Bestätigungs-Email fehlgeschlagen: {}
|
||||||
Failed to send test email to {} : Senden der Test-Email an {} fehlgeschlagen!
|
Failed to send test email to {} : Senden der Test-Email an {} fehlgeschlagen!
|
||||||
@@ -37,15 +40,18 @@ Failed to un-subscribe {} from {} : Abbestellen von {} / {} fehlgeschlagen!
|
|||||||
Failed to unsubscribe! : Abbestellen der Mailin-Liste fehlgeschlagen!
|
Failed to unsubscribe! : Abbestellen der Mailin-Liste fehlgeschlagen!
|
||||||
Failed to update list '{}' : Aktualisieren der Liste '{}' fehlgeschlagen!
|
Failed to update list '{}' : Aktualisieren der Liste '{}' fehlgeschlagen!
|
||||||
Failed to update MailingList! : Aktualisierung der Mailing-Liste fehlgeschlagen!
|
Failed to update MailingList! : Aktualisierung der Mailing-Liste fehlgeschlagen!
|
||||||
|
Failed to update password in database! : Aktualisierung des Passworts in der Datenbank fehlgeschlagen!
|
||||||
Fill all fields, please! : Bitte alle Felder ausfüllen!
|
Fill all fields, please! : Bitte alle Felder ausfüllen!
|
||||||
File {} does not exist! : Datei {} existiert nicht!
|
File {} does not exist! : Datei {} existiert nicht!
|
||||||
Find the forwarded message in the attachment(s)!\n : Die weitergeleitete Nachricht findest du im Anhang dieser E-Mail!\n
|
Find the forwarded message in the attachment(s)!\n : Die weitergeleitete Nachricht findest du im Anhang dieser E-Mail!\n
|
||||||
forward_attached : als Anhang weiterleiten
|
forward_attached : als Anhang weiterleiten
|
||||||
hidden : versteckt
|
hidden : versteckt
|
||||||
hide_receivers : Empfänger verbergen
|
hide_receivers : Empfänger verbergen
|
||||||
|
If that was you, please open the following link in your web browser\: : Falls Sie das waren, öffnen Sie den folgenden Link in einem Web-Browser:
|
||||||
|
If you did not expect this email, please ignore it. : Falls Sie diese Email nicht angefordert hatten, können Sie sie einfach ignorieren.
|
||||||
If you received this mail, the SMTP settings of your mailing list are correct. : Wenn Sie diese Nachricht empfangen haben, sind die SMTP-Einstellungen Ihrer Mailing-Liste korrekt.
|
If you received this mail, the SMTP settings of your mailing list are correct. : Wenn Sie diese Nachricht empfangen haben, sind die SMTP-Einstellungen Ihrer Mailing-Liste korrekt.
|
||||||
IMAP credentials are required! : IMAP-Zugangsdaten sind erforderlich!
|
IMAP credentials are required! : IMAP-Zugangsdaten sind erforderlich!
|
||||||
Invalid or missing token : Ungültiger oder fehlender Token!
|
Invalid or missing token! : Ungültiger oder fehlender Token!
|
||||||
Invalid username/password : Ungültiger Nutzername oder ungültiges Passwort!
|
Invalid username/password : Ungültiger Nutzername oder ungültiges Passwort!
|
||||||
Invalid email/password combination! : Ungültige E-Mail-/Passwort-Kombination!
|
Invalid email/password combination! : Ungültige E-Mail-/Passwort-Kombination!
|
||||||
List '{}' requires attention! : Liste '{}' erfordert Aufmerksamkeit!
|
List '{}' requires attention! : Liste '{}' erfordert Aufmerksamkeit!
|
||||||
@@ -54,12 +60,14 @@ List email ({}) is not a valid email address! : Listen-E-Mail-Adresse ({}) ist k
|
|||||||
List name and address are required! : Name und Adresse der Liste sind notwendige Felder!
|
List name and address are required! : Name und Adresse der Liste sind notwendige Felder!
|
||||||
made public : veröffentlicht
|
made public : veröffentlicht
|
||||||
Mailing list '{}' was {}! : Mailing-Liste '{}' wurde {}!
|
Mailing list '{}' was {}! : Mailing-Liste '{}' wurde {}!
|
||||||
|
Missing email address! : Email-Adresse fehlt!
|
||||||
Message deleted : Nachricht gelöscht
|
Message deleted : Nachricht gelöscht
|
||||||
missing user email address! : E-Mail-Adresse des Listenmitglieds nicht angegeben!
|
missing user email address! : E-Mail-Adresse des Listenmitglieds nicht angegeben!
|
||||||
Missing username or password! : Nutzername oder Passwort fehlen!
|
Missing username or password! : Nutzername oder Passwort fehlen!
|
||||||
moderator : Moderator
|
moderator : Moderator
|
||||||
Name and email are required fields for list subscription! : Name und E-Mail-Adresse sind für das Abonnieren der Mailingliste erforderlich!
|
Name and email are required fields for list subscription! : Name und E-Mail-Adresse sind für das Abonnieren der Mailingliste erforderlich!
|
||||||
no : nein
|
no : nein
|
||||||
|
no active List found! : keine aktive Verteilerliste gefunden!
|
||||||
No handler for path {}! : Kein Handler für den Pfad '{}'!
|
No handler for path {}! : Kein Handler für den Pfad '{}'!
|
||||||
no list email provided! : Keine Listen-Email übertragen!
|
no list email provided! : Keine Listen-Email übertragen!
|
||||||
No list provided by form data! : Formular-Daten enthalten keine Liste!
|
No list provided by form data! : Formular-Daten enthalten keine Liste!
|
||||||
@@ -74,21 +82,24 @@ original_from : ursprünglicher Absender
|
|||||||
owner : Besitzer
|
owner : Besitzer
|
||||||
Passwords do not match! : Passworte stimmen nicht überein!
|
Passwords do not match! : Passworte stimmen nicht überein!
|
||||||
Password to short or to simple! : Passwort zu kurz oder zu einfach!
|
Password to short or to simple! : Passwort zu kurz oder zu einfach!
|
||||||
|
Please set a password! : Bitte geben Sie ein Passwort ein!
|
||||||
Problem during unscubsription of {} from {}\: : Es ist ein Problem beim Austragen von {} aus der Liste {} aufgetreten:
|
Problem during unscubsription of {} from {}\: : Es ist ein Problem beim Austragen von {} aus der Liste {} aufgetreten:
|
||||||
public : öffentlich
|
public : öffentlich
|
||||||
Query '{}' failed\: : Query '{}' fehlgeschlagen:
|
Query '{}' failed\: : Query '{}' fehlgeschlagen:
|
||||||
reply_to_list : Antwort an Liste
|
reply_to_list : Antwort an Liste
|
||||||
|
Reset your password at {} : Passwort auf {} zurücksetzen
|
||||||
Sent confirmation mail to '{}. : Bestätigungs-Email wurde an '{} versendet.
|
Sent confirmation mail to '{}. : Bestätigungs-Email wurde an '{} versendet.
|
||||||
|
Somebody asked to reset your account password at {}. : Jemand hat eine Passwort-Änderung für Ihren Account auf {} angefordert.
|
||||||
SMTP credentials are required! : SMTP-Zugangsdaten sind erforderlich!
|
SMTP credentials are required! : SMTP-Zugangsdaten sind erforderlich!
|
||||||
subscriber : Abonniert
|
subscriber : Abonniert
|
||||||
Subscription failed\: {} : Abonnieren der Liste fehlgeschlagen: {}
|
Subscription failed\: {} : Abonnieren der Liste fehlgeschlagen: {}
|
||||||
Sucessfully updated MailingList! : Mailing-Liste aktualisiert!
|
Sucessfully updated MailingList! : Mailing-Liste aktualisiert!
|
||||||
Successfully subscribed '{}' to '{}'. : '{}' hat die Mailingliste '{}' erfolgreich abonniert.
|
Successfully subscribed '{}' to '{}'. : '{}' hat die Mailingliste '{}' erfolgreich abonniert.
|
||||||
Sucessfully un-subscribed from '{}'. : '{}' erfolgreich abbestellt.
|
Sucessfully un-subscribed from '{}'. : '{}' erfolgreich abbestellt.
|
||||||
Templates have been reloaded : Vorlagen wurden neu geladen!
|
Templates have been reloaded! : Vorlagen wurden neu geladen!
|
||||||
The mailing list you are trying to view does not exist! : Die Mailingliste, auf die Sie zugreifen wollen, gibt es nicht!
|
The mailing list you are trying to view does not exist! : Die Mailingliste, auf die Sie zugreifen wollen, gibt es nicht!
|
||||||
This list received an email from {}, who is not member of the list.\nThe email has been moved to the '{}' folder.\nYou may manually forward this message or drop it. : Diese Liste hat eine E-Mail von {} empfangen. Der Absender ist nicht Mitglied der Liste.\nDie Email wurde in den '{}'-Ordner verschoben.\nSie können die Nachricht manuell weiterleiten oder verwerfen.
|
This list received an email from {}, who is not member of the list.\nThe email has been moved to the '{}' folder.\nYou may manually forward this message or drop it. : Diese Liste hat eine E-Mail von {} empfangen. Der Absender ist nicht Mitglied der Liste.\nDie Email wurde in den '{}'-Ordner verschoben.\nSie können die Nachricht manuell weiterleiten oder verwerfen.
|
||||||
Unknown user or token : Nutzer oder Token unbekannt!
|
Unknown user or token! : Nutzer oder Token unbekannt!
|
||||||
Updated user permissions : Nutzer-Berechtigungen aktualisiert
|
Updated user permissions : Nutzer-Berechtigungen aktualisiert
|
||||||
User database is empty. Create admin user first\: : Nutzer-Datenbank ist leer. Admin-Nutzer wird hiermit angelegt:
|
User database is empty. Create admin user first\: : Nutzer-Datenbank ist leer. Admin-Nutzer wird hiermit angelegt:
|
||||||
Was not able to check existence of table {}! : Konnte Existenz der Tabelle {} nicht prüfen!
|
Was not able to check existence of table {}! : Konnte Existenz der Tabelle {} nicht prüfen!
|
||||||
@@ -96,6 +107,7 @@ Was not able to redirect to {} page\: {} : Weiterleitung nach {} fehlgeschlagen:
|
|||||||
yes : ja
|
yes : ja
|
||||||
You already are member of this list! : Sie haben diese Liste bereits abonniert!
|
You already are member of this list! : Sie haben diese Liste bereits abonniert!
|
||||||
You are not allowed to access the archive of this list! : Du hast keine Berechtigung, das Archiv dieser Liste anzusehen!
|
You are not allowed to access the archive of this list! : Du hast keine Berechtigung, das Archiv dieser Liste anzusehen!
|
||||||
|
You are not allowed to alter settings of this list! : Du hast keine Berechtigung, die Einstellungen dieser Liste zu ändern!
|
||||||
You are not allowed to alter user permissions! : Sie haben nicht die Berechtigung, um Berechtigungen zu ändern!
|
You are not allowed to alter user permissions! : Sie haben nicht die Berechtigung, um Berechtigungen zu ändern!
|
||||||
You are not allowed to create new mailing lists! : Ihnen ist es nicht gestattet, neue Mailinglisten anzulegen!
|
You are not allowed to create new mailing lists! : Ihnen ist es nicht gestattet, neue Mailinglisten anzulegen!
|
||||||
You are not allowed to edit '{}' : Du bist nicht berechtigt, '{}' zu bearbeiten!
|
You are not allowed to edit '{}' : Du bist nicht berechtigt, '{}' zu bearbeiten!
|
||||||
@@ -113,3 +125,5 @@ You are trying to access a non-existing list! : Du versuchst auf eine nicht exis
|
|||||||
You have tried to send a message to the list '{}', which failed. This is because you are not a (privileged) member of this list.\n : Sie haben versucht, eine Nachricht an die Liste '{}' zu senden. Das wurde verweigert, da Sie kein Mitglied der Liste (mit entsprechenden Berechtigungen) sind.\n
|
You have tried to send a message to the list '{}', which failed. This is because you are not a (privileged) member of this list.\n : Sie haben versucht, eine Nachricht an die Liste '{}' zu senden. Das wurde verweigert, da Sie kein Mitglied der Liste (mit entsprechenden Berechtigungen) sind.\n
|
||||||
You may go to {} and subscribe to the list, then try again. : Sie können zu {} gehen und die Liste abonnieren. Versuchen Sie es danach erneut.
|
You may go to {} and subscribe to the list, then try again. : Sie können zu {} gehen und die Liste abonnieren. Versuchen Sie es danach erneut.
|
||||||
Your message to {} was rejected! : Ihre Nachricht an {} wurde zurückgewiesen!
|
Your message to {} was rejected! : Ihre Nachricht an {} wurde zurückgewiesen!
|
||||||
|
Your password is to simple! : Ihr Passwort ist zu einfach!
|
||||||
|
Your password has been updated! : Ihr Passwort wurde aktualisiert!
|
||||||
@@ -4,6 +4,7 @@ import junit.framework.TestCase;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
import static de.srsoftware.widerhall.Util.*;
|
||||||
|
|
||||||
public class UtilTest extends TestCase {
|
public class UtilTest extends TestCase {
|
||||||
|
|
||||||
@@ -17,17 +18,17 @@ public class UtilTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testHex(){
|
public void testHex(){
|
||||||
assertEquals("00",Util.hex(0));
|
assertEquals("00",hex(0));
|
||||||
assertEquals("09",Util.hex(9));
|
assertEquals("09",hex(9));
|
||||||
assertEquals("0A",Util.hex(10));
|
assertEquals("0A",hex(10));
|
||||||
assertEquals("0F",Util.hex(15));
|
assertEquals("0F",hex(15));
|
||||||
assertEquals("10",Util.hex(16));
|
assertEquals("10",hex(16));
|
||||||
assertEquals("19",Util.hex(25));
|
assertEquals("19",hex(25));
|
||||||
assertEquals("FF",Util.hex(255));
|
assertEquals("FF",hex(255));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSha256() {
|
public void testSha256() {
|
||||||
assertEquals("9F722959A023C02A3BA0FAFDBA81ADED642D6610EFF5DCA32DCE35132E16B6C5",Util.sha256("Dies ist ein Test"));
|
assertEquals("9F722959A023C02A3BA0FAFDBA81ADED642D6610EFF5DCA32DCE35132E16B6C5",sha256("Dies ist ein Test"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTranslate() {
|
public void testTranslate() {
|
||||||
@@ -35,30 +36,40 @@ public class UtilTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testIsEmail() {
|
public void testIsEmail() {
|
||||||
assertFalse(Util.isEmail("Test"));
|
assertFalse(isEmail("Test"));
|
||||||
assertFalse(Util.isEmail("Test@"));
|
assertFalse(isEmail("Test@"));
|
||||||
assertFalse(Util.isEmail("@Test"));
|
assertFalse(isEmail("@Test"));
|
||||||
assertTrue(Util.isEmail("Test@Domain"));
|
assertTrue(isEmail("Test@Domain"));
|
||||||
assertFalse(Util.isEmail("Test@Domain@Test"));
|
assertFalse(isEmail("Test@Domain@Test"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSimplePassword() {
|
public void testSimplePassword() {
|
||||||
assertTrue(Util.simplePassword("$@%€#")); // too short
|
assertTrue(simplePassword("$@%€#")); // too short
|
||||||
assertTrue(Util.simplePassword("test123")); // no special chars
|
assertTrue(simplePassword("test123")); // no special chars
|
||||||
assertFalse(Util.simplePassword("test$23")); // contains special chars
|
assertFalse(simplePassword("test$23")); // contains special chars
|
||||||
assertTrue(Util.simplePassword("skgjafdsg")); // chars only
|
assertTrue(simplePassword("skgjafdsg")); // chars only
|
||||||
assertTrue(Util.simplePassword("986535465")); // digits only
|
assertTrue(simplePassword("986535465")); // digits only
|
||||||
assertFalse(Util.simplePassword("test9523")); // mixed digits and chars
|
assertFalse(simplePassword("test9523")); // mixed digits and chars
|
||||||
assertFalse(Util.simplePassword("8986546054")); // digits only, but long enough
|
assertFalse(simplePassword("8986546054")); // digits only, but long enough
|
||||||
assertFalse(Util.simplePassword("salgksdjbw")); // chars only, but long enough
|
assertFalse(simplePassword("salgksdjbw")); // chars only, but long enough
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUnsetFlags(){
|
public void testUnsetFlags(){
|
||||||
assertEquals(0,Util.unset(31,1,2,4,8,16));
|
assertEquals(0,unset(31,1,2,4,8,16));
|
||||||
assertEquals(1,Util.unset(31,2,4,8,16));
|
assertEquals(1,unset(31,2,4,8,16));
|
||||||
assertEquals(2,Util.unset(31,1,4,8,16));
|
assertEquals(2,unset(31,1,4,8,16));
|
||||||
assertEquals(4,Util.unset(31,1,2,8,16));
|
assertEquals(4,unset(31,1,2,8,16));
|
||||||
assertEquals(8,Util.unset(31,1,2,4,16));
|
assertEquals(8,unset(31,1,2,4,16));
|
||||||
assertEquals(16,Util.unset(31,1,2,4,8));
|
assertEquals(16,unset(31,1,2,4,8));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBoundedChar(){
|
||||||
|
assertEquals('0',boundedChar(0));
|
||||||
|
assertEquals('9',boundedChar(9));
|
||||||
|
assertEquals('A',boundedChar(10));
|
||||||
|
assertEquals('Z',boundedChar(35));
|
||||||
|
assertEquals('a',boundedChar(36));
|
||||||
|
assertEquals('z',boundedChar(61));
|
||||||
|
assertEquals('0',boundedChar(62));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,7 +110,7 @@ public class ListMemberTest extends TestCase {
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
public void testSafeMap() {
|
public void testSafeMap() {
|
||||||
var user = new User("email","name","salt","hash",0);
|
var user = new User("email","name","salt","hash",null,0);
|
||||||
var lm = new ListMember(null,user,ListMember.STATE_AWAITING_CONFIRMATION,"token");
|
var lm = new ListMember(null,user,ListMember.STATE_AWAITING_CONFIRMATION,"token");
|
||||||
assertEquals(Map.of(EMAIL,"email",NAME,"name",STATE,"erwartet Bestätigung"),lm.safeMap());
|
assertEquals(Map.of(EMAIL,"email",NAME,"name",STATE,"erwartet Bestätigung"),lm.safeMap());
|
||||||
}
|
}
|
||||||
@@ -137,7 +137,7 @@ public class ListMemberTest extends TestCase {
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
public void testUser() {
|
public void testUser() {
|
||||||
var user = new User("email","name","salt","hash",0);
|
var user = new User("email","name","salt","hash",null,0);
|
||||||
var lm = new ListMember(null,user,ListMember.STATE_AWAITING_CONFIRMATION,"token");
|
var lm = new ListMember(null,user,ListMember.STATE_AWAITING_CONFIRMATION,"token");
|
||||||
assertEquals(user,lm.user());
|
assertEquals(user,lm.user());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
«navigation()»
|
«navigation()»
|
||||||
«userinfo()»
|
«userinfo()»
|
||||||
«messages()»
|
«messages()»
|
||||||
<h1>Widerhall List Creation</h1>
|
<h1>Widerhall Listen-Erzeugung</h1>
|
||||||
«list_data_form()»
|
«list_data_form()»
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
«navigation()»
|
«navigation()»
|
||||||
«userinfo()»
|
«userinfo()»
|
||||||
«messages()»
|
«messages()»
|
||||||
<h1>Widerhall List Setup</h1>
|
<h1>Widerhall Listen-Bearbeitung</h1>
|
||||||
«list_data_form()»
|
«list_data_form()»
|
||||||
«footer()»
|
«footer()»
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -19,5 +19,6 @@
|
|||||||
<button type="submit">Einloggen…</button>
|
<button type="submit">Einloggen…</button>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
|
<a href="reset-pw«if(data.email)»?email=«data.email»«endif»">Forgot password?</a>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
33
static/templates/new_password_form.st
Normal file
33
static/templates/new_password_form.st
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
«head()»
|
||||||
|
«userinfo()»
|
||||||
|
|
||||||
|
<body id="login">
|
||||||
|
«navigation()»
|
||||||
|
«messages()»
|
||||||
|
<h1>neues Account-Passwort setzen</h1>
|
||||||
|
<form method="POST">
|
||||||
|
<fieldset>
|
||||||
|
|
||||||
|
Hallo «if(data.user.name)»«data.user.name»«else»«data.user.email»«endif»! Du kannst hier ein neues Passwort für deinen Account «data.email» setzen:
|
||||||
|
<legend>Login-Daten</legend>
|
||||||
|
<label>
|
||||||
|
<input enabled="false" value="«data.user.email»" />
|
||||||
|
Email-Adresse
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input type="password" name="password" value="" id="password" />
|
||||||
|
Passwort
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input type="password" name="password-repeat" value="" id="password-repeat" />
|
||||||
|
Passwort (Wiederholung)
|
||||||
|
</label>
|
||||||
|
<input type="hidden" name="token" value="«data.token»" />
|
||||||
|
<button type="submit">neues Passwort speichern</button>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
<a href="reset-pw">Passwort vergessen?</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
22
static/templates/reset-pw.st
Normal file
22
static/templates/reset-pw.st
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
«head()»
|
||||||
|
<body id="login">
|
||||||
|
«navigation()»
|
||||||
|
«messages()»
|
||||||
|
<h1>Widerhall Passwort-Hilfe</h1>
|
||||||
|
<form method="POST">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Passwort verloren?</legend>
|
||||||
|
Falls Sie ihr Passwort vergessen oder verloren haben, geben Sie bitte unten Ihre Emailadresse ein.
|
||||||
|
Nach dem Klicken des „Passwort zurücksetzen“-Links bekommen Sie eine Email mit einem Link.
|
||||||
|
Dieser Link erlaubt es Ihnen, ein neues Passwort zu vergeben.
|
||||||
|
<label>
|
||||||
|
<input type="text" name="email" value="«data.email»" id="email" />
|
||||||
|
Email-Adresse
|
||||||
|
</label>
|
||||||
|
<button type="submit">Passwort zurücksetzen</button>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
18
static/templates/reset_link_sent.st
Normal file
18
static/templates/reset_link_sent.st
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
«head()»
|
||||||
|
<body id="login">
|
||||||
|
«navigation()»
|
||||||
|
«messages()»
|
||||||
|
|
||||||
|
<h1>Bestätigung</h1>
|
||||||
|
<fieldset>
|
||||||
|
<legend>
|
||||||
|
Link gesendet
|
||||||
|
</legend>
|
||||||
|
Ihnen wurde eine Email gesendet:<br/>
|
||||||
|
Diese Mail enthält einen Link, welches beweist, dass Sie diese Emailadresse besitzen.
|
||||||
|
Wenn Sie den empfangenen Link in einem Webbrowser öffnen, können Sie ein neues Passwort vergeben.
|
||||||
|
</fieldset>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -11,11 +11,11 @@
|
|||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Abonnieren von "«data.list»"</legend>
|
<legend>Abonnieren von "«data.list»"</legend>
|
||||||
<label>
|
<label>
|
||||||
<input type="text" name="name" value="«if(data.name)»«data.name»«else»«data.user.name»«endif»">
|
<input type="text" name="name" value="«if(data.user)»«data.user.name»«else»«data.name»«endif»">
|
||||||
Name
|
Name
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<input type="text" name="email" value="«if(data.email)»«data.email»«else»«data.user.email»«endif»">
|
<input type="text" name="email" value="«if(data.user)»«data.user.email»«else»«data.email»«endif»">
|
||||||
E-Mail
|
E-Mail
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
|
|||||||
Reference in New Issue
Block a user