working on string-templated based static pages
This commit is contained in:
@@ -3,23 +3,16 @@ package de.srsoftware.widerhall;
|
||||
import de.srsoftware.widerhall.mail.Forwarder;
|
||||
import de.srsoftware.widerhall.mail.ImapClient;
|
||||
import de.srsoftware.widerhall.mail.MessageHandler;
|
||||
import de.srsoftware.widerhall.web.Index;
|
||||
import de.srsoftware.widerhall.web.Login;
|
||||
import de.srsoftware.widerhall.web.Static;
|
||||
import de.srsoftware.widerhall.web.Rest;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.server.session.SessionHandler;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import static de.srsoftware.widerhall.Constants.*;
|
||||
|
||||
public class Application {
|
||||
|
||||
@@ -33,11 +26,12 @@ public class Application {
|
||||
var server = new Server();
|
||||
var connector = new ServerConnector(server);
|
||||
connector.setPort(config.serverPort());
|
||||
|
||||
SessionHandler sh = new SessionHandler();
|
||||
server.setConnectors(new Connector[]{connector});
|
||||
ServletContextHandler context = new ServletContextHandler(server, "/");
|
||||
ServletContextHandler context = new ServletContextHandler(server, "/",sh,null,null,null);
|
||||
context.addServlet(Rest.class,"/api");
|
||||
context.addServlet(Login.class,"/login");
|
||||
context.addServlet(Index.class,"/");
|
||||
context.addServlet(Static.class,"/static/*");
|
||||
|
||||
server.start();
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ public class Configuration {
|
||||
|
||||
private void setDefaults() throws MalformedURLException {
|
||||
if (data == null) data = new JSONObject();
|
||||
baseDir();
|
||||
serverPort();
|
||||
tokenUrl();
|
||||
loginUrl();
|
||||
@@ -70,12 +71,22 @@ public class Configuration {
|
||||
}
|
||||
|
||||
public String clientId() {
|
||||
if (!data.containsKey(Constants.CLIENT_ID)) data.put(CLIENT_ID,"widerhall");
|
||||
if (!data.containsKey(CLIENT_ID)) data.put(CLIENT_ID,"widerhall");
|
||||
return (String) data.get(CLIENT_ID);
|
||||
}
|
||||
|
||||
public Object clientSecret() {
|
||||
if (!data.containsKey(Constants.CLIENT_SECRET)) data.put(CLIENT_SECRET,"changeme");
|
||||
if (!data.containsKey(CLIENT_SECRET)) data.put(CLIENT_SECRET,"changeme");
|
||||
return (String) data.get(CLIENT_SECRET);
|
||||
}
|
||||
|
||||
public String dbLocation() {
|
||||
if (!data.containsKey(DB_FILE)) data.put(DB_FILE,System.getProperty("user.home")+"/.config/widerhall/db.sqlite3");
|
||||
return (String) data.get(DB_FILE);
|
||||
}
|
||||
|
||||
public String baseDir() {
|
||||
if (!data.containsKey(Constants.BASE_DIR)) data.put(BASE_DIR,System.getProperty("user.dir")+"/static");
|
||||
return (String) data.get(BASE_DIR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,4 +13,6 @@ public class Constants {
|
||||
public static final String BASE_URL = "base_url";
|
||||
public static final String CLIENT_ID = "client_id";
|
||||
public static final String CLIENT_SECRET = "client_secret";
|
||||
public static final String DB_FILE = "db_file";
|
||||
public static final String BASE_DIR = "base_dir";
|
||||
}
|
||||
|
||||
65
src/main/java/de/srsoftware/widerhall/Util.java
Normal file
65
src/main/java/de/srsoftware/widerhall/Util.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package de.srsoftware.widerhall;
|
||||
|
||||
import de.srsoftware.examples.translations.App;
|
||||
import de.srsoftware.tools.translations.Translation;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Util {
|
||||
|
||||
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-]+)*$";
|
||||
|
||||
public static String urlEncode(Map<String, Object> data) {
|
||||
String params = data.entrySet()
|
||||
.stream()
|
||||
.map(entry -> encode(entry.getKey()) + "=" + encode(entry.getValue()))
|
||||
.collect(Collectors.joining("&"));
|
||||
return params;
|
||||
}
|
||||
|
||||
private static String encode(Object value) {
|
||||
return URLEncoder.encode(value.toString(), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
|
||||
public static MessageDigest getSha256() {
|
||||
try {
|
||||
return MessageDigest.getInstance("SHA-256");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String sha256(String s) {
|
||||
byte[] bytes = SHA256.digest(s.getBytes(StandardCharsets.UTF_8));
|
||||
return hex(bytes);
|
||||
}
|
||||
|
||||
private static String hex(byte[] bytes) {
|
||||
StringBuffer buf = new StringBuffer(bytes.length*2);
|
||||
for (var byt : bytes) buf.append(hex(byt));
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private static String hex(byte b){
|
||||
return (b<16 ? "0" : "") + Integer.toHexString(b);
|
||||
}
|
||||
|
||||
public static String t(String tx, Object ... fills){
|
||||
return Translation.get(Application.class,tx,fills);
|
||||
}
|
||||
|
||||
public static boolean isEmail(String email) {
|
||||
return email.matches(EMAIL_PATTERN);
|
||||
}
|
||||
}
|
||||
167
src/main/java/de/srsoftware/widerhall/data/Database.java
Normal file
167
src/main/java/de/srsoftware/widerhall/data/Database.java
Normal file
@@ -0,0 +1,167 @@
|
||||
package de.srsoftware.widerhall.data;
|
||||
|
||||
import de.srsoftware.widerhall.Configuration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
|
||||
import static de.srsoftware.widerhall.Util.t;
|
||||
|
||||
public class Database {
|
||||
public static final String EMAIL = "email";
|
||||
public static final String NAME = "name";
|
||||
public static final String HASHED_PASS = "hashedPassword";
|
||||
public static final String SALT = "salt";
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Database.class);
|
||||
private static final String VARCHAR = "VARCHAR(255)";
|
||||
private static Database singleton = null;
|
||||
private static Connection conn;
|
||||
|
||||
public Request insertInto(String tbName) {
|
||||
return query("INSERT INTO "+tbName);
|
||||
}
|
||||
|
||||
public class Request{
|
||||
|
||||
private final String sql;
|
||||
private HashMap<String,List<Object>> where = new HashMap<>();
|
||||
private HashMap<String,Object> values = 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, Object value) {
|
||||
var list = where.get(key);
|
||||
if (list == null) where.put(key,list = new ArrayList<Object>());
|
||||
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 {
|
||||
var sb = new StringBuilder(sql);
|
||||
var args = new ArrayList<Object>();
|
||||
if (!values.isEmpty()){
|
||||
var keys = new ArrayList<String>();
|
||||
for (var entry : values.entrySet()) {
|
||||
keys.add(entry.getKey());
|
||||
args.add(entry.getValue());
|
||||
}
|
||||
sb.append("("+String.join(", ",keys)+")");
|
||||
sb.append(" VALUES ");
|
||||
var arr = new String[args.size()];
|
||||
Arrays.fill(arr,"?");
|
||||
var marks = String.join(", ",arr);
|
||||
sb.append("(").append(marks).append(")");
|
||||
}
|
||||
var sql = sb.toString();
|
||||
LOG.debug(sql);
|
||||
try {
|
||||
var stmt = conn.prepareStatement(sql);
|
||||
if (!args.isEmpty()) {
|
||||
for (int i = 0; i < args.size(); i++) stmt.setObject(i+1, args.get(i));
|
||||
}
|
||||
stmt.execute();
|
||||
} catch (SQLException sqle) {
|
||||
throw new SQLException(t("Query '{}' failed:",sql),sqle);
|
||||
}
|
||||
}
|
||||
|
||||
public ResultSet exec() throws SQLException {
|
||||
var sb = new StringBuilder(sql);
|
||||
var args = new ArrayList<Object>();
|
||||
if (!where.isEmpty()){
|
||||
var clauses = new ArrayList<String>();
|
||||
sb.append(" WHERE ");
|
||||
|
||||
for (var entry : where.entrySet()){
|
||||
var arr = new String[entry.getValue().size()];
|
||||
Arrays.fill(arr,"?");
|
||||
var marks = String.join(", ",arr);
|
||||
clauses.add("("+entry.getKey()+" IN ("+marks+"))");
|
||||
args.addAll(entry.getValue());
|
||||
}
|
||||
sb.append(String.join(" AND ",clauses));
|
||||
|
||||
}
|
||||
var sql = sb.toString();
|
||||
LOG.debug(sql);
|
||||
try {
|
||||
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();
|
||||
} catch (SQLException sqle) {
|
||||
throw new SQLException(t("Query '{}' failed:",sql),sqle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Database(Connection connection) {
|
||||
this.conn = connection;
|
||||
}
|
||||
|
||||
public static Database open() {
|
||||
if (singleton == null){
|
||||
Configuration config = Configuration.instance();
|
||||
String dbFile = config.dbLocation();
|
||||
String url = "jdbc:sqlite:"+dbFile;
|
||||
LOG.debug("Opening {}",url);
|
||||
new File(dbFile).getParentFile().mkdirs();
|
||||
try {
|
||||
singleton = new Database(DriverManager.getConnection(url)).assertTables();
|
||||
} catch (SQLException sqle) {
|
||||
sqle.printStackTrace();
|
||||
}
|
||||
}
|
||||
return singleton;
|
||||
}
|
||||
|
||||
private Database assertTables() throws SQLException {
|
||||
if (!tableExists("Users")) createUsersTable();
|
||||
return this;
|
||||
}
|
||||
|
||||
private void createUsersTable() throws SQLException {
|
||||
query("CREATE TABLE Users ("+EMAIL+" "+ VARCHAR +", "+SALT+" "+VARCHAR+", "+HASHED_PASS+" "+VARCHAR+", "+NAME+" "+VARCHAR+");").run();
|
||||
}
|
||||
|
||||
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();
|
||||
int val = 0;
|
||||
if (rs.next()) val = rs.getInt(1);
|
||||
rs.close();
|
||||
return val > 0;
|
||||
} catch (SQLException e) {
|
||||
throw new SQLException(t("Was not able to check existence of table {}!",tbName),e);
|
||||
}
|
||||
}
|
||||
|
||||
public Request query(String sql) {
|
||||
return new Request(sql);
|
||||
}
|
||||
}
|
||||
80
src/main/java/de/srsoftware/widerhall/data/User.java
Normal file
80
src/main/java/de/srsoftware/widerhall/data/User.java
Normal file
@@ -0,0 +1,80 @@
|
||||
package de.srsoftware.widerhall.data;
|
||||
|
||||
import de.srsoftware.widerhall.Util;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Map;
|
||||
|
||||
import static de.srsoftware.widerhall.data.Database.*;
|
||||
|
||||
public class User {
|
||||
private static Database database = Database.open();
|
||||
private String email, salt, hashedPass, name;
|
||||
|
||||
public User(String email, String name, String salt, String hashedPass) {
|
||||
this.email = email;
|
||||
this.name = name;
|
||||
this.salt = salt;
|
||||
this.hashedPass = hashedPass;
|
||||
}
|
||||
|
||||
public static User create(String email, String name, String password) throws SQLException {
|
||||
var salt = Util.sha256(email + name + LocalDate.now());
|
||||
var hashedPass = Util.sha256(password+salt);
|
||||
return new User(email,name,salt,hashedPass).save();
|
||||
}
|
||||
|
||||
public static User load(String email, String password) throws InvalidKeyException, SQLException {
|
||||
ResultSet rs = database
|
||||
.query("SELECT * FROM Users")
|
||||
.where(EMAIL,email)
|
||||
.exec();
|
||||
|
||||
try {
|
||||
if (rs.next()) {
|
||||
email = rs.getString(EMAIL);
|
||||
var name = rs.getString(NAME);
|
||||
var hashedPassword = rs.getString(HASHED_PASS);
|
||||
var salt = rs.getString(SALT);
|
||||
var loadedUser = new User(email, name, salt, hashedPassword);
|
||||
if (loadedUser.matching(password)) return loadedUser;
|
||||
} else if (noUsers()){
|
||||
return User.create(email,"Admin",password);
|
||||
}
|
||||
} finally {
|
||||
rs.close();
|
||||
}
|
||||
|
||||
throw new InvalidKeyException();
|
||||
}
|
||||
|
||||
private static boolean noUsers() throws SQLException {
|
||||
var rs = database.query("SELECT count(*) FROM users").exec();
|
||||
try {
|
||||
if (rs.next()) {
|
||||
return rs.getInt(1) < 1;
|
||||
}
|
||||
} finally {
|
||||
rs.close();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean matching(String password) {
|
||||
return hashedPass.equals(Util.sha256(password+salt));
|
||||
}
|
||||
|
||||
private User save() throws SQLException {
|
||||
database.insertInto("Users")
|
||||
.values(Map.of(EMAIL,email,NAME,name,SALT,salt,HASHED_PASS,hashedPass))
|
||||
.run();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Map<String,String> map() {
|
||||
return Map.of(EMAIL,email,NAME,name);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package de.srsoftware.widerhall.web;
|
||||
|
||||
import de.srsoftware.tools.Tag;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public class Index extends HttpServlet {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Index.class);
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
resp.setContentType("text/html");
|
||||
resp.setStatus(HttpServletResponse.SC_OK);
|
||||
String auth = req.getHeader("Authorization");
|
||||
if (auth == null) {
|
||||
resp.sendRedirect("login");
|
||||
return;
|
||||
}
|
||||
LOG.debug("Authorization: {}",auth);
|
||||
|
||||
resp.getWriter().println(page(auth));
|
||||
|
||||
}
|
||||
|
||||
private Tag head() {
|
||||
return new Tag("meta")
|
||||
.attr("charset","utf-8")
|
||||
.addTo(new Tag("head"));
|
||||
|
||||
}
|
||||
|
||||
private Tag page(String auth) {
|
||||
var body = new Tag("body").content(auth);
|
||||
return body.addTo(head().addTo(new Tag("html")));
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
package de.srsoftware.widerhall.web;
|
||||
|
||||
import de.srsoftware.widerhall.Configuration;
|
||||
import de.srsoftware.widerhall.web.tags.Page;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Login extends HttpServlet {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Login.class);
|
||||
private final Configuration config;
|
||||
|
||||
public Login(){
|
||||
this.config = Configuration.instance();
|
||||
LOG.debug("Creating new instance of Login.class");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
var error = req.getParameter("error");
|
||||
if (error != null){
|
||||
var description = req.getParameter("error_description");
|
||||
sendError(resp,error+": "+description);
|
||||
return;
|
||||
}
|
||||
LOG.debug("params: {}",req.getParameterMap());
|
||||
var code = req.getParameter("code");
|
||||
if (code != null){
|
||||
getTokenFor(code,resp);
|
||||
resp.getWriter().println(new Page("rceived code: "+code));
|
||||
return;
|
||||
}
|
||||
resp.sendRedirect(loginUrl());
|
||||
}
|
||||
|
||||
private static String urlEncode(Map<String, Object> data) {
|
||||
String params = data.entrySet()
|
||||
.stream()
|
||||
.map(entry -> encode(entry.getKey()) + "=" + encode(entry.getValue()))
|
||||
.collect(Collectors.joining("&"));
|
||||
return params;
|
||||
}
|
||||
|
||||
private static String encode(Object value) {
|
||||
return URLEncoder.encode(value.toString(),StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private void getTokenFor(String code, HttpServletResponse resp) throws IOException {
|
||||
var url = config.tokenUrl();
|
||||
LOG.debug("Sending 'POST' request to URL '{}'",url);
|
||||
HttpsURLConnection httpClient = (HttpsURLConnection) url.openConnection();
|
||||
|
||||
//add reuqest header
|
||||
httpClient.setRequestMethod("POST");
|
||||
httpClient.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded");
|
||||
httpClient.setRequestProperty( "Accept", "*/*" );
|
||||
//httpClient.setRequestProperty("User-Agent", "Mozilla/5.0");
|
||||
//httpClient.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
|
||||
|
||||
String urlParameters = urlEncode(Map.of(
|
||||
"code",code,
|
||||
"client_id",config.clientId(),
|
||||
"client_secret",config.clientSecret(),
|
||||
"grant_type","authorization_code"));
|
||||
|
||||
LOG.debug("Posting parameters '{}'",urlParameters);
|
||||
|
||||
// Send post request
|
||||
httpClient.setDoOutput(true);
|
||||
httpClient.setDoInput(true);
|
||||
try (DataOutputStream wr = new DataOutputStream(httpClient.getOutputStream())) {
|
||||
wr.writeBytes(urlParameters);
|
||||
wr.flush();
|
||||
}
|
||||
|
||||
int responseCode = httpClient.getResponseCode();
|
||||
LOG.debug("Response Code: {}",responseCode);
|
||||
|
||||
try (BufferedReader in = new BufferedReader(new InputStreamReader(httpClient.getInputStream()))) {
|
||||
|
||||
String line;
|
||||
StringBuilder response = new StringBuilder();
|
||||
|
||||
while ((line = in.readLine()) != null) {
|
||||
response.append(line);
|
||||
}
|
||||
|
||||
//print result
|
||||
//System.out.println(response.toString());
|
||||
resp.getWriter().println(response);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void sendError(HttpServletResponse resp, String error) throws IOException {
|
||||
LOG.debug("error: {}",error);
|
||||
resp.sendError(HttpServletResponse.SC_BAD_REQUEST,error);
|
||||
}
|
||||
|
||||
private String loginUrl() {
|
||||
return config.loginUrl()+"?"+urlEncode(Map.of(
|
||||
"response_type","code",
|
||||
"client_id",config.clientId(),
|
||||
"state",123456,
|
||||
"redirect_uri",redirectUri(),
|
||||
"scope","openid"
|
||||
));
|
||||
}
|
||||
|
||||
private String redirectUri() {
|
||||
int port = config.serverPort();
|
||||
return config.baseUrl()+(port == 80 ? "" : ":"+port)+"/login";
|
||||
}
|
||||
}
|
||||
138
src/main/java/de/srsoftware/widerhall/web/Static.java
Normal file
138
src/main/java/de/srsoftware/widerhall/web/Static.java
Normal file
@@ -0,0 +1,138 @@
|
||||
package de.srsoftware.widerhall.web;
|
||||
|
||||
import de.srsoftware.widerhall.Configuration;
|
||||
import de.srsoftware.widerhall.Util;
|
||||
import de.srsoftware.widerhall.data.User;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.stringtemplate.v4.STGroup;
|
||||
import org.stringtemplate.v4.STGroupDir;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Map;
|
||||
|
||||
import static de.srsoftware.widerhall.Util.t;
|
||||
|
||||
public class Static extends HttpServlet {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Static.class);
|
||||
private final String baseDir;
|
||||
private final STGroup templates;
|
||||
|
||||
public Static(){
|
||||
var config = Configuration.instance();
|
||||
baseDir = config.baseDir();
|
||||
var templateDir = String.join(File.separator,baseDir,"templates");
|
||||
templates = new STGroupDir(templateDir,'{','}');
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String error = handleGet(req, resp);
|
||||
if (error != null) resp.sendError(400,error);
|
||||
}
|
||||
|
||||
private String handleGet(HttpServletRequest req, HttpServletResponse resp) {
|
||||
var path = req.getPathInfo();
|
||||
path = path == null ? "index" : path.substring(1);
|
||||
switch (path){
|
||||
case "css":
|
||||
return loadFile("style.css",resp);
|
||||
case "js":
|
||||
return loadFile("widerhall.js",resp);
|
||||
case "jquery":
|
||||
return loadFile("jquery-3.6.0.min.js",resp);
|
||||
case "login":
|
||||
return loadTemplate(path, null, resp);
|
||||
}
|
||||
|
||||
var u = req.getSession().getAttribute("user");
|
||||
if (u instanceof User user){
|
||||
Map<String,Object> data = Map.of("user",user.map());
|
||||
return loadTemplate(path,data,resp);
|
||||
}
|
||||
return loginRedirect(resp);
|
||||
}
|
||||
|
||||
private String loadTemplate(String path, Map<String, ? extends Object> data, HttpServletResponse resp) {
|
||||
var template = templates.getInstanceOf(path);
|
||||
if (template != null){
|
||||
try {
|
||||
template.add("data",data);
|
||||
resp.getWriter().println(template.render());
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
return t("Failed to load template '{}'",path);
|
||||
}
|
||||
}
|
||||
return t("No template for path {}!",path);
|
||||
}
|
||||
|
||||
|
||||
private String loginRedirect(HttpServletResponse resp) {
|
||||
try {
|
||||
resp.sendRedirect("/static/login");
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
return t("Was not able to redirect to login page: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private String loadFile(String filename, HttpServletResponse resp) {
|
||||
var path = String.join(File.separator,baseDir,filename);
|
||||
LOG.debug("loading {}",path);
|
||||
var file = new File(path);
|
||||
if (!file.exists()) return t("File {} does not exist!",filename);
|
||||
try {
|
||||
var content = Files.readString(file.toPath());
|
||||
resp.getWriter().println(content);
|
||||
} catch (IOException e) {
|
||||
return t("Failed to load file '{}'!",filename);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String error = handlePost(req, resp);
|
||||
if (error != null) resp.sendError(400,error);
|
||||
}
|
||||
|
||||
private String handlePost(HttpServletRequest req, HttpServletResponse resp) {
|
||||
var path = req.getPathInfo();
|
||||
if (path == null) path = "/";
|
||||
switch (path){
|
||||
case "/login":
|
||||
return handleLogin(req,resp);
|
||||
}
|
||||
|
||||
return t("No handler for path {}!",path);
|
||||
}
|
||||
|
||||
private String handleLogin(HttpServletRequest req, HttpServletResponse resp) {
|
||||
var email = req.getParameter("email");
|
||||
var pass = req.getParameter("pass");
|
||||
if (email == null || pass == null) return loginRedirect(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,pass);
|
||||
req.getSession().setAttribute("user",user);
|
||||
resp.sendRedirect("/static");
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
LOG.warn("Static.handleLogin failed:",e);
|
||||
Thread.sleep(10000);
|
||||
} finally {
|
||||
return loadTemplate("login", Map.of("error",t("Invalid username/password")), resp);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package de.srsoftware.widerhall.web.tags;
|
||||
|
||||
import de.srsoftware.tools.Tag;
|
||||
|
||||
public class Header extends Tag {
|
||||
public Header() {
|
||||
super("head");
|
||||
new Tag("meta").attr("charset","utf-8").addTo(this);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package de.srsoftware.widerhall.web.tags;
|
||||
|
||||
import de.srsoftware.tools.Tag;
|
||||
|
||||
public class Page extends Tag {
|
||||
public Page(String content) {
|
||||
super("html");
|
||||
new Header().addTo(this);
|
||||
new Tag("body").content(content).addTo(this);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user