weiter gebastelt
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -1,64 +0,0 @@
|
|||||||
/* © SRSoftware 2024 */
|
|
||||||
package de.srsoftware;
|
|
||||||
|
|
||||||
import de.srsoftware.oidc.api.User;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.annotation.WebServlet;
|
|
||||||
import javax.servlet.http.HttpServlet;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
@WebServlet(urlPatterns = "/")
|
|
||||||
public class LightOICD extends HttpServlet {
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(LightOICD.class);
|
|
||||||
private static final Templates templates;
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
templates = Templates.singleton();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
|
|
||||||
var path = Arrays.stream(req.getRequestURI().split("/")).skip(1).toList();
|
|
||||||
User user = null;
|
|
||||||
if (path.isEmpty()) {
|
|
||||||
landingPage(req, resp, user);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (path.remove(0)) {
|
|
||||||
default:
|
|
||||||
helloWorld(req, resp, path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void helloWorld(HttpServletRequest req, HttpServletResponse resp, List<String> path) throws IOException {
|
|
||||||
LOG.debug("helloWorld(…), path = {}", path);
|
|
||||||
resp.setContentType("text/html");
|
|
||||||
PrintWriter out = resp.getWriter();
|
|
||||||
out.println("<html><head><title>Hello World Servlet</title></head>");
|
|
||||||
out.println("<body>");
|
|
||||||
out.println("<h1>Hello Guys!</h1>");
|
|
||||||
out.println("<ul>");
|
|
||||||
path.forEach(part -> out.println("<li>" + part + "</li>"));
|
|
||||||
out.println("</ul>");
|
|
||||||
out.println("</body></html>");
|
|
||||||
out.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void landingPage(HttpServletRequest req, HttpServletResponse resp, User user) throws IOException {
|
|
||||||
LOG.debug("landingPage(…)");
|
|
||||||
var index = templates.get("index.html", Map.of("user","Darling"));
|
|
||||||
resp.setContentType("text/html");
|
|
||||||
resp.getWriter().println(index.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/* © SRSoftware 2024 */
|
||||||
|
package de.srsoftware.oidc.light;
|
||||||
|
|
||||||
|
public class Constants {
|
||||||
|
public static final String BODY = "body";
|
||||||
|
public static final String EMAIL = "email";
|
||||||
|
public static final String ERR_PAGE_NOT_FOUND = "page_not_found";
|
||||||
|
public static final String ERR_REDIRECT_FAILED = "redirect_failed";
|
||||||
|
public static final String HEAD = "head";
|
||||||
|
public static final String MESSAGES = "messages.txt";
|
||||||
|
public static final String PAGE_LOGIN = "login";
|
||||||
|
public static final String PAGE_START = "start";
|
||||||
|
public static final String PAGE_WELCOME = "welcome";
|
||||||
|
public static final String PASSWORD = "password";
|
||||||
|
public static final String TARGET = "target";
|
||||||
|
public static final String TITLE = "title";
|
||||||
|
public static final String TITLE_LOGIN = "title_login";
|
||||||
|
public static final String TITLE_WELCOME = "title_welcom";
|
||||||
|
public static final String USER = "user";
|
||||||
|
}
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
/* © SRSoftware 2024 */
|
||||||
|
package de.srsoftware.oidc.light;
|
||||||
|
|
||||||
|
import static de.srsoftware.oidc.light.Constants.*;
|
||||||
|
import static de.srsoftware.oidc.light.Templates.braced;
|
||||||
|
|
||||||
|
import de.srsoftware.oidc.api.User;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@WebServlet(urlPatterns = "/")
|
||||||
|
public class LightOICD extends HttpServlet {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(LightOICD.class);
|
||||||
|
private static final Templates templates;
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
templates = Templates.singleton();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
|
||||||
|
var uri = req.getRequestURI();
|
||||||
|
var path = Arrays.stream(uri.split("/")).skip(1).collect(Collectors.toList());
|
||||||
|
if (path.isEmpty()) {
|
||||||
|
path.add(PAGE_START);
|
||||||
|
}
|
||||||
|
|
||||||
|
var optUser = loadUser(req);
|
||||||
|
handleGet(path, optUser, req, resp).ifPresent(resp.getWriter()::println);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
|
var uri = req.getRequestURI();
|
||||||
|
var path = Arrays.stream(uri.split("/")).skip(1).collect(Collectors.toList());
|
||||||
|
if (path.isEmpty()) {
|
||||||
|
path.add(PAGE_START);
|
||||||
|
}
|
||||||
|
|
||||||
|
var optUser = loadUser(req);
|
||||||
|
handlePost(path, optUser, req, resp).ifPresent(resp.getWriter()::println);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<String> handleGet(List<String> path, Optional<User> optUser, HttpServletRequest req, HttpServletResponse resp) {
|
||||||
|
String token = path.remove(0);
|
||||||
|
if (optUser.isPresent()) {
|
||||||
|
var user = optUser.get();
|
||||||
|
switch (token) {
|
||||||
|
case PAGE_START:
|
||||||
|
return pageStart(user, req, resp);
|
||||||
|
case PAGE_WELCOME:
|
||||||
|
return pageWelcome(user,req, resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (token) {
|
||||||
|
case PAGE_LOGIN:
|
||||||
|
return pageLogin(req, resp);
|
||||||
|
case PAGE_START:
|
||||||
|
case PAGE_WELCOME:
|
||||||
|
return redirect(resp, PAGE_LOGIN);
|
||||||
|
}
|
||||||
|
return templates.message(ERR_PAGE_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private Optional<String> handlePost(List<String> path, Optional<User> optUser, HttpServletRequest req, HttpServletResponse resp) {
|
||||||
|
String token = path.remove(0);
|
||||||
|
if (optUser.isPresent()) {
|
||||||
|
var user = optUser.get();
|
||||||
|
switch (token) {
|
||||||
|
case PAGE_START:
|
||||||
|
return pageStart(user, req, resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (token) {
|
||||||
|
case PAGE_LOGIN:
|
||||||
|
return postLogin(req, resp);
|
||||||
|
case PAGE_START:
|
||||||
|
return redirect(resp, PAGE_LOGIN);
|
||||||
|
}
|
||||||
|
return templates.message(ERR_PAGE_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<User> loadUser(HttpServletRequest req) {
|
||||||
|
HttpSession session = req.getSession();
|
||||||
|
if (session.getAttribute(USER) instanceof User user) {
|
||||||
|
return Optional.of(user);
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private Optional<String> pageLogin(HttpServletRequest req, HttpServletResponse resp) {
|
||||||
|
LOG.debug("pageLogin(…)");
|
||||||
|
try {
|
||||||
|
var title = templates.message(TITLE_LOGIN).orElse(TITLE_LOGIN);
|
||||||
|
var head = templates.get("head.snippet", Map.of(TITLE, title)).get();
|
||||||
|
var login = templates.get("login.snippet", Map.of(USER, "Darling", EMAIL, "", PASSWORD, "")).get();
|
||||||
|
var page = templates.get("scaffold.html", Map.of(BODY, login, HEAD, head)).get();
|
||||||
|
resp.setContentType("text/html");
|
||||||
|
resp.getWriter().println(page);
|
||||||
|
return Optional.empty();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Optional.of(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<String> pageStart(User user, HttpServletRequest req, HttpServletResponse resp) {
|
||||||
|
LOG.debug("pageStart(…)");
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<String> pageWelcome(User user, HttpServletRequest req, HttpServletResponse resp) {
|
||||||
|
LOG.debug("pageWelcome(…)");
|
||||||
|
try {
|
||||||
|
var title = templates.message(TITLE_WELCOME).orElse(TITLE_WELCOME);
|
||||||
|
var head = templates.get("head.snippet", Map.of(TITLE, title)).get();
|
||||||
|
var login = templates.get("welcome.snippet", Map.of(USER, "Darling", EMAIL, "", PASSWORD, "")).get();
|
||||||
|
var page = templates.get("scaffold.html", Map.of(BODY, login, HEAD, head)).get();
|
||||||
|
resp.setContentType("text/html");
|
||||||
|
resp.getWriter().println(page);
|
||||||
|
return Optional.empty();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Optional.of(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<String> postLogin(HttpServletRequest req, HttpServletResponse resp) {
|
||||||
|
LOG.debug("postLogin(…)");
|
||||||
|
var email = req.getParameter(EMAIL);
|
||||||
|
if (braced(EMAIL).equals(email)) email = "";
|
||||||
|
var pass = req.getParameter(PASSWORD);
|
||||||
|
var user = tryLogin(email, pass);
|
||||||
|
if (user.isPresent()) {
|
||||||
|
req.getSession().setAttribute(USER, user.get());
|
||||||
|
return redirect(resp, PAGE_WELCOME);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var title = templates.message(TITLE_LOGIN).orElse(TITLE_LOGIN);
|
||||||
|
var head = templates.get("head.snippet", Map.of(TITLE, title)).get();
|
||||||
|
var login = templates.get("login.snippet", Map.of(USER, "Darling", EMAIL, email, PASSWORD, "")).get();
|
||||||
|
var page = templates.get("scaffold.html", Map.of(BODY, login, HEAD, head)).get();
|
||||||
|
resp.setContentType("text/html");
|
||||||
|
resp.getWriter().println(page);
|
||||||
|
return Optional.empty();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Optional.of(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<User> tryLogin(String email, String pass) {
|
||||||
|
if (email == null || pass == null) return Optional.empty();
|
||||||
|
if (email.equals(pass)) return Optional.of(new User());
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<String> redirect(HttpServletResponse resp, String path) {
|
||||||
|
try {
|
||||||
|
resp.sendRedirect(path);
|
||||||
|
} catch (IOException e) {
|
||||||
|
return templates.message(ERR_REDIRECT_FAILED, Map.of(TARGET, path));
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
/* © SRSoftware 2024 */
|
/* © SRSoftware 2024 */
|
||||||
package de.srsoftware;
|
package de.srsoftware.oidc.light;
|
||||||
|
|
||||||
|
import static de.srsoftware.oidc.light.Constants.MESSAGES;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -15,6 +18,7 @@ public class Templates {
|
|||||||
private static Templates singleton = null;
|
private static Templates singleton = null;
|
||||||
private static Logger LOG = LoggerFactory.getLogger(Templates.class);
|
private static Logger LOG = LoggerFactory.getLogger(Templates.class);
|
||||||
private Path dir = searchTemplates();
|
private Path dir = searchTemplates();
|
||||||
|
private Map<String, String> messages = null;
|
||||||
|
|
||||||
public Templates() throws FileNotFoundException {}
|
public Templates() throws FileNotFoundException {}
|
||||||
|
|
||||||
@@ -41,11 +45,14 @@ public class Templates {
|
|||||||
return singleton;
|
return singleton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<String> get(String path) {
|
||||||
|
return get(path, Map.of());
|
||||||
|
}
|
||||||
|
|
||||||
public Optional<String> get(String path, Map<String, String> replacements) {
|
public Optional<String> get(String path, Map<String, String> replacements) {
|
||||||
var file = dir.resolve(path);
|
var file = dir.resolve(path);
|
||||||
try {
|
try {
|
||||||
return Optional.of(Files.readString(file)).map(s -> replaceKeys(s,replacements));
|
return Optional.of(Files.readString(file)).map(s -> replaceKeys(s, replacements));
|
||||||
// TODO: replacements
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.warn("Failed to read {}", path, e);
|
LOG.warn("Failed to read {}", path, e);
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
@@ -54,7 +61,35 @@ public class Templates {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String replaceKeys(String text, Map<String, String> replacements) {
|
private String replaceKeys(String text, Map<String, String> replacements) {
|
||||||
for (Map.Entry<String, String> replacement : replacements.entrySet()) text = text.replace("{"+replacement.getKey()+"}",replacement.getValue());
|
for (Map.Entry<String, String> replacement : replacements.entrySet())
|
||||||
|
text = text.replace(braced(replacement.getKey()), replacement.getValue());
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<String> message(String code) {
|
||||||
|
return message(code, Map.of());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<String> message(String code, Map<String, String> replacements) {
|
||||||
|
if (this.messages == null) {
|
||||||
|
get(MESSAGES).map(s -> s.split("\n")).ifPresent(this::setMessages);
|
||||||
|
}
|
||||||
|
return Optional.ofNullable(messages.get(code)).map(text -> replaceKeys(text, replacements));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setMessages(String[] lines) {
|
||||||
|
this.messages = new HashMap<>();
|
||||||
|
for (String line : lines) {
|
||||||
|
var parts = line.split(" ", 2);
|
||||||
|
if (parts.length < 2) {
|
||||||
|
LOG.warn("Invalid format in {} file, skipped {}", MESSAGES, line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
messages.put(parts[0], parts[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String braced(String key) {
|
||||||
|
return String.join(key, "{", "}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>{title}</title>
|
||||||
|
<style>
|
||||||
|
body{
|
||||||
|
background-color: #555;
|
||||||
|
color: #eeffee;
|
||||||
|
}
|
||||||
|
label{
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
fieldset{
|
||||||
|
border-radius: 10px;
|
||||||
|
display: inline;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<h1>Login</h1>
|
||||||
|
|
||||||
|
<form action="login" method="POST">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Light OIDC Login</legend>
|
||||||
|
<label>
|
||||||
|
<input type="text" name="email" value="{email}" />
|
||||||
|
Email address
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input type="password" name="password" value="{password}" />
|
||||||
|
Password
|
||||||
|
</label>
|
||||||
|
<button type="submit">Login</button>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
title_login LightOIDC Login
|
||||||
|
title_welcome Willkommen bei LightOIDC!
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
{head}
|
||||||
|
<body>
|
||||||
|
{body}
|
||||||
|
</html>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Willkommen!
|
||||||
Reference in New Issue
Block a user