divided Backend into several controllers
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -8,7 +8,11 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static java.lang.System.Logger.Level.ERROR;
|
||||||
|
import static java.lang.System.Logger.Level.WARNING;
|
||||||
|
|
||||||
public abstract class Cookie implements Map.Entry<String, String> {
|
public abstract class Cookie implements Map.Entry<String, String> {
|
||||||
|
static final System.Logger LOG = System.getLogger(SessionToken.class.getSimpleName());
|
||||||
private final String key;
|
private final String key;
|
||||||
private String value = null;
|
private String value = null;
|
||||||
|
|
||||||
@@ -18,6 +22,7 @@ public abstract class Cookie implements Map.Entry<String, String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public <T extends Cookie> T addTo(Headers headers) {
|
public <T extends Cookie> T addTo(Headers headers) {
|
||||||
|
LOG.log(ERROR,"sending cookie {0}={1}",key,value);
|
||||||
headers.add("Set-Cookie", "%s=%s".formatted(key, value));
|
headers.add("Set-Cookie", "%s=%s".formatted(key, value));
|
||||||
return (T)this;
|
return (T)this;
|
||||||
}
|
}
|
||||||
@@ -37,7 +42,14 @@ public abstract class Cookie implements Map.Entry<String, String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected static List<String> of(HttpExchange ex) {
|
protected static List<String> of(HttpExchange ex) {
|
||||||
return Optional.ofNullable(ex.getRequestHeaders().get("Cookie")).stream().flatMap(List::stream).flatMap(s -> Arrays.stream(s.split(";"))).map(String::trim).toList();
|
return Optional.ofNullable(ex.getRequestHeaders()
|
||||||
|
.get("Cookie"))
|
||||||
|
.stream()
|
||||||
|
.flatMap(List::stream)
|
||||||
|
.flatMap(s -> Arrays.stream(s.split(";")))
|
||||||
|
.map(String::trim)
|
||||||
|
.peek(cookie -> LOG.log(WARNING,"received cookie {0}",cookie))
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -4,17 +4,23 @@ package de.srsoftware.cookies;
|
|||||||
|
|
||||||
import com.sun.net.httpserver.HttpExchange;
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import static java.lang.System.Logger.Level.DEBUG;
|
||||||
|
import static java.lang.System.Logger.Level.WARNING;
|
||||||
|
|
||||||
public class SessionToken extends Cookie {
|
public class SessionToken extends Cookie {
|
||||||
private final String sessionId;
|
private final String sessionId;
|
||||||
|
|
||||||
public SessionToken(String sessionId) {
|
public SessionToken(String sessionId) {
|
||||||
super("sessionToken", sessionId);
|
super("sessionToken", sessionId+"; Path=/api");
|
||||||
this.sessionId = sessionId;
|
this.sessionId = sessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Optional<SessionToken> from(HttpExchange ex) {
|
public static Optional<SessionToken> from(HttpExchange ex) {
|
||||||
return Cookie.of(ex).stream().filter(cookie -> cookie.startsWith("sessionToken=")).map(cookie -> cookie.split("=", 2)[1]).map(id -> new SessionToken(id)).findAny();
|
return Cookie.of(ex).stream().filter(cookie -> cookie.startsWith("sessionToken="))
|
||||||
|
|
||||||
|
.map(cookie -> cookie.split("=", 2)[1]).map(id -> new SessionToken(id)).findAny();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String sessionId() {
|
public String sessionId() {
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ import java.util.Date;
|
|||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
public class ColorLogger implements System.Logger {
|
public class ColorLogger implements System.Logger {
|
||||||
private final String name;
|
private final String name;
|
||||||
private static int rootLevel = INFO.getSeverity();
|
private static int rootLevel = INFO.getSeverity();
|
||||||
private static DateFormat TIME = new SimpleDateFormat("hh:mm:ss.SSS");
|
private static DateFormat TIME = new SimpleDateFormat("hh:mm:ss.SSS");
|
||||||
private static DateFormat DATE = new SimpleDateFormat("yyyy-MM-dd");
|
private static DateFormat DATE = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
private static String lastDate = null;
|
private static String lastDate = null;
|
||||||
|
|
||||||
public ColorLogger(String name) {
|
public ColorLogger(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@@ -52,11 +52,11 @@ public class ColorLogger implements System.Logger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String colorize(String message, int severity) {
|
private static String colorize(String message, int severity) {
|
||||||
var color = severity >= ERROR.getSeverity() ? RED : severity >= WARNING.getSeverity() ? YELLOW : severity >= INFO.getSeverity() ? WHITE_BRIGHT : WHITE;
|
var color = severity >= ERROR.getSeverity() ? RED : severity >= WARNING.getSeverity() ? YELLOW : severity >= INFO.getSeverity() ? WHITE_BRIGHT : WHITE;
|
||||||
var date = new Date();
|
var date = new Date();
|
||||||
var day =DATE.format(date);
|
var day = DATE.format(date);
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
if (!day.equals(lastDate)){
|
if (!day.equals(lastDate)) {
|
||||||
lastDate = day;
|
lastDate = day;
|
||||||
sb.append(WHITE).append(day).append("\n");
|
sb.append(WHITE).append(day).append("\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
/* © SRSoftware 2024 */
|
/* © SRSoftware 2024 */
|
||||||
package de.srsoftware.oidc.api;
|
package de.srsoftware.oidc.api;
|
||||||
|
|
||||||
import static java.lang.System.Logger.Level.DEBUG;
|
import static java.lang.System.Logger.Level.*;
|
||||||
import static java.lang.System.Logger.Level.INFO;
|
|
||||||
import static java.net.HttpURLConnection.*;
|
import static java.net.HttpURLConnection.*;
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
@@ -18,14 +17,14 @@ import java.util.stream.Stream;
|
|||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public abstract class PathHandler implements HttpHandler {
|
public abstract class PathHandler implements HttpHandler {
|
||||||
public static final String CONTENT_TYPE = "Content-Type";
|
public static final String CONTENT_TYPE = "Content-Type";
|
||||||
public static final String DELETE = "DELETE";
|
public static final String DELETE = "DELETE";
|
||||||
private static final String FORWARDED_HOST = "x-forwarded-host";
|
private static final String FORWARDED_HOST = "x-forwarded-host";
|
||||||
public static final String GET = "GET";
|
public static final String GET = "GET";
|
||||||
public static final String HOST = "host";
|
public static final String HOST = "host";
|
||||||
public static final String JSON = "application/json";
|
public static final String JSON = "application/json";
|
||||||
public static System.Logger LOG = System.getLogger(PathHandler.class.getSimpleName());
|
public static System.Logger LOG = System.getLogger(PathHandler.class.getSimpleName());
|
||||||
public static final String POST = "POST";
|
public static final String POST = "POST";
|
||||||
|
|
||||||
private String[] paths;
|
private String[] paths;
|
||||||
|
|
||||||
@@ -99,9 +98,9 @@ public abstract class PathHandler implements HttpHandler {
|
|||||||
|
|
||||||
public static String hostname(HttpExchange ex) {
|
public static String hostname(HttpExchange ex) {
|
||||||
var headers = ex.getRequestHeaders();
|
var headers = ex.getRequestHeaders();
|
||||||
var host = headers.getFirst(FORWARDED_HOST);
|
var host = headers.getFirst(FORWARDED_HOST);
|
||||||
if (host == null) host = headers.getFirst(HOST);
|
if (host == null) host = headers.getFirst(HOST);
|
||||||
return host == null ? null : "https://"+host;
|
return host == null ? null : "https://" + host;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JSONObject json(HttpExchange ex) throws IOException {
|
public static JSONObject json(HttpExchange ex) throws IOException {
|
||||||
@@ -112,6 +111,11 @@ public abstract class PathHandler implements HttpHandler {
|
|||||||
return getHeader(ex, "Accept-Language").map(s -> Arrays.stream(s.split(","))).flatMap(Stream::findFirst);
|
return getHeader(ex, "Accept-Language").map(s -> Arrays.stream(s.split(","))).flatMap(Stream::findFirst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean notFound(HttpExchange ex) throws IOException {
|
||||||
|
LOG.log(WARNING, "not implemented");
|
||||||
|
return sendEmptyResponse(HTTP_NOT_FOUND, ex);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean sendEmptyResponse(int statusCode, HttpExchange ex) throws IOException {
|
public static boolean sendEmptyResponse(int statusCode, HttpExchange ex) throws IOException {
|
||||||
ex.sendResponseHeaders(statusCode, 0);
|
ex.sendResponseHeaders(statusCode, 0);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -9,7 +9,10 @@ import static java.lang.System.Logger.Level.ERROR;
|
|||||||
import com.sun.net.httpserver.HttpServer;
|
import com.sun.net.httpserver.HttpServer;
|
||||||
import de.srsoftware.logging.ColorLogger;
|
import de.srsoftware.logging.ColorLogger;
|
||||||
import de.srsoftware.oidc.api.User;
|
import de.srsoftware.oidc.api.User;
|
||||||
import de.srsoftware.oidc.backend.Backend;
|
import de.srsoftware.oidc.backend.ClientController;
|
||||||
|
import de.srsoftware.oidc.backend.TokenController;
|
||||||
|
import de.srsoftware.oidc.backend.UserController;
|
||||||
|
import de.srsoftware.oidc.backend.WellKnownController;
|
||||||
import de.srsoftware.oidc.datastore.file.FileStore;
|
import de.srsoftware.oidc.datastore.file.FileStore;
|
||||||
import de.srsoftware.oidc.datastore.file.UuidHasher;
|
import de.srsoftware.oidc.datastore.file.UuidHasher;
|
||||||
import de.srsoftware.oidc.web.Forward;
|
import de.srsoftware.oidc.web.Forward;
|
||||||
@@ -21,17 +24,20 @@ import java.util.*;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
public class Application {
|
public class Application {
|
||||||
public static final String BACKEND = "/api";
|
public static final String API_CLIENT = "/api/client";
|
||||||
private static final String FAVICON = "/favicon.ico";
|
private static final String API_TOKEN = "/api/token";
|
||||||
public static final String ROOT = "/";
|
public static final String API_USER = "/api/user";
|
||||||
public static final String STATIC_PATH = "/web";
|
public static final String FIRST_USER = "admin";
|
||||||
private static final String WELL_KNOWN = "/.well-known";
|
public static final String FIRST_USER_PASS = "admin";
|
||||||
public static final String FIRST_USER = "admin";
|
public static final String FIRST_UUID = UUID.randomUUID().toString();
|
||||||
public static final String FIRST_USER_PASS = "admin";
|
public static final String ROOT = "/";
|
||||||
public static final String FIRST_UUID = UUID.randomUUID().toString();
|
public static final String STATIC_PATH = "/web";
|
||||||
public static final String INDEX = STATIC_PATH + "/index.html";
|
|
||||||
private static final String BASE_PATH = "basePath";
|
private static final String BASE_PATH = "basePath";
|
||||||
private static System.Logger LOG = new ColorLogger("Application").setLogLevel(DEBUG);
|
private static final String FAVICON = "/favicon.ico";
|
||||||
|
private static final String INDEX = STATIC_PATH + "/index.html";
|
||||||
|
private static final String WELL_KNOWN = "/.well-known";
|
||||||
|
private static System.Logger LOG = new ColorLogger("Application").setLogLevel(DEBUG);
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
var argMap = map(args);
|
var argMap = map(args);
|
||||||
@@ -44,8 +50,12 @@ public class Application {
|
|||||||
HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
|
HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
|
||||||
new StaticPages(basePath).bindPath(STATIC_PATH, FAVICON).on(server);
|
new StaticPages(basePath).bindPath(STATIC_PATH, FAVICON).on(server);
|
||||||
new Forward(INDEX).bindPath(ROOT).on(server);
|
new Forward(INDEX).bindPath(ROOT).on(server);
|
||||||
new Backend(fileStore, fileStore, fileStore, fileStore).bindPath(BACKEND, WELL_KNOWN).on(server);
|
new WellKnownController().bindPath(WELL_KNOWN).on(server);
|
||||||
server.setExecutor(Executors.newCachedThreadPool());
|
new UserController(fileStore, fileStore).bindPath(API_USER).on(server);
|
||||||
|
new TokenController().bindPath(API_TOKEN).on(server);
|
||||||
|
new ClientController(fileStore, fileStore, fileStore).bindPath(API_CLIENT).on(server);
|
||||||
|
//server.setExecutor(Executors.newCachedThreadPool());
|
||||||
|
server.setExecutor(Executors.newSingleThreadExecutor());
|
||||||
server.start();
|
server.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,244 +0,0 @@
|
|||||||
/* © SRSoftware 2024 */
|
|
||||||
package de.srsoftware.oidc.backend;
|
|
||||||
|
|
||||||
import static de.srsoftware.oidc.api.Constants.*;
|
|
||||||
import static de.srsoftware.oidc.api.Permission.MANAGE_CLIENTS;
|
|
||||||
import static de.srsoftware.oidc.api.User.*;
|
|
||||||
import static java.lang.System.Logger.Level.ERROR;
|
|
||||||
import static java.lang.System.Logger.Level.WARNING;
|
|
||||||
import static java.net.HttpURLConnection.*;
|
|
||||||
|
|
||||||
import com.sun.net.httpserver.HttpExchange;
|
|
||||||
import de.srsoftware.cookies.SessionToken;
|
|
||||||
import de.srsoftware.oidc.api.*;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
public class Backend extends PathHandler {
|
|
||||||
private static final System.Logger LOG = System.getLogger(Backend.class.getSimpleName());
|
|
||||||
private final AuthorizationService authorizations;
|
|
||||||
private final SessionService sessions;
|
|
||||||
private final UserService users;
|
|
||||||
private final ClientService clients;
|
|
||||||
|
|
||||||
public Backend(AuthorizationService authorizationService, ClientService clientService, SessionService sessionService, UserService userService) {
|
|
||||||
authorizations = authorizationService;
|
|
||||||
clients = clientService;
|
|
||||||
sessions = sessionService;
|
|
||||||
users = userService;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean addClient(HttpExchange ex, Session session) throws IOException {
|
|
||||||
if (!session.user().hasPermission(MANAGE_CLIENTS)) return badRequest(ex, "NOT ALLOWED");
|
|
||||||
var json = json(ex);
|
|
||||||
var redirects = new HashSet<String>();
|
|
||||||
for (Object o : json.getJSONArray(REDIRECT_URIS)) {
|
|
||||||
if (o instanceof String s) redirects.add(s);
|
|
||||||
}
|
|
||||||
var client = new Client(json.getString(CLIENT_ID), json.getString(NAME), json.getString(SECRET), redirects);
|
|
||||||
clients.add(client);
|
|
||||||
return sendContent(ex, client);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean authorize(HttpExchange ex, Session session) throws IOException {
|
|
||||||
var user = session.user();
|
|
||||||
var json = json(ex);
|
|
||||||
var clientId = json.getString(CLIENT_ID);
|
|
||||||
var redirect = json.getString(REDIRECT_URI);
|
|
||||||
var optClient = clients.getClient(clientId);
|
|
||||||
if (optClient.isEmpty()) return badRequest(ex, Map.of(CAUSE, "unknown client", CLIENT_ID, clientId));
|
|
||||||
var client = optClient.get();
|
|
||||||
|
|
||||||
if (!client.redirectUris().contains(redirect)) return badRequest(ex, Map.of(CAUSE, "unknown redirect uri", REDIRECT_URI, redirect));
|
|
||||||
|
|
||||||
if (!authorizations.isAuthorized(client, session.user())) {
|
|
||||||
if (json.has(CONFIRMED) && json.getBoolean(CONFIRMED)) {
|
|
||||||
authorizations.authorize(client, user, null);
|
|
||||||
} else {
|
|
||||||
return sendContent(ex, Map.of(CONFIRMED, false, NAME, client.name()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var state = json.getString(STATE);
|
|
||||||
var code = client.generateCode();
|
|
||||||
return sendContent(ex, Map.of(CONFIRMED, true, CODE, code, REDIRECT_URI, redirect, STATE, state));
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean clients(HttpExchange ex, Session session) throws IOException {
|
|
||||||
var user = session.user();
|
|
||||||
if (!user.hasPermission(MANAGE_CLIENTS)) return sendEmptyResponse(HTTP_FORBIDDEN, ex);
|
|
||||||
var json = new JSONObject();
|
|
||||||
clients.listClients().forEach(client -> json.put(client.id(), Map.of("name", client.name(), "redirect_uris", client.redirectUris())));
|
|
||||||
return sendContent(ex, json);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean deleteClient(HttpExchange ex, Session session) throws IOException {
|
|
||||||
if (!session.user().hasPermission(MANAGE_CLIENTS)) return badRequest(ex, "NOT ALLOWED");
|
|
||||||
var json = json(ex);
|
|
||||||
var id = json.getString(CLIENT_ID);
|
|
||||||
clients.getClient(id).ifPresent(clients::remove);
|
|
||||||
return sendEmptyResponse(HTTP_OK, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean doLogin(HttpExchange ex) throws IOException {
|
|
||||||
var body = json(ex);
|
|
||||||
|
|
||||||
var username = body.has(USERNAME) ? body.getString(USERNAME) : null;
|
|
||||||
var password = body.has(PASSWORD) ? body.getString(PASSWORD) : null;
|
|
||||||
|
|
||||||
Optional<User> user = users.load(username, password);
|
|
||||||
if (user.isPresent()) return sendUserAndCookie(ex, sessions.createSession(user.get()));
|
|
||||||
return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean doDelete(String path, HttpExchange ex) throws IOException {
|
|
||||||
var optSession = getSession(ex);
|
|
||||||
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
|
||||||
|
|
||||||
// post-login paths
|
|
||||||
var session = optSession.get();
|
|
||||||
switch (path) {
|
|
||||||
case "/client":
|
|
||||||
return deleteClient(ex, session);
|
|
||||||
}
|
|
||||||
LOG.log(ERROR, "not implemented");
|
|
||||||
return sendEmptyResponse(HTTP_NOT_FOUND, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean doGet(String path, HttpExchange ex) throws IOException {
|
|
||||||
// pre-login paths
|
|
||||||
switch (path) {
|
|
||||||
case "/openid-configuration":
|
|
||||||
return openidConfig(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
var optSession = getSession(ex);
|
|
||||||
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
|
||||||
|
|
||||||
// post-login paths
|
|
||||||
var session = optSession.get();
|
|
||||||
switch (path) {
|
|
||||||
case "/logout":
|
|
||||||
return logout(ex, session);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG.log(WARNING, "not implemented");
|
|
||||||
return sendEmptyResponse(HTTP_NOT_FOUND, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean doPost(String path, HttpExchange ex) throws IOException {
|
|
||||||
// pre-login paths
|
|
||||||
switch (path) {
|
|
||||||
case "/login":
|
|
||||||
return doLogin(ex);
|
|
||||||
case "/token":
|
|
||||||
return provideToken(ex);
|
|
||||||
}
|
|
||||||
var optSession = getSession(ex);
|
|
||||||
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
|
||||||
|
|
||||||
// post-login paths
|
|
||||||
var session = optSession.get();
|
|
||||||
switch (path) {
|
|
||||||
case "/add/client":
|
|
||||||
return addClient(ex, session);
|
|
||||||
case "/authorize":
|
|
||||||
return authorize(ex, session);
|
|
||||||
case "/client":
|
|
||||||
return loadClient(ex, session);
|
|
||||||
case "/clients":
|
|
||||||
return clients(ex, session);
|
|
||||||
case "/update/password":
|
|
||||||
return updatePassword(ex, session);
|
|
||||||
case "/update/user":
|
|
||||||
return updateUser(ex, session);
|
|
||||||
case "/user":
|
|
||||||
return sendUserAndCookie(ex, session);
|
|
||||||
}
|
|
||||||
LOG.log(WARNING, "not implemented");
|
|
||||||
return sendEmptyResponse(HTTP_NOT_FOUND, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<Session> getSession(HttpExchange ex) {
|
|
||||||
return SessionToken.from(ex).map(SessionToken::sessionId).flatMap(sessions::retrieve);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean loadClient(HttpExchange ex, Session session) throws IOException {
|
|
||||||
if (!session.user().hasPermission(MANAGE_CLIENTS)) return sendEmptyResponse(HTTP_FORBIDDEN, ex);
|
|
||||||
var json = json(ex);
|
|
||||||
if (json.has(CLIENT_ID)) {
|
|
||||||
var clientID = json.getString(CLIENT_ID);
|
|
||||||
var client = clients.getClient(clientID).map(Client::map).map(JSONObject::new);
|
|
||||||
if (client.isPresent()) return sendContent(ex, client.get());
|
|
||||||
}
|
|
||||||
return sendEmptyResponse(HTTP_NOT_FOUND, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean logout(HttpExchange ex, Session session) throws IOException {
|
|
||||||
sessions.dropSession(session.id());
|
|
||||||
new SessionToken("").addTo(ex);
|
|
||||||
return sendEmptyResponse(HTTP_OK, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean provideToken(HttpExchange ex) throws IOException {
|
|
||||||
var map = deserialize(body(ex));
|
|
||||||
LOG.log(WARNING, "map: {0}", map);
|
|
||||||
LOG.log(ERROR, "{0}.provideToken(ex) not implemented!", getClass().getSimpleName());
|
|
||||||
var grantType = map.get(GRANT_TYPE);
|
|
||||||
if (!ATUH_CODE.equals(grantType)) sendContent(ex, HTTP_BAD_REQUEST, Map.of(ERROR, "unknown grant type", GRANT_TYPE, grantType));
|
|
||||||
return sendEmptyResponse(HTTP_NOT_FOUND, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, String> deserialize(String body) {
|
|
||||||
return Arrays.stream(body.split("&")).map(s -> s.split("=")).collect(Collectors.toMap(arr -> arr[0], arr -> arr[1]));
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean openidConfig(HttpExchange ex) throws IOException {
|
|
||||||
var host = hostname(ex);
|
|
||||||
return sendContent(ex, Map.of("token_endpoint", host + "/api/token", "authorization_endpoint", host + "/web/authorization.html", "userinfo_endpoint", host + "/api/userinfo", "jwks_uri", host + "/api/jwks"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean sendUserAndCookie(HttpExchange ex, Session session) throws IOException {
|
|
||||||
new SessionToken(session.id()).addTo(ex);
|
|
||||||
return sendContent(ex, session.user().map(false));
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean updatePassword(HttpExchange ex, Session session) throws IOException {
|
|
||||||
var user = session.user();
|
|
||||||
var json = json(ex);
|
|
||||||
var uuid = json.getString(UUID);
|
|
||||||
if (!uuid.equals(user.uuid())) {
|
|
||||||
return sendEmptyResponse(HTTP_FORBIDDEN, ex);
|
|
||||||
}
|
|
||||||
var oldPass = json.getString("oldpass");
|
|
||||||
if (!users.passwordMatches(oldPass, user.hashedPassword())) return badRequest(ex, "wrong password");
|
|
||||||
|
|
||||||
var newpass = json.getJSONArray("newpass");
|
|
||||||
var newPass1 = newpass.getString(0);
|
|
||||||
if (!newPass1.equals(newpass.getString(1))) {
|
|
||||||
return badRequest(ex, "password mismatch");
|
|
||||||
}
|
|
||||||
users.updatePassword(user, newPass1);
|
|
||||||
return sendContent(ex, user.map(false));
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean updateUser(HttpExchange ex, Session session) throws IOException {
|
|
||||||
var user = session.user();
|
|
||||||
var json = json(ex);
|
|
||||||
var uuid = json.getString(UUID);
|
|
||||||
if (!uuid.equals(user.uuid())) {
|
|
||||||
return sendEmptyResponse(HTTP_FORBIDDEN, ex);
|
|
||||||
}
|
|
||||||
user.username(json.getString(USERNAME));
|
|
||||||
user.email(json.getString(EMAIL));
|
|
||||||
users.save(user);
|
|
||||||
return sendContent(ex, user.map(false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/* © SRSoftware 2024 */
|
||||||
|
package de.srsoftware.oidc.backend;
|
||||||
|
|
||||||
|
import static de.srsoftware.oidc.api.Constants.*;
|
||||||
|
import static de.srsoftware.oidc.api.Permission.MANAGE_CLIENTS;
|
||||||
|
import static java.lang.System.Logger.Level.ERROR;
|
||||||
|
import static java.net.HttpURLConnection.*;
|
||||||
|
|
||||||
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
|
import de.srsoftware.oidc.api.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
public class ClientController extends Controller {
|
||||||
|
private static final System.Logger LOG = System.getLogger(ClientController.class.getSimpleName());
|
||||||
|
private final AuthorizationService authorizations;
|
||||||
|
private final ClientService clients;
|
||||||
|
|
||||||
|
public ClientController(AuthorizationService authorizationService, ClientService clientService, SessionService sessionService) {
|
||||||
|
super(sessionService);
|
||||||
|
authorizations = authorizationService;
|
||||||
|
clients = clientService;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean add(HttpExchange ex, Session session) throws IOException {
|
||||||
|
if (!session.user().hasPermission(MANAGE_CLIENTS)) return badRequest(ex, "NOT ALLOWED");
|
||||||
|
var json = json(ex);
|
||||||
|
var redirects = new HashSet<String>();
|
||||||
|
for (Object o : json.getJSONArray(REDIRECT_URIS)) {
|
||||||
|
if (o instanceof String s) redirects.add(s);
|
||||||
|
}
|
||||||
|
var client = new Client(json.getString(CLIENT_ID), json.getString(NAME), json.getString(SECRET), redirects);
|
||||||
|
clients.add(client);
|
||||||
|
return sendContent(ex, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean authorize(HttpExchange ex, Session session) throws IOException {
|
||||||
|
var user = session.user();
|
||||||
|
var json = json(ex);
|
||||||
|
var clientId = json.getString(CLIENT_ID);
|
||||||
|
var redirect = json.getString(REDIRECT_URI);
|
||||||
|
var optClient = clients.getClient(clientId);
|
||||||
|
if (optClient.isEmpty()) return badRequest(ex, Map.of(CAUSE, "unknown client", CLIENT_ID, clientId));
|
||||||
|
var client = optClient.get();
|
||||||
|
|
||||||
|
if (!client.redirectUris().contains(redirect)) return badRequest(ex, Map.of(CAUSE, "unknown redirect uri", REDIRECT_URI, redirect));
|
||||||
|
|
||||||
|
if (!authorizations.isAuthorized(client, session.user())) {
|
||||||
|
if (json.has(CONFIRMED) && json.getBoolean(CONFIRMED)) {
|
||||||
|
authorizations.authorize(client, user, null);
|
||||||
|
} else {
|
||||||
|
return sendContent(ex, Map.of(CONFIRMED, false, NAME, client.name()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var state = json.getString(STATE);
|
||||||
|
var code = client.generateCode();
|
||||||
|
return sendContent(ex, Map.of(CONFIRMED, true, CODE, code, REDIRECT_URI, redirect, STATE, state));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean deleteClient(HttpExchange ex, Session session) throws IOException {
|
||||||
|
if (!session.user().hasPermission(MANAGE_CLIENTS)) return badRequest(ex, "NOT ALLOWED");
|
||||||
|
var json = json(ex);
|
||||||
|
var id = json.getString(CLIENT_ID);
|
||||||
|
clients.getClient(id).ifPresent(clients::remove);
|
||||||
|
return sendEmptyResponse(HTTP_OK, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doDelete(String path, HttpExchange ex) throws IOException {
|
||||||
|
var optSession = getSession(ex);
|
||||||
|
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
||||||
|
|
||||||
|
// post-login paths
|
||||||
|
var session = optSession.get();
|
||||||
|
switch (path) {
|
||||||
|
case "/":
|
||||||
|
return deleteClient(ex, session);
|
||||||
|
}
|
||||||
|
LOG.log(ERROR, "not implemented");
|
||||||
|
return sendEmptyResponse(HTTP_NOT_FOUND, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doPost(String path, HttpExchange ex) throws IOException {
|
||||||
|
var optSession = getSession(ex);
|
||||||
|
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
||||||
|
|
||||||
|
// post-login paths
|
||||||
|
var session = optSession.get();
|
||||||
|
switch (path) {
|
||||||
|
case "/":
|
||||||
|
return load(ex, session);
|
||||||
|
case "/add":
|
||||||
|
return add(ex, session);
|
||||||
|
case "/authorize":
|
||||||
|
return authorize(ex, session);
|
||||||
|
case "/list":
|
||||||
|
return list(ex, session);
|
||||||
|
}
|
||||||
|
return notFound(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean list(HttpExchange ex, Session session) throws IOException {
|
||||||
|
var user = session.user();
|
||||||
|
if (!user.hasPermission(MANAGE_CLIENTS)) return sendEmptyResponse(HTTP_FORBIDDEN, ex);
|
||||||
|
var json = new JSONObject();
|
||||||
|
clients.listClients().forEach(client -> json.put(client.id(), Map.of("name", client.name(), "redirect_uris", client.redirectUris())));
|
||||||
|
return sendContent(ex, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean load(HttpExchange ex, Session session) throws IOException {
|
||||||
|
if (!session.user().hasPermission(MANAGE_CLIENTS)) return sendEmptyResponse(HTTP_FORBIDDEN, ex);
|
||||||
|
var json = json(ex);
|
||||||
|
if (json.has(CLIENT_ID)) {
|
||||||
|
var clientID = json.getString(CLIENT_ID);
|
||||||
|
var client = clients.getClient(clientID).map(Client::map).map(JSONObject::new);
|
||||||
|
if (client.isPresent()) return sendContent(ex, client.get());
|
||||||
|
}
|
||||||
|
return sendEmptyResponse(HTTP_NOT_FOUND, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/* © SRSoftware 2024 */
|
||||||
|
package de.srsoftware.oidc.backend;
|
||||||
|
|
||||||
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
|
import de.srsoftware.cookies.SessionToken;
|
||||||
|
import de.srsoftware.oidc.api.PathHandler;
|
||||||
|
import de.srsoftware.oidc.api.Session;
|
||||||
|
import de.srsoftware.oidc.api.SessionService;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public abstract class Controller extends PathHandler {
|
||||||
|
protected final SessionService sessions;
|
||||||
|
|
||||||
|
Controller(SessionService sessionService) {
|
||||||
|
sessions = sessionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Optional<Session> getSession(HttpExchange ex) {
|
||||||
|
return SessionToken.from(ex).map(SessionToken::sessionId).flatMap(sessions::retrieve);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/* © SRSoftware 2024 */
|
||||||
|
package de.srsoftware.oidc.backend;
|
||||||
|
|
||||||
|
import static de.srsoftware.oidc.api.Constants.ATUH_CODE;
|
||||||
|
import static de.srsoftware.oidc.api.Constants.GRANT_TYPE;
|
||||||
|
import static java.lang.System.Logger.Level.ERROR;
|
||||||
|
import static java.lang.System.Logger.Level.WARNING;
|
||||||
|
import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
|
||||||
|
import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
|
||||||
|
|
||||||
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
|
import de.srsoftware.oidc.api.PathHandler;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class TokenController extends PathHandler {
|
||||||
|
private Map<String, String> deserialize(String body) {
|
||||||
|
return Arrays.stream(body.split("&")).map(s -> s.split("=")).collect(Collectors.toMap(arr -> arr[0], arr -> arr[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doPost(String path, HttpExchange ex) throws IOException {
|
||||||
|
// pre-login paths
|
||||||
|
switch (path) {
|
||||||
|
case "/":
|
||||||
|
return provideToken(ex);
|
||||||
|
}
|
||||||
|
return notFound(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean provideToken(HttpExchange ex) throws IOException {
|
||||||
|
var map = deserialize(body(ex));
|
||||||
|
LOG.log(WARNING, "post data: {0}", map);
|
||||||
|
LOG.log(ERROR, "{0}.provideToken(ex) not implemented!", getClass().getSimpleName());
|
||||||
|
var grantType = map.get(GRANT_TYPE);
|
||||||
|
if (!ATUH_CODE.equals(grantType)) sendContent(ex, HTTP_BAD_REQUEST, Map.of(ERROR, "unknown grant type", GRANT_TYPE, grantType));
|
||||||
|
return sendEmptyResponse(HTTP_NOT_FOUND, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/* © SRSoftware 2024 */
|
||||||
|
package de.srsoftware.oidc.backend;
|
||||||
|
|
||||||
|
import static de.srsoftware.oidc.api.User.*;
|
||||||
|
import static java.lang.System.Logger.Level.WARNING;
|
||||||
|
import static java.net.HttpURLConnection.*;
|
||||||
|
|
||||||
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
|
import de.srsoftware.cookies.SessionToken;
|
||||||
|
import de.srsoftware.oidc.api.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class UserController extends Controller {
|
||||||
|
private final UserService users;
|
||||||
|
|
||||||
|
public UserController(SessionService sessionService, UserService userService) {
|
||||||
|
super(sessionService);
|
||||||
|
users = userService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doGet(String path, HttpExchange ex) throws IOException {
|
||||||
|
var optSession = getSession(ex);
|
||||||
|
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
||||||
|
|
||||||
|
// post-login paths
|
||||||
|
var session = optSession.get();
|
||||||
|
switch (path) {
|
||||||
|
case "/logout":
|
||||||
|
return logout(ex, session);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG.log(WARNING, "not implemented");
|
||||||
|
return sendEmptyResponse(HTTP_NOT_FOUND, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doPost(String path, HttpExchange ex) throws IOException {
|
||||||
|
switch (path) {
|
||||||
|
case "/login":
|
||||||
|
return login(ex);
|
||||||
|
}
|
||||||
|
var optSession = getSession(ex);
|
||||||
|
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
||||||
|
|
||||||
|
// post-login paths
|
||||||
|
var session = optSession.get();
|
||||||
|
switch (path) {
|
||||||
|
case "/":
|
||||||
|
return sendUserAndCookie(ex, session);
|
||||||
|
case "/password":
|
||||||
|
return updatePassword(ex, session);
|
||||||
|
case "/update":
|
||||||
|
return updateUser(ex, session);
|
||||||
|
}
|
||||||
|
return notFound(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean login(HttpExchange ex) throws IOException {
|
||||||
|
var body = json(ex);
|
||||||
|
|
||||||
|
var username = body.has(USERNAME) ? body.getString(USERNAME) : null;
|
||||||
|
var password = body.has(PASSWORD) ? body.getString(PASSWORD) : null;
|
||||||
|
|
||||||
|
Optional<User> user = users.load(username, password);
|
||||||
|
if (user.isPresent()) return sendUserAndCookie(ex, sessions.createSession(user.get()));
|
||||||
|
return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean logout(HttpExchange ex, Session session) throws IOException {
|
||||||
|
sessions.dropSession(session.id());
|
||||||
|
new SessionToken("").addTo(ex);
|
||||||
|
return sendEmptyResponse(HTTP_OK, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean sendUserAndCookie(HttpExchange ex, Session session) throws IOException {
|
||||||
|
new SessionToken(session.id()).addTo(ex);
|
||||||
|
return sendContent(ex, session.user().map(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean updatePassword(HttpExchange ex, Session session) throws IOException {
|
||||||
|
var user = session.user();
|
||||||
|
var json = json(ex);
|
||||||
|
var uuid = json.getString(UUID);
|
||||||
|
if (!uuid.equals(user.uuid())) {
|
||||||
|
return sendEmptyResponse(HTTP_FORBIDDEN, ex);
|
||||||
|
}
|
||||||
|
var oldPass = json.getString("oldpass");
|
||||||
|
if (!users.passwordMatches(oldPass, user.hashedPassword())) return badRequest(ex, "wrong password");
|
||||||
|
|
||||||
|
var newpass = json.getJSONArray("newpass");
|
||||||
|
var newPass1 = newpass.getString(0);
|
||||||
|
if (!newPass1.equals(newpass.getString(1))) {
|
||||||
|
return badRequest(ex, "password mismatch");
|
||||||
|
}
|
||||||
|
users.updatePassword(user, newPass1);
|
||||||
|
return sendContent(ex, user.map(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean updateUser(HttpExchange ex, Session session) throws IOException {
|
||||||
|
var user = session.user();
|
||||||
|
var json = json(ex);
|
||||||
|
var uuid = json.getString(UUID);
|
||||||
|
if (!uuid.equals(user.uuid())) {
|
||||||
|
return sendEmptyResponse(HTTP_FORBIDDEN, ex);
|
||||||
|
}
|
||||||
|
user.username(json.getString(USERNAME));
|
||||||
|
user.email(json.getString(EMAIL));
|
||||||
|
users.save(user);
|
||||||
|
return sendContent(ex, user.map(false));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/* © SRSoftware 2024 */
|
||||||
|
package de.srsoftware.oidc.backend;
|
||||||
|
|
||||||
|
import static java.lang.System.Logger.Level.WARNING;
|
||||||
|
import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
|
||||||
|
|
||||||
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
|
import de.srsoftware.oidc.api.PathHandler;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class WellKnownController extends PathHandler {
|
||||||
|
@Override
|
||||||
|
public boolean doGet(String path, HttpExchange ex) throws IOException {
|
||||||
|
switch (path) {
|
||||||
|
case "/openid-configuration":
|
||||||
|
return openidConfig(ex);
|
||||||
|
}
|
||||||
|
LOG.log(WARNING, "not implemented");
|
||||||
|
return sendEmptyResponse(HTTP_NOT_FOUND, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean openidConfig(HttpExchange ex) throws IOException {
|
||||||
|
var host = hostname(ex);
|
||||||
|
return sendContent(ex, Map.of("token_endpoint", host + "/api/token", "authorization_endpoint", host + "/web/authorization.html", "userinfo_endpoint", host + "/api/userinfo", "jwks_uri", host + "/api/jwks"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,7 +34,7 @@ function denyAutorization(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function backendAutorization(){
|
function backendAutorization(){
|
||||||
fetch(api+"/authorize",{
|
fetch(client_controller+"/authorize",{
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(json),
|
body: JSON.stringify(json),
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ function handleRemove(response){
|
|||||||
function remove(clientId){
|
function remove(clientId){
|
||||||
var message = document.getElementById('message').innerHTML;
|
var message = document.getElementById('message').innerHTML;
|
||||||
if (confirm(message.replace("{}",clientId))) {
|
if (confirm(message.replace("{}",clientId))) {
|
||||||
fetch(api+"/client",{
|
fetch(client_controller+"/delete",{
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
body : JSON.stringify({ client_id : clientId })
|
body : JSON.stringify({ client_id : clientId })
|
||||||
}).then(handleRemove);
|
}).then(handleRemove);
|
||||||
@@ -31,4 +31,4 @@ function edit(clientId){
|
|||||||
redirect("edit_client.html?id="+clientId);
|
redirect("edit_client.html?id="+clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch(api+"/clients",{method:'POST'}).then(handleClients);
|
fetch(client_controller+"/list",{method:'POST'}).then(handleClients);
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
var api = "/api";
|
var api = "/api";
|
||||||
|
var client_controller = "/api/client"
|
||||||
|
var user_controller = "/api/user"
|
||||||
var web = "/web";
|
var web = "/web";
|
||||||
|
|
||||||
const UNAUTHORIZED = 401;
|
const UNAUTHORIZED = 401;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ function doRedirect(){
|
|||||||
function tryLogin(){
|
function tryLogin(){
|
||||||
var username = getValue('username');
|
var username = getValue('username');
|
||||||
var password = getValue('password');
|
var password = getValue('password');
|
||||||
fetch(api+"/login",{
|
fetch(user_controller+"/login",{
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ function handleLogout(response){
|
|||||||
if (response.ok) document.body.innerHTML += 'success';
|
if (response.ok) document.body.innerHTML += 'success';
|
||||||
redirect('index.html')
|
redirect('index.html')
|
||||||
}
|
}
|
||||||
fetch(api+"/logout").then(handleLogout)
|
fetch(user_controller+"/logout").then(handleLogout)
|
||||||
@@ -6,7 +6,7 @@ function addClient(){
|
|||||||
secret : getValue('client-secret'),
|
secret : getValue('client-secret'),
|
||||||
redirect_uris : getValue('redirect-urls').split("\n")
|
redirect_uris : getValue('redirect-urls').split("\n")
|
||||||
};
|
};
|
||||||
fetch(api+'/add/client',{
|
fetch(client_controller+'/add',{
|
||||||
method : 'POST',
|
method : 'POST',
|
||||||
headers : {
|
headers : {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ function update(){
|
|||||||
email : getValue('email'),
|
email : getValue('email'),
|
||||||
uuid : getValue('uuid')
|
uuid : getValue('uuid')
|
||||||
}
|
}
|
||||||
fetch(api+'/update/user',{
|
fetch(user_controller+'/update',{
|
||||||
method : 'POST',
|
method : 'POST',
|
||||||
headers : {
|
headers : {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
@@ -68,7 +68,7 @@ function updatePass(){
|
|||||||
newpass : [getValue('newpass1'),getValue('newpass2')],
|
newpass : [getValue('newpass1'),getValue('newpass2')],
|
||||||
uuid : getValue('uuid')
|
uuid : getValue('uuid')
|
||||||
}
|
}
|
||||||
fetch(api+'/update/password',{
|
fetch(user_controller+'/password',{
|
||||||
method : 'POST',
|
method : 'POST',
|
||||||
headers : {
|
headers : {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
|
|||||||
@@ -24,4 +24,4 @@ async function handleNavigation(response){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch(api+"/user",{method:'POST'}).then(handleUser);
|
fetch(user_controller+"/",{method:'POST'}).then(handleUser);
|
||||||
Reference in New Issue
Block a user