From 26df2e565455dabbe5c378c49e9e4ba06eab5c9d Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Fri, 15 Apr 2022 11:33:28 +0200 Subject: [PATCH] working on configuration --- .gitignore | 2 + config/config.template.json | 5 + pom.xml | 8 +- .../de/srsoftware/widerhall/Application.java | 19 +-- .../srsoftware/widerhall/Configuration.java | 114 ++++++++++-------- .../de/srsoftware/widerhall/Constants.java | 6 +- .../srsoftware/widerhall/data/Database.java | 4 +- .../widerhall/web/{Static.java => Web.java} | 24 ++-- static/templates/css.st | 23 ++++ static/templates/index.st | 11 +- static/{widerhall.js => templates/js.st} | 0 static/templates/login.st | 56 +++++---- 12 files changed, 158 insertions(+), 114 deletions(-) create mode 100644 config/config.template.json rename src/main/java/de/srsoftware/widerhall/web/{Static.java => Web.java} (87%) create mode 100644 static/templates/css.st rename static/{widerhall.js => templates/js.st} (100%) diff --git a/.gitignore b/.gitignore index ee44a96..07051a7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .idea target +config/config.json +*.sqlite3 diff --git a/config/config.template.json b/config/config.template.json new file mode 100644 index 0000000..78e1d54 --- /dev/null +++ b/config/config.template.json @@ -0,0 +1,5 @@ +{ + "port" : 80, + "base_dir" : "/home/srichter/workspace/Widerhall/static", + "base_url" : "http://localhost", +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index cc2ad6f..626e079 100644 --- a/pom.xml +++ b/pom.xml @@ -84,10 +84,8 @@ org.antlr - stringtemplate - 4.0.2 + ST4 + 4.3.3 - - - \ No newline at end of file + diff --git a/src/main/java/de/srsoftware/widerhall/Application.java b/src/main/java/de/srsoftware/widerhall/Application.java index a65c605..f56546a 100644 --- a/src/main/java/de/srsoftware/widerhall/Application.java +++ b/src/main/java/de/srsoftware/widerhall/Application.java @@ -3,7 +3,7 @@ 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.Static; +import de.srsoftware.widerhall.web.Web; import de.srsoftware.widerhall.web.Rest; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; @@ -11,18 +11,23 @@ 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 java.io.File; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class Application { + private static final Logger LOG = LoggerFactory.getLogger(Application.class); public static void main(String[] args) throws Exception { - var config = Configuration.setFile(new File("/tmp/config.json")); + var config = Configuration.instance(); + // the following construct allows the initial config file to point to another config file, which is then loaded: + while (!config.configFile().equals(config.file())) config.load(config.configFile()); + //startMailSystem(json); - startWebserver(config); + startWebserver(); } - private static void startWebserver(Configuration config) throws Exception { + private static void startWebserver() throws Exception { + var config = Configuration.instance(); var server = new Server(); var connector = new ServerConnector(server); connector.setPort(config.serverPort()); @@ -31,7 +36,7 @@ public class Application { server.setConnectors(new Connector[]{connector}); ServletContextHandler context = new ServletContextHandler(server, "/",sh,null,null,null); context.addServlet(Rest.class,"/api"); - context.addServlet(Static.class,"/static/*"); + context.addServlet(Web.class,"/web/*"); server.start(); } diff --git a/src/main/java/de/srsoftware/widerhall/Configuration.java b/src/main/java/de/srsoftware/widerhall/Configuration.java index 6da7154..583b197 100644 --- a/src/main/java/de/srsoftware/widerhall/Configuration.java +++ b/src/main/java/de/srsoftware/widerhall/Configuration.java @@ -3,66 +3,93 @@ package de.srsoftware.widerhall; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; import java.nio.file.Files; + import static de.srsoftware.widerhall.Constants.*; public class Configuration { + private static final Logger LOG = LoggerFactory.getLogger(Configuration.class); private static Configuration singleton = null; private JSONObject data; - private final File file; + private File file; + + public static Configuration instance() { + if (singleton == null) singleton = new Configuration().setDefaults(); + return singleton; + } - public Configuration(File configFile) throws IOException, ParseException { - this.file = configFile; - if (!configFile.exists()){ - setDefaults(); - save(); + /** + * Merges configuration from file into current configuration. + * Existing entries will be replaced. + * @param file + * @return + * @throws IOException + * @throws ParseException + */ + public Configuration load(File file) { + this.file = file; + if (file.exists()) try { + var newVals = (JSONObject) new JSONParser().parse(Files.readString(file.toPath())); + data.putAll(newVals); + } catch (ParseException | IOException e){ + LOG.warn("Was not able to load configuration from {}:",file,e); } - var content = Files.readString(configFile.toPath()); - data = (JSONObject) new JSONParser().parse(content); + return this; } - public static Configuration setFile(File file) throws IOException, ParseException { - singleton = new Configuration(file); - return singleton; + public Configuration save(File file) throws IOException { + this.file = file; + return save(); } - public static Configuration instance() { - return singleton; + public Configuration save() throws IOException { + if (file == null) throw new NullPointerException("Cannot save configuration: file is null!"); + file.getParentFile().mkdirs(); + Files.writeString(file.toPath(),data.toJSONString()); + return this; } - private void setDefaults() throws MalformedURLException { + private Configuration setDefaults() { if (data == null) data = new JSONObject(); - baseDir(); - serverPort(); - tokenUrl(); - loginUrl(); + configFile(); + dbFile(); baseUrl(); - clientId(); - clientSecret(); + serverPort(); + return this; } - private void save() throws IOException { - Files.writeString(file.toPath(),data.toJSONString()); + private JSONObject locations() { + Object o = data.get(LOCATIONS); + if (!(o instanceof JSONObject)) data.put(LOCATIONS,o = new JSONObject()); + return (JSONObject) o; } - public int serverPort() { - if (!data.containsKey(PORT)) data.put(PORT,80L); - var o = data.get(PORT); - return (int) (long) o; + public String baseDir() { + var locations = locations(); + if (!locations.containsKey(BASE)) locations.put(BASE,System.getProperty("user.dir")); + return (String) locations.get(BASE); + } + + public File configFile() { + var locations = locations(); + if (!locations.containsKey(CONFIG)) locations.put(CONFIG, String.join(File.separator,baseDir(),"config","config.json")); + return new File((String) locations.get(CONFIG)); } - public URL tokenUrl() throws MalformedURLException { - if (!data.containsKey(TOKEN_URL)) data.put(TOKEN_URL,"http://localhost:"+serverPort()+"/oauth/token"); - return new URL((String) data.get(TOKEN_URL)); + public File dbFile() { + var locations = locations(); + if (!locations.containsKey(DB)) locations.put(DB, String.join(File.separator,baseDir(),"db","db.sqlite3")); + return new File((String) locations.get(DB)); } - public String loginUrl() { - if (!data.containsKey(LOGIN_URL)) data.put(LOGIN_URL,"http://localhost:"+serverPort()+"/oauth/login"); - return (String) data.get(LOGIN_URL); + public int serverPort() { + if (!data.containsKey(PORT)) data.put(PORT,80L); + var o = data.get(PORT); + return (int) (long) o; } public String baseUrl() { @@ -70,23 +97,8 @@ public class Configuration { return (String) data.get(BASE_URL); } - public String clientId() { - if (!data.containsKey(CLIENT_ID)) data.put(CLIENT_ID,"widerhall"); - return (String) data.get(CLIENT_ID); - } - - public Object clientSecret() { - 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); + public File file() { + return file; } } diff --git a/src/main/java/de/srsoftware/widerhall/Constants.java b/src/main/java/de/srsoftware/widerhall/Constants.java index 520c846..d220f9c 100644 --- a/src/main/java/de/srsoftware/widerhall/Constants.java +++ b/src/main/java/de/srsoftware/widerhall/Constants.java @@ -13,6 +13,8 @@ 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"; + public static final String DB = "database"; + public static final String BASE = "base"; + public static final String CONFIG = "configuration"; + public static final String LOCATIONS = "locations"; } diff --git a/src/main/java/de/srsoftware/widerhall/data/Database.java b/src/main/java/de/srsoftware/widerhall/data/Database.java index 7ed26e3..66e1d27 100644 --- a/src/main/java/de/srsoftware/widerhall/data/Database.java +++ b/src/main/java/de/srsoftware/widerhall/data/Database.java @@ -127,10 +127,10 @@ public class Database { public static Database open() { if (singleton == null){ Configuration config = Configuration.instance(); - String dbFile = config.dbLocation(); + var dbFile = config.dbFile(); String url = "jdbc:sqlite:"+dbFile; LOG.debug("Opening {}",url); - new File(dbFile).getParentFile().mkdirs(); + dbFile.getParentFile().mkdirs(); try { singleton = new Database(DriverManager.getConnection(url)).assertTables(); } catch (SQLException sqle) { diff --git a/src/main/java/de/srsoftware/widerhall/web/Static.java b/src/main/java/de/srsoftware/widerhall/web/Web.java similarity index 87% rename from src/main/java/de/srsoftware/widerhall/web/Static.java rename to src/main/java/de/srsoftware/widerhall/web/Web.java index 6b4e872..444dcd3 100644 --- a/src/main/java/de/srsoftware/widerhall/web/Static.java +++ b/src/main/java/de/srsoftware/widerhall/web/Web.java @@ -6,7 +6,7 @@ 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 org.stringtemplate.v4.STRawGroupDir; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; @@ -19,17 +19,19 @@ import java.util.Map; import static de.srsoftware.widerhall.Util.t; -public class Static extends HttpServlet { +public class Web extends HttpServlet { - private static final Logger LOG = LoggerFactory.getLogger(Static.class); + private static final Logger LOG = LoggerFactory.getLogger(Web.class); + private static final String LOGIN = "login"; private final String baseDir; private final STGroup templates; + private static final String WEB_ROOT = "/web"; - public Static(){ + public Web(){ var config = Configuration.instance(); baseDir = config.baseDir(); - var templateDir = String.join(File.separator,baseDir,"templates"); - templates = new STGroupDir(templateDir,'{','}'); + var templateDir = String.join(File.separator,baseDir,"static","templates"); + templates = new STRawGroupDir(templateDir,'«','»'); } @Override @@ -43,13 +45,11 @@ public class Static extends HttpServlet { path = path == null ? "index" : path.substring(1); switch (path){ case "css": - return loadFile("style.css",resp); case "js": - return loadFile("widerhall.js",resp); + case "login": + return loadTemplate(path,null,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"); @@ -77,7 +77,7 @@ public class Static extends HttpServlet { private String loginRedirect(HttpServletResponse resp) { try { - resp.sendRedirect("/static/login"); + resp.sendRedirect(String.join("/",WEB_ROOT,LOGIN)); return null; } catch (IOException e) { return t("Was not able to redirect to login page: {}", e.getMessage()); @@ -123,7 +123,7 @@ public class Static extends HttpServlet { try { var user = User.load(email,pass); req.getSession().setAttribute("user",user); - resp.sendRedirect("/static"); + resp.sendRedirect(String.join("/",WEB_ROOT,"index")); } catch (Exception e) { try { LOG.warn("Static.handleLogin failed:",e); diff --git a/static/templates/css.st b/static/templates/css.st new file mode 100644 index 0000000..0ab22cd --- /dev/null +++ b/static/templates/css.st @@ -0,0 +1,23 @@ +label { + display: block; + margin: 5px 0; +} + +#login form { + width: 450px; + margin: 0 auto; +} + +h1 { + text-align: center; +} + +.error{ + display: block; + text-align: center; + background: orange; +} + +.user{ + background: lime; +} \ No newline at end of file diff --git a/static/templates/index.st b/static/templates/index.st index be3a403..4a42af9 100644 --- a/static/templates/index.st +++ b/static/templates/index.st @@ -1,14 +1,13 @@ -index(data) ::= << - - + + + - Logged in as {data.user.name} + Logged in as «data.user.name»

Users

Lists

- ->> \ No newline at end of file + \ No newline at end of file diff --git a/static/widerhall.js b/static/templates/js.st similarity index 100% rename from static/widerhall.js rename to static/templates/js.st diff --git a/static/templates/login.st b/static/templates/login.st index a9fa1d0..01d1a5f 100644 --- a/static/templates/login.st +++ b/static/templates/login.st @@ -1,30 +1,28 @@ -login(data) ::= << - - - - - - - -

Widerhall login

- {if(data.error)} - {data.error} - {endif} -
-
- Login-Daten - - - -
-
- - ->> \ No newline at end of file + + + + + + + +

Widerhall login

+ «if(data.error)» + «data.error» + «endif» +
+
+ Login-Daten + + + +
+
+ + \ No newline at end of file