Browse Source

working on configuration

drop_old_mail
Stephan Richter 3 years ago
parent
commit
26df2e5654
  1. 2
      .gitignore
  2. 5
      config/config.template.json
  3. 8
      pom.xml
  4. 19
      src/main/java/de/srsoftware/widerhall/Application.java
  5. 114
      src/main/java/de/srsoftware/widerhall/Configuration.java
  6. 6
      src/main/java/de/srsoftware/widerhall/Constants.java
  7. 4
      src/main/java/de/srsoftware/widerhall/data/Database.java
  8. 24
      src/main/java/de/srsoftware/widerhall/web/Web.java
  9. 23
      static/templates/css.st
  10. 11
      static/templates/index.st
  11. 0
      static/templates/js.st
  12. 56
      static/templates/login.st

2
.gitignore vendored

@ -1,2 +1,4 @@
.idea .idea
target target
config/config.json
*.sqlite3

5
config/config.template.json

@ -0,0 +1,5 @@
{
"port" : 80,
"base_dir" : "/home/srichter/workspace/Widerhall/static",
"base_url" : "http://localhost",
}

8
pom.xml

@ -84,10 +84,8 @@
<dependency> <dependency>
<groupId>org.antlr</groupId> <groupId>org.antlr</groupId>
<artifactId>stringtemplate</artifactId> <artifactId>ST4</artifactId>
<version>4.0.2</version> <version>4.3.3</version>
</dependency> </dependency>
</dependencies> </dependencies>
</project>
</project>

19
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.Forwarder;
import de.srsoftware.widerhall.mail.ImapClient; import de.srsoftware.widerhall.mail.ImapClient;
import de.srsoftware.widerhall.mail.MessageHandler; 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 de.srsoftware.widerhall.web.Rest;
import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server; 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.server.session.SessionHandler;
import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletContextHandler;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import org.slf4j.Logger;
import java.io.File; import org.slf4j.LoggerFactory;
public class Application { public class Application {
private static final Logger LOG = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) throws Exception { 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); //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 server = new Server();
var connector = new ServerConnector(server); var connector = new ServerConnector(server);
connector.setPort(config.serverPort()); connector.setPort(config.serverPort());
@ -31,7 +36,7 @@ public class Application {
server.setConnectors(new Connector[]{connector}); server.setConnectors(new Connector[]{connector});
ServletContextHandler context = new ServletContextHandler(server, "/",sh,null,null,null); ServletContextHandler context = new ServletContextHandler(server, "/",sh,null,null,null);
context.addServlet(Rest.class,"/api"); context.addServlet(Rest.class,"/api");
context.addServlet(Static.class,"/static/*"); context.addServlet(Web.class,"/web/*");
server.start(); server.start();
} }

114
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.JSONObject;
import org.json.simple.parser.JSONParser; import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException; import org.json.simple.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files; import java.nio.file.Files;
import static de.srsoftware.widerhall.Constants.*; import static de.srsoftware.widerhall.Constants.*;
public class Configuration { public class Configuration {
private static final Logger LOG = LoggerFactory.getLogger(Configuration.class);
private static Configuration singleton = null; private static Configuration singleton = null;
private JSONObject data; 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; * Merges configuration from file into current configuration.
if (!configFile.exists()){ * Existing entries will be replaced.
setDefaults(); * @param file
save(); * @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()); return this;
data = (JSONObject) new JSONParser().parse(content);
} }
public static Configuration setFile(File file) throws IOException, ParseException { public Configuration save(File file) throws IOException {
singleton = new Configuration(file); this.file = file;
return singleton; return save();
} }
public static Configuration instance() { public Configuration save() throws IOException {
return singleton; 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(); if (data == null) data = new JSONObject();
baseDir(); configFile();
serverPort(); dbFile();
tokenUrl();
loginUrl();
baseUrl(); baseUrl();
clientId(); serverPort();
clientSecret(); return this;
} }
private void save() throws IOException { private JSONObject locations() {
Files.writeString(file.toPath(),data.toJSONString()); Object o = data.get(LOCATIONS);
if (!(o instanceof JSONObject)) data.put(LOCATIONS,o = new JSONObject());
return (JSONObject) o;
} }
public int serverPort() { public String baseDir() {
if (!data.containsKey(PORT)) data.put(PORT,80L); var locations = locations();
var o = data.get(PORT); if (!locations.containsKey(BASE)) locations.put(BASE,System.getProperty("user.dir"));
return (int) (long) o; 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 { public File dbFile() {
if (!data.containsKey(TOKEN_URL)) data.put(TOKEN_URL,"http://localhost:"+serverPort()+"/oauth/token"); var locations = locations();
return new URL((String) data.get(TOKEN_URL)); 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() { public int serverPort() {
if (!data.containsKey(LOGIN_URL)) data.put(LOGIN_URL,"http://localhost:"+serverPort()+"/oauth/login"); if (!data.containsKey(PORT)) data.put(PORT,80L);
return (String) data.get(LOGIN_URL); var o = data.get(PORT);
return (int) (long) o;
} }
public String baseUrl() { public String baseUrl() {
@ -70,23 +97,8 @@ public class Configuration {
return (String) data.get(BASE_URL); 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() { public File file() {
if (!data.containsKey(DB_FILE)) data.put(DB_FILE,System.getProperty("user.home")+"/.config/widerhall/db.sqlite3"); return file;
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);
} }
} }

6
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 BASE_URL = "base_url";
public static final String CLIENT_ID = "client_id"; public static final String CLIENT_ID = "client_id";
public static final String CLIENT_SECRET = "client_secret"; public static final String CLIENT_SECRET = "client_secret";
public static final String DB_FILE = "db_file"; public static final String DB = "database";
public static final String BASE_DIR = "base_dir"; public static final String BASE = "base";
public static final String CONFIG = "configuration";
public static final String LOCATIONS = "locations";
} }

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

@ -127,10 +127,10 @@ public class Database {
public static Database open() { public static Database open() {
if (singleton == null){ if (singleton == null){
Configuration config = Configuration.instance(); Configuration config = Configuration.instance();
String dbFile = config.dbLocation(); var dbFile = config.dbFile();
String url = "jdbc:sqlite:"+dbFile; String url = "jdbc:sqlite:"+dbFile;
LOG.debug("Opening {}",url); LOG.debug("Opening {}",url);
new File(dbFile).getParentFile().mkdirs(); dbFile.getParentFile().mkdirs();
try { try {
singleton = new Database(DriverManager.getConnection(url)).assertTables(); singleton = new Database(DriverManager.getConnection(url)).assertTables();
} catch (SQLException sqle) { } catch (SQLException sqle) {

24
src/main/java/de/srsoftware/widerhall/web/Static.java → 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.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.stringtemplate.v4.STGroup; import org.stringtemplate.v4.STGroup;
import org.stringtemplate.v4.STGroupDir; import org.stringtemplate.v4.STRawGroupDir;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServlet;
@ -19,17 +19,19 @@ import java.util.Map;
import static de.srsoftware.widerhall.Util.t; 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 String baseDir;
private final STGroup templates; private final STGroup templates;
private static final String WEB_ROOT = "/web";
public Static(){ public Web(){
var config = Configuration.instance(); var config = Configuration.instance();
baseDir = config.baseDir(); baseDir = config.baseDir();
var templateDir = String.join(File.separator,baseDir,"templates"); var templateDir = String.join(File.separator,baseDir,"static","templates");
templates = new STGroupDir(templateDir,'{','}'); templates = new STRawGroupDir(templateDir,'«',');
} }
@Override @Override
@ -43,13 +45,11 @@ public class Static extends HttpServlet {
path = path == null ? "index" : path.substring(1); path = path == null ? "index" : path.substring(1);
switch (path){ switch (path){
case "css": case "css":
return loadFile("style.css",resp);
case "js": case "js":
return loadFile("widerhall.js",resp); case "login":
return loadTemplate(path,null,resp);
case "jquery": case "jquery":
return loadFile("jquery-3.6.0.min.js",resp); return loadFile("jquery-3.6.0.min.js",resp);
case "login":
return loadTemplate(path, null, resp);
} }
var u = req.getSession().getAttribute("user"); var u = req.getSession().getAttribute("user");
@ -77,7 +77,7 @@ public class Static extends HttpServlet {
private String loginRedirect(HttpServletResponse resp) { private String loginRedirect(HttpServletResponse resp) {
try { try {
resp.sendRedirect("/static/login"); resp.sendRedirect(String.join("/",WEB_ROOT,LOGIN));
return null; return null;
} catch (IOException e) { } catch (IOException e) {
return t("Was not able to redirect to login page: {}", e.getMessage()); return t("Was not able to redirect to login page: {}", e.getMessage());
@ -123,7 +123,7 @@ public class Static extends HttpServlet {
try { try {
var user = User.load(email,pass); var user = User.load(email,pass);
req.getSession().setAttribute("user",user); req.getSession().setAttribute("user",user);
resp.sendRedirect("/static"); resp.sendRedirect(String.join("/",WEB_ROOT,"index"));
} catch (Exception e) { } catch (Exception e) {
try { try {
LOG.warn("Static.handleLogin failed:",e); LOG.warn("Static.handleLogin failed:",e);

23
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;
}

11
static/templates/index.st

@ -1,14 +1,13 @@
index(data) ::= <<
<html> <html>
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<script src="static/jquery"></script> <script src="jquery"></script>
<script src="static/js"></script> <script src="js"></script>
<link rel="stylesheet" href="css" />
</head> </head>
<body> <body>
<span class="user">Logged in as <em>{data.user.name}</em></span> <span class="user">Logged in as <em>«data.user.name»</em></span>
<h2>Users</h2> <h2>Users</h2>
<h2>Lists</h2> <h2>Lists</h2>
</body> </body>
</html> </html>
>>

0
static/widerhall.js → static/templates/js.st

56
static/templates/login.st

@ -1,30 +1,28 @@
login(data) ::= <<
<html> <html>
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<script src="/static/jquery"></script> <script src="jquery"></script>
<script src="/static/js"></script> <script src="js"></script>
<link rel="stylesheet" href="/static/css" /> <link rel="stylesheet" href="css" />
</head> </head>
<body id="login"> <body id="login">
<h1>Widerhall login</h1> <h1>Widerhall login</h1>
{if(data.error)} «if(data.error)»
<span class="error">{data.error}</span> <span class="error">«data.error»</span>
{endif} «endif»
<form method="POST"> <form method="POST">
<fieldset> <fieldset>
<legend>Login-Daten</legend> <legend>Login-Daten</legend>
<label> <label>
<input type="text" name="email" value="" id="email" /> <input type="text" name="email" value="" id="email" />
E-Mail-Adresse E-Mail-Adresse
</label> </label>
<label> <label>
<input type="password" name="pass" value="" id="password" /> <input type="password" name="pass" value="" id="password" />
Passwort Passwort
</label> </label>
<button type="submit">Einloggen</button> <button type="submit">Einloggen</button>
</fieldset> </fieldset>
</form> </form>
</body> </body>
</html> </html>
>>
Loading…
Cancel
Save