You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
7.5 KiB
200 lines
7.5 KiB
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.STRawGroupDir; |
|
|
|
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.sql.SQLException; |
|
import java.util.HashMap; |
|
import java.util.Map; |
|
|
|
import static de.srsoftware.widerhall.Constants.*; |
|
import static de.srsoftware.widerhall.Util.t; |
|
|
|
public class Web extends HttpServlet { |
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(Web.class); |
|
private static final String LOGIN = "login"; |
|
private static final String LOGOUT = "logout"; |
|
private static final String REGISTER = "register"; |
|
private final String baseDir; |
|
private STGroup templates; |
|
private static final String WEB_ROOT = "/web"; |
|
|
|
public Web(){ |
|
var config = Configuration.instance(); |
|
baseDir = config.baseDir(); |
|
loadTemplates(); |
|
} |
|
|
|
@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); |
|
String notes = null; |
|
switch (path){ |
|
case "reload": |
|
loadTemplates(); |
|
path = INDEX; |
|
notes = t("Templates have been reloaded"); |
|
break; |
|
case "css": |
|
case "js": |
|
return loadTemplate(path,null,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 throwables) { |
|
return "Error reading user database!"; |
|
} |
|
case LOGOUT: |
|
req.getSession().invalidate(); |
|
return redirectTo(INDEX,resp); |
|
case "jquery": |
|
return loadFile("jquery-3.6.0.min.js",resp); |
|
} |
|
|
|
var o = req.getSession().getAttribute("user"); |
|
if (o instanceof User user){ |
|
var data = new HashMap<String,Object>(); |
|
data.put(USER,user.map()); |
|
data.put(NOTES,notes); |
|
return loadTemplate(path,data,resp); |
|
} |
|
return redirectTo(LOGIN,resp); |
|
} |
|
|
|
private void loadTemplates() { |
|
var templateDir = String.join(File.separator,baseDir,"static","templates"); |
|
templates = new STRawGroupDir(templateDir,'«','»'); |
|
} |
|
|
|
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 redirectTo(String page, HttpServletResponse resp) { |
|
try { |
|
resp.sendRedirect(String.join("/",WEB_ROOT,page)); |
|
return null; |
|
} catch (IOException e) { |
|
return t("Was not able to redirect to {} page: {}", page, e.getMessage()); |
|
} |
|
} |
|
|
|
private String loadFile(String filename, HttpServletResponse resp) { |
|
var path = String.join(File.separator,baseDir,"static",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(); |
|
path = path == null ? INDEX : path.substring(1); |
|
switch (path){ |
|
case LOGIN: |
|
return handleLogin(req,resp); |
|
case REGISTER: |
|
return registerUser(req,resp); |
|
} |
|
|
|
return t("No handler for path {}!",path); |
|
} |
|
|
|
private String registerUser(HttpServletRequest req, HttpServletResponse resp) { |
|
|
|
var email = req.getParameter("email"); |
|
var pass = req.getParameter("pass"); |
|
var pass_repeat = req.getParameter("pass_repeat"); |
|
var name = req.getParameter("name"); |
|
|
|
if (email == null || email.isBlank() || |
|
name == null || name.isBlank() || |
|
pass == null || pass.isBlank() || |
|
pass_repeat == null || pass_repeat.isBlank()) return loadTemplate(REGISTER,Map.of(ERROR,"Fill all fields, please!",NAME,name,EMAIL,email),resp); |
|
if (!pass.equals(pass_repeat)) return loadTemplate(REGISTER,Map.of(ERROR,"Passwords do not match!",NAME,name,EMAIL,email),resp); |
|
if (Util.simplePassword(pass)) return loadTemplate(REGISTER,Map.of(ERROR,"Password to short or to simple!",NAME,name,EMAIL,email),resp); |
|
|
|
try { |
|
if (User.noUsers()) { // we are registering the first user, which is forced to be „Admin“ |
|
name = ADMIN; |
|
} else { |
|
if (ADMIN.equals(name)) return loadTemplate(REGISTER,Map.of(ERROR,t("Name must not be „{}“",ADMIN),NAME,name,EMAIL,email),resp); |
|
} |
|
} catch (SQLException e) { |
|
return t("Failed to access user database: {}",e.getMessage()); |
|
} |
|
|
|
|
|
try { |
|
var user = User.create(email, name, pass); |
|
req.getSession().setAttribute("user",user); |
|
return redirectTo(INDEX,resp); |
|
} catch (SQLException e) { |
|
return t("Failed to create new user: {}",e.getMessage()); |
|
} |
|
} |
|
|
|
private String handleLogin(HttpServletRequest req, HttpServletResponse resp) { |
|
var email = req.getParameter("email"); |
|
var pass = req.getParameter("pass"); |
|
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); |
|
try { |
|
var user = User.load(email,pass); |
|
req.getSession().setAttribute("user",user); |
|
resp.sendRedirect(String.join("/",WEB_ROOT,"index")); |
|
} 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; |
|
} |
|
|
|
}
|
|
|