From 1b81ae1bb69d81b4d357b87e4858208432e178f0 Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 14 May 2021 20:35:44 -0400 Subject: [PATCH 001/144] test --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50c77b02..641f9a10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -154,4 +154,4 @@ Typescript refactor ### v0.6.1 Fix build system -- Rework rollup with typescript and environment variables \ No newline at end of file +- Rework rollup with typescript and environment variables From 2e7ea88f947f56ff3f436af035b64c8007eba128 Mon Sep 17 00:00:00 2001 From: stzups Date: Mon, 17 May 2021 09:58:24 -0400 Subject: [PATCH 002/144] add js debug mechanism - html can be edited, compiled js will resolve to diff directory --- ...cribbleshareBackendConfigImplementation.java | 6 ++++++ .../backend/server/http/HttpServerHandler.java | 17 +++++++++++++++-- .../scribbleshare-frontend/src/login.html | 14 ++++++++++++++ scribbleshare-app/scribbleshare.properties | 5 +++-- 4 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 scribbleshare-app/scribbleshare-frontend/src/login.html diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfigImplementation.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfigImplementation.java index 882c99ef..727e78a2 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfigImplementation.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfigImplementation.java @@ -8,6 +8,7 @@ public class ScribbleshareBackendConfigImplementation extends ScribbleshareConfi private static final ConfigKey HTML_ROOT = new OptionalConfigKey<>("html.root", "html"); private static final ConfigKey MIME_TYPES_FILE_PATH = new OptionalConfigKey<>("mimetypes.path", "mime.types"); private static final ConfigKey HTTP_CACHE_SECONDS = new OptionalConfigKey<>("http.cache.seconds", 0); + private static final ConfigKey DEBUG_JS_ROOT = new OptionalConfigKey<>("debug.js.root", ""); @Override public String getHttpRoot() { @@ -24,4 +25,9 @@ public String getMimeTypesFilePath() { return getString(MIME_TYPES_FILE_PATH); } + @Override + public String getDebugJsRoot() { + return getString(DEBUG_JS_ROOT); + } + } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 0de0a647..9940de6d 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -42,6 +42,7 @@ public interface Config extends HttpConfig { String getHttpRoot(); int getHttpCacheSeconds(); String getMimeTypesFilePath(); + String getDebugJsRoot(); } private static final long MAX_AGE_NO_EXPIRE = 31536000;//one year, max age of a cookie @@ -62,6 +63,7 @@ public interface Config extends HttpConfig { private final HttpConfig config; private final ScribbleshareDatabase database; + private final File jsRoot; private final File httpRoot; private final int httpCacheSeconds; private final MimeTypes mimeTypes = new MimeTypes(); @@ -69,8 +71,13 @@ public interface Config extends HttpConfig { public HttpServerHandler(Config config, ScribbleshareDatabase database) { this.config = config; this.database = database; - + httpRoot = new File(config.getHttpRoot()); + if (config.getDebugJsRoot().equals("")) { + jsRoot = httpRoot; + } else { + jsRoot = new File(config.getDebugJsRoot()); + } httpCacheSeconds = config.getHttpCacheSeconds(); String path = config.getMimeTypesFilePath(); // check for mime types in working directory @@ -250,7 +257,13 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr return; } - File file = new File(httpRoot, filePath); + File root; + if (filePath.endsWith(".js")) { + root = jsRoot; + } else { + root = httpRoot; + } + File file = new File(root, filePath); if (file.isHidden() || !file.exists() || file.isDirectory() || !file.isFile()) { if (new File(httpRoot, filePath.substring(0, filePath.length() - DEFAULT_FILE_EXTENSION.length())).isDirectory()) { // /test -> /test/ if test is a valid directory and /test.html does not exist sendRedirect(ctx, request, path + "/" + rawQuery); diff --git a/scribbleshare-app/scribbleshare-frontend/src/login.html b/scribbleshare-app/scribbleshare-frontend/src/login.html new file mode 100644 index 00000000..68b840b1 --- /dev/null +++ b/scribbleshare-app/scribbleshare-frontend/src/login.html @@ -0,0 +1,14 @@ + + + + Login + + +
+ + + Remember me + +
+ + \ No newline at end of file diff --git a/scribbleshare-app/scribbleshare.properties b/scribbleshare-app/scribbleshare.properties index 16818b9d..b2255263 100644 --- a/scribbleshare-app/scribbleshare.properties +++ b/scribbleshare-app/scribbleshare.properties @@ -2,6 +2,7 @@ ssl=false postgres.url=jdbc:postgresql://localhost:5432/scribbleshare postgres.user=scribbleshare_backend postgres.password=changeme -html.root=scribbleshare-frontend/build +html.root=scribbleshare-frontend/src domain=localhost -port=3456 \ No newline at end of file +port=3456 +debug.js.root=scribbleshare-frontend/build \ No newline at end of file From ec619b26e41570907306377da9ea3806e4e4d747 Mon Sep 17 00:00:00 2001 From: stzups Date: Mon, 17 May 2021 10:55:58 -0400 Subject: [PATCH 003/144] add login endpoint --- .../server/http/HttpServerHandler.java | 59 +++++++++++++++++-- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 9940de6d..11f02097 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -8,6 +8,7 @@ import io.netty.handler.codec.http.DefaultHttpHeaders; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpHeaderValues; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpRequest; @@ -26,6 +27,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -133,6 +135,53 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr // check if this is a special request switch (route[0]) { + case "login": { + if (route.length != 1 || !request.method().equals(HttpMethod.POST)) { + break; + } + + String contentType = request.headers().get(HttpHeaderNames.CONTENT_TYPE); + if (contentType == null || !contentType.contentEquals(HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED)) { + send(ctx, request, HttpResponseStatus.BAD_REQUEST); + return; + } + + //todo check host/origin/referer + + Map form = parseQuery(request.content().toString(StandardCharsets.UTF_8)); + if (form == null) { + send(ctx, request, HttpResponseStatus.BAD_REQUEST); + return; + } + + String username = form.get("username"); + String password = form.get("password"); + + if (username == null || password == null) { + send(ctx, request, HttpResponseStatus.BAD_REQUEST); + return; + } + + String rememberRaw = form.get("remember"); + boolean remember; + if (rememberRaw != null) { + if (rememberRaw.equals("on")) { + remember = true; + } else { + send(ctx, request, HttpResponseStatus.BAD_REQUEST); + return; + } + } else { + remember = false; + } + + + System.out.println(username + ", " + password + ", " + remember); + send(ctx, request, HttpResponseStatus.OK); + return; + + //break; + } case "api": { if (route.length < 2) { send(ctx, request, HttpResponseStatus.NOT_FOUND); @@ -397,7 +446,7 @@ private static String getFilePath(String path) { /** * Returns String array with length of 2, with the first element as the path and the second element as the raw query * Example: - * /index.html?key=value&otherKey=otherValue -> [ /index.html, ?key=value&otherKey=otherValue ] + * /index.html?key=value&otherKey=otherValue -> [ /index.html, key=value&otherKey=otherValue ] */ public static String[] splitQuery(String uri) { int index = uri.lastIndexOf(QUERY_DELIMITER); @@ -410,20 +459,18 @@ public static String[] splitQuery(String uri) { } else if (uri.indexOf(QUERY_DELIMITER) != index) { // make sure there is only one ? in the uri return null; } else { - return new String[] {uri.substring(0, index), uri.substring(index)}; + return new String[] {uri.substring(0, index), uri.substring(index + 1)}; } } /** - * Parses ?key=value&otherKey=otherValue&keyWithEmptyValue to a Map of key-value pairs + * Parses key=value&otherKey=otherValue&keyWithEmptyValue to a Map of key-value pairs */ public static Map parseQuery(String query) { if (query.isEmpty()) return Collections.emptyMap(); // no query to parse - if (!query.startsWith("?")) return null; // malformed, should start with ? Map queries = new HashMap<>(); - String[] keyValuePairs = query.substring(1) // query starts with ? - .split(QUERY_SEPARATOR); + String[] keyValuePairs = query.split(QUERY_SEPARATOR); for (String keyValuePair : keyValuePairs) { String[] split = keyValuePair.split(QUERY_PAIR_SEPARATOR, 3); // a limit of 2 (expected) would not detect malformed queries such as ?key==, so we need to go one more if (split.length == 1) { // key with no value, such as ?key From b206e12b1967601a9ef3e4ed0c838d67702f867f Mon Sep 17 00:00:00 2001 From: stzups Date: Mon, 17 May 2021 11:20:48 -0400 Subject: [PATCH 004/144] improve login --- .../server/http/HttpServerHandler.java | 100 ++++++++++-------- 1 file changed, 53 insertions(+), 47 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 11f02097..a9946c1e 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -62,6 +62,11 @@ public interface Config extends HttpConfig { // abc-ABC_123.file private static final String FILE_NAME_REGEX = "a-zA-Z0-9-_"; + + private static final String LOGIN_PATH = "/login"; // which path the server will handle login requests + private static final String LOGIN_FAIL = "/login"; // redirect to bad login, should be the login page + private static final String LOGIN_SUCCESS = "/"; // redirect to good login + private final HttpConfig config; private final ScribbleshareDatabase database; @@ -135,53 +140,6 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr // check if this is a special request switch (route[0]) { - case "login": { - if (route.length != 1 || !request.method().equals(HttpMethod.POST)) { - break; - } - - String contentType = request.headers().get(HttpHeaderNames.CONTENT_TYPE); - if (contentType == null || !contentType.contentEquals(HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED)) { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); - return; - } - - //todo check host/origin/referer - - Map form = parseQuery(request.content().toString(StandardCharsets.UTF_8)); - if (form == null) { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); - return; - } - - String username = form.get("username"); - String password = form.get("password"); - - if (username == null || password == null) { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); - return; - } - - String rememberRaw = form.get("remember"); - boolean remember; - if (rememberRaw != null) { - if (rememberRaw.equals("on")) { - remember = true; - } else { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); - return; - } - } else { - remember = false; - } - - - System.out.println(username + ", " + password + ", " + remember); - send(ctx, request, HttpResponseStatus.OK); - return; - - //break; - } case "api": { if (route.length < 2) { send(ctx, request, HttpResponseStatus.NOT_FOUND); @@ -280,6 +238,54 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr } + //login + + if (uri.equals(LOGIN_PATH) && request.method().equals(HttpMethod.POST)) { + String contentType = request.headers().get(HttpHeaderNames.CONTENT_TYPE); + if (contentType == null || !contentType.contentEquals(HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED)) { + send(ctx, request, HttpResponseStatus.BAD_REQUEST); + return; + } + + //todo check host/origin/referer + + Map form = parseQuery(request.content().toString(StandardCharsets.UTF_8)); + if (form == null) { + send(ctx, request, HttpResponseStatus.BAD_REQUEST); + return; + } + + String username = form.get("username"); + String password = form.get("password"); + + if (username == null || password == null) { + send(ctx, request, HttpResponseStatus.BAD_REQUEST); + return; + } + + String rememberRaw = form.get("remember"); + boolean remember; + if (rememberRaw != null) { + if (rememberRaw.equals("on")) { + remember = true; + } else { + send(ctx, request, HttpResponseStatus.BAD_REQUEST); + return; + } + } else { + remember = false; + } + + + System.out.println(username + ", " + password + ", " + remember); + if (true) { + sendRedirect(ctx, request, LOGIN_SUCCESS); + } else { + sendRedirect(ctx, request, LOGIN_FAIL); + } + return; + } + // otherwise try to serve a regular HTTP file resource if (!HttpMethod.GET.equals(request.method())) { From a45cbdbd69535dfd47e01b47e923e92031f78b21 Mon Sep 17 00:00:00 2001 From: stzups Date: Mon, 17 May 2021 14:05:58 -0400 Subject: [PATCH 005/144] bcrypt --- .../server/http/HttpServerHandler.java | 21 ++++++++-- .../server/http/PasswordValidator.java | 7 ++++ scribbleshare-commons/build.gradle | 1 + .../data/database/ScribbleshareDatabase.java | 3 +- .../implementations/PostgresDatabase.java | 22 +++++++++- .../scribbleshare/data/objects/User.java | 8 +++- .../objects/authentication/login/Login.java | 40 +++++++++++++++++++ .../sql/1-scribbleshare.sql | 9 +++++ 8 files changed, 103 insertions(+), 8 deletions(-) create mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/PasswordValidator.java create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index a9946c1e..b6522067 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -22,6 +22,7 @@ import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.data.objects.authentication.http.HttpSession; import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpSession; +import net.stzups.scribbleshare.data.objects.authentication.login.Login; import java.io.File; import java.io.FileInputStream; @@ -46,7 +47,6 @@ public interface Config extends HttpConfig { String getMimeTypesFilePath(); String getDebugJsRoot(); } - private static final long MAX_AGE_NO_EXPIRE = 31536000;//one year, max age of a cookie @@ -255,6 +255,8 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr return; } + // validate + String username = form.get("username"); String password = form.get("password"); @@ -278,11 +280,22 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr System.out.println(username + ", " + password + ", " + remember); - if (true) { - sendRedirect(ctx, request, LOGIN_SUCCESS); - } else { + + Login login = database.getLogin(username); + Long id = Login.verify(login, password.getBytes(StandardCharsets.UTF_8)); + if (id == null) { + //todo rate limit and generic error handling + if (login == null) { + //bad username + } else { + //bad password + } + sendRedirect(ctx, request, LOGIN_FAIL); + return; } + + sendRedirect(ctx, request, LOGIN_SUCCESS); return; } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/PasswordValidator.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/PasswordValidator.java new file mode 100644 index 00000000..b09c03de --- /dev/null +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/PasswordValidator.java @@ -0,0 +1,7 @@ +package net.stzups.scribbleshare.backend.server.http; + +public class PasswordValidator { + static boolean validate(String password) { + return true; + } +} diff --git a/scribbleshare-commons/build.gradle b/scribbleshare-commons/build.gradle index dd846643..8f8a9826 100644 --- a/scribbleshare-commons/build.gradle +++ b/scribbleshare-commons/build.gradle @@ -10,4 +10,5 @@ dependencies { api 'io.netty:netty-all:4.1.55.Final' implementation 'org.postgresql:postgresql:42.2.13' implementation 'redis.clients:jedis:3.5.2' + implementation('at.favre.lib:bcrypt:0.9.0') } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java index e4832bd0..e2ae9f3f 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java @@ -4,7 +4,8 @@ import net.stzups.scribbleshare.data.database.databases.PersistentSessionDatabase; import net.stzups.scribbleshare.data.database.databases.ResourceDatabase; import net.stzups.scribbleshare.data.database.databases.SessionDatabase; +import net.stzups.scribbleshare.data.objects.authentication.login.Login; public interface ScribbleshareDatabase extends MiscDatabase, PersistentSessionDatabase, ResourceDatabase, SessionDatabase { - + Login getLogin(String username); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index 020e08ce..d980a8ce 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -11,6 +11,7 @@ import net.stzups.scribbleshare.data.objects.User; import net.stzups.scribbleshare.data.objects.authentication.http.HttpSession; import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpSession; +import net.stzups.scribbleshare.data.objects.authentication.login.Login; import net.stzups.scribbleshare.data.objects.canvas.Canvas; import org.postgresql.util.PSQLException; @@ -29,6 +30,22 @@ import java.util.Random; public class PostgresDatabase implements AutoCloseable, ScribbleshareDatabase { + public Login getLogin(String username) { + try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM logins WHERE username=?")) { + preparedStatement.setString(1, username); + try (ResultSet resultSet = preparedStatement.executeQuery()) { + if (resultSet.next()) { + return new Login(resultSet.getLong("id"), resultSet.getBytes("hashed_password")); + } else { + return null; + } + } + } catch (SQLException e) { + e.printStackTrace(); + return null; + } + } + public interface Config { String getUrl(); String getUser(); @@ -64,7 +81,7 @@ public void close() throws SQLException { @Override public User createUser() { - User user = new User(RANDOM.nextLong(), new Long[0], new Long[0]); + User user = new User(RANDOM.nextLong(), new Long[0], new Long[0], ""); try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO users(id, owned_documents, shared_documents) VALUES (?, ?, ?)")) { preparedStatement.setLong(1, user.getId()); preparedStatement.setArray(2, connection.createArrayOf("bigint", user.getOwnedDocuments().toArray())); @@ -84,7 +101,8 @@ public User getUser(long id) { if (resultSet.next()) { return new User(id, (Long[]) (resultSet.getArray("owned_documents").getArray()), - (Long[]) (resultSet.getArray("shared_documents").getArray())); + (Long[]) (resultSet.getArray("shared_documents").getArray()), + resultSet.getString("username")); } else { return null; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/User.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/User.java index f5b75100..030ca7f1 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/User.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/User.java @@ -8,11 +8,13 @@ public class User { private final long id; private final Set ownedDocuments; private final Set sharedDocuments; + private final String username; - public User(long id, Long[] ownedDocuments, Long[] sharedDocuments) { + public User(long id, Long[] ownedDocuments, Long[] sharedDocuments, String username) { this.id = id; this.ownedDocuments = new HashSet<>(Arrays.asList(ownedDocuments)); this.sharedDocuments = new HashSet<>(Arrays.asList(sharedDocuments)); + this.username = username; } public long getId() { @@ -27,6 +29,10 @@ public Set getSharedDocuments() { return sharedDocuments; } + public String getUsername() { + return username; + } + @Override public String toString() { return "User{id=" + id + ",ownedDocuments=" + ownedDocuments + ",sharedDocuments=" + sharedDocuments + "}"; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java new file mode 100644 index 00000000..7c3b0c23 --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java @@ -0,0 +1,40 @@ +package net.stzups.scribbleshare.data.objects.authentication.login; + +import at.favre.lib.crypto.bcrypt.BCrypt; + +import java.util.Arrays; + +public class Login { + private final long id; + private final byte[] hashedPassword; + + public Login(long id, byte[] hashedPassword) { + this.id = id; + this.hashedPassword = hashedPassword; + } + + public long getId() { + return id; + } + + public static Long verify(Login login, byte[] plaintext) { + byte[] hashedPassword; + if (login == null) { + hashedPassword = new byte[0]; + } else { + hashedPassword = login.hashedPassword; + } + + boolean verified = BCrypt.verifyer().verify(plaintext, hashedPassword).verified; + + Arrays.fill(hashedPassword, (byte) 0); + Arrays.fill(plaintext, (byte) 0); + + if (verified) { + assert login != null; + return login.id; + } else { + return null; + } + } +} diff --git a/scribbleshare-postgres/sql/1-scribbleshare.sql b/scribbleshare-postgres/sql/1-scribbleshare.sql index 7397cf52..2e81a1af 100644 --- a/scribbleshare-postgres/sql/1-scribbleshare.sql +++ b/scribbleshare-postgres/sql/1-scribbleshare.sql @@ -24,11 +24,20 @@ CREATE TABLE users( id bigint NOT NULL, owned_documents bigint[] NOT NULL, shared_documents bigint[] NOT NULL, + username varchar(256) NOT NULL, PRIMARY KEY (id) ); GRANT SELECT, INSERT, UPDATE ON users TO scribbleshare_backend; GRANT SELECT, UPDATE ON users TO scribbleshare_room; +CREATE TABLE logins( + username varchar(256) NOT NULL, + user_id bigint NOT NULL, + hashed_password bytea NOT NULL, + PRIMARY KEY (username) +); +GRANT SELECT, INSERT ON logins TO scribbleshare_backend; + CREATE TABLE documents( id bigint NOT NULL, owner bigint NOT NULL, From 2ff04f24c5f1235196a6ae959feccf022eb320e0 Mon Sep 17 00:00:00 2001 From: stzups Date: Mon, 17 May 2021 15:29:30 -0400 Subject: [PATCH 006/144] even more log in functionality --- .../backend/server/http/HttpServerHandler.java | 9 ++++++--- .../data/objects/authentication/http/HttpSession.java | 4 ++-- .../net/stzups/scribbleshare/server/http/HttpUtils.java | 8 +++++++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index b6522067..a156a739 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -6,6 +6,7 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.DefaultHttpHeaders; +import io.netty.handler.codec.http.EmptyHttpHeaders; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpHeaderValues; @@ -286,16 +287,18 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr if (id == null) { //todo rate limit and generic error handling if (login == null) { - //bad username + Scribbleshare.getLogger(ctx).info("Bad username " + username); } else { - //bad password + Scribbleshare.getLogger(ctx).info("Bad password for username " + username); } sendRedirect(ctx, request, LOGIN_FAIL); return; } - sendRedirect(ctx, request, LOGIN_SUCCESS); + HttpHeaders httpHeaders = EmptyHttpHeaders.INSTANCE; + database.addHttpSession(new HttpSession(config, database.getUser(login.getId()), httpHeaders)); + sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); return; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSession.java index 510f242d..aab8b0d9 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSession.java @@ -57,11 +57,11 @@ public static ClientCookie getClientCookie(HttpRequest request, String name) { public static final String COOKIE_NAME = "session"; - public HttpSession(long user) { + protected HttpSession(long user) { super(user); } - public HttpSession(long id, long user, Timestamp creation, byte[] hashedToken) { + protected HttpSession(long id, long user, Timestamp creation, byte[] hashedToken) { super(id, user, creation, hashedToken); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java index 2749360f..7e5582ab 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java @@ -7,6 +7,7 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.DefaultHttpResponse; +import io.netty.handler.codec.http.EmptyHttpHeaders; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpChunkedInput; @@ -113,13 +114,18 @@ public static void send(ChannelHandlerContext ctx, FullHttpRequest request, Http } } - public static void sendRedirect(ChannelHandlerContext ctx, FullHttpRequest request, String newUri) { + public static void sendRedirect(ChannelHandlerContext ctx, FullHttpRequest request, HttpHeaders headers, String newUri) { FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.MOVED_PERMANENTLY, Unpooled.EMPTY_BUFFER); + response.headers().set(headers); response.headers().set(HttpHeaderNames.LOCATION, newUri); send(ctx, request, response); } + public static void sendRedirect(ChannelHandlerContext ctx, FullHttpRequest request, String newUri) { + sendRedirect(ctx, request, EmptyHttpHeaders.INSTANCE, newUri); + } + public static void send(ChannelHandlerContext ctx, FullHttpRequest request, HttpResponseStatus status) { FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, Unpooled.EMPTY_BUFFER); From 6e7ba472e3de34e429a0ceff7df364f4d7dc7853 Mon Sep 17 00:00:00 2001 From: stzups Date: Mon, 17 May 2021 16:05:38 -0400 Subject: [PATCH 007/144] add dummy password --- .../data/objects/authentication/login/Login.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java index 7c3b0c23..067ddf1b 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java @@ -5,6 +5,16 @@ import java.util.Arrays; public class Login { + private static final byte[] DUMMY; + static { + DUMMY = BCrypt.withDefaults().hash(6, new byte[0]); + } + private static byte[] getDummy() { + byte[] dummy = new byte[DUMMY.length]; + System.arraycopy(DUMMY, 0, dummy, 0, dummy.length); + return dummy; + } + private final long id; private final byte[] hashedPassword; @@ -20,7 +30,7 @@ public long getId() { public static Long verify(Login login, byte[] plaintext) { byte[] hashedPassword; if (login == null) { - hashedPassword = new byte[0]; + hashedPassword = getDummy();//todo is this helpful in a hypothetical timing attack? } else { hashedPassword = login.hashedPassword; } From 6d0a5f8798bedbe2d37e51dcf6d7705e9025ad29 Mon Sep 17 00:00:00 2001 From: stzups Date: Mon, 17 May 2021 16:08:05 -0400 Subject: [PATCH 008/144] probably fix memory leak --- .../authentication/http/HttpSession.java | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSession.java index aab8b0d9..5073cd14 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSession.java @@ -42,11 +42,11 @@ public static ClientCookie getClientCookie(HttpRequest request, String name) { Set cookies = ServerCookieDecoder.STRICT.decode(cookiesHeader); for (Cookie cookie : cookies) { if (cookie.name().equals(name)) { - ByteBuf b = Unpooled.wrappedBuffer(cookie.value().getBytes(StandardCharsets.UTF_8)); - ByteBuf byteBuf = Base64.decode(b); - b.release(); - ClientCookie c = new ClientCookie(byteBuf); - byteBuf.release(); + ByteBuf tokenBase64 = Unpooled.wrappedBuffer(cookie.value().getBytes(StandardCharsets.UTF_8)); + ByteBuf token = Base64.decode(tokenBase64); + tokenBase64.release(); + ClientCookie c = new ClientCookie(token); + token.release(); return c; } } @@ -75,10 +75,14 @@ public HttpSession(long id, ByteBuf byteBuf) { } protected DefaultCookie getCookie(String name) { - ByteBuf byteBuf = Unpooled.buffer(); - byteBuf.writeLong(getId()); - byteBuf.writeBytes(super.generateToken()); - return new DefaultCookie(name, Base64.encode(byteBuf).toString(StandardCharsets.UTF_8)); + ByteBuf token = Unpooled.buffer(); + token.writeLong(getId()); + token.writeBytes(super.generateToken()); + ByteBuf tokenBase64 = Base64.encode(token); + DefaultCookie cookie = new DefaultCookie(name, tokenBase64.toString(StandardCharsets.UTF_8)); + tokenBase64.release(); + token.release(); + return cookie; } private void setCookie(HttpConfig config, HttpHeaders headers) { From 1fb1de054c9aebe53855e154f58fab28e5d44eb5 Mon Sep 17 00:00:00 2001 From: stzups Date: Mon, 17 May 2021 17:03:52 -0400 Subject: [PATCH 009/144] rework, start to add register --- .../server/http/HttpServerHandler.java | 64 +++++++++++++++++-- .../server/http/PasswordValidator.java | 7 -- .../scribbleshare-frontend/src/register.html | 13 ++++ .../data/database/ScribbleshareDatabase.java | 1 + .../data/database/databases/MiscDatabase.java | 2 +- .../implementations/PostgresDatabase.java | 22 +++++-- .../scribbleshare/data/objects/User.java | 9 +++ .../objects/authentication/login/Login.java | 20 +++++- 8 files changed, 117 insertions(+), 21 deletions(-) delete mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/PasswordValidator.java create mode 100644 scribbleshare-app/scribbleshare-frontend/src/register.html diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index a156a739..1710fe41 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -64,10 +64,14 @@ public interface Config extends HttpConfig { private static final String FILE_NAME_REGEX = "a-zA-Z0-9-_"; - private static final String LOGIN_PATH = "/login"; // which path the server will handle login requests - private static final String LOGIN_FAIL = "/login"; // redirect to bad login, should be the login page + private static final String LOGIN_PAGE = "/login"; // the login page, where login requests should come from + private static final String LOGIN_PATH = "/login"; // where login requests should go private static final String LOGIN_SUCCESS = "/"; // redirect to good login + private static final String REGISTER_PAGE = "/register"; // the register page, where register requests should come from + private static final String REGISTER_PATH = "/register"; // where register requests should go + private static final String REGISTER_SUCCESS = LOGIN_PAGE; // redirect for a good register, should be the login page + private final HttpConfig config; private final ScribbleshareDatabase database; @@ -248,7 +252,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr return; } - //todo check host/origin/referer + //todo check host/origin/referer to make sure they originate from LOGIN_PAGE Map form = parseQuery(request.content().toString(StandardCharsets.UTF_8)); if (form == null) { @@ -292,7 +296,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr Scribbleshare.getLogger(ctx).info("Bad password for username " + username); } - sendRedirect(ctx, request, LOGIN_FAIL); + sendRedirect(ctx, request, LOGIN_PAGE); return; } @@ -300,6 +304,49 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr database.addHttpSession(new HttpSession(config, database.getUser(login.getId()), httpHeaders)); sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); return; + } else if (uri.equals(REGISTER_PATH) && request.method().equals(HttpMethod.POST)) { + String contentType = request.headers().get(HttpHeaderNames.CONTENT_TYPE); + if (contentType == null || !contentType.contentEquals(HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED)) { + send(ctx, request, HttpResponseStatus.BAD_REQUEST); + return; + } + + //todo check host/origin/referer to make sure they originate from LOGIN_PAGE + + Map form = parseQuery(request.content().toString(StandardCharsets.UTF_8)); + if (form == null) { + send(ctx, request, HttpResponseStatus.BAD_REQUEST); + return; + } + + // validate + + String username = form.get("username"); + String password = form.get("password"); + + if (username == null || password == null) { + send(ctx, request, HttpResponseStatus.BAD_REQUEST); + return; + } + + //todo validate + if (false) { + //todo rate limit and generic error handling + + sendRedirect(ctx, request, REGISTER_PAGE); + return; + } + + User user = new User(username); + database.addUser(user); + Login login = new Login(user, password.getBytes(StandardCharsets.UTF_8)); + database.addLogin(login); + + + System.out.println(username + ", register " + password); + + sendRedirect(ctx, request, REGISTER_SUCCESS); + return; } // otherwise try to serve a regular HTTP file resource @@ -391,10 +438,12 @@ private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders header user = database.getUser(persistentHttpSession.getUser()); } else { //return false; todo - user = database.createUser(); + user = new User(); + database.addUser(user); } } else { - user = database.createUser(); + user = new User(); + database.addUser(user); } HttpSession httpSession = new HttpSession(config, user, headers); @@ -410,7 +459,8 @@ private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders header return true; } else { //todo copied and bad - User user = database.createUser(); + User user = new User(); + database.addUser(user); httpSession = new HttpSession(config, user, headers); database.addHttpSession(httpSession); diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/PasswordValidator.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/PasswordValidator.java deleted file mode 100644 index b09c03de..00000000 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/PasswordValidator.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.stzups.scribbleshare.backend.server.http; - -public class PasswordValidator { - static boolean validate(String password) { - return true; - } -} diff --git a/scribbleshare-app/scribbleshare-frontend/src/register.html b/scribbleshare-app/scribbleshare-frontend/src/register.html new file mode 100644 index 00000000..56462123 --- /dev/null +++ b/scribbleshare-app/scribbleshare-frontend/src/register.html @@ -0,0 +1,13 @@ + + + + Register + + +
+ + + +
+ + \ No newline at end of file diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java index e2ae9f3f..86a6d8ec 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java @@ -8,4 +8,5 @@ public interface ScribbleshareDatabase extends MiscDatabase, PersistentSessionDatabase, ResourceDatabase, SessionDatabase { Login getLogin(String username); + void addLogin(Login login); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/MiscDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/MiscDatabase.java index 257714f2..0aff19c2 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/MiscDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/MiscDatabase.java @@ -5,7 +5,7 @@ import net.stzups.scribbleshare.data.objects.User; public interface MiscDatabase { - User createUser(); + void addUser(User user); User getUser(long id); void updateUser(User user); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index d980a8ce..3701363c 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -30,12 +30,13 @@ import java.util.Random; public class PostgresDatabase implements AutoCloseable, ScribbleshareDatabase { + @Override public Login getLogin(String username) { try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM logins WHERE username=?")) { preparedStatement.setString(1, username); try (ResultSet resultSet = preparedStatement.executeQuery()) { if (resultSet.next()) { - return new Login(resultSet.getLong("id"), resultSet.getBytes("hashed_password")); + return new Login(username, resultSet.getLong("id"), resultSet.getBytes("hashed_password")); } else { return null; } @@ -46,6 +47,18 @@ public Login getLogin(String username) { } } + @Override + public void addLogin(Login login) { + try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO logins(username, user_id, hashed_password) VALUES(?, ?, ?)")) { + preparedStatement.setString(1, login.getUsername()); + preparedStatement.setLong(2, login.getId()); + preparedStatement.setBinaryStream(3, new ByteArrayInputStream(login.getHashedPassword())); + preparedStatement.execute(); + } catch (SQLException e) { + e.printStackTrace();//todo error handling + } + } + public interface Config { String getUrl(); String getUser(); @@ -80,17 +93,16 @@ public void close() throws SQLException { } @Override - public User createUser() { - User user = new User(RANDOM.nextLong(), new Long[0], new Long[0], ""); - try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO users(id, owned_documents, shared_documents) VALUES (?, ?, ?)")) { + public void addUser(User user) { + try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO users(id, owned_documents, shared_documents, username) VALUES (?, ?, ?, ?)")) { preparedStatement.setLong(1, user.getId()); preparedStatement.setArray(2, connection.createArrayOf("bigint", user.getOwnedDocuments().toArray())); preparedStatement.setArray(3, connection.createArrayOf("bigint", user.getSharedDocuments().toArray())); + preparedStatement.setString(4, user.getUsername()); preparedStatement.execute(); } catch (SQLException e) { e.printStackTrace(); } - return user; } @Override diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/User.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/User.java index 030ca7f1..b2fa15a8 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/User.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/User.java @@ -2,14 +2,23 @@ import java.util.Arrays; import java.util.HashSet; +import java.util.Random; import java.util.Set; public class User { + private static final Random RANDOM = new Random(); private final long id; private final Set ownedDocuments; private final Set sharedDocuments; private final String username; + public User() { + this(""); + } + + public User(String username) { + this(RANDOM.nextLong(), new Long[0], new Long[0], username); + } public User(long id, Long[] ownedDocuments, Long[] sharedDocuments, String username) { this.id = id; this.ownedDocuments = new HashSet<>(Arrays.asList(ownedDocuments)); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java index 067ddf1b..68406f44 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java @@ -1,6 +1,7 @@ package net.stzups.scribbleshare.data.objects.authentication.login; import at.favre.lib.crypto.bcrypt.BCrypt; +import net.stzups.scribbleshare.data.objects.User; import java.util.Arrays; @@ -15,18 +16,35 @@ private static byte[] getDummy() { return dummy; } + private final String username; private final long id; private final byte[] hashedPassword; - public Login(long id, byte[] hashedPassword) { + public Login(User user, byte[] password) { + this.id = user.getId(); + this.username = user.getUsername(); + this.hashedPassword = BCrypt.withDefaults().hash(6, password); + Arrays.fill(password, (byte) 0); + } + + public Login(String username, long id, byte[] hashedPassword) { + this.username = username; this.id = id; this.hashedPassword = hashedPassword; } + public String getUsername() { + return username; + } + public long getId() { return id; } + public byte[] getHashedPassword() { + return hashedPassword; + } + public static Long verify(Login login, byte[] plaintext) { byte[] hashedPassword; if (login == null) { From 053bd6c7a19c913780e5d1792e825dc5a02f3eb3 Mon Sep 17 00:00:00 2001 From: stzups Date: Mon, 17 May 2021 17:08:15 -0400 Subject: [PATCH 010/144] fix header thing --- .../scribbleshare/backend/server/http/HttpServerHandler.java | 3 +-- .../data/database/implementations/PostgresDatabase.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 1710fe41..6b6be734 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -6,7 +6,6 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.DefaultHttpHeaders; -import io.netty.handler.codec.http.EmptyHttpHeaders; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpHeaderValues; @@ -300,7 +299,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr return; } - HttpHeaders httpHeaders = EmptyHttpHeaders.INSTANCE; + HttpHeaders httpHeaders = new DefaultHttpHeaders(); database.addHttpSession(new HttpSession(config, database.getUser(login.getId()), httpHeaders)); sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); return; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index 3701363c..26333d63 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -36,7 +36,7 @@ public Login getLogin(String username) { preparedStatement.setString(1, username); try (ResultSet resultSet = preparedStatement.executeQuery()) { if (resultSet.next()) { - return new Login(username, resultSet.getLong("id"), resultSet.getBytes("hashed_password")); + return new Login(username, resultSet.getLong("user_id"), resultSet.getBytes("hashed_password")); } else { return null; } From 5690d3c34347669c57cb7898f9f559c83eba3b2e Mon Sep 17 00:00:00 2001 From: stzups Date: Mon, 17 May 2021 18:09:33 -0400 Subject: [PATCH 011/144] maybe add existing temp user registration --- .../server/http/HttpServerHandler.java | 48 +++++++++++-------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 6b6be734..34ac55ce 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -245,15 +245,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr //login if (uri.equals(LOGIN_PATH) && request.method().equals(HttpMethod.POST)) { - String contentType = request.headers().get(HttpHeaderNames.CONTENT_TYPE); - if (contentType == null || !contentType.contentEquals(HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED)) { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); - return; - } - - //todo check host/origin/referer to make sure they originate from LOGIN_PAGE - - Map form = parseQuery(request.content().toString(StandardCharsets.UTF_8)); + Map form = parseForm(request); if (form == null) { send(ctx, request, HttpResponseStatus.BAD_REQUEST); return; @@ -304,15 +296,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); return; } else if (uri.equals(REGISTER_PATH) && request.method().equals(HttpMethod.POST)) { - String contentType = request.headers().get(HttpHeaderNames.CONTENT_TYPE); - if (contentType == null || !contentType.contentEquals(HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED)) { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); - return; - } - - //todo check host/origin/referer to make sure they originate from LOGIN_PAGE - - Map form = parseQuery(request.content().toString(StandardCharsets.UTF_8)); + Map form = parseForm(request); if (form == null) { send(ctx, request, HttpResponseStatus.BAD_REQUEST); return; @@ -336,12 +320,23 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr return; } - User user = new User(username); - database.addUser(user); + User user; + HttpSession.ClientCookie cookie = HttpSession.ClientCookie.getClientCookie(request, HttpSession.COOKIE_NAME); + if (cookie != null) { + HttpSession httpSession = database.getHttpSession(cookie.getId()); + if (httpSession != null) { + user = database.getUser(httpSession.getUser()); + } else { + user = new User(username); + database.addUser(user); + } + } else { + user = new User(username); + database.addUser(user); + } Login login = new Login(user, password.getBytes(StandardCharsets.UTF_8)); database.addLogin(login); - System.out.println(username + ", register " + password); sendRedirect(ctx, request, REGISTER_SUCCESS); @@ -555,4 +550,15 @@ public static Map parseQuery(String query) { return queries; } + + public static Map parseForm(FullHttpRequest request) { + String contentType = request.headers().get(HttpHeaderNames.CONTENT_TYPE); + if (contentType == null || !contentType.contentEquals(HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED)) { + return null; + } + + //todo check host/origin/referer to make sure they originate from LOGIN_PAGE + + return parseQuery(request.content().toString(StandardCharsets.UTF_8)); + } } \ No newline at end of file From b23464ad70798ed154c7ecffc6c252f9e1aa1284 Mon Sep 17 00:00:00 2001 From: stzups Date: Mon, 17 May 2021 18:48:58 -0400 Subject: [PATCH 012/144] probably didn't add logout --- .../server/http/HttpServerHandler.java | 36 +++++++++++++++++-- .../scribbleshare-frontend/src/logout.html | 11 ++++++ .../database/databases/SessionDatabase.java | 1 + .../implementations/PostgresDatabase.java | 10 ++++++ .../http/PersistentHttpSession.java | 2 +- 5 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 scribbleshare-app/scribbleshare-frontend/src/logout.html diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 34ac55ce..0e65100c 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -64,13 +64,17 @@ public interface Config extends HttpConfig { private static final String LOGIN_PAGE = "/login"; // the login page, where login requests should come from - private static final String LOGIN_PATH = "/login"; // where login requests should go - private static final String LOGIN_SUCCESS = "/"; // redirect to good login + private static final String LOGIN_PATH = PersistentHttpSession.LOGIN_PATH; // where login requests should go + private static final String LOGIN_SUCCESS = "/"; // redirect for a good login, should be the main page private static final String REGISTER_PAGE = "/register"; // the register page, where register requests should come from private static final String REGISTER_PATH = "/register"; // where register requests should go private static final String REGISTER_SUCCESS = LOGIN_PAGE; // redirect for a good register, should be the login page + private static final String LOGOUT_PAGE = "/logout"; // the logout page, where logout requests should come from + private static final String LOGOUT_PATH = "/logout"; // where logout requests should go + private static final String LOGOUT_SUCCESS = LOGIN_PAGE; // redirect for a good logout, should be the login page + private final HttpConfig config; private final ScribbleshareDatabase database; @@ -244,6 +248,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr //login + //todo validate for extra fields that should not happen if (uri.equals(LOGIN_PATH) && request.method().equals(HttpMethod.POST)) { Map form = parseForm(request); if (form == null) { @@ -320,6 +325,8 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr return; } + //todo check for existing username and user with username + User user; HttpSession.ClientCookie cookie = HttpSession.ClientCookie.getClientCookie(request, HttpSession.COOKIE_NAME); if (cookie != null) { @@ -341,6 +348,31 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr sendRedirect(ctx, request, REGISTER_SUCCESS); return; + } else if (uri.equals(LOGOUT_PAGE) && request.method().equals(HttpMethod.POST)) { + Map form = parseForm(request); + if (form == null) { + send(ctx, request, HttpResponseStatus.BAD_REQUEST); + return; + } + + User user; + HttpSession.ClientCookie cookie = HttpSession.ClientCookie.getClientCookie(request, HttpSession.COOKIE_NAME); + if (cookie != null) { + database.removeHttpSession(cookie.getId());//todo timing attack???? + +/* HttpSession httpSession = database.getHttpSession(cookie.getId()); + if (httpSession != null) { + user = database.getUser(httpSession.getUser()); + } else {//bad + user = null; + }*/ + } else {//no auth + user = null; + } + + + sendRedirect(ctx, request, LOGIN_SUCCESS); + return; } // otherwise try to serve a regular HTTP file resource diff --git a/scribbleshare-app/scribbleshare-frontend/src/logout.html b/scribbleshare-app/scribbleshare-frontend/src/logout.html new file mode 100644 index 00000000..0bd05b97 --- /dev/null +++ b/scribbleshare-app/scribbleshare-frontend/src/logout.html @@ -0,0 +1,11 @@ + + + + Logout + + +
+ +
+ + \ No newline at end of file diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java index bceecd4a..88fd95c2 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java @@ -7,4 +7,5 @@ public interface SessionDatabase { HttpSession getHttpSession(long id); void addHttpSession(HttpSession httpSession); + void removeHttpSession(long id); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index 26333d63..cffc788e 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -294,6 +294,16 @@ public void addHttpSession(HttpSession httpSession) { } } + @Override + public void removeHttpSession(long id) { + try (PreparedStatement preparedStatement = connection.prepareStatement("DELETE FROM key_value WHERE key=?")) { + preparedStatement.setLong(1, id); + preparedStatement.execute(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + @Override public long addResource(long owner, Resource resource) { long id = RANDOM.nextLong(); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpSession.java index 6721a753..99a8bf60 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpSession.java @@ -16,7 +16,7 @@ public class PersistentHttpSession extends HttpSession { private static final TemporalAmount MAX_SESSION_AGE = Duration.ofDays(90);//todo public static final String COOKIE_NAME = "persistent_session"; - public static final String LOGIN_PATH = "/"; + public static final String LOGIN_PATH = "/login"; public PersistentHttpSession(long id, long user, Timestamp creation, byte[] hashedToken) { super(id, user, creation, hashedToken); From bfdd9876edd48812234c4e416aa8e657fa4b5292 Mon Sep 17 00:00:00 2001 From: stzups Date: Mon, 17 May 2021 21:54:13 -0400 Subject: [PATCH 013/144] rework db sessions --- .../server/http/HttpServerHandler.java | 36 +++++----- .../data/database/ScribbleshareDatabase.java | 17 ++++- .../data/database/databases/MiscDatabase.java | 19 ------ .../databases/PersistentSessionDatabase.java | 6 +- .../database/databases/SessionDatabase.java | 6 +- .../implementations/PostgresDatabase.java | 30 +++++---- .../implementations/RedisDatabase.java | 16 ++--- ...{HttpSession.java => HttpUserSession.java} | 23 ++++--- ...on.java => PersistentHttpUserSession.java} | 29 +++----- .../http/{Session.java => UserSession.java} | 66 +++++++++---------- .../sql/1-scribbleshare.sql | 50 +++++++++----- .../room/server/HttpAuthenticator.java | 6 +- 12 files changed, 151 insertions(+), 153 deletions(-) delete mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/MiscDatabase.java rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/{HttpSession.java => HttpUserSession.java} (83%) rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/{PersistentHttpSession.java => PersistentHttpUserSession.java} (57%) rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/{Session.java => UserSession.java} (50%) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 0e65100c..0cf9fc98 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -20,8 +20,8 @@ import net.stzups.scribbleshare.data.objects.Resource; import net.stzups.scribbleshare.data.objects.User; import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; -import net.stzups.scribbleshare.data.objects.authentication.http.HttpSession; -import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpSession; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; +import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; import net.stzups.scribbleshare.data.objects.authentication.login.Login; import java.io.File; @@ -64,7 +64,7 @@ public interface Config extends HttpConfig { private static final String LOGIN_PAGE = "/login"; // the login page, where login requests should come from - private static final String LOGIN_PATH = PersistentHttpSession.LOGIN_PATH; // where login requests should go + private static final String LOGIN_PATH = PersistentHttpUserSession.LOGIN_PATH; // where login requests should go private static final String LOGIN_SUCCESS = "/"; // redirect for a good login, should be the main page private static final String REGISTER_PAGE = "/register"; // the register page, where register requests should come from @@ -297,7 +297,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr } HttpHeaders httpHeaders = new DefaultHttpHeaders(); - database.addHttpSession(new HttpSession(config, database.getUser(login.getId()), httpHeaders)); + database.addHttpSession(new HttpUserSession(config, database.getUser(login.getId()), httpHeaders)); sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); return; } else if (uri.equals(REGISTER_PATH) && request.method().equals(HttpMethod.POST)) { @@ -328,9 +328,9 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr //todo check for existing username and user with username User user; - HttpSession.ClientCookie cookie = HttpSession.ClientCookie.getClientCookie(request, HttpSession.COOKIE_NAME); + HttpUserSession.ClientCookie cookie = HttpUserSession.ClientCookie.getClientCookie(request, HttpUserSession.COOKIE_NAME); if (cookie != null) { - HttpSession httpSession = database.getHttpSession(cookie.getId()); + HttpUserSession httpSession = database.getHttpSession(cookie.getId()); if (httpSession != null) { user = database.getUser(httpSession.getUser()); } else { @@ -356,7 +356,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr } User user; - HttpSession.ClientCookie cookie = HttpSession.ClientCookie.getClientCookie(request, HttpSession.COOKIE_NAME); + HttpUserSession.ClientCookie cookie = HttpUserSession.ClientCookie.getClientCookie(request, HttpUserSession.COOKIE_NAME); if (cookie != null) { database.removeHttpSession(cookie.getId());//todo timing attack???? @@ -417,7 +417,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr return; } HttpHeaders headers = new DefaultHttpHeaders(); - if (path.equals(PersistentHttpSession.LOGIN_PATH)) { + if (path.equals(PersistentHttpUserSession.LOGIN_PATH)) { logIn(ctx, config, request, headers); } headers.set(HttpHeaderNames.CACHE_CONTROL, "public,max-age=" + httpCacheSeconds);//cache but revalidate if stale todo set to private cache for resources behind authentication @@ -425,9 +425,9 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr } private Long authenticate(ChannelHandlerContext ctx, FullHttpRequest request) { - HttpSession.ClientCookie cookie = HttpSession.ClientCookie.getClientCookie(request, HttpSession.COOKIE_NAME); + HttpUserSession.ClientCookie cookie = HttpUserSession.ClientCookie.getClientCookie(request, HttpUserSession.COOKIE_NAME); if (cookie != null) { - HttpSession httpSession = database.getHttpSession(cookie.getId()); + HttpUserSession httpSession = database.getHttpSession(cookie.getId()); if (httpSession != null && httpSession.validate(cookie.getToken())) { Scribbleshare.getLogger(ctx).info("Authenticated with id " + httpSession.getUser()); return httpSession.getUser(); @@ -454,12 +454,12 @@ private void logIn(ChannelHandlerContext ctx, HttpConfig config, FullHttpRequest } private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders headers) { - HttpSession.ClientCookie cookie = HttpSession.ClientCookie.getClientCookie(request, HttpSession.COOKIE_NAME); + HttpUserSession.ClientCookie cookie = HttpUserSession.ClientCookie.getClientCookie(request, HttpUserSession.COOKIE_NAME); if (cookie == null) { User user; - HttpSession.ClientCookie cookiePersistent = HttpSession.ClientCookie.getClientCookie(request, PersistentHttpSession.COOKIE_NAME); + HttpUserSession.ClientCookie cookiePersistent = HttpUserSession.ClientCookie.getClientCookie(request, PersistentHttpUserSession.COOKIE_NAME); if (cookiePersistent != null) { - PersistentHttpSession persistentHttpSession = database.getAndRemovePersistentHttpSession(cookiePersistent.getId()); + PersistentHttpUserSession persistentHttpSession = database.getAndRemovePersistentHttpSession(cookiePersistent.getId()); if (persistentHttpSession != null && persistentHttpSession.validate(cookiePersistent.getToken())) { user = database.getUser(persistentHttpSession.getUser()); } else { @@ -472,26 +472,26 @@ private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders header database.addUser(user); } - HttpSession httpSession = new HttpSession(config, user, headers); + HttpUserSession httpSession = new HttpUserSession(config, user, headers); database.addHttpSession(httpSession); //this is single use and always refreshed - PersistentHttpSession persistentHttpSession = new PersistentHttpSession(config, httpSession, headers); + PersistentHttpUserSession persistentHttpSession = new PersistentHttpUserSession(config, httpSession, headers); database.addPersistentHttpSession(persistentHttpSession); return true; } else { - HttpSession httpSession = database.getHttpSession(cookie.getId()); + HttpUserSession httpSession = database.getHttpSession(cookie.getId()); if (httpSession != null && httpSession.validate(cookie.getToken())) { return true; } else { //todo copied and bad User user = new User(); database.addUser(user); - httpSession = new HttpSession(config, user, headers); + httpSession = new HttpUserSession(config, user, headers); database.addHttpSession(httpSession); //this is single use and always refreshed - PersistentHttpSession persistentHttpSession = new PersistentHttpSession(config, httpSession, headers); + PersistentHttpUserSession persistentHttpSession = new PersistentHttpUserSession(config, httpSession, headers); database.addPersistentHttpSession(persistentHttpSession); return true; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java index 86a6d8ec..06854e62 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java @@ -1,12 +1,25 @@ package net.stzups.scribbleshare.data.database; -import net.stzups.scribbleshare.data.database.databases.MiscDatabase; import net.stzups.scribbleshare.data.database.databases.PersistentSessionDatabase; import net.stzups.scribbleshare.data.database.databases.ResourceDatabase; import net.stzups.scribbleshare.data.database.databases.SessionDatabase; +import net.stzups.scribbleshare.data.objects.Document; +import net.stzups.scribbleshare.data.objects.InviteCode; +import net.stzups.scribbleshare.data.objects.User; import net.stzups.scribbleshare.data.objects.authentication.login.Login; -public interface ScribbleshareDatabase extends MiscDatabase, PersistentSessionDatabase, ResourceDatabase, SessionDatabase { +public interface ScribbleshareDatabase extends PersistentSessionDatabase, ResourceDatabase, SessionDatabase { + void addUser(User user); + User getUser(long id); + void updateUser(User user); + + Document createDocument(User owner); + Document getDocument(long id); + void updateDocument(Document document); + void deleteDocument(Document document); + + InviteCode getInviteCode(String code); + InviteCode getInviteCode(Document document); Login getLogin(String username); void addLogin(Login login); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/MiscDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/MiscDatabase.java deleted file mode 100644 index 0aff19c2..00000000 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/MiscDatabase.java +++ /dev/null @@ -1,19 +0,0 @@ -package net.stzups.scribbleshare.data.database.databases; - -import net.stzups.scribbleshare.data.objects.Document; -import net.stzups.scribbleshare.data.objects.InviteCode; -import net.stzups.scribbleshare.data.objects.User; - -public interface MiscDatabase { - void addUser(User user); - User getUser(long id); - void updateUser(User user); - - Document createDocument(User owner); - Document getDocument(long id); - void updateDocument(Document document); - void deleteDocument(Document document); - - InviteCode getInviteCode(String code); - InviteCode getInviteCode(Document document); -} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java index 84e9b978..37afc853 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java @@ -1,8 +1,8 @@ package net.stzups.scribbleshare.data.database.databases; -import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpSession; +import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; public interface PersistentSessionDatabase { - PersistentHttpSession getAndRemovePersistentHttpSession(long id); - void addPersistentHttpSession(PersistentHttpSession persistentHttpSession); + PersistentHttpUserSession getAndRemovePersistentHttpSession(long id); + void addPersistentHttpSession(PersistentHttpUserSession persistentHttpSession); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java index 88fd95c2..548ebcb2 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java @@ -1,11 +1,11 @@ package net.stzups.scribbleshare.data.database.databases; -import net.stzups.scribbleshare.data.objects.authentication.http.HttpSession; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; public interface SessionDatabase { - HttpSession getHttpSession(long id); - void addHttpSession(HttpSession httpSession); + HttpUserSession getHttpSession(long id); + void addHttpSession(HttpUserSession httpSession); void removeHttpSession(long id); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index cffc788e..e9fb2800 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -9,8 +9,8 @@ import net.stzups.scribbleshare.data.objects.InviteCode; import net.stzups.scribbleshare.data.objects.Resource; import net.stzups.scribbleshare.data.objects.User; -import net.stzups.scribbleshare.data.objects.authentication.http.HttpSession; -import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpSession; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; +import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; import net.stzups.scribbleshare.data.objects.authentication.login.Login; import net.stzups.scribbleshare.data.objects.canvas.Canvas; import org.postgresql.util.PSQLException; @@ -252,11 +252,11 @@ public InviteCode getInviteCode(Document document) {//gets an invite code for a } @Override - public void addPersistentHttpSession(PersistentHttpSession persistentHttpSession) { + public void addPersistentHttpSession(PersistentHttpUserSession persistentHttpSession) { try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO persistent_user_sessions(id, \"user\", creation_time, hashed_token) VALUES (?, ?, ?, ?)")) { preparedStatement.setLong(1, persistentHttpSession.getId()); preparedStatement.setLong(2, persistentHttpSession.getUser()); - preparedStatement.setTimestamp(3, persistentHttpSession.getCreation()); + preparedStatement.setTimestamp(3, persistentHttpSession.getCreated()); preparedStatement.setBinaryStream(4, new ByteArrayInputStream(persistentHttpSession.getHashedToken())); preparedStatement.execute(); } catch (SQLException e) { @@ -265,12 +265,16 @@ public void addPersistentHttpSession(PersistentHttpSession persistentHttpSession } @Override - public HttpSession getHttpSession(long id) { - try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT value FROM key_value WHERE key=?")) { + public HttpUserSession getHttpSession(long id) { + try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM key_value WHERE key=?")) { preparedStatement.setLong(1, id); try (ResultSet resultSet = preparedStatement.executeQuery()) { if (resultSet.next()) { - return new HttpSession(id, Unpooled.wrappedBuffer(resultSet.getBinaryStream("value").readAllBytes())); + return new HttpUserSession(id, + resultSet.getTimestamp("created"), + resultSet.getTimestamp("expires"), + resultSet.getLong("user_id"), + Unpooled.wrappedBuffer(resultSet.getBinaryStream("data").readAllBytes())); } else { return null; } @@ -282,7 +286,7 @@ public HttpSession getHttpSession(long id) { } @Override - public void addHttpSession(HttpSession httpSession) { + public void addHttpSession(HttpUserSession httpSession) { ByteBuf byteBuf = Unpooled.buffer(); httpSession.serialize(byteBuf); try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO key_value(key, value) VALUES (?, ?)")) { @@ -357,14 +361,18 @@ public Resource getResource(long id, long owner) { * Remove a user session for a token and return the removed user session */ @Override - public PersistentHttpSession getAndRemovePersistentHttpSession(long id) {//todo combine - PersistentHttpSession persistentHttpSession; + public PersistentHttpUserSession getAndRemovePersistentHttpSession(long id) {//todo combine + PersistentHttpUserSession persistentHttpSession; try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM persistent_user_sessions WHERE id=?")) { preparedStatement.setLong(1, id); try (ResultSet resultSet = preparedStatement.executeQuery()) { if (resultSet.next()) { - persistentHttpSession = new PersistentHttpSession(id, resultSet.getLong("user"), resultSet.getTimestamp("creation_time"), resultSet.getBinaryStream("hashed_token").readAllBytes()); + persistentHttpSession = new PersistentHttpUserSession(id, + resultSet.getTimestamp("created"), + resultSet.getTimestamp("expires"), + resultSet.getLong("user_id"), + Unpooled.wrappedBuffer(resultSet.getBinaryStream("data").readAllBytes())); } else { System.out.println("PersistentUserSession with id " + id + " does not exist"); return null; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/RedisDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/RedisDatabase.java index 2610f55d..42227ea8 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/RedisDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/RedisDatabase.java @@ -1,12 +1,8 @@ package net.stzups.scribbleshare.data.database.implementations; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import net.stzups.scribbleshare.data.database.databases.SessionDatabase; -import net.stzups.scribbleshare.data.objects.authentication.http.HttpSession; import redis.clients.jedis.Jedis; -public class RedisDatabase implements AutoCloseable, SessionDatabase { +public class RedisDatabase implements AutoCloseable { private final Jedis jedis; public RedisDatabase(String host) { @@ -17,23 +13,23 @@ public RedisDatabase(String host) { public void close() { jedis.close(); } - +/* @Override - public HttpSession getHttpSession(long id) { + public HttpUserSession getHttpSession(long id) { byte[] b = jedis.get(Unpooled.copyLong(id).array()); if (b == null) { return null; } - return new HttpSession(id, Unpooled.wrappedBuffer(b)); + return new HttpUserSession(id, Unpooled.wrappedBuffer(b)); } @Override - public void addHttpSession(HttpSession httpSession) { + public void addHttpSession(HttpUserSession httpSession) { ByteBuf byteBuf = Unpooled.buffer(); httpSession.serialize(byteBuf); jedis.set(Unpooled.copyLong(httpSession.getId()).array(), byteBuf.array()); - } + }*/ /* @Override diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java similarity index 83% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSession.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java index 5073cd14..f18d7b4a 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java @@ -15,16 +15,18 @@ import java.nio.charset.StandardCharsets; import java.sql.Timestamp; +import java.time.Duration; +import java.time.temporal.TemporalAmount; import java.util.Set; -public class HttpSession extends Session { +public class HttpUserSession extends UserSession { public static class ClientCookie { private final long id; private final byte[] token; ClientCookie(ByteBuf byteBuf) { id = byteBuf.readLong(); - token = new byte[16];//todo + token = new byte[UserSession.TOKEN_LENGTH]; byteBuf.readBytes(token); } @@ -56,22 +58,19 @@ public static ClientCookie getClientCookie(HttpRequest request, String name) { } public static final String COOKIE_NAME = "session"; + private static final Duration AGE = Duration.ofDays(1); - protected HttpSession(long user) { - super(user); + protected HttpUserSession(long user, TemporalAmount age) { + super(user, age); } - protected HttpSession(long id, long user, Timestamp creation, byte[] hashedToken) { - super(id, user, creation, hashedToken); - } - - public HttpSession(HttpConfig config, User user, HttpHeaders headers) { - super(user.getId()); + public HttpUserSession(HttpConfig config, User user, HttpHeaders headers) { + super(user.getId(), AGE); setCookie(config, headers); } - public HttpSession(long id, ByteBuf byteBuf) { - super(id, byteBuf); + public HttpUserSession(long id, Timestamp creation, Timestamp expiration, long userId, ByteBuf byteBuf) { + super(id, creation, expiration, userId, byteBuf); } protected DefaultCookie getCookie(String name) { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java similarity index 57% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpSession.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java index 99a8bf60..bf58091c 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java @@ -1,5 +1,6 @@ package net.stzups.scribbleshare.data.objects.authentication.http; +import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.cookie.CookieHeaderNames; @@ -8,25 +9,23 @@ import java.sql.Timestamp; import java.time.Duration; -import java.time.Instant; import java.time.temporal.ChronoUnit; -import java.time.temporal.TemporalAmount; - -public class PersistentHttpSession extends HttpSession { - private static final TemporalAmount MAX_SESSION_AGE = Duration.ofDays(90);//todo +public class PersistentHttpUserSession extends HttpUserSession { + private static final Duration AGE = Duration.ofDays(90); public static final String COOKIE_NAME = "persistent_session"; public static final String LOGIN_PATH = "/login"; - public PersistentHttpSession(long id, long user, Timestamp creation, byte[] hashedToken) { - super(id, user, creation, hashedToken); - } - public PersistentHttpSession(HttpConfig config, HttpSession httpSession, HttpHeaders headers) { - super(httpSession.getUser()); + public PersistentHttpUserSession(HttpConfig config, HttpUserSession httpSession, HttpHeaders headers) { + super(httpSession.getUser(), AGE); setCookie(config, headers); } + public PersistentHttpUserSession(long id, Timestamp creation, Timestamp expiration, long userId, ByteBuf byteBuf) { + super(id, creation, expiration, userId, byteBuf); + } + private void setCookie(HttpConfig config, HttpHeaders headers) { DefaultCookie cookie = getCookie(COOKIE_NAME); cookie.setDomain(config.getDomain()); @@ -34,16 +33,8 @@ private void setCookie(HttpConfig config, HttpHeaders headers) { if (config.getSSL()) cookie.setSecure(true); cookie.setHttpOnly(true); cookie.setSameSite(CookieHeaderNames.SameSite.Strict); - cookie.setMaxAge(MAX_SESSION_AGE.get(ChronoUnit.SECONDS)); //persistent cookie + cookie.setMaxAge(AGE.get(ChronoUnit.SECONDS)); //persistent cookie headers.add(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.STRICT.encode(cookie)); } - - @Override - public boolean validate(byte[] token) { - if (Instant.now().isAfter(getCreation().toInstant().plus(MAX_SESSION_AGE))) { - return false; - } - return super.validate(token); - } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/Session.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/UserSession.java similarity index 50% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/Session.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/UserSession.java index 91211bdc..25e9552e 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/Session.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/UserSession.java @@ -7,9 +7,13 @@ import java.security.SecureRandom; import java.sql.Timestamp; import java.time.Instant; +import java.time.temporal.TemporalAmount; import java.util.Arrays; -public class Session { +public class UserSession { + protected static final int TOKEN_LENGTH = 16; + private static final int HASHED_TOKEN_LENGTH = 32; + private static final SecureRandom secureRandom = new SecureRandom(); private static final MessageDigest messageDigest; @@ -22,40 +26,31 @@ public class Session { } private final long id; - private final long user; - private final Timestamp creation; - private byte[] hashedToken; - - protected Session(long user) { - this.id = secureRandom.nextLong(); - this.user = user; - this.creation = new Timestamp(Instant.now().toEpochMilli()); - } - - protected Session(long id, long user, Timestamp creation, byte[] hashedToken) { - this.id = id; - this.user = user; - this.creation = creation; - this.hashedToken = hashedToken; + private final Timestamp created; + private final Timestamp expires; + private final long userId; + private final byte[] hashedToken = new byte[HASHED_TOKEN_LENGTH]; + + protected UserSession(long userId, TemporalAmount age) { + id = secureRandom.nextLong(); + created = new Timestamp(Instant.now().toEpochMilli()); + expires = new Timestamp(created.toInstant().plus(age).toEpochMilli()); + this.userId = userId; } - public Session(long id, ByteBuf byteBuf) { + public UserSession(long id, Timestamp created, Timestamp expires, long userId, ByteBuf byteBuf) { this.id = id; - this.user = byteBuf.readLong(); - this.creation = Timestamp.from(Instant.ofEpochMilli(byteBuf.readLong())); - hashedToken = new byte[32];//todo + this.created = created; + this.expires = expires; + this.userId = userId; byteBuf.readBytes(hashedToken); } - protected int getTokenLength() { - return 16;//todo - } - - /** should be called once after instance creation */ - byte[] generateToken() { - byte[] token = new byte[getTokenLength()]; + protected byte[] generateToken() { + byte[] token = new byte[TOKEN_LENGTH]; secureRandom.nextBytes(token); - hashedToken = messageDigest.digest(token); + + System.arraycopy(messageDigest.digest(token), 0, hashedToken, 0, hashedToken.length); return token; } @@ -64,11 +59,11 @@ public long getId() { } public long getUser() { - return user; + return userId; } - public Timestamp getCreation() { - return creation; + public Timestamp getCreated() { + return created; } public byte[] getHashedToken() { @@ -76,18 +71,17 @@ public byte[] getHashedToken() { } public boolean validate(byte[] token) { - return Arrays.equals(messageDigest.digest(token), this.hashedToken); + return Arrays.equals(messageDigest.digest(token), this.hashedToken) + && Instant.now().isBefore(expires.toInstant()); } public void serialize(ByteBuf byteBuf) { - byteBuf.writeLong(user); - byteBuf.writeLong(creation.getTime()); byteBuf.writeBytes(hashedToken); } @Override public String toString() { - return "Session{id=" + id + ",user" + user + ",creationTime=" + creation + "}"; + return "Session{id=" + id + ",userId" + userId + ",created=" + created + ",expires=" + expires + "}"; } @Override @@ -97,6 +91,6 @@ public int hashCode() { @Override public boolean equals(Object object) { - return object instanceof Session && id == ((Session) object).id; + return object instanceof UserSession && id == ((UserSession) object).id; } } diff --git a/scribbleshare-postgres/sql/1-scribbleshare.sql b/scribbleshare-postgres/sql/1-scribbleshare.sql index 2e81a1af..f1559f76 100644 --- a/scribbleshare-postgres/sql/1-scribbleshare.sql +++ b/scribbleshare-postgres/sql/1-scribbleshare.sql @@ -11,15 +11,6 @@ GRANT USAGE ON SCHEMA public TO scribbleshare_backend; GRANT CONNECT ON DATABASE scribbleshare TO scribbleshare_room; GRANT USAGE ON SCHEMA public TO scribbleshare_room; -CREATE TABLE persistent_user_sessions( - id bigint NOT NULL, - "user" bigint NOT NULL, - creation_time timestamp, - hashed_token bytea NOT NULL, - PRIMARY KEY (id) -); -GRANT SELECT, INSERT, DELETE ON persistent_user_sessions TO scribbleshare_backend; - CREATE TABLE users( id bigint NOT NULL, owned_documents bigint[] NOT NULL, @@ -30,6 +21,35 @@ CREATE TABLE users( GRANT SELECT, INSERT, UPDATE ON users TO scribbleshare_backend; GRANT SELECT, UPDATE ON users TO scribbleshare_room; +CREATE TABLE persistent_user_sessions( + id bigint NOT NULL, + created timestamp NOT NULL, + expires timestamp NOT NULL, + user_id bigint NOT NULL, + data bytea NOT NULL, + PRIMARY KEY (id) +); +GRANT SELECT, INSERT ON persistent_user_sessions TO scribbleshare_backend; + +CREATE TABLE user_sessions( + id bigint NOT NULL, + created timestamp NOT NULL, + expires timestamp NOT NULL, + user_id bigint NOT NULL, + data bytea NOT NULL, + PRIMARY KEY (id) +); +GRANT SELECT, INSERT ON user_sessions TO scribbleshare_backend; +GRANT SELECT ON user_sessions TO scribbleshare_room; + +CREATE TABLE expired_sessions( + id bigint NOT NULL, + data bytea NOT NULL, + PRIMARY KEY (id) +); +GRANT SELECT, INSERT ON expired_sessions TO scribbleshare_backend; +GRANT SELECT, INSERT ON expired_sessions TO scribbleshare_room; + CREATE TABLE logins( username varchar(256) NOT NULL, user_id bigint NOT NULL, @@ -38,6 +58,10 @@ CREATE TABLE logins( ); GRANT SELECT, INSERT ON logins TO scribbleshare_backend; + + + + CREATE TABLE documents( id bigint NOT NULL, owner bigint NOT NULL, @@ -63,11 +87,3 @@ CREATE TABLE invite_codes( PRIMARY KEY (code) ); GRANT SELECT, INSERT, DELETE ON invite_codes TO scribbleshare_room; - -CREATE TABLE key_value( - key bigint NOT NULL, - value bytea NOT NULL, - PRIMARY KEY (key) -); -GRANT SELECT, INSERT ON key_value TO scribbleshare_backend; -GRANT SELECT ON key_value TO scribbleshare_room; diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java index e705a4a8..cf8274cc 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java @@ -9,7 +9,7 @@ import io.netty.util.AttributeKey; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.data.database.databases.SessionDatabase; -import net.stzups.scribbleshare.data.objects.authentication.http.HttpSession; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; import java.util.List; import java.util.logging.Level; @@ -59,9 +59,9 @@ protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List Date: Mon, 17 May 2021 22:19:29 -0400 Subject: [PATCH 014/144] change validation --- .../implementations/PostgresDatabase.java | 4 ++-- .../authentication/http/HttpUserSession.java | 15 ++++++++++----- .../http/PersistentHttpUserSession.java | 12 +++++++++--- .../authentication/http/UserSession.java | 16 +++++++--------- scribbleshare-postgres/sql/1-scribbleshare.sql | 18 +++++------------- 5 files changed, 33 insertions(+), 32 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index e9fb2800..39da5f4d 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -272,7 +272,7 @@ public HttpUserSession getHttpSession(long id) { if (resultSet.next()) { return new HttpUserSession(id, resultSet.getTimestamp("created"), - resultSet.getTimestamp("expires"), + resultSet.getTimestamp("expired"), resultSet.getLong("user_id"), Unpooled.wrappedBuffer(resultSet.getBinaryStream("data").readAllBytes())); } else { @@ -370,7 +370,7 @@ public PersistentHttpUserSession getAndRemovePersistentHttpSession(long id) {//t if (resultSet.next()) { persistentHttpSession = new PersistentHttpUserSession(id, resultSet.getTimestamp("created"), - resultSet.getTimestamp("expires"), + resultSet.getTimestamp("expired"), resultSet.getLong("user_id"), Unpooled.wrappedBuffer(resultSet.getBinaryStream("data").readAllBytes())); } else { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java index f18d7b4a..cca287e2 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java @@ -16,7 +16,7 @@ import java.nio.charset.StandardCharsets; import java.sql.Timestamp; import java.time.Duration; -import java.time.temporal.TemporalAmount; +import java.time.Instant; import java.util.Set; public class HttpUserSession extends UserSession { @@ -58,14 +58,14 @@ public static ClientCookie getClientCookie(HttpRequest request, String name) { } public static final String COOKIE_NAME = "session"; - private static final Duration AGE = Duration.ofDays(1); + private static final Duration MAX_AGE = Duration.ofDays(1); - protected HttpUserSession(long user, TemporalAmount age) { - super(user, age); + protected HttpUserSession(long user) { + super(user); } public HttpUserSession(HttpConfig config, User user, HttpHeaders headers) { - super(user.getId(), AGE); + super(user.getId()); setCookie(config, headers); } @@ -94,4 +94,9 @@ private void setCookie(HttpConfig config, HttpHeaders headers) { //session cookie, so no max age headers.add(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.STRICT.encode(cookie)); } + + @Override + public boolean validate(byte[] token) { + return super.validate(token) && Instant.now().isBefore(getCreated().toInstant().plus(MAX_AGE)); + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java index bf58091c..2455d7b3 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java @@ -9,16 +9,17 @@ import java.sql.Timestamp; import java.time.Duration; +import java.time.Instant; import java.time.temporal.ChronoUnit; public class PersistentHttpUserSession extends HttpUserSession { - private static final Duration AGE = Duration.ofDays(90); + private static final Duration MAX_AGE = Duration.ofDays(90); public static final String COOKIE_NAME = "persistent_session"; public static final String LOGIN_PATH = "/login"; public PersistentHttpUserSession(HttpConfig config, HttpUserSession httpSession, HttpHeaders headers) { - super(httpSession.getUser(), AGE); + super(httpSession.getUser()); setCookie(config, headers); } @@ -33,8 +34,13 @@ private void setCookie(HttpConfig config, HttpHeaders headers) { if (config.getSSL()) cookie.setSecure(true); cookie.setHttpOnly(true); cookie.setSameSite(CookieHeaderNames.SameSite.Strict); - cookie.setMaxAge(AGE.get(ChronoUnit.SECONDS)); //persistent cookie + cookie.setMaxAge(MAX_AGE.get(ChronoUnit.SECONDS)); //persistent cookie headers.add(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.STRICT.encode(cookie)); } + + @Override + public boolean validate(byte[] token) { + return super.validate(token) && Instant.now().isBefore(getCreated().toInstant().plus(MAX_AGE)); + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/UserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/UserSession.java index 25e9552e..c37081b9 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/UserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/UserSession.java @@ -7,7 +7,6 @@ import java.security.SecureRandom; import java.sql.Timestamp; import java.time.Instant; -import java.time.temporal.TemporalAmount; import java.util.Arrays; public class UserSession { @@ -27,21 +26,21 @@ public class UserSession { private final long id; private final Timestamp created; - private final Timestamp expires; + private final Timestamp expired; private final long userId; private final byte[] hashedToken = new byte[HASHED_TOKEN_LENGTH]; - protected UserSession(long userId, TemporalAmount age) { + protected UserSession(long userId) { id = secureRandom.nextLong(); created = new Timestamp(Instant.now().toEpochMilli()); - expires = new Timestamp(created.toInstant().plus(age).toEpochMilli()); + expired = created; this.userId = userId; } - public UserSession(long id, Timestamp created, Timestamp expires, long userId, ByteBuf byteBuf) { + public UserSession(long id, Timestamp created, Timestamp expired, long userId, ByteBuf byteBuf) { this.id = id; this.created = created; - this.expires = expires; + this.expired = expired; this.userId = userId; byteBuf.readBytes(hashedToken); } @@ -71,8 +70,7 @@ public byte[] getHashedToken() { } public boolean validate(byte[] token) { - return Arrays.equals(messageDigest.digest(token), this.hashedToken) - && Instant.now().isBefore(expires.toInstant()); + return Arrays.equals(messageDigest.digest(token), this.hashedToken) && created.equals(expired); } public void serialize(ByteBuf byteBuf) { @@ -81,7 +79,7 @@ public void serialize(ByteBuf byteBuf) { @Override public String toString() { - return "Session{id=" + id + ",userId" + userId + ",created=" + created + ",expires=" + expires + "}"; + return "Session{id=" + id + ",userId" + userId + ",created=" + created + ",expires=" + expired + "}"; } @Override diff --git a/scribbleshare-postgres/sql/1-scribbleshare.sql b/scribbleshare-postgres/sql/1-scribbleshare.sql index f1559f76..165e7d1d 100644 --- a/scribbleshare-postgres/sql/1-scribbleshare.sql +++ b/scribbleshare-postgres/sql/1-scribbleshare.sql @@ -24,31 +24,23 @@ GRANT SELECT, UPDATE ON users TO scribbleshare_room; CREATE TABLE persistent_user_sessions( id bigint NOT NULL, created timestamp NOT NULL, - expires timestamp NOT NULL, + expired timestamp NOT NULL, user_id bigint NOT NULL, data bytea NOT NULL, PRIMARY KEY (id) ); -GRANT SELECT, INSERT ON persistent_user_sessions TO scribbleshare_backend; +GRANT SELECT, UPDATE, INSERT ON persistent_user_sessions TO scribbleshare_backend; CREATE TABLE user_sessions( id bigint NOT NULL, created timestamp NOT NULL, - expires timestamp NOT NULL, + expired timestamp NOT NULL, user_id bigint NOT NULL, data bytea NOT NULL, PRIMARY KEY (id) ); -GRANT SELECT, INSERT ON user_sessions TO scribbleshare_backend; -GRANT SELECT ON user_sessions TO scribbleshare_room; - -CREATE TABLE expired_sessions( - id bigint NOT NULL, - data bytea NOT NULL, - PRIMARY KEY (id) -); -GRANT SELECT, INSERT ON expired_sessions TO scribbleshare_backend; -GRANT SELECT, INSERT ON expired_sessions TO scribbleshare_room; +GRANT SELECT, UPDATE, INSERT ON user_sessions TO scribbleshare_backend; +GRANT SELECT, UPDATE ON user_sessions TO scribbleshare_room; CREATE TABLE logins( username varchar(256) NOT NULL, From e2b05e6e92e3b64c2bac06436b58b376f0d9a86c Mon Sep 17 00:00:00 2001 From: stzups Date: Mon, 17 May 2021 22:32:10 -0400 Subject: [PATCH 015/144] refactor http cookie --- .../server/http/HttpServerHandler.java | 17 ++++--- .../http/HttpSessionCookie.java | 49 ++++++++++++++++++ .../authentication/http/HttpUserSession.java | 50 +++---------------- .../http/PersistentHttpUserSession.java | 10 +++- .../authentication/http/UserSession.java | 2 +- .../room/server/HttpAuthenticator.java | 5 +- 6 files changed, 77 insertions(+), 56 deletions(-) create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 0cf9fc98..1a8e3951 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -20,6 +20,7 @@ import net.stzups.scribbleshare.data.objects.Resource; import net.stzups.scribbleshare.data.objects.User; import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; import net.stzups.scribbleshare.data.objects.authentication.login.Login; @@ -328,7 +329,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr //todo check for existing username and user with username User user; - HttpUserSession.ClientCookie cookie = HttpUserSession.ClientCookie.getClientCookie(request, HttpUserSession.COOKIE_NAME); + HttpSessionCookie cookie = HttpUserSession.getCookie(request); if (cookie != null) { HttpUserSession httpSession = database.getHttpSession(cookie.getId()); if (httpSession != null) { @@ -356,7 +357,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr } User user; - HttpUserSession.ClientCookie cookie = HttpUserSession.ClientCookie.getClientCookie(request, HttpUserSession.COOKIE_NAME); + HttpSessionCookie cookie = HttpUserSession.getCookie(request); if (cookie != null) { database.removeHttpSession(cookie.getId());//todo timing attack???? @@ -425,10 +426,10 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr } private Long authenticate(ChannelHandlerContext ctx, FullHttpRequest request) { - HttpUserSession.ClientCookie cookie = HttpUserSession.ClientCookie.getClientCookie(request, HttpUserSession.COOKIE_NAME); + HttpSessionCookie cookie = HttpUserSession.getCookie(request); if (cookie != null) { HttpUserSession httpSession = database.getHttpSession(cookie.getId()); - if (httpSession != null && httpSession.validate(cookie.getToken())) { + if (httpSession != null && httpSession.validate(cookie)) { Scribbleshare.getLogger(ctx).info("Authenticated with id " + httpSession.getUser()); return httpSession.getUser(); } else { @@ -454,13 +455,13 @@ private void logIn(ChannelHandlerContext ctx, HttpConfig config, FullHttpRequest } private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders headers) { - HttpUserSession.ClientCookie cookie = HttpUserSession.ClientCookie.getClientCookie(request, HttpUserSession.COOKIE_NAME); + HttpSessionCookie cookie = HttpUserSession.getCookie(request); if (cookie == null) { User user; - HttpUserSession.ClientCookie cookiePersistent = HttpUserSession.ClientCookie.getClientCookie(request, PersistentHttpUserSession.COOKIE_NAME); + HttpSessionCookie cookiePersistent = PersistentHttpUserSession.getCookie(request); if (cookiePersistent != null) { PersistentHttpUserSession persistentHttpSession = database.getAndRemovePersistentHttpSession(cookiePersistent.getId()); - if (persistentHttpSession != null && persistentHttpSession.validate(cookiePersistent.getToken())) { + if (persistentHttpSession != null && persistentHttpSession.validate(cookiePersistent)) { user = database.getUser(persistentHttpSession.getUser()); } else { //return false; todo @@ -481,7 +482,7 @@ private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders header return true; } else { HttpUserSession httpSession = database.getHttpSession(cookie.getId()); - if (httpSession != null && httpSession.validate(cookie.getToken())) { + if (httpSession != null && httpSession.validate(cookie)) { return true; } else { //todo copied and bad diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java new file mode 100644 index 00000000..e789f284 --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java @@ -0,0 +1,49 @@ +package net.stzups.scribbleshare.data.objects.authentication.http; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.cookie.Cookie; +import io.netty.handler.codec.http.cookie.ServerCookieDecoder; + +import java.nio.charset.StandardCharsets; +import java.util.Set; + +public class HttpSessionCookie { + private final long id; + private final byte[] token; + + HttpSessionCookie(ByteBuf byteBuf) { + id = byteBuf.readLong(); + token = new byte[UserSession.TOKEN_LENGTH]; + byteBuf.readBytes(token); + } + + public long getId() { + return id; + } + + public byte[] getToken() { + return token; + } + + static HttpSessionCookie getHttpSessionCookie(HttpRequest request, String name) { + String cookiesHeader = request.headers().get(HttpHeaderNames.COOKIE); + if (cookiesHeader != null) { + Set cookies = ServerCookieDecoder.STRICT.decode(cookiesHeader); + for (Cookie cookie : cookies) { + if (cookie.name().equals(name)) { + ByteBuf tokenBase64 = Unpooled.wrappedBuffer(cookie.value().getBytes(StandardCharsets.UTF_8)); + ByteBuf token = Base64.decode(tokenBase64); + tokenBase64.release(); + HttpSessionCookie c = new HttpSessionCookie(token); + token.release(); + return c; + } + } + } + return null; + } +} \ No newline at end of file diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java index cca287e2..abf7f686 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java @@ -6,10 +6,8 @@ import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.cookie.Cookie; import io.netty.handler.codec.http.cookie.CookieHeaderNames; import io.netty.handler.codec.http.cookie.DefaultCookie; -import io.netty.handler.codec.http.cookie.ServerCookieDecoder; import io.netty.handler.codec.http.cookie.ServerCookieEncoder; import net.stzups.scribbleshare.data.objects.User; @@ -17,48 +15,11 @@ import java.sql.Timestamp; import java.time.Duration; import java.time.Instant; -import java.util.Set; public class HttpUserSession extends UserSession { - public static class ClientCookie { - private final long id; - private final byte[] token; - - ClientCookie(ByteBuf byteBuf) { - id = byteBuf.readLong(); - token = new byte[UserSession.TOKEN_LENGTH]; - byteBuf.readBytes(token); - } - - public long getId() { - return id; - } - - public byte[] getToken() { - return token; - } - - public static ClientCookie getClientCookie(HttpRequest request, String name) { - String cookiesHeader = request.headers().get(HttpHeaderNames.COOKIE); - if (cookiesHeader != null) { - Set cookies = ServerCookieDecoder.STRICT.decode(cookiesHeader); - for (Cookie cookie : cookies) { - if (cookie.name().equals(name)) { - ByteBuf tokenBase64 = Unpooled.wrappedBuffer(cookie.value().getBytes(StandardCharsets.UTF_8)); - ByteBuf token = Base64.decode(tokenBase64); - tokenBase64.release(); - ClientCookie c = new ClientCookie(token); - token.release(); - return c; - } - } - } - return null; - } - } + private static final Duration MAX_AGE = Duration.ofDays(1); public static final String COOKIE_NAME = "session"; - private static final Duration MAX_AGE = Duration.ofDays(1); protected HttpUserSession(long user) { super(user); @@ -95,8 +56,11 @@ private void setCookie(HttpConfig config, HttpHeaders headers) { headers.add(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.STRICT.encode(cookie)); } - @Override - public boolean validate(byte[] token) { - return super.validate(token) && Instant.now().isBefore(getCreated().toInstant().plus(MAX_AGE)); + public static HttpSessionCookie getCookie(HttpRequest request) { + return HttpSessionCookie.getHttpSessionCookie(request, COOKIE_NAME); + } + + public boolean validate(HttpSessionCookie cookie) { + return validate(cookie.getToken()) && Instant.now().isBefore(getCreated().toInstant().plus(MAX_AGE)); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java index 2455d7b3..4e2faaa3 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java @@ -3,6 +3,7 @@ import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.cookie.CookieHeaderNames; import io.netty.handler.codec.http.cookie.DefaultCookie; import io.netty.handler.codec.http.cookie.ServerCookieEncoder; @@ -14,6 +15,7 @@ public class PersistentHttpUserSession extends HttpUserSession { private static final Duration MAX_AGE = Duration.ofDays(90); + public static final String COOKIE_NAME = "persistent_session"; public static final String LOGIN_PATH = "/login"; @@ -39,8 +41,12 @@ private void setCookie(HttpConfig config, HttpHeaders headers) { headers.add(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.STRICT.encode(cookie)); } + public static HttpSessionCookie getCookie(HttpRequest request) { + return HttpSessionCookie.getHttpSessionCookie(request, COOKIE_NAME); + } + @Override - public boolean validate(byte[] token) { - return super.validate(token) && Instant.now().isBefore(getCreated().toInstant().plus(MAX_AGE)); + public boolean validate(HttpSessionCookie cookie) { + return validate(cookie.getToken()) && Instant.now().isBefore(getCreated().toInstant().plus(MAX_AGE)); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/UserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/UserSession.java index c37081b9..1409bf63 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/UserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/UserSession.java @@ -69,7 +69,7 @@ public byte[] getHashedToken() { return hashedToken; } - public boolean validate(byte[] token) { + protected boolean validate(byte[] token) { return Arrays.equals(messageDigest.digest(token), this.hashedToken) && created.equals(expired); } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java index cf8274cc..f285d5cd 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java @@ -9,6 +9,7 @@ import io.netty.util.AttributeKey; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.data.database.databases.SessionDatabase; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; import java.util.List; @@ -59,10 +60,10 @@ protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List Date: Mon, 17 May 2021 22:41:18 -0400 Subject: [PATCH 016/144] refactor login --- .../objects/authentication/login/Login.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java index 68406f44..11f1a9da 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java @@ -6,14 +6,14 @@ import java.util.Arrays; public class Login { + private static final int COST = 6; // todo + + private static final BCrypt.Hasher HASHER = BCrypt.withDefaults(); + private static final BCrypt.Verifyer VERIFIER = BCrypt.verifyer(); + private static final byte[] DUMMY; static { - DUMMY = BCrypt.withDefaults().hash(6, new byte[0]); - } - private static byte[] getDummy() { - byte[] dummy = new byte[DUMMY.length]; - System.arraycopy(DUMMY, 0, dummy, 0, dummy.length); - return dummy; + DUMMY = HASHER.hash(COST, new byte[0]); // todo new byte[0] - use a different dummy plaintext? } private final String username; @@ -23,7 +23,7 @@ private static byte[] getDummy() { public Login(User user, byte[] password) { this.id = user.getId(); this.username = user.getUsername(); - this.hashedPassword = BCrypt.withDefaults().hash(6, password); + this.hashedPassword = HASHER.hash(COST, password); Arrays.fill(password, (byte) 0); } @@ -48,15 +48,17 @@ public byte[] getHashedPassword() { public static Long verify(Login login, byte[] plaintext) { byte[] hashedPassword; if (login == null) { - hashedPassword = getDummy();//todo is this helpful in a hypothetical timing attack? + hashedPassword = DUMMY; // still verify hash even when we know it will fail to protect against timing attack } else { hashedPassword = login.hashedPassword; } - boolean verified = BCrypt.verifyer().verify(plaintext, hashedPassword).verified; + boolean verified = VERIFIER.verify(plaintext, hashedPassword).verified; - Arrays.fill(hashedPassword, (byte) 0); Arrays.fill(plaintext, (byte) 0); + if (hashedPassword != DUMMY) { // don't clear dummy, it will be reused + Arrays.fill(hashedPassword, (byte) 0); + } if (verified) { assert login != null; From cc20868aa1917105f60d64f9a13c0d022806d8c8 Mon Sep 17 00:00:00 2001 From: stzups Date: Mon, 17 May 2021 23:35:15 -0400 Subject: [PATCH 017/144] add expiration for database --- .../server/http/HttpServerHandler.java | 22 ++++--- .../databases/PersistentSessionDatabase.java | 3 +- .../database/databases/SessionDatabase.java | 4 +- .../implementations/PostgresDatabase.java | 60 ++++++++++++------- .../authentication/http/HttpUserSession.java | 4 ++ .../authentication/http/UserSession.java | 4 ++ 6 files changed, 60 insertions(+), 37 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 1a8e3951..e0a42a29 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -356,19 +356,17 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr return; } - User user; + HttpHeaders headers = new DefaultHttpHeaders(); + //todo authenticate so only authenticated users can log out HttpSessionCookie cookie = HttpUserSession.getCookie(request); if (cookie != null) { - database.removeHttpSession(cookie.getId());//todo timing attack???? - -/* HttpSession httpSession = database.getHttpSession(cookie.getId()); - if (httpSession != null) { - user = database.getUser(httpSession.getUser()); - } else {//bad - user = null; - }*/ - } else {//no auth - user = null; + database.expireHttpSession(cookie.getId()); + //todo clear cookie + } + HttpSessionCookie persistentCookie = PersistentHttpUserSession.getCookie(request); + if (cookie != null) { + database.expireHttpSession(persistentCookie.getId()); + //todo clear cookie } @@ -460,7 +458,7 @@ private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders header User user; HttpSessionCookie cookiePersistent = PersistentHttpUserSession.getCookie(request); if (cookiePersistent != null) { - PersistentHttpUserSession persistentHttpSession = database.getAndRemovePersistentHttpSession(cookiePersistent.getId()); + PersistentHttpUserSession persistentHttpSession = database.getAndExpirePersistentHttpSession(cookiePersistent.getId()); if (persistentHttpSession != null && persistentHttpSession.validate(cookiePersistent)) { user = database.getUser(persistentHttpSession.getUser()); } else { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java index 37afc853..3efa1afb 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java @@ -3,6 +3,7 @@ import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; public interface PersistentSessionDatabase { - PersistentHttpUserSession getAndRemovePersistentHttpSession(long id); + PersistentHttpUserSession getAndExpirePersistentHttpSession(long id); void addPersistentHttpSession(PersistentHttpUserSession persistentHttpSession); + void expirePersistentHttpSession(long id); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java index 548ebcb2..f669a496 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java @@ -3,9 +3,7 @@ import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; public interface SessionDatabase { - - HttpUserSession getHttpSession(long id); void addHttpSession(HttpUserSession httpSession); - void removeHttpSession(long id); + void expireHttpSession(long id); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index 39da5f4d..7d90b2c3 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -253,20 +253,37 @@ public InviteCode getInviteCode(Document document) {//gets an invite code for a @Override public void addPersistentHttpSession(PersistentHttpUserSession persistentHttpSession) { - try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO persistent_user_sessions(id, \"user\", creation_time, hashed_token) VALUES (?, ?, ?, ?)")) { + try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO persistent_user_sessions(id, created, expired, user_id, data) VALUES (?, ?, ?, ?, ?)")) { preparedStatement.setLong(1, persistentHttpSession.getId()); - preparedStatement.setLong(2, persistentHttpSession.getUser()); - preparedStatement.setTimestamp(3, persistentHttpSession.getCreated()); - preparedStatement.setBinaryStream(4, new ByteArrayInputStream(persistentHttpSession.getHashedToken())); + preparedStatement.setTimestamp(2, persistentHttpSession.getCreated()); + preparedStatement.setTimestamp(3, persistentHttpSession.getExpired()); + preparedStatement.setLong(4, persistentHttpSession.getUser()); + + ByteBuf byteBuf = Unpooled.buffer(); + persistentHttpSession.serialize(byteBuf); + preparedStatement.setBinaryStream(5, new ByteBufInputStream(byteBuf)); + byteBuf.release(); + preparedStatement.execute(); } catch (SQLException e) { e.printStackTrace();//todo error handling } } + @Override + public void expirePersistentHttpSession(long id) { + try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE persistent_user_sessions SET expired=? WHERE id=?")) { + preparedStatement.setTimestamp(1, Timestamp.from(Instant.now())); + preparedStatement.setLong(2, id); + preparedStatement.execute(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + @Override public HttpUserSession getHttpSession(long id) { - try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM key_value WHERE key=?")) { + try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM user_sessions WHERE id=?")) { preparedStatement.setLong(1, id); try (ResultSet resultSet = preparedStatement.executeQuery()) { if (resultSet.next()) { @@ -287,11 +304,17 @@ public HttpUserSession getHttpSession(long id) { @Override public void addHttpSession(HttpUserSession httpSession) { - ByteBuf byteBuf = Unpooled.buffer(); - httpSession.serialize(byteBuf); - try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO key_value(key, value) VALUES (?, ?)")) { + try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO user_sessions(id, created, expired, user_id, data) VALUES (?, ?, ?, ?, ?)")) { preparedStatement.setLong(1, httpSession.getId()); - preparedStatement.setBinaryStream(2, new ByteBufInputStream(byteBuf)); + preparedStatement.setTimestamp(2, httpSession.getCreated()); + preparedStatement.setTimestamp(3, httpSession.getExpired()); + preparedStatement.setLong(4, httpSession.getUser()); + + ByteBuf byteBuf = Unpooled.buffer(); + httpSession.serialize(byteBuf); + preparedStatement.setBinaryStream(5, new ByteBufInputStream(byteBuf)); + byteBuf.release(); + preparedStatement.execute(); } catch (SQLException e) { e.printStackTrace(); @@ -299,9 +322,10 @@ public void addHttpSession(HttpUserSession httpSession) { } @Override - public void removeHttpSession(long id) { - try (PreparedStatement preparedStatement = connection.prepareStatement("DELETE FROM key_value WHERE key=?")) { - preparedStatement.setLong(1, id); + public void expireHttpSession(long id) { + try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE user_sessions SET expired=? WHERE id=?")) { + preparedStatement.setTimestamp(1, Timestamp.from(Instant.now())); + preparedStatement.setLong(2, id); preparedStatement.execute(); } catch (SQLException e) { e.printStackTrace(); @@ -361,7 +385,7 @@ public Resource getResource(long id, long owner) { * Remove a user session for a token and return the removed user session */ @Override - public PersistentHttpUserSession getAndRemovePersistentHttpSession(long id) {//todo combine + public PersistentHttpUserSession getAndExpirePersistentHttpSession(long id) {//todo combine PersistentHttpUserSession persistentHttpSession; try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM persistent_user_sessions WHERE id=?")) { @@ -383,13 +407,7 @@ public PersistentHttpUserSession getAndRemovePersistentHttpSession(long id) {//t return null; } - try (PreparedStatement preparedStatement = connection.prepareStatement("DELETE FROM persistent_user_sessions WHERE id=?")) { - preparedStatement.setLong(1, id); - preparedStatement.execute(); - return persistentHttpSession; - } catch (SQLException e) { - e.printStackTrace(); - return null; - } + expirePersistentHttpSession(id);//todo combine with above to single transaction + return persistentHttpSession; } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java index abf7f686..2a89c369 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java @@ -63,4 +63,8 @@ public static HttpSessionCookie getCookie(HttpRequest request) { public boolean validate(HttpSessionCookie cookie) { return validate(cookie.getToken()) && Instant.now().isBefore(getCreated().toInstant().plus(MAX_AGE)); } + + public static void clearCookie(HttpConfig config, HttpHeaders headers) { + + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/UserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/UserSession.java index 1409bf63..5149bf57 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/UserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/UserSession.java @@ -65,6 +65,10 @@ public Timestamp getCreated() { return created; } + public Timestamp getExpired() { + return expired; + } + public byte[] getHashedToken() { return hashedToken; } From aa654518e056cfa80d339faae86017fccfe9961e Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 18 May 2021 10:34:09 -0400 Subject: [PATCH 018/144] fix npe, probably rework debug --- .../server/BackendHttpServerInitializer.java | 3 +- .../server/http/HttpServerHandler.java | 6 +-- .../scribbleshare/server/http/DebugLog.java | 21 +++++++++ .../server/http/HttpExceptionHandler.java | 19 ++++++++ .../server/http/HttpServerInitializer.java | 45 ++++++------------- .../server/RoomHttpServerInitializer.java | 1 + 6 files changed, 60 insertions(+), 35 deletions(-) create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/DebugLog.java create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpExceptionHandler.java diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java index 903c8878..a028aba0 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java @@ -27,6 +27,7 @@ protected void initChannel(SocketChannel channel) { channel.pipeline() .addLast(new HttpContentCompressor()) .addLast(new ChunkedWriteHandler()) - .addLast(httpServerHandler); + .addLast(httpServerHandler) + .addLast(httpExceptionHandler()); } } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index e0a42a29..6b870a37 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -364,7 +364,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr //todo clear cookie } HttpSessionCookie persistentCookie = PersistentHttpUserSession.getCookie(request); - if (cookie != null) { + if (persistentCookie != null) { database.expireHttpSession(persistentCookie.getId()); //todo clear cookie } @@ -416,9 +416,9 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr return; } HttpHeaders headers = new DefaultHttpHeaders(); - if (path.equals(PersistentHttpUserSession.LOGIN_PATH)) { + /* if (path.equals(PersistentHttpUserSession.LOGIN_PATH)) { logIn(ctx, config, request, headers); - } + }*/ headers.set(HttpHeaderNames.CACHE_CONTROL, "public,max-age=" + httpCacheSeconds);//cache but revalidate if stale todo set to private cache for resources behind authentication sendFile(ctx, request, headers, file, mimeTypes.getMimeType(file)); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/DebugLog.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/DebugLog.java new file mode 100644 index 00000000..3d1793e8 --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/DebugLog.java @@ -0,0 +1,21 @@ +package net.stzups.scribbleshare.server.http; + +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import net.stzups.scribbleshare.Scribbleshare; + +@ChannelHandler.Sharable +public class DebugLog extends ChannelDuplexHandler { + @Override + public void channelActive(ChannelHandlerContext ctx) { + Scribbleshare.getLogger(ctx).info("Connection opened"); + ctx.fireChannelActive(); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) { + Scribbleshare.getLogger(ctx).info("Connection closed"); + ctx.fireChannelInactive(); + } +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpExceptionHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpExceptionHandler.java new file mode 100644 index 00000000..64f08551 --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpExceptionHandler.java @@ -0,0 +1,19 @@ +package net.stzups.scribbleshare.server.http; + +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.HttpResponseStatus; +import net.stzups.scribbleshare.Scribbleshare; + +import java.util.logging.Level; + +@ChannelHandler.Sharable +public class HttpExceptionHandler extends ChannelDuplexHandler { + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) { + Scribbleshare.getLogger(ctx).log(Level.WARNING, "Uncaught exception", throwable); + HttpUtils.send(ctx, null, HttpResponseStatus.INTERNAL_SERVER_ERROR); + //todo ctx.close(); + } +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java index 4a1001df..cf6b7836 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java @@ -1,8 +1,6 @@ package net.stzups.scribbleshare.server.http; -import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.http.HttpObjectAggregator; @@ -15,7 +13,6 @@ import javax.net.ssl.SSLException; import java.io.File; -import java.util.logging.Level; @ChannelHandler.Sharable public class HttpServerInitializer extends ChannelInitializer { @@ -29,7 +26,9 @@ public interface Config { private final Config config; private final SslContext sslContext; + private final DebugLog debugLog = new DebugLog(); private final HttpHandler httpHandler = new HttpHandler(); + private final HttpExceptionHandler httpExceptionHandler = new HttpExceptionHandler(); protected HttpServerInitializer(Config config) throws SSLException { this.config = config; @@ -44,38 +43,22 @@ protected HttpServerInitializer(Config config) throws SSLException { } } + protected HttpExceptionHandler httpExceptionHandler() { + return httpExceptionHandler; + } + @Override protected void initChannel(SocketChannel channel) { Scribbleshare.setLogger(channel); - channel.pipeline() - .addLast(new ChannelDuplexHandler() { - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) { - Scribbleshare.getLogger(ctx).log(Level.WARNING, "Uncaught exception", throwable); - //todo ctx.close(); - } - - @Override - public void channelActive(ChannelHandlerContext ctx) { - Scribbleshare.getLogger(ctx).info("Connection opened"); - ctx.fireChannelActive(); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) { - Scribbleshare.getLogger(ctx).info("Connection closed"); - ctx.fireChannelInactive(); - } - }).addLast(new GlobalTrafficShapingHandler(channel.eventLoop(), 0, 0, 1000) { - @Override - protected void doAccounting(TrafficCounter counter) { - if (config.getDebugLogTraffic()) System.out.print("\rread " + (double) counter.lastReadThroughput() / 1000 * 8 + "kb/s, write " + (double) counter.lastWriteThroughput() / 1000 * 8 + "kb/s"); - } - }); - if (sslContext != null) { - channel.pipeline().addLast(sslContext.newHandler(channel.alloc())); - } + channel.pipeline().addLast(debugLog); + if (config.getDebugLogTraffic()) channel.pipeline().addLast(new GlobalTrafficShapingHandler(channel.eventLoop(), 0, 0, 1000) { + @Override + protected void doAccounting(TrafficCounter counter) { + System.out.print("\rread " + (double) counter.lastReadThroughput() / 1000 * 8 + "kb/s, write " + (double) counter.lastWriteThroughput() / 1000 * 8 + "kb/s"); + } + }); + if (sslContext != null) channel.pipeline().addLast(sslContext.newHandler(channel.alloc())); channel.pipeline() .addLast(new HttpServerCodec()) .addLast(new HttpObjectAggregator(Integer.MAX_VALUE)) //2gb todo decrease diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java index 73d36716..b2968634 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java @@ -49,6 +49,7 @@ protected void initChannel(SocketChannel channel) { channel.pipeline() .addLast(httpAuthenticator) + .addLast(httpExceptionHandler()) .addLast(new WebSocketServerCompressionHandler()) .addLast(new WebSocketServerProtocolHandler(config.getWebsocketPath(), null, true)) .addLast(serverMessageEncoder) From 01b91a8f0c40949a2cf5e94700e93455488dc7bd Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 18 May 2021 11:01:51 -0400 Subject: [PATCH 019/144] remember me --- .../backend/server/http/HttpServerHandler.java | 6 +++++- .../authentication/http/PersistentHttpUserSession.java | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 6b870a37..c076e697 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -298,7 +298,11 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr } HttpHeaders httpHeaders = new DefaultHttpHeaders(); - database.addHttpSession(new HttpUserSession(config, database.getUser(login.getId()), httpHeaders)); + HttpUserSession userSession = new HttpUserSession(config, database.getUser(login.getId()), httpHeaders); + database.addHttpSession(userSession); + if (remember) { + database.addPersistentHttpSession(new PersistentHttpUserSession(config, userSession, httpHeaders)); + } sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); return; } else if (uri.equals(REGISTER_PATH) && request.method().equals(HttpMethod.POST)) { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java index 4e2faaa3..901a50f6 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java @@ -32,7 +32,7 @@ public PersistentHttpUserSession(long id, Timestamp creation, Timestamp expirati private void setCookie(HttpConfig config, HttpHeaders headers) { DefaultCookie cookie = getCookie(COOKIE_NAME); cookie.setDomain(config.getDomain()); - cookie.setPath(LOGIN_PATH); + cookie.setPath("/"); if (config.getSSL()) cookie.setSecure(true); cookie.setHttpOnly(true); cookie.setSameSite(CookieHeaderNames.SameSite.Strict); From e0ed28df94279b99852d2a3b48e500085400fab2 Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 18 May 2021 11:51:21 -0400 Subject: [PATCH 020/144] start to rework db - exception handling --- .../server/http/HttpServerHandler.java | 4 +- .../databases/PersistentSessionDatabase.java | 17 +++++- .../database/databases/SessionDatabase.java | 17 +++++- .../implementations/PostgresDatabase.java | 55 +++++++++---------- 4 files changed, 58 insertions(+), 35 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index c076e697..48b015cb 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -364,12 +364,12 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr //todo authenticate so only authenticated users can log out HttpSessionCookie cookie = HttpUserSession.getCookie(request); if (cookie != null) { - database.expireHttpSession(cookie.getId()); + database.updateHttpSession(cookie.getId()); //todo clear cookie } HttpSessionCookie persistentCookie = PersistentHttpUserSession.getCookie(request); if (persistentCookie != null) { - database.expireHttpSession(persistentCookie.getId()); + database.updateHttpSession(persistentCookie.getId()); //todo clear cookie } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java index 3efa1afb..5a6b3cf1 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java @@ -2,8 +2,21 @@ import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; +import java.sql.SQLException; + public interface PersistentSessionDatabase { + /** + * Get existing {@link PersistentHttpUserSession} and expire it, or null if it does exist + */ PersistentHttpUserSession getAndExpirePersistentHttpSession(long id); - void addPersistentHttpSession(PersistentHttpUserSession persistentHttpSession); - void expirePersistentHttpSession(long id); + + /** + * Add new {@link PersistentHttpUserSession} + */ + void addPersistentHttpSession(PersistentHttpUserSession persistentHttpSession) throws SQLException; + + /** + * Expire existing {@link PersistentHttpUserSession} + */ + void expirePersistentHttpSession(PersistentHttpUserSession persistentHttpSession) throws SQLException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java index f669a496..1a4eacd4 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java @@ -2,8 +2,21 @@ import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; +import java.sql.SQLException; + public interface SessionDatabase { + /** + * Get existing {@link HttpUserSession}, or null if it does not exist + */ HttpUserSession getHttpSession(long id); - void addHttpSession(HttpUserSession httpSession); - void expireHttpSession(long id); + + /** + * Add new {@link HttpUserSession} + */ + void addHttpSession(HttpUserSession httpUserSession) throws SQLException; + + /** + * Expire existing {@link HttpUserSession} + */ + void updateHttpSession(HttpUserSession httpUserSession) throws SQLException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index 7d90b2c3..bfdf52ee 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -252,7 +252,7 @@ public InviteCode getInviteCode(Document document) {//gets an invite code for a } @Override - public void addPersistentHttpSession(PersistentHttpUserSession persistentHttpSession) { + public void addPersistentHttpSession(PersistentHttpUserSession persistentHttpSession) throws SQLException { try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO persistent_user_sessions(id, created, expired, user_id, data) VALUES (?, ?, ?, ?, ?)")) { preparedStatement.setLong(1, persistentHttpSession.getId()); preparedStatement.setTimestamp(2, persistentHttpSession.getCreated()); @@ -265,19 +265,15 @@ public void addPersistentHttpSession(PersistentHttpUserSession persistentHttpSes byteBuf.release(); preparedStatement.execute(); - } catch (SQLException e) { - e.printStackTrace();//todo error handling } } @Override - public void expirePersistentHttpSession(long id) { + public void expirePersistentHttpSession(PersistentHttpUserSession persistentHttpUserSession) throws SQLException { try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE persistent_user_sessions SET expired=? WHERE id=?")) { preparedStatement.setTimestamp(1, Timestamp.from(Instant.now())); - preparedStatement.setLong(2, id); + preparedStatement.setLong(2, persistentHttpUserSession.getId()); preparedStatement.execute(); - } catch (SQLException e) { - e.printStackTrace(); } } @@ -286,15 +282,15 @@ public HttpUserSession getHttpSession(long id) { try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM user_sessions WHERE id=?")) { preparedStatement.setLong(1, id); try (ResultSet resultSet = preparedStatement.executeQuery()) { - if (resultSet.next()) { - return new HttpUserSession(id, - resultSet.getTimestamp("created"), - resultSet.getTimestamp("expired"), - resultSet.getLong("user_id"), - Unpooled.wrappedBuffer(resultSet.getBinaryStream("data").readAllBytes())); - } else { - return null; + if (!resultSet.next()) { + return null; // does not exist } + + return new HttpUserSession(id, + resultSet.getTimestamp("created"), + resultSet.getTimestamp("expired"), + resultSet.getLong("user_id"), + Unpooled.wrappedBuffer(resultSet.getBinaryStream("data").readAllBytes())); } } catch (SQLException | IOException e) { e.printStackTrace(); @@ -303,32 +299,28 @@ public HttpUserSession getHttpSession(long id) { } @Override - public void addHttpSession(HttpUserSession httpSession) { + public void addHttpSession(HttpUserSession httpUserSession) throws SQLException { try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO user_sessions(id, created, expired, user_id, data) VALUES (?, ?, ?, ?, ?)")) { - preparedStatement.setLong(1, httpSession.getId()); - preparedStatement.setTimestamp(2, httpSession.getCreated()); - preparedStatement.setTimestamp(3, httpSession.getExpired()); - preparedStatement.setLong(4, httpSession.getUser()); + preparedStatement.setLong(1, httpUserSession.getId()); + preparedStatement.setTimestamp(2, httpUserSession.getCreated()); + preparedStatement.setTimestamp(3, httpUserSession.getExpired()); + preparedStatement.setLong(4, httpUserSession.getUser()); ByteBuf byteBuf = Unpooled.buffer(); - httpSession.serialize(byteBuf); + httpUserSession.serialize(byteBuf); preparedStatement.setBinaryStream(5, new ByteBufInputStream(byteBuf)); byteBuf.release(); preparedStatement.execute(); - } catch (SQLException e) { - e.printStackTrace(); } } @Override - public void expireHttpSession(long id) { + public void updateHttpSession(HttpUserSession httpUserSession) throws SQLException { try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE user_sessions SET expired=? WHERE id=?")) { preparedStatement.setTimestamp(1, Timestamp.from(Instant.now())); - preparedStatement.setLong(2, id); + preparedStatement.setLong(2, httpUserSession.getUser()); preparedStatement.execute(); - } catch (SQLException e) { - e.printStackTrace(); } } @@ -398,7 +390,7 @@ public PersistentHttpUserSession getAndExpirePersistentHttpSession(long id) {//t resultSet.getLong("user_id"), Unpooled.wrappedBuffer(resultSet.getBinaryStream("data").readAllBytes())); } else { - System.out.println("PersistentUserSession with id " + id + " does not exist"); + //todo return null; } } @@ -407,7 +399,12 @@ public PersistentHttpUserSession getAndExpirePersistentHttpSession(long id) {//t return null; } - expirePersistentHttpSession(id);//todo combine with above to single transaction + try { + expirePersistentHttpSession(persistentHttpSession); + } catch (SQLException e) { + e.printStackTrace(); + return null; + } return persistentHttpSession; } } From 183b4a554948acaf17015818eef53cda42b57e97 Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 18 May 2021 13:10:31 -0400 Subject: [PATCH 021/144] rework db again --- .../server/http/HttpServerHandler.java | 216 +++++++++--------- .../databases/PersistentSessionDatabase.java | 8 +- .../database/databases/SessionDatabase.java | 5 +- .../implementations/PostgresDatabase.java | 37 ++- .../room/server/HttpAuthenticator.java | 2 +- 5 files changed, 134 insertions(+), 134 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 48b015cb..68d95602 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -64,6 +64,9 @@ public interface Config extends HttpConfig { private static final String FILE_NAME_REGEX = "a-zA-Z0-9-_"; + + private static final String AUTHENTICATE_PAGE = "/"; // the page where new users will be automatically created + private static final String LOGIN_PAGE = "/login"; // the login page, where login requests should come from private static final String LOGIN_PATH = PersistentHttpUserSession.LOGIN_PATH; // where login requests should go private static final String LOGIN_SUCCESS = "/"; // redirect for a good login, should be the main page @@ -249,133 +252,141 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr //login - //todo validate for extra fields that should not happen - if (uri.equals(LOGIN_PATH) && request.method().equals(HttpMethod.POST)) { - Map form = parseForm(request); - if (form == null) { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); - return; - } - - // validate + if (request.method().equals(HttpMethod.POST)) { + //todo validate for extra fields that should not happen + if (uri.equals(LOGIN_PATH)) { + Map form = parseForm(request); + if (form == null) { + send(ctx, request, HttpResponseStatus.BAD_REQUEST); + return; + } - String username = form.get("username"); - String password = form.get("password"); + // validate - if (username == null || password == null) { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); - return; - } + String username = form.get("username"); + String password = form.get("password"); - String rememberRaw = form.get("remember"); - boolean remember; - if (rememberRaw != null) { - if (rememberRaw.equals("on")) { - remember = true; - } else { + if (username == null || password == null) { send(ctx, request, HttpResponseStatus.BAD_REQUEST); return; } - } else { - remember = false; - } - - System.out.println(username + ", " + password + ", " + remember); - - Login login = database.getLogin(username); - Long id = Login.verify(login, password.getBytes(StandardCharsets.UTF_8)); - if (id == null) { - //todo rate limit and generic error handling - if (login == null) { - Scribbleshare.getLogger(ctx).info("Bad username " + username); + String rememberRaw = form.get("remember"); + boolean remember; + if (rememberRaw != null) { + if (rememberRaw.equals("on")) { + remember = true; + } else { + send(ctx, request, HttpResponseStatus.BAD_REQUEST); + return; + } } else { - Scribbleshare.getLogger(ctx).info("Bad password for username " + username); + remember = false; } - sendRedirect(ctx, request, LOGIN_PAGE); - return; - } - HttpHeaders httpHeaders = new DefaultHttpHeaders(); - HttpUserSession userSession = new HttpUserSession(config, database.getUser(login.getId()), httpHeaders); - database.addHttpSession(userSession); - if (remember) { - database.addPersistentHttpSession(new PersistentHttpUserSession(config, userSession, httpHeaders)); - } - sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); - return; - } else if (uri.equals(REGISTER_PATH) && request.method().equals(HttpMethod.POST)) { - Map form = parseForm(request); - if (form == null) { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); - return; - } + System.out.println(username + ", " + password + ", " + remember); - // validate + Login login = database.getLogin(username); + Long id = Login.verify(login, password.getBytes(StandardCharsets.UTF_8)); + if (id == null) { + //todo rate limit and generic error handling + if (login == null) { + Scribbleshare.getLogger(ctx).info("Bad username " + username); + } else { + Scribbleshare.getLogger(ctx).info("Bad password for username " + username); + } - String username = form.get("username"); - String password = form.get("password"); + sendRedirect(ctx, request, LOGIN_PAGE); + return; + } - if (username == null || password == null) { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); + HttpHeaders httpHeaders = new DefaultHttpHeaders(); + HttpUserSession userSession = new HttpUserSession(config, database.getUser(login.getId()), httpHeaders); + database.addHttpSession(userSession); + if (remember) { + database.addPersistentHttpSession(new PersistentHttpUserSession(config, userSession, httpHeaders)); + } + sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); return; - } + } else if (uri.equals(REGISTER_PATH)) { + Map form = parseForm(request); + if (form == null) { + send(ctx, request, HttpResponseStatus.BAD_REQUEST); + return; + } - //todo validate - if (false) { - //todo rate limit and generic error handling + // validate - sendRedirect(ctx, request, REGISTER_PAGE); - return; - } + String username = form.get("username"); + String password = form.get("password"); + + if (username == null || password == null) { + send(ctx, request, HttpResponseStatus.BAD_REQUEST); + return; + } - //todo check for existing username and user with username + //todo validate + if (false) { + //todo rate limit and generic error handling - User user; - HttpSessionCookie cookie = HttpUserSession.getCookie(request); - if (cookie != null) { - HttpUserSession httpSession = database.getHttpSession(cookie.getId()); - if (httpSession != null) { - user = database.getUser(httpSession.getUser()); + sendRedirect(ctx, request, REGISTER_PAGE); + return; + } + + //todo check for existing username and user with username + + User user; + HttpSessionCookie cookie = HttpUserSession.getCookie(request); + if (cookie != null) { + HttpUserSession httpSession = database.getHttpSession(cookie); + if (httpSession != null) { + user = database.getUser(httpSession.getUser()); + } else { + user = new User(username); + database.addUser(user); + } } else { user = new User(username); database.addUser(user); } - } else { - user = new User(username); - database.addUser(user); - } - Login login = new Login(user, password.getBytes(StandardCharsets.UTF_8)); - database.addLogin(login); + Login login = new Login(user, password.getBytes(StandardCharsets.UTF_8)); + database.addLogin(login); - System.out.println(username + ", register " + password); + System.out.println(username + ", register " + password); - sendRedirect(ctx, request, REGISTER_SUCCESS); - return; - } else if (uri.equals(LOGOUT_PAGE) && request.method().equals(HttpMethod.POST)) { - Map form = parseForm(request); - if (form == null) { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); + sendRedirect(ctx, request, REGISTER_SUCCESS); return; - } + } else if (uri.equals(LOGOUT_PAGE)) { + Map form = parseForm(request); + if (form == null) { + send(ctx, request, HttpResponseStatus.BAD_REQUEST); + return; + } - HttpHeaders headers = new DefaultHttpHeaders(); - //todo authenticate so only authenticated users can log out - HttpSessionCookie cookie = HttpUserSession.getCookie(request); - if (cookie != null) { - database.updateHttpSession(cookie.getId()); - //todo clear cookie - } - HttpSessionCookie persistentCookie = PersistentHttpUserSession.getCookie(request); - if (persistentCookie != null) { - database.updateHttpSession(persistentCookie.getId()); - //todo clear cookie - } + HttpHeaders headers = new DefaultHttpHeaders(); + //todo authenticate so only authenticated users can log out + HttpSessionCookie cookie = HttpUserSession.getCookie(request); + if (cookie != null) { + HttpUserSession httpUserSession = database.getHttpSession(cookie); + if (httpUserSession == null) { + //todo bad + return; + } + database.expireHttpSession(httpUserSession); + //todo clear cookie + } + HttpSessionCookie persistentCookie = PersistentHttpUserSession.getCookie(request); + if (persistentCookie != null) { + PersistentHttpUserSession persistentHttpUserSession = database.getAndExpirePersistentHttpSession(persistentCookie); + //todo clear cookie + } - sendRedirect(ctx, request, LOGIN_SUCCESS); - return; + + sendRedirect(ctx, request, LOGIN_SUCCESS); + return; + } } // otherwise try to serve a regular HTTP file resource @@ -419,8 +430,9 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr } return; } + HttpHeaders headers = new DefaultHttpHeaders(); - /* if (path.equals(PersistentHttpUserSession.LOGIN_PATH)) { +/* if (path.equals(AUTHENTICATE_PAGE)) { logIn(ctx, config, request, headers); }*/ headers.set(HttpHeaderNames.CACHE_CONTROL, "public,max-age=" + httpCacheSeconds);//cache but revalidate if stale todo set to private cache for resources behind authentication @@ -430,7 +442,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr private Long authenticate(ChannelHandlerContext ctx, FullHttpRequest request) { HttpSessionCookie cookie = HttpUserSession.getCookie(request); if (cookie != null) { - HttpUserSession httpSession = database.getHttpSession(cookie.getId()); + HttpUserSession httpSession = database.getHttpSession(cookie); if (httpSession != null && httpSession.validate(cookie)) { Scribbleshare.getLogger(ctx).info("Authenticated with id " + httpSession.getUser()); return httpSession.getUser(); @@ -462,7 +474,7 @@ private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders header User user; HttpSessionCookie cookiePersistent = PersistentHttpUserSession.getCookie(request); if (cookiePersistent != null) { - PersistentHttpUserSession persistentHttpSession = database.getAndExpirePersistentHttpSession(cookiePersistent.getId()); + PersistentHttpUserSession persistentHttpSession = database.getAndExpirePersistentHttpSession(cookiePersistent); if (persistentHttpSession != null && persistentHttpSession.validate(cookiePersistent)) { user = database.getUser(persistentHttpSession.getUser()); } else { @@ -483,7 +495,7 @@ private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders header database.addPersistentHttpSession(persistentHttpSession); return true; } else { - HttpUserSession httpSession = database.getHttpSession(cookie.getId()); + HttpUserSession httpSession = database.getHttpSession(cookie); if (httpSession != null && httpSession.validate(cookie)) { return true; } else { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java index 5a6b3cf1..6ca45728 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java @@ -1,5 +1,6 @@ package net.stzups.scribbleshare.data.database.databases; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; import java.sql.SQLException; @@ -8,15 +9,10 @@ public interface PersistentSessionDatabase { /** * Get existing {@link PersistentHttpUserSession} and expire it, or null if it does exist */ - PersistentHttpUserSession getAndExpirePersistentHttpSession(long id); + PersistentHttpUserSession getAndExpirePersistentHttpSession(HttpSessionCookie cookie); /** * Add new {@link PersistentHttpUserSession} */ void addPersistentHttpSession(PersistentHttpUserSession persistentHttpSession) throws SQLException; - - /** - * Expire existing {@link PersistentHttpUserSession} - */ - void expirePersistentHttpSession(PersistentHttpUserSession persistentHttpSession) throws SQLException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java index 1a4eacd4..02a2a492 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java @@ -1,5 +1,6 @@ package net.stzups.scribbleshare.data.database.databases; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; import java.sql.SQLException; @@ -8,7 +9,7 @@ public interface SessionDatabase { /** * Get existing {@link HttpUserSession}, or null if it does not exist */ - HttpUserSession getHttpSession(long id); + HttpUserSession getHttpSession(HttpSessionCookie cookie); /** * Add new {@link HttpUserSession} @@ -18,5 +19,5 @@ public interface SessionDatabase { /** * Expire existing {@link HttpUserSession} */ - void updateHttpSession(HttpUserSession httpUserSession) throws SQLException; + void expireHttpSession(HttpUserSession httpUserSession) throws SQLException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index bfdf52ee..88a7aed8 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -9,6 +9,7 @@ import net.stzups.scribbleshare.data.objects.InviteCode; import net.stzups.scribbleshare.data.objects.Resource; import net.stzups.scribbleshare.data.objects.User; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; import net.stzups.scribbleshare.data.objects.authentication.login.Login; @@ -269,24 +270,16 @@ public void addPersistentHttpSession(PersistentHttpUserSession persistentHttpSes } @Override - public void expirePersistentHttpSession(PersistentHttpUserSession persistentHttpUserSession) throws SQLException { - try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE persistent_user_sessions SET expired=? WHERE id=?")) { - preparedStatement.setTimestamp(1, Timestamp.from(Instant.now())); - preparedStatement.setLong(2, persistentHttpUserSession.getId()); - preparedStatement.execute(); - } - } - - @Override - public HttpUserSession getHttpSession(long id) { + public HttpUserSession getHttpSession(HttpSessionCookie cookie) { try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM user_sessions WHERE id=?")) { - preparedStatement.setLong(1, id); + preparedStatement.setLong(1, cookie.getId()); try (ResultSet resultSet = preparedStatement.executeQuery()) { if (!resultSet.next()) { return null; // does not exist } - return new HttpUserSession(id, + return new HttpUserSession( + resultSet.getLong("id"), resultSet.getTimestamp("created"), resultSet.getTimestamp("expired"), resultSet.getLong("user_id"), @@ -316,7 +309,7 @@ public void addHttpSession(HttpUserSession httpUserSession) throws SQLException } @Override - public void updateHttpSession(HttpUserSession httpUserSession) throws SQLException { + public void expireHttpSession(HttpUserSession httpUserSession) throws SQLException { try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE user_sessions SET expired=? WHERE id=?")) { preparedStatement.setTimestamp(1, Timestamp.from(Instant.now())); preparedStatement.setLong(2, httpUserSession.getUser()); @@ -377,14 +370,18 @@ public Resource getResource(long id, long owner) { * Remove a user session for a token and return the removed user session */ @Override - public PersistentHttpUserSession getAndExpirePersistentHttpSession(long id) {//todo combine + public PersistentHttpUserSession getAndExpirePersistentHttpSession(HttpSessionCookie cookie) {//todo combine PersistentHttpUserSession persistentHttpSession; - try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM persistent_user_sessions WHERE id=?")) { - preparedStatement.setLong(1, id); + try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM persistent_user_sessions WHERE id=?; UPDATE persistent_user_sessions SET expired=? WHERE id=?")) { + preparedStatement.setLong(1, cookie.getId()); + + preparedStatement.setTimestamp(2, Timestamp.from(Instant.now())); + preparedStatement.setLong(3, cookie.getId()); try (ResultSet resultSet = preparedStatement.executeQuery()) { if (resultSet.next()) { - persistentHttpSession = new PersistentHttpUserSession(id, + persistentHttpSession = new PersistentHttpUserSession( + resultSet.getLong("id"), resultSet.getTimestamp("created"), resultSet.getTimestamp("expired"), resultSet.getLong("user_id"), @@ -399,12 +396,6 @@ public PersistentHttpUserSession getAndExpirePersistentHttpSession(long id) {//t return null; } - try { - expirePersistentHttpSession(persistentHttpSession); - } catch (SQLException e) { - e.printStackTrace(); - return null; - } return persistentHttpSession; } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java index f285d5cd..0a80aee3 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java @@ -62,7 +62,7 @@ protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List Date: Tue, 18 May 2021 13:11:23 -0400 Subject: [PATCH 022/144] fix order --- .../data/database/implementations/PostgresDatabase.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index 88a7aed8..74070781 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -373,10 +373,10 @@ public Resource getResource(long id, long owner) { public PersistentHttpUserSession getAndExpirePersistentHttpSession(HttpSessionCookie cookie) {//todo combine PersistentHttpUserSession persistentHttpSession; - try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM persistent_user_sessions WHERE id=?; UPDATE persistent_user_sessions SET expired=? WHERE id=?")) { - preparedStatement.setLong(1, cookie.getId()); + try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE persistent_user_sessions SET expired=? WHERE id=?; SELECT * FROM persistent_user_sessions WHERE id=?")) { + preparedStatement.setTimestamp(1, Timestamp.from(Instant.now())); + preparedStatement.setLong(2, cookie.getId()); - preparedStatement.setTimestamp(2, Timestamp.from(Instant.now())); preparedStatement.setLong(3, cookie.getId()); try (ResultSet resultSet = preparedStatement.executeQuery()) { if (resultSet.next()) { From 8d0a9c98471c599b7d023a369996b16a452ffe0c Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 18 May 2021 13:21:28 -0400 Subject: [PATCH 023/144] add clear cookie --- .../server/http/HttpServerHandler.java | 6 ++--- .../authentication/http/HttpUserSession.java | 22 ++++++++++--------- .../http/PersistentHttpUserSession.java | 20 ++++++----------- .../scribbleshare/server/http/HttpUtils.java | 6 +++++ 4 files changed, 28 insertions(+), 26 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 68d95602..7434efcb 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -375,16 +375,16 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr } database.expireHttpSession(httpUserSession); - //todo clear cookie + httpUserSession.clearCookie(config, headers); } HttpSessionCookie persistentCookie = PersistentHttpUserSession.getCookie(request); if (persistentCookie != null) { PersistentHttpUserSession persistentHttpUserSession = database.getAndExpirePersistentHttpSession(persistentCookie); - //todo clear cookie + persistentHttpUserSession.clearCookie(config, headers); } - sendRedirect(ctx, request, LOGIN_SUCCESS); + sendRedirect(ctx, request, headers, LOGOUT_SUCCESS); return; } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java index 2a89c369..505dfb10 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java @@ -3,13 +3,13 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.handler.codec.base64.Base64; -import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.cookie.Cookie; import io.netty.handler.codec.http.cookie.CookieHeaderNames; import io.netty.handler.codec.http.cookie.DefaultCookie; -import io.netty.handler.codec.http.cookie.ServerCookieEncoder; import net.stzups.scribbleshare.data.objects.User; +import net.stzups.scribbleshare.server.http.HttpUtils; import java.nio.charset.StandardCharsets; import java.sql.Timestamp; @@ -27,7 +27,7 @@ protected HttpUserSession(long user) { public HttpUserSession(HttpConfig config, User user, HttpHeaders headers) { super(user.getId()); - setCookie(config, headers); + HttpUtils.setCookie(headers, getCookie(config)); } public HttpUserSession(long id, Timestamp creation, Timestamp expiration, long userId, ByteBuf byteBuf) { @@ -45,15 +45,21 @@ protected DefaultCookie getCookie(String name) { return cookie; } - private void setCookie(HttpConfig config, HttpHeaders headers) { + protected Cookie getCookie(HttpConfig config) { DefaultCookie cookie = getCookie(COOKIE_NAME); cookie.setDomain(config.getDomain()); - //not used cookie.setPath(""); if (config.getSSL()) cookie.setSecure(true); cookie.setHttpOnly(true); cookie.setSameSite(CookieHeaderNames.SameSite.Strict); //session cookie, so no max age - headers.add(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.STRICT.encode(cookie)); + + return cookie; + } + + public void clearCookie(HttpConfig config, HttpHeaders headers) { + Cookie cookie = getCookie(config); + cookie.setMaxAge(0);//todo + HttpUtils.setCookie(headers, cookie); } public static HttpSessionCookie getCookie(HttpRequest request) { @@ -63,8 +69,4 @@ public static HttpSessionCookie getCookie(HttpRequest request) { public boolean validate(HttpSessionCookie cookie) { return validate(cookie.getToken()) && Instant.now().isBefore(getCreated().toInstant().plus(MAX_AGE)); } - - public static void clearCookie(HttpConfig config, HttpHeaders headers) { - - } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java index 901a50f6..2ff01bef 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java @@ -1,12 +1,10 @@ package net.stzups.scribbleshare.data.objects.authentication.http; import io.netty.buffer.ByteBuf; -import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.cookie.CookieHeaderNames; -import io.netty.handler.codec.http.cookie.DefaultCookie; -import io.netty.handler.codec.http.cookie.ServerCookieEncoder; +import io.netty.handler.codec.http.cookie.Cookie; +import net.stzups.scribbleshare.server.http.HttpUtils; import java.sql.Timestamp; import java.time.Duration; @@ -22,23 +20,19 @@ public class PersistentHttpUserSession extends HttpUserSession { public PersistentHttpUserSession(HttpConfig config, HttpUserSession httpSession, HttpHeaders headers) { super(httpSession.getUser()); - setCookie(config, headers); + HttpUtils.setCookie(headers, getCookie(config)); } public PersistentHttpUserSession(long id, Timestamp creation, Timestamp expiration, long userId, ByteBuf byteBuf) { super(id, creation, expiration, userId, byteBuf); } - private void setCookie(HttpConfig config, HttpHeaders headers) { - DefaultCookie cookie = getCookie(COOKIE_NAME); - cookie.setDomain(config.getDomain()); - cookie.setPath("/"); - if (config.getSSL()) cookie.setSecure(true); - cookie.setHttpOnly(true); - cookie.setSameSite(CookieHeaderNames.SameSite.Strict); + @Override + protected Cookie getCookie(HttpConfig config) { + Cookie cookie = super.getCookie(config); cookie.setMaxAge(MAX_AGE.get(ChronoUnit.SECONDS)); //persistent cookie - headers.add(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.STRICT.encode(cookie)); + return cookie; } public static HttpSessionCookie getCookie(HttpRequest request) { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java index 7e5582ab..9013110a 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java @@ -18,6 +18,8 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpUtil; import io.netty.handler.codec.http.HttpVersion; +import io.netty.handler.codec.http.cookie.Cookie; +import io.netty.handler.codec.http.cookie.ServerCookieEncoder; import io.netty.handler.stream.ChunkedFile; import io.netty.handler.stream.ChunkedInput; import net.stzups.scribbleshare.Scribbleshare; @@ -171,4 +173,8 @@ public static void sendFile(ChannelHandlerContext ctx, FullHttpRequest request, send(ctx, request, HttpResponseStatus.NOT_FOUND); } } + + public static void setCookie(HttpHeaders headers, Cookie cookie) { + headers.add(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.STRICT.encode(cookie)); + } } From 01985452c9d2c0c01df12ece4c821d84c404b861 Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 18 May 2021 13:57:08 -0400 Subject: [PATCH 024/144] fix logout --- .../server/http/HttpServerHandler.java | 46 ++++++++++++------- .../databases/PersistentSessionDatabase.java | 11 +++-- .../implementations/PostgresDatabase.java | 22 +++++---- 3 files changed, 50 insertions(+), 29 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 7434efcb..6079a096 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -30,6 +30,7 @@ import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.sql.SQLException; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -305,7 +306,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr HttpUserSession userSession = new HttpUserSession(config, database.getUser(login.getId()), httpHeaders); database.addHttpSession(userSession); if (remember) { - database.addPersistentHttpSession(new PersistentHttpUserSession(config, userSession, httpHeaders)); + database.addPersistentHttpUserSession(new PersistentHttpUserSession(config, userSession, httpHeaders)); } sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); return; @@ -365,25 +366,38 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr } HttpHeaders headers = new DefaultHttpHeaders(); - //todo authenticate so only authenticated users can log out HttpSessionCookie cookie = HttpUserSession.getCookie(request); if (cookie != null) { HttpUserSession httpUserSession = database.getHttpSession(cookie); - if (httpUserSession == null) { - //todo bad - return; + if (httpUserSession != null) { + if (httpUserSession.validate(cookie)) { + database.expireHttpSession(httpUserSession); + httpUserSession.clearCookie(config, headers); + } else { + Scribbleshare.getLogger(ctx).warning("Tried to log out of existing session with bad authentication"); + } + } else { + Scribbleshare.getLogger(ctx).warning("Tried to log out of non existent session"); } - - database.expireHttpSession(httpUserSession); - httpUserSession.clearCookie(config, headers); } + HttpSessionCookie persistentCookie = PersistentHttpUserSession.getCookie(request); if (persistentCookie != null) { - PersistentHttpUserSession persistentHttpUserSession = database.getAndExpirePersistentHttpSession(persistentCookie); - persistentHttpUserSession.clearCookie(config, headers); + PersistentHttpUserSession persistentHttpUserSession = database.getPersistentHttpUserSession(persistentCookie); + if (persistentHttpUserSession != null) { + if (persistentHttpUserSession.validate(persistentCookie)) { + database.expirePersistentHttpUserSession(persistentHttpUserSession); + persistentHttpUserSession.clearCookie(config, headers); + } else { + Scribbleshare.getLogger(ctx).warning("Tried to log out of existing persistent session with bad authentication"); + //todo error + } + } else { + Scribbleshare.getLogger(ctx).warning("Tried to log out of non existent persistent session"); + //todo error + } } - sendRedirect(ctx, request, headers, LOGOUT_SUCCESS); return; } @@ -458,7 +472,7 @@ private Long authenticate(ChannelHandlerContext ctx, FullHttpRequest request) { return null; } - private void logIn(ChannelHandlerContext ctx, HttpConfig config, FullHttpRequest request, HttpHeaders headers) { + private void logIn(ChannelHandlerContext ctx, HttpConfig config, FullHttpRequest request, HttpHeaders headers) throws SQLException { if (!logIn(config, request, headers)) { Scribbleshare.getLogger(ctx).warning("Bad authentication"); send(ctx, request, HttpResponseStatus.UNAUTHORIZED); @@ -468,13 +482,13 @@ private void logIn(ChannelHandlerContext ctx, HttpConfig config, FullHttpRequest } } - private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders headers) { + private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders headers) throws SQLException { HttpSessionCookie cookie = HttpUserSession.getCookie(request); if (cookie == null) { User user; HttpSessionCookie cookiePersistent = PersistentHttpUserSession.getCookie(request); if (cookiePersistent != null) { - PersistentHttpUserSession persistentHttpSession = database.getAndExpirePersistentHttpSession(cookiePersistent); + PersistentHttpUserSession persistentHttpSession = database.getPersistentHttpUserSession(cookiePersistent); if (persistentHttpSession != null && persistentHttpSession.validate(cookiePersistent)) { user = database.getUser(persistentHttpSession.getUser()); } else { @@ -492,7 +506,7 @@ private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders header //this is single use and always refreshed PersistentHttpUserSession persistentHttpSession = new PersistentHttpUserSession(config, httpSession, headers); - database.addPersistentHttpSession(persistentHttpSession); + database.addPersistentHttpUserSession(persistentHttpSession); return true; } else { HttpUserSession httpSession = database.getHttpSession(cookie); @@ -507,7 +521,7 @@ private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders header //this is single use and always refreshed PersistentHttpUserSession persistentHttpSession = new PersistentHttpUserSession(config, httpSession, headers); - database.addPersistentHttpSession(persistentHttpSession); + database.addPersistentHttpUserSession(persistentHttpSession); return true; } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java index 6ca45728..335c648e 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java @@ -7,12 +7,17 @@ public interface PersistentSessionDatabase { /** - * Get existing {@link PersistentHttpUserSession} and expire it, or null if it does exist + * Get existing {@link PersistentHttpUserSession}, or null if it does exist */ - PersistentHttpUserSession getAndExpirePersistentHttpSession(HttpSessionCookie cookie); + PersistentHttpUserSession getPersistentHttpUserSession(HttpSessionCookie cookie); /** * Add new {@link PersistentHttpUserSession} */ - void addPersistentHttpSession(PersistentHttpUserSession persistentHttpSession) throws SQLException; + void addPersistentHttpUserSession(PersistentHttpUserSession persistentHttpSession) throws SQLException; + + /** + * Expire existing {@link PersistentHttpUserSession} + */ + void expirePersistentHttpUserSession(PersistentHttpUserSession persistentHttpUserSession) throws SQLException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index 74070781..35b97a5d 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -253,7 +253,7 @@ public InviteCode getInviteCode(Document document) {//gets an invite code for a } @Override - public void addPersistentHttpSession(PersistentHttpUserSession persistentHttpSession) throws SQLException { + public void addPersistentHttpUserSession(PersistentHttpUserSession persistentHttpSession) throws SQLException { try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO persistent_user_sessions(id, created, expired, user_id, data) VALUES (?, ?, ?, ?, ?)")) { preparedStatement.setLong(1, persistentHttpSession.getId()); preparedStatement.setTimestamp(2, persistentHttpSession.getCreated()); @@ -366,18 +366,12 @@ public Resource getResource(long id, long owner) { } } - /** - * Remove a user session for a token and return the removed user session - */ @Override - public PersistentHttpUserSession getAndExpirePersistentHttpSession(HttpSessionCookie cookie) {//todo combine + public PersistentHttpUserSession getPersistentHttpUserSession(HttpSessionCookie cookie) {//todo combine PersistentHttpUserSession persistentHttpSession; - try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE persistent_user_sessions SET expired=? WHERE id=?; SELECT * FROM persistent_user_sessions WHERE id=?")) { - preparedStatement.setTimestamp(1, Timestamp.from(Instant.now())); - preparedStatement.setLong(2, cookie.getId()); - - preparedStatement.setLong(3, cookie.getId()); + try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM persistent_user_sessions WHERE id=?")) { + preparedStatement.setLong(1, cookie.getId()); try (ResultSet resultSet = preparedStatement.executeQuery()) { if (resultSet.next()) { persistentHttpSession = new PersistentHttpUserSession( @@ -398,4 +392,12 @@ public PersistentHttpUserSession getAndExpirePersistentHttpSession(HttpSessionCo return persistentHttpSession; } + + @Override + public void expirePersistentHttpUserSession(PersistentHttpUserSession session) throws SQLException { + try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE persistent_user_sessions SET expired=? WHERE id=?; ")) { + preparedStatement.setTimestamp(1, Timestamp.from(Instant.now())); + preparedStatement.setLong(2, session.getId()); + } + } } From 633801d88b2e37194eb2f03a317647cdadd6f92e Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 18 May 2021 13:59:06 -0400 Subject: [PATCH 025/144] rename --- .../data/database/ScribbleshareDatabase.java | 6 +++--- .../{SessionDatabase.java => HttpSessionDatabase.java} | 2 +- ...atabase.java => PersistentHttpSessionDatabase.java} | 2 +- .../scribbleshare/room/server/HttpAuthenticator.java | 10 +++++----- 4 files changed, 10 insertions(+), 10 deletions(-) rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/{SessionDatabase.java => HttpSessionDatabase.java} (94%) rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/{PersistentSessionDatabase.java => PersistentHttpSessionDatabase.java} (94%) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java index 06854e62..4a268786 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java @@ -1,14 +1,14 @@ package net.stzups.scribbleshare.data.database; -import net.stzups.scribbleshare.data.database.databases.PersistentSessionDatabase; +import net.stzups.scribbleshare.data.database.databases.HttpSessionDatabase; +import net.stzups.scribbleshare.data.database.databases.PersistentHttpSessionDatabase; import net.stzups.scribbleshare.data.database.databases.ResourceDatabase; -import net.stzups.scribbleshare.data.database.databases.SessionDatabase; import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.InviteCode; import net.stzups.scribbleshare.data.objects.User; import net.stzups.scribbleshare.data.objects.authentication.login.Login; -public interface ScribbleshareDatabase extends PersistentSessionDatabase, ResourceDatabase, SessionDatabase { +public interface ScribbleshareDatabase extends PersistentHttpSessionDatabase, ResourceDatabase, HttpSessionDatabase { void addUser(User user); User getUser(long id); void updateUser(User user); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java similarity index 94% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java index 02a2a492..8fb34152 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/SessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java @@ -5,7 +5,7 @@ import java.sql.SQLException; -public interface SessionDatabase { +public interface HttpSessionDatabase { /** * Get existing {@link HttpUserSession}, or null if it does not exist */ diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java similarity index 94% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java index 335c648e..37fa122f 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentSessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java @@ -5,7 +5,7 @@ import java.sql.SQLException; -public interface PersistentSessionDatabase { +public interface PersistentHttpSessionDatabase { /** * Get existing {@link PersistentHttpUserSession}, or null if it does exist */ diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java index 0a80aee3..61b74e3e 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java @@ -8,7 +8,7 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.util.AttributeKey; import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.data.database.databases.SessionDatabase; +import net.stzups.scribbleshare.data.database.databases.HttpSessionDatabase; import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; @@ -26,11 +26,11 @@ public static long getUser(ChannelHandlerContext ctx) { } private final RoomHttpServerInitializer.Config config; - private final SessionDatabase sessionDatabase; + private final HttpSessionDatabase httpSessionDatabase; - public HttpAuthenticator(RoomHttpServerInitializer.Config config, SessionDatabase sessionDatabase) { + public HttpAuthenticator(RoomHttpServerInitializer.Config config, HttpSessionDatabase httpSessionDatabase) { this.config = config; - this.sessionDatabase = sessionDatabase; + this.httpSessionDatabase = httpSessionDatabase; } @Override @@ -62,7 +62,7 @@ protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List Date: Tue, 18 May 2021 14:05:26 -0400 Subject: [PATCH 026/144] fix cookie being overwritten --- .../backend/server/http/HttpServerHandler.java | 3 ++- .../authentication/http/HttpUserSession.java | 13 +++++++------ .../http/PersistentHttpUserSession.java | 7 ++++--- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 6079a096..a84368b6 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -306,7 +306,8 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr HttpUserSession userSession = new HttpUserSession(config, database.getUser(login.getId()), httpHeaders); database.addHttpSession(userSession); if (remember) { - database.addPersistentHttpUserSession(new PersistentHttpUserSession(config, userSession, httpHeaders)); + PersistentHttpUserSession persistentHttpUserSession = new PersistentHttpUserSession(config, userSession, httpHeaders); + database.addPersistentHttpUserSession(persistentHttpUserSession); } sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); return; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java index 505dfb10..96f2d28c 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java @@ -34,7 +34,7 @@ public HttpUserSession(long id, Timestamp creation, Timestamp expiration, long u super(id, creation, expiration, userId, byteBuf); } - protected DefaultCookie getCookie(String name) { + protected DefaultCookie getCookie(HttpConfig config, String name) { ByteBuf token = Unpooled.buffer(); token.writeLong(getId()); token.writeBytes(super.generateToken()); @@ -42,20 +42,21 @@ protected DefaultCookie getCookie(String name) { DefaultCookie cookie = new DefaultCookie(name, tokenBase64.toString(StandardCharsets.UTF_8)); tokenBase64.release(); token.release(); - return cookie; - } - protected Cookie getCookie(HttpConfig config) { - DefaultCookie cookie = getCookie(COOKIE_NAME); cookie.setDomain(config.getDomain()); if (config.getSSL()) cookie.setSecure(true); cookie.setHttpOnly(true); cookie.setSameSite(CookieHeaderNames.SameSite.Strict); - //session cookie, so no max age return cookie; } + private Cookie getCookie(HttpConfig config) { + //session cookie, so no max age + + return getCookie(config, COOKIE_NAME); + } + public void clearCookie(HttpConfig config, HttpHeaders headers) { Cookie cookie = getCookie(config); cookie.setMaxAge(0);//todo diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java index 2ff01bef..741fbe33 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java @@ -4,6 +4,7 @@ import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.cookie.Cookie; +import io.netty.handler.codec.http.cookie.DefaultCookie; import net.stzups.scribbleshare.server.http.HttpUtils; import java.sql.Timestamp; @@ -27,9 +28,9 @@ public PersistentHttpUserSession(long id, Timestamp creation, Timestamp expirati super(id, creation, expiration, userId, byteBuf); } - @Override - protected Cookie getCookie(HttpConfig config) { - Cookie cookie = super.getCookie(config); + private Cookie getCookie(HttpConfig config) { + DefaultCookie cookie = getCookie(config, COOKIE_NAME); + cookie.setMaxAge(MAX_AGE.get(ChronoUnit.SECONDS)); //persistent cookie return cookie; From 7ce86f2914486a02e6b12908a12d44a0459f4a2d Mon Sep 17 00:00:00 2001 From: stzups Date: Wed, 19 May 2021 14:30:31 -0400 Subject: [PATCH 027/144] tiny change --- .../java/net/stzups/scribbleshare/util/LogFactory.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/LogFactory.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/LogFactory.java index 333e4b3b..8b778e64 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/LogFactory.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/LogFactory.java @@ -3,6 +3,7 @@ import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.nio.charset.StandardCharsets; +import java.text.DateFormat; import java.text.SimpleDateFormat; import java.time.Instant; import java.util.Date; @@ -17,6 +18,8 @@ * Helper class used to format log messages */ public class LogFactory { + private static final DateFormat FORMAT = new SimpleDateFormat("[yyyy-MM-dd] [HH:mm:ss] "); + /** * Creates or finds a Java logger and sets formatting to the following: * [yyyy-MM-dd] [hh:mm:ss] [name] [level (if not INFO)] message @@ -43,12 +46,10 @@ public static void setLogger(Logger logger, String name) { Handler handler = new ConsoleHandler(); logger.addHandler(handler); handler.setFormatter(new Formatter() { - private final SimpleDateFormat dateFormat = new SimpleDateFormat("[yyyy-MM-dd] [HH:mm:ss] "); - @Override public String format(LogRecord record) { String level = (record.getLevel() == Level.INFO) ? "" : "[" + record.getLevel() + "] "; // include Logger Level if it is not Level.INFO - return dateFormat.format(Date.from(Instant.now())) + return FORMAT.format(Date.from(Instant.now())) + "[" + name + "] " + level + record.getMessage() From 9b40cd3c7d23a8742dd84ecc55078512bd39b44d Mon Sep 17 00:00:00 2001 From: stzups Date: Wed, 19 May 2021 14:30:56 -0400 Subject: [PATCH 028/144] remove verbose log message --- .../stzups/scribbleshare/config/configs/PropertiesConfig.java | 1 - 1 file changed, 1 deletion(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/PropertiesConfig.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/PropertiesConfig.java index a7f711bc..d12e5afe 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/PropertiesConfig.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/PropertiesConfig.java @@ -24,7 +24,6 @@ public PropertiesConfig(String path) { properties = new Properties(); File file = new File(path); if (file.exists()) {//load user defined config if created - Scribbleshare.getLogger().info("Loading config properties from " + file.getName() + "..."); try (FileInputStream fileInputStream = new FileInputStream(file)) { properties.load(fileInputStream); } catch (IOException e) { From dd4d71948525565d30f9ac5f8b5beadc2fc086e9 Mon Sep 17 00:00:00 2001 From: stzups Date: Wed, 19 May 2021 14:32:15 -0400 Subject: [PATCH 029/144] remove unused ManualConfig.java --- .../config/configs/ManualConfig.java | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/ManualConfig.java diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/ManualConfig.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/ManualConfig.java deleted file mode 100644 index e87a05d5..00000000 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/ManualConfig.java +++ /dev/null @@ -1,19 +0,0 @@ -package net.stzups.scribbleshare.config.configs; - -import net.stzups.scribbleshare.config.ConfigProvider; - -import java.util.Collections; -import java.util.Map; - -public class ManualConfig implements ConfigProvider { - private final Map keyValues; - - public ManualConfig(String key, String value) { - keyValues = Collections.singletonMap(key, value); - } - - @Override - public String get(String key) { - return keyValues.get(key); - } -} From d3cef0d101db54623a878512fa4d11a10e38c52a Mon Sep 17 00:00:00 2001 From: stzups Date: Wed, 19 May 2021 14:35:35 -0400 Subject: [PATCH 030/144] refactor --- .../authentication/http/HttpUserSession.java | 16 +++++++--------- .../http/PersistentHttpUserSession.java | 16 ++++++++-------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java index 96f2d28c..4a87b165 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java @@ -34,12 +34,16 @@ public HttpUserSession(long id, Timestamp creation, Timestamp expiration, long u super(id, creation, expiration, userId, byteBuf); } - protected DefaultCookie getCookie(HttpConfig config, String name) { + protected String getCookieName() { + return COOKIE_NAME; + } + + public DefaultCookie getCookie(HttpConfig config) { ByteBuf token = Unpooled.buffer(); token.writeLong(getId()); token.writeBytes(super.generateToken()); ByteBuf tokenBase64 = Base64.encode(token); - DefaultCookie cookie = new DefaultCookie(name, tokenBase64.toString(StandardCharsets.UTF_8)); + DefaultCookie cookie = new DefaultCookie(getCookieName(), tokenBase64.toString(StandardCharsets.UTF_8)); tokenBase64.release(); token.release(); @@ -51,15 +55,9 @@ protected DefaultCookie getCookie(HttpConfig config, String name) { return cookie; } - private Cookie getCookie(HttpConfig config) { - //session cookie, so no max age - - return getCookie(config, COOKIE_NAME); - } - public void clearCookie(HttpConfig config, HttpHeaders headers) { Cookie cookie = getCookie(config); - cookie.setMaxAge(0);//todo + cookie.setMaxAge(0); HttpUtils.setCookie(headers, cookie); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java index 741fbe33..307b32b5 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java @@ -2,8 +2,6 @@ import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.HttpHeaders; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.cookie.Cookie; import io.netty.handler.codec.http.cookie.DefaultCookie; import net.stzups.scribbleshare.server.http.HttpUtils; @@ -28,18 +26,20 @@ public PersistentHttpUserSession(long id, Timestamp creation, Timestamp expirati super(id, creation, expiration, userId, byteBuf); } - private Cookie getCookie(HttpConfig config) { - DefaultCookie cookie = getCookie(config, COOKIE_NAME); + @Override + protected String getCookieName() { + return COOKIE_NAME; + } + + @Override + public DefaultCookie getCookie(HttpConfig config) { + DefaultCookie cookie = super.getCookie(config); cookie.setMaxAge(MAX_AGE.get(ChronoUnit.SECONDS)); //persistent cookie return cookie; } - public static HttpSessionCookie getCookie(HttpRequest request) { - return HttpSessionCookie.getHttpSessionCookie(request, COOKIE_NAME); - } - @Override public boolean validate(HttpSessionCookie cookie) { return validate(cookie.getToken()) && Instant.now().isBefore(getCreated().toInstant().plus(MAX_AGE)); From 5f4ba4fc3d30a424881f4fb45e9a19356485bc9d Mon Sep 17 00:00:00 2001 From: stzups Date: Thu, 20 May 2021 11:00:38 -0400 Subject: [PATCH 031/144] refactor names again --- .../backend/server/http/HttpServerHandler.java | 12 ++++++------ .../authentication/http/HttpSessionCookie.java | 2 +- .../objects/authentication/http/HttpUserSession.java | 5 ----- .../scribbleshare/room/server/HttpAuthenticator.java | 2 +- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index a84368b6..a462080f 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -339,7 +339,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr //todo check for existing username and user with username User user; - HttpSessionCookie cookie = HttpUserSession.getCookie(request); + HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); if (cookie != null) { HttpUserSession httpSession = database.getHttpSession(cookie); if (httpSession != null) { @@ -367,7 +367,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr } HttpHeaders headers = new DefaultHttpHeaders(); - HttpSessionCookie cookie = HttpUserSession.getCookie(request); + HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); if (cookie != null) { HttpUserSession httpUserSession = database.getHttpSession(cookie); if (httpUserSession != null) { @@ -382,7 +382,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr } } - HttpSessionCookie persistentCookie = PersistentHttpUserSession.getCookie(request); + HttpSessionCookie persistentCookie = HttpSessionCookie.getHttpSessionCookie(request, PersistentHttpUserSession.COOKIE_NAME); if (persistentCookie != null) { PersistentHttpUserSession persistentHttpUserSession = database.getPersistentHttpUserSession(persistentCookie); if (persistentHttpUserSession != null) { @@ -455,7 +455,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr } private Long authenticate(ChannelHandlerContext ctx, FullHttpRequest request) { - HttpSessionCookie cookie = HttpUserSession.getCookie(request); + HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); if (cookie != null) { HttpUserSession httpSession = database.getHttpSession(cookie); if (httpSession != null && httpSession.validate(cookie)) { @@ -484,10 +484,10 @@ private void logIn(ChannelHandlerContext ctx, HttpConfig config, FullHttpRequest } private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders headers) throws SQLException { - HttpSessionCookie cookie = HttpUserSession.getCookie(request); + HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); if (cookie == null) { User user; - HttpSessionCookie cookiePersistent = PersistentHttpUserSession.getCookie(request); + HttpSessionCookie cookiePersistent = HttpSessionCookie.getHttpSessionCookie(request, PersistentHttpUserSession.COOKIE_NAME); if (cookiePersistent != null) { PersistentHttpUserSession persistentHttpSession = database.getPersistentHttpUserSession(cookiePersistent); if (persistentHttpSession != null && persistentHttpSession.validate(cookiePersistent)) { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java index e789f284..6cb65fdb 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java @@ -29,7 +29,7 @@ public byte[] getToken() { return token; } - static HttpSessionCookie getHttpSessionCookie(HttpRequest request, String name) { + public static HttpSessionCookie getHttpSessionCookie(HttpRequest request, String name) { String cookiesHeader = request.headers().get(HttpHeaderNames.COOKIE); if (cookiesHeader != null) { Set cookies = ServerCookieDecoder.STRICT.decode(cookiesHeader); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java index 4a87b165..c5779f8a 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java @@ -4,7 +4,6 @@ import io.netty.buffer.Unpooled; import io.netty.handler.codec.base64.Base64; import io.netty.handler.codec.http.HttpHeaders; -import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.cookie.Cookie; import io.netty.handler.codec.http.cookie.CookieHeaderNames; import io.netty.handler.codec.http.cookie.DefaultCookie; @@ -61,10 +60,6 @@ public void clearCookie(HttpConfig config, HttpHeaders headers) { HttpUtils.setCookie(headers, cookie); } - public static HttpSessionCookie getCookie(HttpRequest request) { - return HttpSessionCookie.getHttpSessionCookie(request, COOKIE_NAME); - } - public boolean validate(HttpSessionCookie cookie) { return validate(cookie.getToken()) && Instant.now().isBefore(getCreated().toInstant().plus(MAX_AGE)); } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java index 61b74e3e..c61efeca 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java @@ -60,7 +60,7 @@ protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List Date: Fri, 21 May 2021 17:49:59 -0400 Subject: [PATCH 032/144] start to rework state --- .../server/http}/HttpAuthenticator.java | 38 +-- .../server/RoomHttpServerInitializer.java | 3 +- .../room/server/websocket/Client.java | 10 +- .../websocket/ClientMessageHandler.java | 16 +- .../room/server/websocket/Room.java | 22 +- .../room/server/websocket/State.java | 231 ------------------ .../room/server/websocket/state/State.java | 26 ++ .../state/states/HandshakeState.java | 91 +++++++ .../websocket/state/states/InitialState.java | 28 +++ .../websocket/state/states/ReadyState.java | 97 ++++++++ .../websocket/state/states/RoomState.java | 92 +++++++ 11 files changed, 373 insertions(+), 281 deletions(-) rename {scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server => scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http}/HttpAuthenticator.java (68%) delete mode 100644 scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/State.java create mode 100644 scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/State.java create mode 100644 scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java create mode 100644 scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java create mode 100644 scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java create mode 100644 scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpAuthenticator.java similarity index 68% rename from scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpAuthenticator.java index c61efeca..eb79065c 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/HttpAuthenticator.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpAuthenticator.java @@ -1,10 +1,9 @@ -package net.stzups.scribbleshare.room.server; +package net.stzups.scribbleshare.server.http; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToMessageDecoder; import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.util.AttributeKey; import net.stzups.scribbleshare.Scribbleshare; @@ -13,50 +12,39 @@ import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; import java.util.List; -import java.util.logging.Level; import static net.stzups.scribbleshare.server.http.HttpUtils.send; @ChannelHandler.Sharable public class HttpAuthenticator extends MessageToMessageDecoder { - private static final AttributeKey USER = AttributeKey.valueOf(HttpAuthenticator.class, "USER"); - public static long getUser(ChannelHandlerContext ctx) { + public static Long getUser(ChannelHandlerContext ctx) { return ctx.channel().attr(USER).get(); } - private final RoomHttpServerInitializer.Config config; private final HttpSessionDatabase httpSessionDatabase; + private final String uri; - public HttpAuthenticator(RoomHttpServerInitializer.Config config, HttpSessionDatabase httpSessionDatabase) { - this.config = config; - this.httpSessionDatabase = httpSessionDatabase; + public HttpAuthenticator(HttpSessionDatabase httpSessionDatabase) { + this(httpSessionDatabase, null); } - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - Scribbleshare.getLogger(ctx).log(Level.WARNING, "Unhandled exception, serving HTTP 500", cause); - if (ctx.channel().isActive()) { - send(ctx, null, HttpResponseStatus.INTERNAL_SERVER_ERROR); - } + public HttpAuthenticator(HttpSessionDatabase httpSessionDatabase, String uri) { + this.httpSessionDatabase = httpSessionDatabase; + this.uri = uri; } @Override - protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List out) { - if (ctx.channel().attr(USER).get() != null) { - out.add(request.retain()); - return; - } - - if (!request.uri().equals(config.getWebsocketPath())) { + protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List out) throws Exception { + if (uri != null && !request.uri().equals(uri)) { send(ctx, request, HttpResponseStatus.NOT_FOUND); Scribbleshare.getLogger(ctx).warning("Bad uri"); return; } - if (!request.method().equals(HttpMethod.GET)) { - send(ctx, request, HttpResponseStatus.METHOD_NOT_ALLOWED); - Scribbleshare.getLogger(ctx).warning("Bad method"); + Long user = ctx.channel().attr(USER).get(); + if (user != null) { + out.add(request.retain()); return; } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java index b2968634..61792f2e 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java @@ -10,6 +10,7 @@ import net.stzups.scribbleshare.room.server.websocket.ClientMessageHandler; import net.stzups.scribbleshare.room.server.websocket.protocol.ClientMessageDecoder; import net.stzups.scribbleshare.room.server.websocket.protocol.ServerMessageEncoder; +import net.stzups.scribbleshare.server.http.HttpAuthenticator; import net.stzups.scribbleshare.server.http.HttpServerInitializer; import javax.net.ssl.SSLException; @@ -38,7 +39,7 @@ public RoomHttpServerInitializer(Config config, ScribbleshareDatabase database) super(config); this.config = config; this.database = database; - httpAuthenticator = new HttpAuthenticator(config, database); + httpAuthenticator = new HttpAuthenticator(database); } @Override diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Client.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Client.java index 21ed36f0..83c47a49 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Client.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Client.java @@ -19,7 +19,7 @@ public class Client { private List messages = new ArrayList<>(); - Client(User user, Channel channel) { + public Client(User user, Channel channel) { this.user = user; this.channel = channel; regenerateId(); @@ -42,22 +42,22 @@ public short regenerateId() { } } - void queueMessage(ServerMessage serverMessage) { + public void queueMessage(ServerMessage serverMessage) { messages.add(serverMessage); } - void sendMessage(ServerMessage serverMessage) { + public void sendMessage(ServerMessage serverMessage) { channel.writeAndFlush(Collections.singletonList(serverMessage)); } - void flushMessages() { + public void flushMessages() { if (messages.size() > 0) { channel.writeAndFlush(messages); messages = new ArrayList<>();//clear() won't work here as the above line does not block and writes later } } - void disconnect() { + public void disconnect() { try { channel.close().sync(); } catch (InterruptedException e) { diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java index f282503b..55dc25bc 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java @@ -6,31 +6,31 @@ import io.netty.util.Attribute; import io.netty.util.AttributeKey; import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessage; +import net.stzups.scribbleshare.room.server.websocket.state.State; +import net.stzups.scribbleshare.room.server.websocket.state.states.InitialState; +import net.stzups.scribbleshare.server.http.HttpAuthenticator; import java.util.logging.Level; @ChannelHandler.Sharable public class ClientMessageHandler extends SimpleChannelInboundHandler { private static final AttributeKey STATE = AttributeKey.valueOf(ClientMessageHandler.class, "STATE"); - private static final AttributeKey CLIENT = AttributeKey.valueOf(ClientMessageHandler.class, "CLIENT"); - private static final AttributeKey ROOM = AttributeKey.valueOf(ClientMessageHandler.class, "ROOM"); public static Attribute getState(ChannelHandlerContext ctx) { return ctx.channel().attr(STATE); } - public static Attribute getClient(ChannelHandlerContext ctx) { - return ctx.channel().attr(CLIENT); - } + private final ScribbleshareDatabase database; - public static Attribute getRoom(ChannelHandlerContext ctx) { - return ctx.channel().attr(ROOM); + public ClientMessageHandler(ScribbleshareDatabase database) { + this.database = database; } @Override public void channelActive(ChannelHandlerContext ctx) { - State.INITIAL.setState(ctx); + State.setState(ctx, new InitialState(database.getUser(HttpAuthenticator.getUser(ctx)))); } @Override diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java index 31e3d4ab..a983a2ab 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java @@ -21,7 +21,7 @@ import java.util.Timer; import java.util.TimerTask; -class Room { +public class Room { private static final int SEND_PERIOD = 1000; private static final Map rooms = new HashMap<>(); @@ -51,7 +51,7 @@ public void run() { Scribbleshare.getLogger().info("Started " + this); } - static Room getRoom(ScribbleshareDatabase database, Document document) throws DeserializationException { + public static Room getRoom(ScribbleshareDatabase database, Document document) throws DeserializationException { Room room = rooms.get(document); if (room == null) { return new Room(database, document); @@ -59,7 +59,7 @@ static Room getRoom(ScribbleshareDatabase database, Document document) throws De return room; } - void end() { + public void end() { rooms.remove(document); if (canvas.isDirty()) { ByteBuf byteBuf = Unpooled.buffer(); @@ -70,7 +70,7 @@ void end() { Scribbleshare.getLogger().info("Ended room " + this); } - Document getDocument() { + public Document getDocument() { return document; } @@ -82,7 +82,7 @@ public Canvas getCanvas() { * Creates a new client using its channel. * todo */ - void addClient(Client client) { + public void addClient(Client client) { //for the new client client.queueMessage(new ServerMessageOpenDocument(document, canvas));//todo @@ -104,7 +104,7 @@ void addClient(Client client) { * * @param client client to remove */ - void removeClient(Client client) { + public void removeClient(Client client) { clients.remove(client); sendMessage(new ServerMessageRemoveClient(client)); Scribbleshare.getLogger().info("Removed " + client + " to " + this); @@ -119,7 +119,7 @@ void removeClient(Client client) { * @param serverMessage message to send * @param except client to exclude */ - void sendPacketExcept(ServerMessage serverMessage, Client except) { + public void sendPacketExcept(ServerMessage serverMessage, Client except) { for (Client client : clients) { if (except != client) { client.sendMessage(serverMessage); @@ -132,13 +132,13 @@ void sendPacketExcept(ServerMessage serverMessage, Client except) { * * @param serverMessage the message to send */ - void sendMessage(ServerMessage serverMessage) { + public void sendMessage(ServerMessage serverMessage) { for (Client client : clients) { client.sendMessage(serverMessage); } } - void queueMessageExcept(ServerMessage serverMessage, Client except) { + public void queueMessageExcept(ServerMessage serverMessage, Client except) { for (Client client : clients) { if (except != client) { client.queueMessage(serverMessage); @@ -146,13 +146,13 @@ void queueMessageExcept(ServerMessage serverMessage, Client except) { } } - void queueMessage(ServerMessage serverMessage) { + public void queueMessage(ServerMessage serverMessage) { for (Client client : clients) { client.queueMessage(serverMessage); } } - void flushMessages() { + public void flushMessages() { for (Client client : clients) { client.flushMessages(); } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/State.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/State.java deleted file mode 100644 index 9770802e..00000000 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/State.java +++ /dev/null @@ -1,231 +0,0 @@ -package net.stzups.scribbleshare.room.server.websocket; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; -import io.netty.util.Attribute; -import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.data.objects.Document; -import net.stzups.scribbleshare.data.objects.InviteCode; -import net.stzups.scribbleshare.data.objects.User; -import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.CanvasUpdateException; -import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.CanvasUpdates; -import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; -import net.stzups.scribbleshare.room.server.HttpAuthenticator; -import net.stzups.scribbleshare.room.server.RoomHttpServerInitializer; -import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessage; -import net.stzups.scribbleshare.room.server.websocket.protocol.client.messages.ClientMessageCanvasUpdate; -import net.stzups.scribbleshare.room.server.websocket.protocol.client.messages.ClientMessageDeleteDocument; -import net.stzups.scribbleshare.room.server.websocket.protocol.client.messages.ClientMessageHandshake; -import net.stzups.scribbleshare.room.server.websocket.protocol.client.messages.ClientMessageOpenDocument; -import net.stzups.scribbleshare.room.server.websocket.protocol.client.messages.ClientMessageUpdateDocument; -import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageAddUser; -import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageCanvasUpdate; -import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageDeleteDocument; -import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageGetInvite; -import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageHandshake; -import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageUpdateDocument; - -public enum State {//todo use class instead of enums for state?? - INITIAL { - @Override - public void userEventTriggered(ChannelHandlerContext ctx, Object event) { - if (event instanceof WebSocketServerProtocolHandler.HandshakeComplete) { - Scribbleshare.getLogger(ctx).info("WebSocket connection initialized"); - State.HANDSHAKE.setState(ctx); - return; - } - - if (event instanceof WebSocketServerProtocolHandler.ServerHandshakeStateEvent) return; //deprecated but still fired - - super.userEventTriggered(ctx, event); - } - }, - HANDSHAKE { - @Override - public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) throws ClientMessageException { - switch (clientMessage.getMessageType()) { - case HANDSHAKE: { - ClientMessageHandshake clientPacketHandshake = (ClientMessageHandshake) clientMessage; - - User user = RoomHttpServerInitializer.getDatabase(ctx).getUser(HttpAuthenticator.getUser(ctx)); - if (user == null) { - throw new ClientMessageException(clientMessage, "User does not exist"); - } - Scribbleshare.getLogger(ctx).info("Handshake with invite " + clientPacketHandshake.getCode() + ", " + user); - - Client client = new Client(user, ctx.channel()); - ClientMessageHandler.getClient(ctx).set(client); - - client.queueMessage(new ServerMessageHandshake(client)); - InviteCode inviteCode = RoomHttpServerInitializer.getDatabase(ctx).getInviteCode(clientPacketHandshake.getCode()); - client.queueMessage(new ServerMessageAddUser(client.getUser())); - //figure out which document to open first - if (inviteCode != null) { - Document document = RoomHttpServerInitializer.getDatabase(ctx).getDocument(inviteCode.getDocument()); - if (document != null) { - //if this isn't the user's own document and this isn't part of the user's shared documents then add and update - if (document.getOwner() != client.getUser().getId()) { - if (client.getUser().getSharedDocuments().add(document.getId())) { - RoomHttpServerInitializer.getDatabase(ctx).updateUser(client.getUser()); - } - } - try { - ClientMessageHandler.getRoom(ctx).set(Room.getRoom(RoomHttpServerInitializer.getDatabase(ctx), document)); - } catch (DeserializationException e) { - throw new ClientMessageException(clientMessage, e); - } - } else { - throw new ClientMessageException(clientMessage, "Somehow used invite code for non existent document"); - } - } else { - if (client.getUser().getOwnedDocuments().size() == 0) { - RoomHttpServerInitializer.getDatabase(ctx).createDocument(client.getUser()); - } - } - client.getUser().getOwnedDocuments().removeIf((id) -> { - Document document = RoomHttpServerInitializer.getDatabase(ctx).getDocument(id); - if (document == null) { - return true; - } else { - client.queueMessage(new ServerMessageUpdateDocument(RoomHttpServerInitializer.getDatabase(ctx).getDocument(id))); - return false; - } - });//todo this is bad - client.getUser().getSharedDocuments().removeIf((id) -> { - Document document = RoomHttpServerInitializer.getDatabase(ctx).getDocument(id); - if (document == null) { - return true; - } else { - client.queueMessage(new ServerMessageUpdateDocument(RoomHttpServerInitializer.getDatabase(ctx).getDocument(id))); - return false; - } - }); - client.flushMessages(); - - State.READY.setState(ctx); - break; - } - default: - super.message(ctx, clientMessage); - } - } - }, - READY { - @Override - public void channelInactive(ChannelHandlerContext ctx) { - final Attribute room = ClientMessageHandler.getRoom(ctx); - if (room.get() != null) { - room.get().removeClient(ClientMessageHandler.getClient(ctx).get()); - return; - } - //super.channelInactive(ctx); - } - - @Override - public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) throws ClientMessageException { - final Client client = ClientMessageHandler.getClient(ctx).get(); - final Attribute room = ClientMessageHandler.getRoom(ctx); - - switch (clientMessage.getMessageType()) { - case CANVAS_UPDATE: { - CanvasUpdates[] canvasUpdates = ((ClientMessageCanvasUpdate) clientMessage).getCanvasUpdatesArray(); - try { - room.get().getCanvas().update(canvasUpdates); - } catch (CanvasUpdateException e) { - throw new ClientMessageException(clientMessage, e); - } - room.get().queueMessageExcept(new ServerMessageCanvasUpdate(canvasUpdates), client); - break; - } - case OPEN_DOCUMENT: { - ClientMessageOpenDocument clientPacketOpenDocument = (ClientMessageOpenDocument) clientMessage; - Document document = RoomHttpServerInitializer.getDatabase(ctx).getDocument(clientPacketOpenDocument.getId()); - if (document != null) { - if (room.get() != null) { - room.get().removeClient(client); - } - try { - room.set(Room.getRoom(RoomHttpServerInitializer.getDatabase(ctx), document)); - } catch (DeserializationException e) { - throw new ClientMessageException(clientMessage, e); - } - room.get().addClient(client); - } else { - Scribbleshare.getLogger(ctx).warning(client + " tried to open document not that does not exist"); - } - break; - } - case CREATE_DOCUMENT: { - if (room.get() != null) { - room.get().removeClient(client); - } - try { - room.set(Room.getRoom(RoomHttpServerInitializer.getDatabase(ctx), RoomHttpServerInitializer.getDatabase(ctx).createDocument(client.getUser()))); - ClientMessageHandler.getRoom(ctx).set(room.get()); - } catch (Exception e) { - e.printStackTrace(); - } - client.sendMessage(new ServerMessageUpdateDocument(room.get().getDocument())); - room.get().addClient(client); - break; - } - case DELETE_DOCUMENT: { - ClientMessageDeleteDocument clientMessageDeleteDocument = (ClientMessageDeleteDocument) clientMessage; - if (clientMessageDeleteDocument.getId() == room.get().getDocument().getId()) { - Scribbleshare.getLogger(ctx).info("Deleting live document " + room.get().getDocument()); - room.get().sendMessage(new ServerMessageDeleteDocument(room.get().getDocument())); - room.get().end(); - RoomHttpServerInitializer.getDatabase(ctx).deleteDocument(room.get().getDocument()); - break; - } else { - throw new ClientMessageException(clientMessage, "Tried to delete document which is not currently open"); - } -/* Document document = ScribbleshareRoom.getDatabase().getDocument(clientMessageDeleteDocument.getId()); - if (document == null) { - throw new MessageException(clientMessage, "Tried to delete document with id " + clientMessageDeleteDocument.getId() + " that does not exist"); - } - if (document.getOwner() != client.getUser().getId()) { - throw new MessageException(clientMessage, "Tried to delete document with id " + document.getId() +" which they do not own"); - } - ServerInitializer.getLogger(ctx).info("Deleting dead document " + room.getDocument()); - ScribbleshareRoom.getDatabase().deleteDocument(room.getDocument());*/ - //Room.getRoom(document); - //break;//todo better update logic - } - case UPDATE_DOCUMENT: { - ClientMessageUpdateDocument clientMessageUpdateDocument = (ClientMessageUpdateDocument) clientMessage; - if (clientMessageUpdateDocument.getName().length() > 64) { - throw new ClientMessageException(clientMessage, "Tried to change name to string that is too long (" + clientMessageUpdateDocument.getName().length() + ")"); - } - room.get().getDocument().setName(clientMessageUpdateDocument.getName()); - room.get().queueMessageExcept(new ServerMessageUpdateDocument(room.get().getDocument()), client); - RoomHttpServerInitializer.getDatabase(ctx).updateDocument(room.get().getDocument()); - break;//todo better update logic - } - case GET_INVITE: { - client.sendMessage(new ServerMessageGetInvite(RoomHttpServerInitializer.getDatabase(ctx).getInviteCode(room.get().getDocument()))); - break; - } - default: - super.message(ctx, clientMessage); - } - } - }; - - void setState(ChannelHandlerContext ctx) { - Scribbleshare.getLogger(ctx).info(this.toString()); - ClientMessageHandler.getState(ctx).set(this); - } - - public void channelInactive(ChannelHandlerContext ctx) { - //todo throw new UnsupportedOperationException("Unhandled channel close"); - } - - public void userEventTriggered(ChannelHandlerContext ctx, Object event) { - throw new UnsupportedOperationException("Unhandled Netty userEventTriggered " + event); - } - - public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) throws ClientMessageException { - throw new UnsupportedOperationException("Unhandled ClientMessage " + clientMessage.getClass().getSimpleName()); - } -} diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/State.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/State.java new file mode 100644 index 00000000..327fdf31 --- /dev/null +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/State.java @@ -0,0 +1,26 @@ +package net.stzups.scribbleshare.room.server.websocket.state; + +import io.netty.channel.ChannelHandlerContext; +import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.room.server.websocket.ClientMessageException; +import net.stzups.scribbleshare.room.server.websocket.ClientMessageHandler; +import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessage; + +public abstract class State { + public static void setState(ChannelHandlerContext ctx, State state) { + Scribbleshare.getLogger(ctx).info(state.toString()); + ClientMessageHandler.getState(ctx).set(state); + } + + public void channelInactive(ChannelHandlerContext ctx) { + //todo throw new UnsupportedOperationException("Unhandled channel close"); + } + + public void userEventTriggered(ChannelHandlerContext ctx, Object event) { + throw new UnsupportedOperationException("Unhandled Netty userEventTriggered " + event); + } + + public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) throws ClientMessageException { + throw new UnsupportedOperationException("Unhandled ClientMessage " + clientMessage.getClass().getSimpleName()); + } +} diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java new file mode 100644 index 00000000..6a010f59 --- /dev/null +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java @@ -0,0 +1,91 @@ +package net.stzups.scribbleshare.room.server.websocket.state.states; + +import io.netty.channel.ChannelHandlerContext; +import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.data.objects.Document; +import net.stzups.scribbleshare.data.objects.InviteCode; +import net.stzups.scribbleshare.data.objects.User; +import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; +import net.stzups.scribbleshare.room.server.RoomHttpServerInitializer; +import net.stzups.scribbleshare.room.server.websocket.Client; +import net.stzups.scribbleshare.room.server.websocket.ClientMessageException; +import net.stzups.scribbleshare.room.server.websocket.Room; +import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessage; +import net.stzups.scribbleshare.room.server.websocket.protocol.client.messages.ClientMessageHandshake; +import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageAddUser; +import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageHandshake; +import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageUpdateDocument; +import net.stzups.scribbleshare.room.server.websocket.state.State; + +public class HandshakeState extends State { + private final User user; + + public HandshakeState(User user) { + this.user = user; + } + + @Override + public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) throws ClientMessageException { + Room room = null;//todo + switch (clientMessage.getMessageType()) { + case HANDSHAKE: { + ClientMessageHandshake clientPacketHandshake = (ClientMessageHandshake) clientMessage; + + Scribbleshare.getLogger(ctx).info("Handshake with invite " + clientPacketHandshake.getCode() + ", " + user); + + Client client = new Client(user, ctx.channel()); + + client.queueMessage(new ServerMessageHandshake(client)); + InviteCode inviteCode = RoomHttpServerInitializer.getDatabase(ctx).getInviteCode(clientPacketHandshake.getCode()); + client.queueMessage(new ServerMessageAddUser(client.getUser())); + //figure out which document to open first + if (inviteCode != null) { + Document document = RoomHttpServerInitializer.getDatabase(ctx).getDocument(inviteCode.getDocument()); + if (document != null) { + //if this isn't the user's own document and this isn't part of the user's shared documents then add and update + if (document.getOwner() != client.getUser().getId()) { + if (client.getUser().getSharedDocuments().add(document.getId())) { + RoomHttpServerInitializer.getDatabase(ctx).updateUser(client.getUser()); + } + } + try { + room = Room.getRoom(RoomHttpServerInitializer.getDatabase(ctx), document); + } catch (DeserializationException e) { + throw new ClientMessageException(clientMessage, e); + } + } else { + throw new ClientMessageException(clientMessage, "Somehow used invite code for non existent document"); + } + } else { + if (client.getUser().getOwnedDocuments().size() == 0) { + RoomHttpServerInitializer.getDatabase(ctx).createDocument(client.getUser()); + } + } + client.getUser().getOwnedDocuments().removeIf((id) -> { + Document document = RoomHttpServerInitializer.getDatabase(ctx).getDocument(id); + if (document == null) { + return true; + } else { + client.queueMessage(new ServerMessageUpdateDocument(RoomHttpServerInitializer.getDatabase(ctx).getDocument(id))); + return false; + } + });//todo this is bad + client.getUser().getSharedDocuments().removeIf((id) -> { + Document document = RoomHttpServerInitializer.getDatabase(ctx).getDocument(id); + if (document == null) { + return true; + } else { + client.queueMessage(new ServerMessageUpdateDocument(RoomHttpServerInitializer.getDatabase(ctx).getDocument(id))); + return false; + } + }); + client.flushMessages(); + + setState(ctx, new ReadyState(client)); + break; + } + default: + super.message(ctx, clientMessage); + } + } +} diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java new file mode 100644 index 00000000..a810c83a --- /dev/null +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java @@ -0,0 +1,28 @@ +package net.stzups.scribbleshare.room.server.websocket.state.states; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.data.objects.User; +import net.stzups.scribbleshare.room.server.websocket.state.State; + +public class InitialState extends State { + private final User user; + + public InitialState(User user) { + this.user = user; + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object event) { + if (event instanceof WebSocketServerProtocolHandler.HandshakeComplete) { + Scribbleshare.getLogger(ctx).info("WebSocket connection initialized"); + setState(ctx, new HandshakeState(user)); + return; + } + + if (event instanceof WebSocketServerProtocolHandler.ServerHandshakeStateEvent) return; //deprecated but still fired + + super.userEventTriggered(ctx, event); + } +} diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java new file mode 100644 index 00000000..c6709115 --- /dev/null +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java @@ -0,0 +1,97 @@ +package net.stzups.scribbleshare.room.server.websocket.state.states; + +import io.netty.channel.ChannelHandlerContext; +import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.data.objects.Document; +import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; +import net.stzups.scribbleshare.room.server.RoomHttpServerInitializer; +import net.stzups.scribbleshare.room.server.websocket.Client; +import net.stzups.scribbleshare.room.server.websocket.ClientMessageException; +import net.stzups.scribbleshare.room.server.websocket.Room; +import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessage; +import net.stzups.scribbleshare.room.server.websocket.protocol.client.messages.ClientMessageOpenDocument; +import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageUpdateDocument; +import net.stzups.scribbleshare.room.server.websocket.state.State; + +public class ReadyState extends State { + private final Client client; + + ReadyState(Client client) { + this.client = client; + } + + @Override + public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) throws ClientMessageException { + + switch (clientMessage.getMessageType()) { + case OPEN_DOCUMENT: { + ClientMessageOpenDocument clientPacketOpenDocument = (ClientMessageOpenDocument) clientMessage; + Document document = RoomHttpServerInitializer.getDatabase(ctx).getDocument(clientPacketOpenDocument.getId()); + if (document != null) { + //open + Room room; + try { + room = Room.getRoom(RoomHttpServerInitializer.getDatabase(ctx), document); + } catch (DeserializationException e) { + throw new ClientMessageException(clientMessage, e); + } + room.addClient(client); + setState(ctx, new RoomState(client, room)); + } else { + Scribbleshare.getLogger(ctx).warning(client + " tried to open document not that does not exist"); + } + break; + } + case CREATE_DOCUMENT: { + //create + Document document = RoomHttpServerInitializer.getDatabase(ctx).createDocument(client.getUser()); + client.sendMessage(new ServerMessageUpdateDocument(document)); + //open + Room room; + try { + room = Room.getRoom(RoomHttpServerInitializer.getDatabase(ctx), document); + } catch (DeserializationException e) { + throw new ClientMessageException(clientMessage, e); + } + room.addClient(client); + setState(ctx, new RoomState(client, room)); + break; + } +/* case DELETE_DOCUMENT: { + ClientMessageDeleteDocument clientMessageDeleteDocument = (ClientMessageDeleteDocument) clientMessage; + if (clientMessageDeleteDocument.getId() == room.getDocument().getId()) { + Scribbleshare.getLogger(ctx).info("Deleting live document " + room.getDocument()); + room.sendMessage(new ServerMessageDeleteDocument(room.getDocument())); + room.end(); + RoomHttpServerInitializer.getDatabase(ctx).deleteDocument(room.getDocument()); + break; + } else { + throw new ClientMessageException(clientMessage, "Tried to delete document which is not currently open"); + } +*//* Document document = ScribbleshareRoom.getDatabase().getDocument(clientMessageDeleteDocument.getId()); + if (document == null) { + throw new MessageException(clientMessage, "Tried to delete document with id " + clientMessageDeleteDocument.getId() + " that does not exist"); + } + if (document.getOwner() != client.getUser().getId()) { + throw new MessageException(clientMessage, "Tried to delete document with id " + document.getId() +" which they do not own"); + } + ServerInitializer.getLogger(ctx).info("Deleting dead document " + room.getDocument()); + ScribbleshareRoom.getDatabase().deleteDocument(room.getDocument());*//* + //Room.getRoom(document); + //break;//todo better update logic + } + case UPDATE_DOCUMENT: { + ClientMessageUpdateDocument clientMessageUpdateDocument = (ClientMessageUpdateDocument) clientMessage; + if (clientMessageUpdateDocument.getName().length() > 64) { + throw new ClientMessageException(clientMessage, "Tried to change name to string that is too long (" + clientMessageUpdateDocument.getName().length() + ")"); + } + room.getDocument().setName(clientMessageUpdateDocument.getName()); + room.queueMessageExcept(new ServerMessageUpdateDocument(room.getDocument()), client); + RoomHttpServerInitializer.getDatabase(ctx).updateDocument(room.getDocument()); + break;//todo better update logic + }*/ + default: + super.message(ctx, clientMessage); + } + } +} diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java new file mode 100644 index 00000000..82d9ce9f --- /dev/null +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java @@ -0,0 +1,92 @@ +package net.stzups.scribbleshare.room.server.websocket.state.states; + +import io.netty.channel.ChannelHandlerContext; +import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.CanvasUpdateException; +import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.CanvasUpdates; +import net.stzups.scribbleshare.room.server.RoomHttpServerInitializer; +import net.stzups.scribbleshare.room.server.websocket.Client; +import net.stzups.scribbleshare.room.server.websocket.ClientMessageException; +import net.stzups.scribbleshare.room.server.websocket.Room; +import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessage; +import net.stzups.scribbleshare.room.server.websocket.protocol.client.messages.ClientMessageCanvasUpdate; +import net.stzups.scribbleshare.room.server.websocket.protocol.client.messages.ClientMessageDeleteDocument; +import net.stzups.scribbleshare.room.server.websocket.protocol.client.messages.ClientMessageUpdateDocument; +import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageCanvasUpdate; +import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageDeleteDocument; +import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageUpdateDocument; + +public class RoomState extends ReadyState { + private final Client client; + private final Room room; + + RoomState(Client client, Room room) { + super(client); + this.client = client; + this.room = room; + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) { + room.removeClient(client); + setState(ctx, new ReadyState(client)); + } + + @Override + public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) throws ClientMessageException { + + switch (clientMessage.getMessageType()) { + case CANVAS_UPDATE: { + CanvasUpdates[] canvasUpdates = ((ClientMessageCanvasUpdate) clientMessage).getCanvasUpdatesArray(); + try { + room.getCanvas().update(canvasUpdates); + } catch (CanvasUpdateException e) { + throw new ClientMessageException(clientMessage, e); + } + room.queueMessageExcept(new ServerMessageCanvasUpdate(canvasUpdates), client); + break; + } + case OPEN_DOCUMENT: { + room.removeClient(client); + } + case CREATE_DOCUMENT: { + room.removeClient(client); + } + case DELETE_DOCUMENT: { + ClientMessageDeleteDocument clientMessageDeleteDocument = (ClientMessageDeleteDocument) clientMessage; + if (clientMessageDeleteDocument.getId() == room.getDocument().getId()) { + Scribbleshare.getLogger(ctx).info("Deleting live document " + room.getDocument()); + room.sendMessage(new ServerMessageDeleteDocument(room.getDocument())); + room.end(); + RoomHttpServerInitializer.getDatabase(ctx).deleteDocument(room.getDocument()); + break; + } else { + throw new ClientMessageException(clientMessage, "Tried to delete document which is not currently open"); + } +/* Document document = ScribbleshareRoom.getDatabase().getDocument(clientMessageDeleteDocument.getId()); + if (document == null) { + throw new MessageException(clientMessage, "Tried to delete document with id " + clientMessageDeleteDocument.getId() + " that does not exist"); + } + if (document.getOwner() != client.getUser().getId()) { + throw new MessageException(clientMessage, "Tried to delete document with id " + document.getId() +" which they do not own"); + } + ServerInitializer.getLogger(ctx).info("Deleting dead document " + room.getDocument()); + ScribbleshareRoom.getDatabase().deleteDocument(room.getDocument());*/ + //Room.getRoom(document); + //break;//todo better update logic + } + case UPDATE_DOCUMENT: { + ClientMessageUpdateDocument clientMessageUpdateDocument = (ClientMessageUpdateDocument) clientMessage; + if (clientMessageUpdateDocument.getName().length() > 64) { + throw new ClientMessageException(clientMessage, "Tried to change name to string that is too long (" + clientMessageUpdateDocument.getName().length() + ")"); + } + room.getDocument().setName(clientMessageUpdateDocument.getName()); + room.queueMessageExcept(new ServerMessageUpdateDocument(room.getDocument()), client); + RoomHttpServerInitializer.getDatabase(ctx).updateDocument(room.getDocument()); + break;//todo better update logic + } + default: + super.message(ctx, clientMessage); + } + } +} From 8b7eed6cd41df73bc889d8ec0e662799dc5b4b16 Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 21 May 2021 21:48:28 -0400 Subject: [PATCH 033/144] add intellij build configuration --- .run/index.html.run.xml | 7 +++++++ .run/scribbleshare-backend.run.xml | 11 +++++++++++ .run/scribbleshare-postgres.run.xml | 28 ++++++++++++++++++++++++++++ .run/scribbleshare-room.run.xml | 11 +++++++++++ 4 files changed, 57 insertions(+) create mode 100644 .run/index.html.run.xml create mode 100644 .run/scribbleshare-backend.run.xml create mode 100644 .run/scribbleshare-postgres.run.xml create mode 100644 .run/scribbleshare-room.run.xml diff --git a/.run/index.html.run.xml b/.run/index.html.run.xml new file mode 100644 index 00000000..29ec033e --- /dev/null +++ b/.run/index.html.run.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.run/scribbleshare-backend.run.xml b/.run/scribbleshare-backend.run.xml new file mode 100644 index 00000000..fe2642c2 --- /dev/null +++ b/.run/scribbleshare-backend.run.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/.run/scribbleshare-postgres.run.xml b/.run/scribbleshare-postgres.run.xml new file mode 100644 index 00000000..503dac06 --- /dev/null +++ b/.run/scribbleshare-postgres.run.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.run/scribbleshare-room.run.xml b/.run/scribbleshare-room.run.xml new file mode 100644 index 00000000..a1fcf4d2 --- /dev/null +++ b/.run/scribbleshare-room.run.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file From 46ea78e80869bdc8d04f358992bb94d703701d30 Mon Sep 17 00:00:00 2001 From: stzups Date: Sat, 22 May 2021 00:17:23 -0400 Subject: [PATCH 034/144] fix dependency --- build.gradle | 7 ++ scribbleshare-commons/build.gradle | 3 +- .../ScribbleshareConfigImplementation.java | 8 +- .../stzups/scribbleshare/config/Config.java | 73 ------------------- .../scribbleshare/config/ConfigKey.java | 18 ----- .../scribbleshare/config/ConfigProvider.java | 11 --- .../config/OptionalConfigKey.java | 20 ----- .../config/RequiredConfigKey.java | 19 ----- .../config/configs/ArgumentConfig.java | 54 -------------- .../configs/EnvironmentVariableConfig.java | 18 ----- .../config/configs/PropertiesConfig.java | 41 ----------- 11 files changed, 13 insertions(+), 259 deletions(-) create mode 100644 build.gradle delete mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/Config.java delete mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/ConfigKey.java delete mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/ConfigProvider.java delete mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/OptionalConfigKey.java delete mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/RequiredConfigKey.java delete mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/ArgumentConfig.java delete mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/EnvironmentVariableConfig.java delete mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/PropertiesConfig.java diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..cd47abf4 --- /dev/null +++ b/build.gradle @@ -0,0 +1,7 @@ +allprojects { + repositories { + maven { + url "https://jitpack.io" + } + } +} \ No newline at end of file diff --git a/scribbleshare-commons/build.gradle b/scribbleshare-commons/build.gradle index 8f8a9826..fcea3974 100644 --- a/scribbleshare-commons/build.gradle +++ b/scribbleshare-commons/build.gradle @@ -10,5 +10,6 @@ dependencies { api 'io.netty:netty-all:4.1.55.Final' implementation 'org.postgresql:postgresql:42.2.13' implementation 'redis.clients:jedis:3.5.2' - implementation('at.favre.lib:bcrypt:0.9.0') + implementation 'at.favre.lib:bcrypt:0.9.0' + api 'com.github.stzups:config:master-SNAPSHOT' } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/ScribbleshareConfigImplementation.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/ScribbleshareConfigImplementation.java index 2228ff78..63eb3720 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/ScribbleshareConfigImplementation.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/ScribbleshareConfigImplementation.java @@ -1,9 +1,9 @@ package net.stzups.scribbleshare; -import net.stzups.scribbleshare.config.Config; -import net.stzups.scribbleshare.config.ConfigKey; -import net.stzups.scribbleshare.config.OptionalConfigKey; -import net.stzups.scribbleshare.config.RequiredConfigKey; +import net.stzups.config.Config; +import net.stzups.config.ConfigKey; +import net.stzups.config.OptionalConfigKey; +import net.stzups.config.RequiredConfigKey; public class ScribbleshareConfigImplementation extends Config implements ScribbleshareConfig { private static final ConfigKey NAME = new OptionalConfigKey<>("name", "Scribbleshare"); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/Config.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/Config.java deleted file mode 100644 index 14d5d752..00000000 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/Config.java +++ /dev/null @@ -1,73 +0,0 @@ -package net.stzups.scribbleshare.config; - -import java.util.ArrayList; -import java.util.List; - -/** - * Searches through provided {@link List} to find a value for a key - */ -public class Config { - private final List configProviders; - - protected Config() { - configProviders = new ArrayList<>(); - } - - public Config addConfigProvider(ConfigProvider configProvider) { - configProviders.add(configProvider); - return this; - } - - public Config removeConfigProvider(ConfigProvider configProvider) { - configProviders.remove(configProvider); - return this; - } - - /** - * Gets a String value for a String key from any config provider - */ - private String find(ConfigKey key) { - for (ConfigProvider configProvider : configProviders) { - String value = configProvider.get(key.getKey()); - if (value != null) { - return value; - } - } - - return null; - } - - protected String getString(ConfigKey key) { - String value = find(key); - if (value != null) { - return value; - } - return key.getDefaultValue(null); - } - - protected Integer getInteger(ConfigKey key) { - String value = find(key); - if (value != null) { - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - return key.getDefaultValue(e); - } - } - return key.getDefaultValue(null); - } - - protected Boolean getBoolean(ConfigKey key) { - String value = find(key); - if (value != null) { - if (value.equalsIgnoreCase("true")) { - return true; - } else if (value.equalsIgnoreCase("false")) { - return false; - } else { - return key.getDefaultValue(new IllegalArgumentException(value + " is not true or false")); - } - } - return key.getDefaultValue(null); - } -} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/ConfigKey.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/ConfigKey.java deleted file mode 100644 index 1be2d590..00000000 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/ConfigKey.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.stzups.scribbleshare.config; - -/** - * A {@link String} key that returns a value of type T - */ -public abstract class ConfigKey { - private final String key; - - protected ConfigKey(String key) { - this.key = key; - } - - final String getKey() { - return key; - } - - abstract T getDefaultValue(Exception e); -} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/ConfigProvider.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/ConfigProvider.java deleted file mode 100644 index 7cb7b46e..00000000 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/ConfigProvider.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.stzups.scribbleshare.config; - -/** - * Provides values for keys to a {@link Config} - */ -public interface ConfigProvider { - /** - * Returns a value if this {@link ConfigProvider} has the key, otherwise null - */ - String get(String key); -} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/OptionalConfigKey.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/OptionalConfigKey.java deleted file mode 100644 index ea48540e..00000000 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/OptionalConfigKey.java +++ /dev/null @@ -1,20 +0,0 @@ -package net.stzups.scribbleshare.config; - -/** - * A {@link ConfigKey} that can use a default value if no other value is found - */ -public class OptionalConfigKey extends ConfigKey { - private final T defaultValue; - - public OptionalConfigKey(String key, T defaultValue) { - super(key); - this.defaultValue = defaultValue; - } - - T getDefaultValue(Exception e) { - if (e != null) { - new Exception("Non fatal exception while parsing value for key \"" + getKey() + "\", default value will be used", e).printStackTrace(); - } - return defaultValue; - } -} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/RequiredConfigKey.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/RequiredConfigKey.java deleted file mode 100644 index 44fb32e0..00000000 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/RequiredConfigKey.java +++ /dev/null @@ -1,19 +0,0 @@ -package net.stzups.scribbleshare.config; - -/** - * A {@link ConfigKey} that must have a value, otherwise an exception is thrown - */ -public class RequiredConfigKey extends ConfigKey { - public RequiredConfigKey(String key) { - super(key); - } - - @Override - T getDefaultValue(Exception e) { - if (e != null) { - throw new IllegalArgumentException("Parsing value for required config key \"" + getKey() + "\" caused exception", e); - } else { - throw new IllegalArgumentException("Missing value for required config key \"" + getKey() + "\""); - } - } -} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/ArgumentConfig.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/ArgumentConfig.java deleted file mode 100644 index 3ba3fbf8..00000000 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/ArgumentConfig.java +++ /dev/null @@ -1,54 +0,0 @@ -package net.stzups.scribbleshare.config.configs; - -import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.config.ConfigProvider; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -/** - * Takes arguments from the console and parses them as key value pairs. - */ -public class ArgumentConfig implements ConfigProvider { - private final Map flags = new HashMap<>(); - - /** - * Format: - * --flag value - * --flag "value with space" - * Flags that are not properly formatted will be ignored. - * @param args should be take from program entry point, in the proper format - */ - public ArgumentConfig(String[] args) { - Iterator iterator = Arrays.asList(args).iterator(); - while (iterator.hasNext()) { - String raw = iterator.next(); - String[] split = raw.split("="); - if (split.length == 2) { - String value = split[1]; - if (value.startsWith("\"")) { - value = value.substring(1); - while (iterator.hasNext() && !value.endsWith("\"")) { - value += iterator.next(); - } - if (value.endsWith("\"")) { - value = value.substring(0, value.length() - 1); - } else { - Scribbleshare.getLogger().warning("Malformed argument " + raw + " and " + value + ", should be formatted --key=value or --key=\"value with spaces\""); - continue; - } - } - flags.put(split[0].substring(2), value); - } else { - Scribbleshare.getLogger().warning("Malformed argument " + raw + ", should be formatted --key=value or --key=\"value with spaces\""); - } - } - } - - @Override - public String get(String key) { - return flags.get(key); - } -} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/EnvironmentVariableConfig.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/EnvironmentVariableConfig.java deleted file mode 100644 index 5abed991..00000000 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/EnvironmentVariableConfig.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.stzups.scribbleshare.config.configs; - -import net.stzups.scribbleshare.config.ConfigProvider; - -import java.util.Objects; - -public class EnvironmentVariableConfig implements ConfigProvider { - private final String prefix; - - public EnvironmentVariableConfig(String prefix) { - this.prefix = Objects.requireNonNullElse(prefix, ""); - } - - @Override - public String get(String key) { - return System.getenv(prefix + key); - } -} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/PropertiesConfig.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/PropertiesConfig.java deleted file mode 100644 index d12e5afe..00000000 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/config/configs/PropertiesConfig.java +++ /dev/null @@ -1,41 +0,0 @@ -package net.stzups.scribbleshare.config.configs; - -import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.config.ConfigProvider; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Properties; -import java.util.logging.Level; - -/** - * Loads a file that should be formatted as a Java {@link Properties} file, and adds any values defined in that value. - * This still works if the file does not exist or no values are present in the file. - */ -public class PropertiesConfig implements ConfigProvider { - private final Properties properties; - - /** - * Loads .properties formatted file from given path, only if it exists. - * @param path path to the .properties file - */ - public PropertiesConfig(String path) { - properties = new Properties(); - File file = new File(path); - if (file.exists()) {//load user defined config if created - try (FileInputStream fileInputStream = new FileInputStream(file)) { - properties.load(fileInputStream); - } catch (IOException e) { - Scribbleshare.getLogger().log(Level.WARNING, "Failed to load " + file.getName(), e); - return; - } - Scribbleshare.getLogger().info("Loaded " + properties.size() + " config properties from " + file.getName()); - } - } - - @Override - public String get(String key) { - return properties.getProperty(key); - } -} From 768c4b4d85316671933d3d938d3ad06cb5426082 Mon Sep 17 00:00:00 2001 From: stzups Date: Sat, 22 May 2021 16:09:04 -0400 Subject: [PATCH 035/144] fix package --- .../backend/ScribbleshareBackendConfigImplementation.java | 4 ++-- .../main/java/net/stzups/scribbleshare/Scribbleshare.java | 6 +++--- .../room/ScribbleshareRoomConfigImplementation.java | 4 ++-- .../room/server/RoomHttpServerInitializer.java | 3 ++- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfigImplementation.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfigImplementation.java index 727e78a2..249252fb 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfigImplementation.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfigImplementation.java @@ -1,8 +1,8 @@ package net.stzups.scribbleshare.backend; import net.stzups.scribbleshare.ScribbleshareConfigImplementation; -import net.stzups.scribbleshare.config.ConfigKey; -import net.stzups.scribbleshare.config.OptionalConfigKey; +import net.stzups.config.ConfigKey; +import net.stzups.config.OptionalConfigKey; public class ScribbleshareBackendConfigImplementation extends ScribbleshareConfigImplementation implements ScribbleshareBackendConfig { private static final ConfigKey HTML_ROOT = new OptionalConfigKey<>("html.root", "html"); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/Scribbleshare.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/Scribbleshare.java index 2c9918e7..fec1dc36 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/Scribbleshare.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/Scribbleshare.java @@ -7,9 +7,9 @@ import net.stzups.scribbleshare.server.Server; import net.stzups.scribbleshare.server.http.HttpServerInitializer; import net.stzups.scribbleshare.util.LogFactory; -import net.stzups.scribbleshare.config.configs.ArgumentConfig; -import net.stzups.scribbleshare.config.configs.EnvironmentVariableConfig; -import net.stzups.scribbleshare.config.configs.PropertiesConfig; +import net.stzups.config.configs.ArgumentConfig; +import net.stzups.config.configs.EnvironmentVariableConfig; +import net.stzups.config.configs.PropertiesConfig; import java.util.logging.Logger; diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/ScribbleshareRoomConfigImplementation.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/ScribbleshareRoomConfigImplementation.java index c8d217b3..e9c4b335 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/ScribbleshareRoomConfigImplementation.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/ScribbleshareRoomConfigImplementation.java @@ -1,8 +1,8 @@ package net.stzups.scribbleshare.room; import net.stzups.scribbleshare.ScribbleshareConfigImplementation; -import net.stzups.scribbleshare.config.ConfigKey; -import net.stzups.scribbleshare.config.OptionalConfigKey; +import net.stzups.config.ConfigKey; +import net.stzups.config.OptionalConfigKey; public class ScribbleshareRoomConfigImplementation extends ScribbleshareConfigImplementation implements ScribbleshareRoomConfig { private static final ConfigKey WEBSOCKET_PATH = new OptionalConfigKey<>("websocket.path", "/scribblesocket"); diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java index 61792f2e..f5658cac 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java @@ -31,7 +31,7 @@ public static ScribbleshareDatabase getDatabase(ChannelHandlerContext ctx) { private final ServerMessageEncoder serverMessageEncoder = new ServerMessageEncoder(); private final ClientMessageDecoder clientMessageDecoder = new ClientMessageDecoder(); - private final ClientMessageHandler clientMessageHandler = new ClientMessageHandler(); + private final ClientMessageHandler clientMessageHandler; private final HttpAuthenticator httpAuthenticator; @@ -39,6 +39,7 @@ public RoomHttpServerInitializer(Config config, ScribbleshareDatabase database) super(config); this.config = config; this.database = database; + clientMessageHandler = new ClientMessageHandler(database); httpAuthenticator = new HttpAuthenticator(database); } From f047e8c120ab58ef0ffea566b8f8288179d68a72 Mon Sep 17 00:00:00 2001 From: stzups Date: Sat, 22 May 2021 16:52:55 -0400 Subject: [PATCH 036/144] start to add unit tests --- scribbleshare-commons/build.gradle | 7 +++ .../data/objects/canvas/CanvasTest.java | 49 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 scribbleshare-commons/src/test/java/net/stzups/scribbleshare/data/objects/canvas/CanvasTest.java diff --git a/scribbleshare-commons/build.gradle b/scribbleshare-commons/build.gradle index fcea3974..feb4dd7e 100644 --- a/scribbleshare-commons/build.gradle +++ b/scribbleshare-commons/build.gradle @@ -12,4 +12,11 @@ dependencies { implementation 'redis.clients:jedis:3.5.2' implementation 'at.favre.lib:bcrypt:0.9.0' api 'com.github.stzups:config:master-SNAPSHOT' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0' } + +test { + useJUnitPlatform() +} + diff --git a/scribbleshare-commons/src/test/java/net/stzups/scribbleshare/data/objects/canvas/CanvasTest.java b/scribbleshare-commons/src/test/java/net/stzups/scribbleshare/data/objects/canvas/CanvasTest.java new file mode 100644 index 00000000..d765a791 --- /dev/null +++ b/scribbleshare-commons/src/test/java/net/stzups/scribbleshare/data/objects/canvas/CanvasTest.java @@ -0,0 +1,49 @@ +package net.stzups.scribbleshare.data.objects.canvas; + +import static org.junit.jupiter.api.Assertions.*; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; +import org.junit.jupiter.api.Test; + +public class CanvasTest { + @Test + public void serializeEmpty() throws DeserializationException { + Canvas canvas = new Canvas(); + + ByteBuf byteBuf = Unpooled.buffer(); + canvas.serialize(byteBuf); + + Canvas c; + c = new Canvas(byteBuf); + byteBuf.release(); + + assertEquals(canvas.getCanvasObjects(), c.getCanvasObjects()); + } + + private static final int MULTIPLE_AMOUNT = 20; + + @Test + public void serializeEmptyMultiple() throws DeserializationException { + Canvas[] canvases = new Canvas[MULTIPLE_AMOUNT]; + for (int i = 0; i < canvases.length; i++) { + canvases[i] = new Canvas(); + } + + ByteBuf byteBuf = Unpooled.buffer(); + byteBuf.writeInt(canvases.length); + for (Canvas canvas : canvases) { + canvas.serialize(byteBuf); + } + + Canvas[] c = new Canvas[byteBuf.readInt()]; + for (int i = 0; i < c.length; i++) { + c[i] = new Canvas(byteBuf); + } + + assertEquals(canvases.length, c.length); + for (int i = 0; i < c.length; i++) { + assertEquals(canvases[i].getCanvasObjects(), c[i].getCanvasObjects()); + } + } +} From a2c63341426429397066a3b88fb0df387cafaf4c Mon Sep 17 00:00:00 2001 From: stzups Date: Sat, 22 May 2021 16:58:00 -0400 Subject: [PATCH 037/144] add equals --- .../scribbleshare/data/objects/canvas/Canvas.java | 10 ++++++++++ .../scribbleshare/data/objects/canvas/CanvasTest.java | 9 +++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/Canvas.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/Canvas.java index 253db879..8c59a9f3 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/Canvas.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/Canvas.java @@ -83,6 +83,16 @@ public void serialize(ByteBuf byteBuf) { } } + @Override + public boolean equals(Object object) { + if (!(object instanceof Canvas)) { + return false; + } + + Canvas canvas = (Canvas) object; + return canvas.canvasObjects.equals(canvasObjects); + } + @Override public String toString() { return "Canvas{canvasObjects=" + canvasObjects.size() + "}"; diff --git a/scribbleshare-commons/src/test/java/net/stzups/scribbleshare/data/objects/canvas/CanvasTest.java b/scribbleshare-commons/src/test/java/net/stzups/scribbleshare/data/objects/canvas/CanvasTest.java index d765a791..30b11c47 100644 --- a/scribbleshare-commons/src/test/java/net/stzups/scribbleshare/data/objects/canvas/CanvasTest.java +++ b/scribbleshare-commons/src/test/java/net/stzups/scribbleshare/data/objects/canvas/CanvasTest.java @@ -18,10 +18,10 @@ public void serializeEmpty() throws DeserializationException { c = new Canvas(byteBuf); byteBuf.release(); - assertEquals(canvas.getCanvasObjects(), c.getCanvasObjects()); + assertEquals(canvas, c); } - private static final int MULTIPLE_AMOUNT = 20; + private static final int MULTIPLE_AMOUNT = 5; @Test public void serializeEmptyMultiple() throws DeserializationException { @@ -41,9 +41,6 @@ public void serializeEmptyMultiple() throws DeserializationException { c[i] = new Canvas(byteBuf); } - assertEquals(canvases.length, c.length); - for (int i = 0; i < c.length; i++) { - assertEquals(canvases[i].getCanvasObjects(), c[i].getCanvasObjects()); - } + assertArrayEquals(canvases, c); } } From 91cfab350b52b1f30c08a8a419cffa69fa91e5ab Mon Sep 17 00:00:00 2001 From: stzups Date: Sat, 22 May 2021 17:04:40 -0400 Subject: [PATCH 038/144] remove unused method --- .../data/objects/canvas/canvasObject/canvasObjects/Line.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/Line.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/Line.java index fb9d0f4e..ab60f854 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/Line.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/Line.java @@ -17,11 +17,6 @@ private Point(ByteBuf byteBuf) { this.y = byteBuf.readShort(); } - public Point(short x, short y) { - this.x = x; - this.y = y; - } - private void serialize(ByteBuf byteBuf) { byteBuf.writeShort(x); byteBuf.writeShort(y); From cf60b903d575e39eb06484a17c6a5da749bf2ea7 Mon Sep 17 00:00:00 2001 From: stzups Date: Sat, 22 May 2021 17:45:28 -0400 Subject: [PATCH 039/144] add jmh --- scribbleshare-commons/build.gradle | 16 +++++++ .../src/jmh/java/canvas/CanvasBenchmark.java | 43 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 scribbleshare-commons/src/jmh/java/canvas/CanvasBenchmark.java diff --git a/scribbleshare-commons/build.gradle b/scribbleshare-commons/build.gradle index feb4dd7e..1afb16e6 100644 --- a/scribbleshare-commons/build.gradle +++ b/scribbleshare-commons/build.gradle @@ -6,17 +6,33 @@ repositories { mavenCentral() } +sourceSets { + jmh { + compileClasspath += sourceSets.test.runtimeClasspath + runtimeClasspath += sourceSets.test.runtimeClasspath + } +} + dependencies { api 'io.netty:netty-all:4.1.55.Final' implementation 'org.postgresql:postgresql:42.2.13' implementation 'redis.clients:jedis:3.5.2' implementation 'at.favre.lib:bcrypt:0.9.0' api 'com.github.stzups:config:master-SNAPSHOT' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0' + + jmhCompile project + jmhCompile 'org.openjdk.jmh:jmh-core:1.18' + jmhAnnotationProcessor 'org.openjdk.jmh:jmh-generator-annprocess:1.18' } test { useJUnitPlatform() } +task jmh(type: JavaExec, description: 'Executing JMH benchmarks') { + classpath = sourceSets.jmh.runtimeClasspath + main = 'org.openjdk.jmh.Main' +} \ No newline at end of file diff --git a/scribbleshare-commons/src/jmh/java/canvas/CanvasBenchmark.java b/scribbleshare-commons/src/jmh/java/canvas/CanvasBenchmark.java new file mode 100644 index 00000000..bf88b039 --- /dev/null +++ b/scribbleshare-commons/src/jmh/java/canvas/CanvasBenchmark.java @@ -0,0 +1,43 @@ +package canvas; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import net.stzups.scribbleshare.data.objects.canvas.Canvas; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; + +@Fork(1) +@Warmup(iterations = 3) +@Measurement(iterations = 3) +public class CanvasBenchmark { + @org.openjdk.jmh.annotations.State(Scope.Benchmark) + public static class State { + ByteBuf byteBuf; + Canvas canvas; + + @Setup + public void setup() { + byteBuf = Unpooled.buffer(); + + canvas = new Canvas(); + canvas.serialize(byteBuf); + byteBuf.resetReaderIndex(); + byteBuf.resetWriterIndex(); + } + + @TearDown + public void teardown() { + byteBuf.release(); + } + } + + @Benchmark + public void serialize(State state) { + state.canvas.serialize(state.byteBuf); + } +} From 8dfdc2fc73a4e229e9a42b724848d81b3433857d Mon Sep 17 00:00:00 2001 From: stzups Date: Sat, 22 May 2021 17:55:47 -0400 Subject: [PATCH 040/144] rework gradle files --- build.gradle | 1 + jmh.gradle | 17 +++++++++++ .../scribbleshare-backend/build.gradle | 4 --- scribbleshare-commons/build.gradle | 28 ++----------------- scribbleshare-room/build.gradle | 4 +-- .../ClientMessageCanvasUpdateTest.java | 17 +++++++++++ .../ServerMessageCanvasUpdateTest.java | 15 ++++++++++ test.gradle | 8 ++++++ 8 files changed, 61 insertions(+), 33 deletions(-) create mode 100644 jmh.gradle create mode 100644 scribbleshare-room/src/test/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageCanvasUpdateTest.java create mode 100644 scribbleshare-room/src/test/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/message/ServerMessageCanvasUpdateTest.java create mode 100644 test.gradle diff --git a/build.gradle b/build.gradle index cd47abf4..015732a6 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,6 @@ allprojects { repositories { + mavenCentral() maven { url "https://jitpack.io" } diff --git a/jmh.gradle b/jmh.gradle new file mode 100644 index 00000000..fc7ffd67 --- /dev/null +++ b/jmh.gradle @@ -0,0 +1,17 @@ +sourceSets { + jmh { + compileClasspath += sourceSets.test.runtimeClasspath + runtimeClasspath += sourceSets.test.runtimeClasspath + } +} + +dependencies { + jmhCompile project + jmhCompile 'org.openjdk.jmh:jmh-core:1.18' + jmhAnnotationProcessor 'org.openjdk.jmh:jmh-generator-annprocess:1.18' +} + +task jmh(type: JavaExec, description: 'Executing JMH benchmarks') { + classpath = sourceSets.jmh.runtimeClasspath + main = 'org.openjdk.jmh.Main' +} \ No newline at end of file diff --git a/scribbleshare-app/scribbleshare-backend/build.gradle b/scribbleshare-app/scribbleshare-backend/build.gradle index daa7acd7..be083f1f 100644 --- a/scribbleshare-app/scribbleshare-backend/build.gradle +++ b/scribbleshare-app/scribbleshare-backend/build.gradle @@ -3,10 +3,6 @@ plugins { id 'com.github.johnrengelman.shadow' version '6.1.0' } -repositories { - mavenCentral() -} - dependencies { implementation project(':scribbleshare-commons') } diff --git a/scribbleshare-commons/build.gradle b/scribbleshare-commons/build.gradle index 1afb16e6..4fe867f7 100644 --- a/scribbleshare-commons/build.gradle +++ b/scribbleshare-commons/build.gradle @@ -2,16 +2,8 @@ plugins { id 'java-library' } -repositories { - mavenCentral() -} - -sourceSets { - jmh { - compileClasspath += sourceSets.test.runtimeClasspath - runtimeClasspath += sourceSets.test.runtimeClasspath - } -} +apply from: rootProject.file('test.gradle') +apply from: rootProject.file('jmh.gradle') dependencies { api 'io.netty:netty-all:4.1.55.Final' @@ -19,20 +11,4 @@ dependencies { implementation 'redis.clients:jedis:3.5.2' implementation 'at.favre.lib:bcrypt:0.9.0' api 'com.github.stzups:config:master-SNAPSHOT' - - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0' - - jmhCompile project - jmhCompile 'org.openjdk.jmh:jmh-core:1.18' - jmhAnnotationProcessor 'org.openjdk.jmh:jmh-generator-annprocess:1.18' -} - -test { - useJUnitPlatform() -} - -task jmh(type: JavaExec, description: 'Executing JMH benchmarks') { - classpath = sourceSets.jmh.runtimeClasspath - main = 'org.openjdk.jmh.Main' } \ No newline at end of file diff --git a/scribbleshare-room/build.gradle b/scribbleshare-room/build.gradle index 1b460726..2d05155b 100644 --- a/scribbleshare-room/build.gradle +++ b/scribbleshare-room/build.gradle @@ -3,9 +3,7 @@ plugins { id 'com.github.johnrengelman.shadow' version '6.1.0' } -repositories { - mavenCentral() -} +apply from: rootProject.file('test.gradle') dependencies { implementation project(':scribbleshare-commons') diff --git a/scribbleshare-room/src/test/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageCanvasUpdateTest.java b/scribbleshare-room/src/test/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageCanvasUpdateTest.java new file mode 100644 index 00000000..e78f565a --- /dev/null +++ b/scribbleshare-room/src/test/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageCanvasUpdateTest.java @@ -0,0 +1,17 @@ +package net.stzups.scribbleshare.room.server.websocket.protocol.client.messages; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class ClientMessageCanvasUpdateTest { + private ClientMessageCanvasUpdate clientMessageCanvasUpdate; + + @BeforeEach + public void init() { + + } + @Test + public void test() { + + } +} diff --git a/scribbleshare-room/src/test/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/message/ServerMessageCanvasUpdateTest.java b/scribbleshare-room/src/test/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/message/ServerMessageCanvasUpdateTest.java new file mode 100644 index 00000000..92246b58 --- /dev/null +++ b/scribbleshare-room/src/test/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/message/ServerMessageCanvasUpdateTest.java @@ -0,0 +1,15 @@ +package net.stzups.scribbleshare.room.server.websocket.protocol.server.message; + +import static org.junit.jupiter.api.Assertions.*; + +import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.CanvasUpdates; +import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageCanvasUpdate; +import org.junit.jupiter.api.Test; + +public class ServerMessageCanvasUpdateTest { + + @Test + public void test() { + ServerMessageCanvasUpdate serverMessageCanvasUpdate = new ServerMessageCanvasUpdate(new CanvasUpdates[0]); + } +} diff --git a/test.gradle b/test.gradle new file mode 100644 index 00000000..86d42f50 --- /dev/null +++ b/test.gradle @@ -0,0 +1,8 @@ +dependencies { + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0' +} + +test { + useJUnitPlatform() +} From c7e8f1a12749361805750e93ffecfd77d7f3500b Mon Sep 17 00:00:00 2001 From: stzups Date: Sat, 22 May 2021 17:59:38 -0400 Subject: [PATCH 041/144] move extra gradle stuff --- .gitignore | 10 ++++++---- jmh.gradle => gradle/jmh.gradle | 0 test.gradle => gradle/test.gradle | 0 scribbleshare-commons/build.gradle | 4 ++-- scribbleshare-room/build.gradle | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) rename jmh.gradle => gradle/jmh.gradle (100%) rename test.gradle => gradle/test.gradle (100%) diff --git a/.gitignore b/.gitignore index c3251931..5f722e9e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,13 @@ +build + +# IntelliJ IDEA .idea # Gradle .gradle -build + # Gradle binaries -# These are not needed for building the project with Docker -# These would be needed to build the projct without Docker, so instead just install Gradle on your system -gradle +# just install gradle lol +gradle/wrapper gradlew gradlew.bat \ No newline at end of file diff --git a/jmh.gradle b/gradle/jmh.gradle similarity index 100% rename from jmh.gradle rename to gradle/jmh.gradle diff --git a/test.gradle b/gradle/test.gradle similarity index 100% rename from test.gradle rename to gradle/test.gradle diff --git a/scribbleshare-commons/build.gradle b/scribbleshare-commons/build.gradle index 4fe867f7..454a11cb 100644 --- a/scribbleshare-commons/build.gradle +++ b/scribbleshare-commons/build.gradle @@ -2,8 +2,8 @@ plugins { id 'java-library' } -apply from: rootProject.file('test.gradle') -apply from: rootProject.file('jmh.gradle') +apply from: rootProject.file('gradle/test.gradle') +apply from: rootProject.file('gradle/jmh.gradle') dependencies { api 'io.netty:netty-all:4.1.55.Final' diff --git a/scribbleshare-room/build.gradle b/scribbleshare-room/build.gradle index 2d05155b..8ed21f4a 100644 --- a/scribbleshare-room/build.gradle +++ b/scribbleshare-room/build.gradle @@ -3,7 +3,7 @@ plugins { id 'com.github.johnrengelman.shadow' version '6.1.0' } -apply from: rootProject.file('test.gradle') +apply from: rootProject.file('gradle/test.gradle') dependencies { implementation project(':scribbleshare-commons') From e391b11c78c0b22b036cf74e36d4f5aa49cd3266 Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 14:21:40 -0400 Subject: [PATCH 042/144] remove --- .run/index.html.run.xml | 7 ------- .run/scribbleshare-backend.run.xml | 11 ----------- .run/scribbleshare-postgres.run.xml | 28 ---------------------------- .run/scribbleshare-room.run.xml | 11 ----------- 4 files changed, 57 deletions(-) delete mode 100644 .run/index.html.run.xml delete mode 100644 .run/scribbleshare-backend.run.xml delete mode 100644 .run/scribbleshare-postgres.run.xml delete mode 100644 .run/scribbleshare-room.run.xml diff --git a/.run/index.html.run.xml b/.run/index.html.run.xml deleted file mode 100644 index 29ec033e..00000000 --- a/.run/index.html.run.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.run/scribbleshare-backend.run.xml b/.run/scribbleshare-backend.run.xml deleted file mode 100644 index fe2642c2..00000000 --- a/.run/scribbleshare-backend.run.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - \ No newline at end of file diff --git a/.run/scribbleshare-postgres.run.xml b/.run/scribbleshare-postgres.run.xml deleted file mode 100644 index 503dac06..00000000 --- a/.run/scribbleshare-postgres.run.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/.run/scribbleshare-room.run.xml b/.run/scribbleshare-room.run.xml deleted file mode 100644 index a1fcf4d2..00000000 --- a/.run/scribbleshare-room.run.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - \ No newline at end of file From c9b652fc89389eed38d3eead7b3d24d4b11fd173 Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 14:46:08 -0400 Subject: [PATCH 043/144] duplicate registration usernames are handled --- .../backend/server/http/HttpServerHandler.java | 10 ++++++---- .../data/database/ScribbleshareDatabase.java | 3 ++- .../database/implementations/PostgresDatabase.java | 6 ++++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index a462080f..58bab5ac 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -336,8 +336,6 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr return; } - //todo check for existing username and user with username - User user; HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); if (cookie != null) { @@ -353,9 +351,13 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr database.addUser(user); } Login login = new Login(user, password.getBytes(StandardCharsets.UTF_8)); - database.addLogin(login); + if (!database.addLogin(login)) { + Scribbleshare.getLogger(ctx).info("Tried to register with duplicate username " + username); + sendRedirect(ctx, request, REGISTER_PAGE); + return; + } - System.out.println(username + ", register " + password); + Scribbleshare.getLogger(ctx).info("Registered with username " + username); sendRedirect(ctx, request, REGISTER_SUCCESS); return; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java index 4a268786..86dcf7f6 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java @@ -21,5 +21,6 @@ public interface ScribbleshareDatabase extends PersistentHttpSessionDatabase, Re InviteCode getInviteCode(String code); InviteCode getInviteCode(Document document); Login getLogin(String username); - void addLogin(Login login); + /** false if the username already existed */ + boolean addLogin(Login login); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index 35b97a5d..32ec3dd4 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -49,15 +49,17 @@ public Login getLogin(String username) { } @Override - public void addLogin(Login login) { + public boolean addLogin(Login login) { try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO logins(username, user_id, hashed_password) VALUES(?, ?, ?)")) { preparedStatement.setString(1, login.getUsername()); preparedStatement.setLong(2, login.getId()); preparedStatement.setBinaryStream(3, new ByteArrayInputStream(login.getHashedPassword())); preparedStatement.execute(); } catch (SQLException e) { - e.printStackTrace();//todo error handling + return false; } + + return true; } public interface Config { From da4ecc67331bf80ef9cee9a9b121bae4a6faf71d Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 15:03:33 -0400 Subject: [PATCH 044/144] start to rework exceptions --- .../server/http/BadRequestException.java | 7 ++ .../backend/server/http/Form.java | 26 ++++++ .../server/http/HttpServerHandler.java | 90 ++++++++----------- 3 files changed, 70 insertions(+), 53 deletions(-) create mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/BadRequestException.java create mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/Form.java diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/BadRequestException.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/BadRequestException.java new file mode 100644 index 00000000..59b8e3a4 --- /dev/null +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/BadRequestException.java @@ -0,0 +1,7 @@ +package net.stzups.scribbleshare.backend.server.http; + +public class BadRequestException extends Exception { + public BadRequestException(String message) { + super(message); + } +} diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/Form.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/Form.java new file mode 100644 index 00000000..b2af1c95 --- /dev/null +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/Form.java @@ -0,0 +1,26 @@ +package net.stzups.scribbleshare.backend.server.http; + +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpHeaderValues; + +import java.nio.charset.StandardCharsets; +import java.util.Map; + +public class Form { + private final Map form; + + public Form(FullHttpRequest request) throws BadRequestException { + String contentType = request.headers().get(HttpHeaderNames.CONTENT_TYPE); + + if (contentType == null) + throw new BadRequestException("Missing " + HttpHeaderNames.CONTENT_TYPE + " header"); + + if (!contentType.contentEquals(HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED)) + throw new BadRequestException(HttpHeaderNames.CONTENT_TYPE + " header is not " + HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED); + + //todo check host/origin/referer to make sure they originate from LOGIN_PAGE + + this.form = HttpServerHandler.parseQuery(request.content().toString(StandardCharsets.UTF_8)); + } +} diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 58bab5ac..e987a563 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -119,33 +119,23 @@ public HttpServerHandler(Config config, ScribbleshareDatabase database) { } @Override - public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { + public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) { Scribbleshare.getLogger(ctx).info(request.method() + " " + request.uri()); - // sanitize uri - final String uri = getUri(request.uri()); - if (uri == null) { - send(ctx, request, HttpResponseStatus.NOT_FOUND); - return; - } - - // split query from path - final String[] splitQuery = splitQuery(uri); - if (splitQuery == null) { - send(ctx, request, HttpResponseStatus.NOT_FOUND); - return; - } - final String path = splitQuery[0]; - final String rawQuery = splitQuery[1]; - - Map queries = parseQuery(rawQuery); - if (queries == null) { - send(ctx, request, HttpResponseStatus.NOT_FOUND); - return; - } - - String[] route = getRoute(path); - if (route == null) { + final String uri; + final String[] splitQuery; + final String path; + final String rawQuery; + Map queries; + String[] route; + try { + uri = getUri(request.uri()); + splitQuery = splitQuery(uri); + path = splitQuery[0]; + rawQuery = splitQuery[1]; + queries = parseQuery(rawQuery); + route = getRoute(path); + } catch (BadRequestException e) { send(ctx, request, HttpResponseStatus.NOT_FOUND); return; } @@ -535,14 +525,19 @@ private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders header private static final Pattern ALLOWED_CHARACTERS = Pattern.compile("^[/." + QUERY_REGEX + FILE_NAME_REGEX + "]+$"); /** Sanitizes uri */ - public static String getUri(String uri) { - return (ALLOWED_CHARACTERS.matcher(uri).matches()) ? uri : null; + public static String getUri(String uri) throws BadRequestException { + if (!ALLOWED_CHARACTERS.matcher(uri).matches()) + throw new BadRequestException("URI contains illegal characters"); + + return uri; } private static final Pattern ALLOWED_PATH = Pattern.compile("^[\\\\" + File.separator + "." + FILE_NAME_REGEX + "]+$"); - private static String[] getRoute(String path) { - if (!path.startsWith("/")) return null; + private static String[] getRoute(String path) throws BadRequestException { + if (!path.startsWith("/")) + throw new BadRequestException("Route must start with a /"); + String[] route = path.substring(1).split("/"); if (route.length == 0) { return new String[] {""}; @@ -552,7 +547,7 @@ private static String[] getRoute(String path) { } /** Converts uri to filesystem path */ - private static String getFilePath(String path) { + private static String getFilePath(String path) throws BadRequestException { path = path.replace("/", File.separator); if (path.contains(File.separator + '.') // /. @@ -560,9 +555,8 @@ private static String getFilePath(String path) { || path.contains(File.separator + File.separator) // // || path.charAt(0) == '.' // . || path.charAt(path.length() - 1) == '.' // /page. - || !ALLOWED_PATH.matcher(path).matches()) { - return null; - } + || !ALLOWED_PATH.matcher(path).matches()) + throw new BadRequestException("File path contains illegal characters"); if (path.endsWith(File.separator)) { // / -> index.html path = path + DEFAULT_FILE; @@ -578,16 +572,16 @@ private static String getFilePath(String path) { * Example: * /index.html?key=value&otherKey=otherValue -> [ /index.html, key=value&otherKey=otherValue ] */ - public static String[] splitQuery(String uri) { + public static String[] splitQuery(String uri) throws BadRequestException { int index = uri.lastIndexOf(QUERY_DELIMITER); if (index <= 0) { // check for a query - if (uri.contains(QUERY_SEPARATOR) || uri.contains(QUERY_PAIR_SEPARATOR)) { // there is no query, so there should also be no other reserved keywords - return null; + if (uri.contains(QUERY_SEPARATOR) || uri.contains(QUERY_PAIR_SEPARATOR)) { + throw new BadRequestException("Empty query contains illegal characters"); } else { return new String[] {uri, ""}; } - } else if (uri.indexOf(QUERY_DELIMITER) != index) { // make sure there is only one ? in the uri - return null; + } else if (uri.indexOf(QUERY_DELIMITER) != index) { + throw new BadRequestException("Encountered multiple " + QUERY_DELIMITER + " in uri, there should only be one"); } else { return new String[] {uri.substring(0, index), uri.substring(index + 1)}; } @@ -596,8 +590,9 @@ public static String[] splitQuery(String uri) { /** * Parses key=value&otherKey=otherValue&keyWithEmptyValue to a Map of key-value pairs */ - public static Map parseQuery(String query) { - if (query.isEmpty()) return Collections.emptyMap(); // no query to parse + public static Map parseQuery(String query) throws BadRequestException { + if (query.isEmpty()) + return Collections.emptyMap(); // no query to parse Map queries = new HashMap<>(); String[] keyValuePairs = query.split(QUERY_SEPARATOR); @@ -605,8 +600,8 @@ public static Map parseQuery(String query) { String[] split = keyValuePair.split(QUERY_PAIR_SEPARATOR, 3); // a limit of 2 (expected) would not detect malformed queries such as ?key==, so we need to go one more if (split.length == 1) { // key with no value, such as ?key queries.put(split[0], ""); - } else if (split.length != 2) { // malformed, each key should have one value - return null; + } else if (split.length != 2) { + throw new BadRequestException("Each key should have one value of query " + query); } else { queries.put(split[0], split[1]); } @@ -614,15 +609,4 @@ public static Map parseQuery(String query) { return queries; } - - public static Map parseForm(FullHttpRequest request) { - String contentType = request.headers().get(HttpHeaderNames.CONTENT_TYPE); - if (contentType == null || !contentType.contentEquals(HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED)) { - return null; - } - - //todo check host/origin/referer to make sure they originate from LOGIN_PAGE - - return parseQuery(request.content().toString(StandardCharsets.UTF_8)); - } } \ No newline at end of file From 1931c647573ac14503cd9f797f5ccadbd37b1e04 Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 15:12:16 -0400 Subject: [PATCH 045/144] rework form --- .../backend/server/http/Form.java | 20 ++ .../server/http/HttpServerHandler.java | 211 ++++++++---------- 2 files changed, 110 insertions(+), 121 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/Form.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/Form.java index b2af1c95..3ef687d0 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/Form.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/Form.java @@ -23,4 +23,24 @@ public Form(FullHttpRequest request) throws BadRequestException { this.form = HttpServerHandler.parseQuery(request.content().toString(StandardCharsets.UTF_8)); } + + public String getText(String field) throws BadRequestException { + String value = form.get(field); + if (value == null) { + throw new BadRequestException("Missing value for " + field); + } + + return value; + } + + public boolean getCheckbox(String field) throws BadRequestException { + String value = form.get(field); + if (value == null) { //http forms don't include false + return false; + } else if (value.equals("on")) { + return true; + } else { + throw new BadRequestException("Malformed value for " + field); + } + } } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index e987a563..af74e4da 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -8,7 +8,6 @@ import io.netty.handler.codec.http.DefaultHttpHeaders; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpHeaderValues; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpRequest; @@ -243,159 +242,129 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) { //login - if (request.method().equals(HttpMethod.POST)) { - //todo validate for extra fields that should not happen - if (uri.equals(LOGIN_PATH)) { - Map form = parseForm(request); - if (form == null) { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); - return; - } + try { + if (request.method().equals(HttpMethod.POST)) { + //todo validate for extra fields that should not happen + if (uri.equals(LOGIN_PATH)) { + Form form = new Form(request); - // validate + String username = form.getText("username"); + String password = form.getText("password"); + boolean remember = form.getCheckbox("remember"); - String username = form.get("username"); - String password = form.get("password"); - if (username == null || password == null) { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); - return; - } + System.out.println(username + ", " + password + ", " + remember); - String rememberRaw = form.get("remember"); - boolean remember; - if (rememberRaw != null) { - if (rememberRaw.equals("on")) { - remember = true; - } else { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); + Login login = database.getLogin(username); + Long id = Login.verify(login, password.getBytes(StandardCharsets.UTF_8)); + if (id == null) { + //todo rate limit and generic error handling + if (login == null) { + Scribbleshare.getLogger(ctx).info("Bad username " + username); + } else { + Scribbleshare.getLogger(ctx).info("Bad password for username " + username); + } + + sendRedirect(ctx, request, LOGIN_PAGE); return; } - } else { - remember = false; - } - - System.out.println(username + ", " + password + ", " + remember); - - Login login = database.getLogin(username); - Long id = Login.verify(login, password.getBytes(StandardCharsets.UTF_8)); - if (id == null) { - //todo rate limit and generic error handling - if (login == null) { - Scribbleshare.getLogger(ctx).info("Bad username " + username); - } else { - Scribbleshare.getLogger(ctx).info("Bad password for username " + username); + HttpHeaders httpHeaders = new DefaultHttpHeaders(); + HttpUserSession userSession = new HttpUserSession(config, database.getUser(login.getId()), httpHeaders); + database.addHttpSession(userSession); + if (remember) { + PersistentHttpUserSession persistentHttpUserSession = new PersistentHttpUserSession(config, userSession, httpHeaders); + database.addPersistentHttpUserSession(persistentHttpUserSession); } - - sendRedirect(ctx, request, LOGIN_PAGE); + sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); return; - } + } else if (uri.equals(REGISTER_PATH)) { + Form form = new Form(request); - HttpHeaders httpHeaders = new DefaultHttpHeaders(); - HttpUserSession userSession = new HttpUserSession(config, database.getUser(login.getId()), httpHeaders); - database.addHttpSession(userSession); - if (remember) { - PersistentHttpUserSession persistentHttpUserSession = new PersistentHttpUserSession(config, userSession, httpHeaders); - database.addPersistentHttpUserSession(persistentHttpUserSession); - } - sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); - return; - } else if (uri.equals(REGISTER_PATH)) { - Map form = parseForm(request); - if (form == null) { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); - return; - } + // validate - // validate + String username = form.getText("username"); + String password = form.getText("password"); - String username = form.get("username"); - String password = form.get("password"); + //todo validate + if (false) { + //todo rate limit and generic error handling - if (username == null || password == null) { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); - return; - } - - //todo validate - if (false) { - //todo rate limit and generic error handling - - sendRedirect(ctx, request, REGISTER_PAGE); - return; - } + sendRedirect(ctx, request, REGISTER_PAGE); + return; + } - User user; - HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); - if (cookie != null) { - HttpUserSession httpSession = database.getHttpSession(cookie); - if (httpSession != null) { - user = database.getUser(httpSession.getUser()); + User user; + HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); + if (cookie != null) { + HttpUserSession httpSession = database.getHttpSession(cookie); + if (httpSession != null) { + user = database.getUser(httpSession.getUser()); + } else { + user = new User(username); + database.addUser(user); + } } else { user = new User(username); database.addUser(user); } - } else { - user = new User(username); - database.addUser(user); - } - Login login = new Login(user, password.getBytes(StandardCharsets.UTF_8)); - if (!database.addLogin(login)) { - Scribbleshare.getLogger(ctx).info("Tried to register with duplicate username " + username); - sendRedirect(ctx, request, REGISTER_PAGE); - return; - } + Login login = new Login(user, password.getBytes(StandardCharsets.UTF_8)); + if (!database.addLogin(login)) { + Scribbleshare.getLogger(ctx).info("Tried to register with duplicate username " + username); + sendRedirect(ctx, request, REGISTER_PAGE); + return; + } - Scribbleshare.getLogger(ctx).info("Registered with username " + username); + Scribbleshare.getLogger(ctx).info("Registered with username " + username); - sendRedirect(ctx, request, REGISTER_SUCCESS); - return; - } else if (uri.equals(LOGOUT_PAGE)) { - Map form = parseForm(request); - if (form == null) { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); + sendRedirect(ctx, request, REGISTER_SUCCESS); return; - } - - HttpHeaders headers = new DefaultHttpHeaders(); - HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); - if (cookie != null) { - HttpUserSession httpUserSession = database.getHttpSession(cookie); - if (httpUserSession != null) { - if (httpUserSession.validate(cookie)) { - database.expireHttpSession(httpUserSession); - httpUserSession.clearCookie(config, headers); + } else if (uri.equals(LOGOUT_PAGE)) { + Form form = new Form(request);//todo necessary? + + HttpHeaders headers = new DefaultHttpHeaders(); + HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); + if (cookie != null) { + HttpUserSession httpUserSession = database.getHttpSession(cookie); + if (httpUserSession != null) { + if (httpUserSession.validate(cookie)) { + database.expireHttpSession(httpUserSession); + httpUserSession.clearCookie(config, headers); + } else { + Scribbleshare.getLogger(ctx).warning("Tried to log out of existing session with bad authentication"); + } } else { - Scribbleshare.getLogger(ctx).warning("Tried to log out of existing session with bad authentication"); + Scribbleshare.getLogger(ctx).warning("Tried to log out of non existent session"); } - } else { - Scribbleshare.getLogger(ctx).warning("Tried to log out of non existent session"); } - } - HttpSessionCookie persistentCookie = HttpSessionCookie.getHttpSessionCookie(request, PersistentHttpUserSession.COOKIE_NAME); - if (persistentCookie != null) { - PersistentHttpUserSession persistentHttpUserSession = database.getPersistentHttpUserSession(persistentCookie); - if (persistentHttpUserSession != null) { - if (persistentHttpUserSession.validate(persistentCookie)) { - database.expirePersistentHttpUserSession(persistentHttpUserSession); - persistentHttpUserSession.clearCookie(config, headers); + HttpSessionCookie persistentCookie = HttpSessionCookie.getHttpSessionCookie(request, PersistentHttpUserSession.COOKIE_NAME); + if (persistentCookie != null) { + PersistentHttpUserSession persistentHttpUserSession = database.getPersistentHttpUserSession(persistentCookie); + if (persistentHttpUserSession != null) { + if (persistentHttpUserSession.validate(persistentCookie)) { + database.expirePersistentHttpUserSession(persistentHttpUserSession); + persistentHttpUserSession.clearCookie(config, headers); + } else { + Scribbleshare.getLogger(ctx).warning("Tried to log out of existing persistent session with bad authentication"); + //todo error + } } else { - Scribbleshare.getLogger(ctx).warning("Tried to log out of existing persistent session with bad authentication"); + Scribbleshare.getLogger(ctx).warning("Tried to log out of non existent persistent session"); //todo error } - } else { - Scribbleshare.getLogger(ctx).warning("Tried to log out of non existent persistent session"); - //todo error } - } - sendRedirect(ctx, request, headers, LOGOUT_SUCCESS); - return; + sendRedirect(ctx, request, headers, LOGOUT_SUCCESS); + return; + } } + } catch (BadRequestException e) { + send(ctx, request, HttpResponseStatus.BAD_REQUEST); + return; } + // otherwise try to serve a regular HTTP file resource if (!HttpMethod.GET.equals(request.method())) { From eb258cd82e70c4e74a23d493f3cbdab4ed9e51d1 Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 15:21:21 -0400 Subject: [PATCH 046/144] exceptions are printed to console --- .../backend/server/http/HttpServerHandler.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index af74e4da..ed3202e8 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -33,6 +33,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.logging.Level; import java.util.regex.Pattern; import static net.stzups.scribbleshare.server.http.HttpUtils.send; @@ -118,7 +119,7 @@ public HttpServerHandler(Config config, ScribbleshareDatabase database) { } @Override - public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) { + public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { Scribbleshare.getLogger(ctx).info(request.method() + " " + request.uri()); final String uri; @@ -135,6 +136,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) { queries = parseQuery(rawQuery); route = getRoute(path); } catch (BadRequestException e) { + Scribbleshare.getLogger(ctx).log(Level.WARNING, "Exception while handling http request", e); send(ctx, request, HttpResponseStatus.NOT_FOUND); return; } @@ -385,8 +387,11 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) { } // get filesystem filePath from provided filePath - final String filePath = getFilePath(path); - if (filePath == null) { + final String filePath; + try { + filePath = getFilePath(path); + } catch (BadRequestException e) { + Scribbleshare.getLogger(ctx).log(Level.WARNING, "Exception while getting file path for http request", e); send(ctx, request, HttpResponseStatus.NOT_FOUND); return; } From e8fed9656842f84ca2a363bb250cc43a278659ed Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 15:37:07 -0400 Subject: [PATCH 047/144] add NotFoundException --- .../server/http/BadRequestException.java | 7 - .../backend/server/http/Form.java | 1 + .../server/http/HttpServerHandler.java | 201 +++++++++--------- .../server/http/exception/HttpException.java | 15 ++ .../exceptions/BadRequestException.java | 15 ++ .../exceptions/NotFoundException.java | 19 ++ 6 files changed, 152 insertions(+), 106 deletions(-) delete mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/BadRequestException.java create mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/HttpException.java create mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/BadRequestException.java create mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/NotFoundException.java diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/BadRequestException.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/BadRequestException.java deleted file mode 100644 index 59b8e3a4..00000000 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/BadRequestException.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.stzups.scribbleshare.backend.server.http; - -public class BadRequestException extends Exception { - public BadRequestException(String message) { - super(message); - } -} diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/Form.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/Form.java index 3ef687d0..8e618243 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/Form.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/Form.java @@ -3,6 +3,7 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpHeaderValues; +import net.stzups.scribbleshare.backend.server.http.exception.exceptions.BadRequestException; import java.nio.charset.StandardCharsets; import java.util.Map; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index ed3202e8..4720d099 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -14,6 +14,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.stream.ChunkedStream; import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.backend.server.http.exception.HttpException; +import net.stzups.scribbleshare.backend.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.backend.server.http.exception.exceptions.NotFoundException; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.Resource; @@ -119,9 +122,18 @@ public HttpServerHandler(Config config, ScribbleshareDatabase database) { } @Override - public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { + public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) { Scribbleshare.getLogger(ctx).info(request.method() + " " + request.uri()); + try { + channelRead(ctx, request); + } catch (HttpException e) { + send(ctx, request, e.responseStatus()); + } catch (Exception e) { + send(ctx, request, HttpResponseStatus.INTERNAL_SERVER_ERROR); + } + } + private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { final String uri; final String[] splitQuery; final String path; @@ -136,9 +148,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr queries = parseQuery(rawQuery); route = getRoute(path); } catch (BadRequestException e) { - Scribbleshare.getLogger(ctx).log(Level.WARNING, "Exception while handling http request", e); - send(ctx, request, HttpResponseStatus.NOT_FOUND); - return; + throw new NotFoundException("Exception while parsing URI", e); } // check if this is a special request @@ -244,126 +254,121 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr //login - try { - if (request.method().equals(HttpMethod.POST)) { - //todo validate for extra fields that should not happen - if (uri.equals(LOGIN_PATH)) { - Form form = new Form(request); + if (request.method().equals(HttpMethod.POST)) { + //todo validate for extra fields that should not happen + if (uri.equals(LOGIN_PATH)) { + Form form = new Form(request); - String username = form.getText("username"); - String password = form.getText("password"); - boolean remember = form.getCheckbox("remember"); + String username = form.getText("username"); + String password = form.getText("password"); + boolean remember = form.getCheckbox("remember"); - System.out.println(username + ", " + password + ", " + remember); + System.out.println(username + ", " + password + ", " + remember); - Login login = database.getLogin(username); - Long id = Login.verify(login, password.getBytes(StandardCharsets.UTF_8)); - if (id == null) { - //todo rate limit and generic error handling - if (login == null) { - Scribbleshare.getLogger(ctx).info("Bad username " + username); - } else { - Scribbleshare.getLogger(ctx).info("Bad password for username " + username); - } - - sendRedirect(ctx, request, LOGIN_PAGE); - return; + Login login = database.getLogin(username); + Long id = Login.verify(login, password.getBytes(StandardCharsets.UTF_8)); + if (id == null) { + //todo rate limit and generic error handling + if (login == null) { + Scribbleshare.getLogger(ctx).info("Bad username " + username); + } else { + Scribbleshare.getLogger(ctx).info("Bad password for username " + username); } - HttpHeaders httpHeaders = new DefaultHttpHeaders(); - HttpUserSession userSession = new HttpUserSession(config, database.getUser(login.getId()), httpHeaders); - database.addHttpSession(userSession); - if (remember) { - PersistentHttpUserSession persistentHttpUserSession = new PersistentHttpUserSession(config, userSession, httpHeaders); - database.addPersistentHttpUserSession(persistentHttpUserSession); - } - sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); + sendRedirect(ctx, request, LOGIN_PAGE); return; - } else if (uri.equals(REGISTER_PATH)) { - Form form = new Form(request); + } - // validate + HttpHeaders httpHeaders = new DefaultHttpHeaders(); + HttpUserSession userSession = new HttpUserSession(config, database.getUser(login.getId()), httpHeaders); + database.addHttpSession(userSession); + if (remember) { + PersistentHttpUserSession persistentHttpUserSession = new PersistentHttpUserSession(config, userSession, httpHeaders); + database.addPersistentHttpUserSession(persistentHttpUserSession); + } + sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); + return; + } else if (uri.equals(REGISTER_PATH)) { + Form form = new Form(request); - String username = form.getText("username"); - String password = form.getText("password"); + // validate - //todo validate - if (false) { - //todo rate limit and generic error handling + String username = form.getText("username"); + String password = form.getText("password"); - sendRedirect(ctx, request, REGISTER_PAGE); - return; - } + //todo validate + if (false) { + //todo rate limit and generic error handling - User user; - HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); - if (cookie != null) { - HttpUserSession httpSession = database.getHttpSession(cookie); - if (httpSession != null) { - user = database.getUser(httpSession.getUser()); - } else { - user = new User(username); - database.addUser(user); - } + sendRedirect(ctx, request, REGISTER_PAGE); + return; + } + + User user; + HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); + if (cookie != null) { + HttpUserSession httpSession = database.getHttpSession(cookie); + if (httpSession != null) { + user = database.getUser(httpSession.getUser()); } else { user = new User(username); database.addUser(user); } - Login login = new Login(user, password.getBytes(StandardCharsets.UTF_8)); - if (!database.addLogin(login)) { - Scribbleshare.getLogger(ctx).info("Tried to register with duplicate username " + username); - sendRedirect(ctx, request, REGISTER_PAGE); - return; - } + } else { + user = new User(username); + database.addUser(user); + } + Login login = new Login(user, password.getBytes(StandardCharsets.UTF_8)); + if (!database.addLogin(login)) { + Scribbleshare.getLogger(ctx).info("Tried to register with duplicate username " + username); + sendRedirect(ctx, request, REGISTER_PAGE); + return; + } - Scribbleshare.getLogger(ctx).info("Registered with username " + username); + Scribbleshare.getLogger(ctx).info("Registered with username " + username); - sendRedirect(ctx, request, REGISTER_SUCCESS); - return; - } else if (uri.equals(LOGOUT_PAGE)) { - Form form = new Form(request);//todo necessary? - - HttpHeaders headers = new DefaultHttpHeaders(); - HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); - if (cookie != null) { - HttpUserSession httpUserSession = database.getHttpSession(cookie); - if (httpUserSession != null) { - if (httpUserSession.validate(cookie)) { - database.expireHttpSession(httpUserSession); - httpUserSession.clearCookie(config, headers); - } else { - Scribbleshare.getLogger(ctx).warning("Tried to log out of existing session with bad authentication"); - } + sendRedirect(ctx, request, REGISTER_SUCCESS); + return; + } else if (uri.equals(LOGOUT_PAGE)) { + Form form = new Form(request);//todo necessary? + + HttpHeaders headers = new DefaultHttpHeaders(); + HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); + if (cookie != null) { + HttpUserSession httpUserSession = database.getHttpSession(cookie); + if (httpUserSession != null) { + if (httpUserSession.validate(cookie)) { + database.expireHttpSession(httpUserSession); + httpUserSession.clearCookie(config, headers); } else { - Scribbleshare.getLogger(ctx).warning("Tried to log out of non existent session"); + Scribbleshare.getLogger(ctx).warning("Tried to log out of existing session with bad authentication"); } + } else { + Scribbleshare.getLogger(ctx).warning("Tried to log out of non existent session"); } + } - HttpSessionCookie persistentCookie = HttpSessionCookie.getHttpSessionCookie(request, PersistentHttpUserSession.COOKIE_NAME); - if (persistentCookie != null) { - PersistentHttpUserSession persistentHttpUserSession = database.getPersistentHttpUserSession(persistentCookie); - if (persistentHttpUserSession != null) { - if (persistentHttpUserSession.validate(persistentCookie)) { - database.expirePersistentHttpUserSession(persistentHttpUserSession); - persistentHttpUserSession.clearCookie(config, headers); - } else { - Scribbleshare.getLogger(ctx).warning("Tried to log out of existing persistent session with bad authentication"); - //todo error - } + HttpSessionCookie persistentCookie = HttpSessionCookie.getHttpSessionCookie(request, PersistentHttpUserSession.COOKIE_NAME); + if (persistentCookie != null) { + PersistentHttpUserSession persistentHttpUserSession = database.getPersistentHttpUserSession(persistentCookie); + if (persistentHttpUserSession != null) { + if (persistentHttpUserSession.validate(persistentCookie)) { + database.expirePersistentHttpUserSession(persistentHttpUserSession); + persistentHttpUserSession.clearCookie(config, headers); } else { - Scribbleshare.getLogger(ctx).warning("Tried to log out of non existent persistent session"); + Scribbleshare.getLogger(ctx).warning("Tried to log out of existing persistent session with bad authentication"); //todo error } + } else { + Scribbleshare.getLogger(ctx).warning("Tried to log out of non existent persistent session"); + //todo error } - - sendRedirect(ctx, request, headers, LOGOUT_SUCCESS); - return; } + + sendRedirect(ctx, request, headers, LOGOUT_SUCCESS); + return; } - } catch (BadRequestException e) { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); - return; } @@ -391,9 +396,7 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr try { filePath = getFilePath(path); } catch (BadRequestException e) { - Scribbleshare.getLogger(ctx).log(Level.WARNING, "Exception while getting file path for http request", e); - send(ctx, request, HttpResponseStatus.NOT_FOUND); - return; + throw new NotFoundException("Exception while getting file path for http request", e); } File root; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/HttpException.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/HttpException.java new file mode 100644 index 00000000..f007c1f9 --- /dev/null +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/HttpException.java @@ -0,0 +1,15 @@ +package net.stzups.scribbleshare.backend.server.http.exception; + +import io.netty.handler.codec.http.HttpResponseStatus; + +public abstract class HttpException extends Exception { + protected HttpException(String message) { + super(message); + } + + protected HttpException(String message, HttpException cause) { + super(cause); + } + + public abstract HttpResponseStatus responseStatus(); +} diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/BadRequestException.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/BadRequestException.java new file mode 100644 index 00000000..63f20f5c --- /dev/null +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/BadRequestException.java @@ -0,0 +1,15 @@ +package net.stzups.scribbleshare.backend.server.http.exception.exceptions; + +import io.netty.handler.codec.http.HttpResponseStatus; +import net.stzups.scribbleshare.backend.server.http.exception.HttpException; + +public class BadRequestException extends HttpException { + public BadRequestException(String message) { + super(message); + } + + @Override + public HttpResponseStatus responseStatus() { + return HttpResponseStatus.BAD_REQUEST; + } +} diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/NotFoundException.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/NotFoundException.java new file mode 100644 index 00000000..da8298d3 --- /dev/null +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/NotFoundException.java @@ -0,0 +1,19 @@ +package net.stzups.scribbleshare.backend.server.http.exception.exceptions; + +import io.netty.handler.codec.http.HttpResponseStatus; +import net.stzups.scribbleshare.backend.server.http.exception.HttpException; + +public class NotFoundException extends HttpException { + public NotFoundException(String message) { + super(message); + } + + public NotFoundException(String message, HttpException cause) { + super(message, cause); + } + + @Override + public HttpResponseStatus responseStatus() { + return HttpResponseStatus.NOT_FOUND; + } +} From cf931ecdf2cb1432a88ce961b3e64af57f28c8a1 Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 15:39:26 -0400 Subject: [PATCH 048/144] exceptions are logged again --- .../scribbleshare/backend/server/http/HttpServerHandler.java | 3 +++ .../backend/server/http/exception/HttpException.java | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 4720d099..1abbf398 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -31,6 +31,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.lang.ref.WeakReference; import java.nio.charset.StandardCharsets; import java.sql.SQLException; import java.util.Collections; @@ -127,8 +128,10 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) { try { channelRead(ctx, request); } catch (HttpException e) { + Scribbleshare.getLogger(ctx).log(Level.WARNING, "Exception while handling HTTP request", e); send(ctx, request, e.responseStatus()); } catch (Exception e) { + Scribbleshare.getLogger(ctx).log(Level.WARNING, "Exception while handling HTTP request", e); send(ctx, request, HttpResponseStatus.INTERNAL_SERVER_ERROR); } } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/HttpException.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/HttpException.java index f007c1f9..65c0eaee 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/HttpException.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/HttpException.java @@ -8,7 +8,7 @@ protected HttpException(String message) { } protected HttpException(String message, HttpException cause) { - super(cause); + super(message, cause); } public abstract HttpResponseStatus responseStatus(); From 42cddad823902f744e19c91cbb96f686f016fd74 Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 15:48:24 -0400 Subject: [PATCH 049/144] more exceptions --- .../server/http/HttpServerHandler.java | 55 ++++++++----------- .../server/http/exception/HttpException.java | 2 +- .../exceptions/BadRequestException.java | 4 ++ .../exceptions/NotFoundException.java | 2 +- .../exceptions/UnauthorizedException.java | 15 +++++ 5 files changed, 43 insertions(+), 35 deletions(-) create mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/UnauthorizedException.java diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 1abbf398..e8087dbd 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -17,6 +17,7 @@ import net.stzups.scribbleshare.backend.server.http.exception.HttpException; import net.stzups.scribbleshare.backend.server.http.exception.exceptions.BadRequestException; import net.stzups.scribbleshare.backend.server.http.exception.exceptions.NotFoundException; +import net.stzups.scribbleshare.backend.server.http.exception.exceptions.UnauthorizedException; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.Resource; @@ -158,38 +159,30 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr switch (route[0]) { case "api": { - if (route.length < 2) { - send(ctx, request, HttpResponseStatus.NOT_FOUND); - return; - } + if (route.length < 2) + throw new NotFoundException("No route for api"); switch (route[1]) { case "document": { - if (route.length != 3 && route.length != 4) { - break; - } + if (route.length != 3 && route.length != 4) + throw new NotFoundException("Incorrect route length"); Long userId = authenticate(ctx, request); - if (userId == null) { - send(ctx, request, HttpResponseStatus.UNAUTHORIZED); - return; - } User user = database.getUser(userId); - if (user == null) { - Scribbleshare.getLogger(ctx).warning("User with " + userId + " authenticated but does not exist"); - break; - } + if (user == null) //todo + throw new UnauthorizedException("User with " + userId + " authenticated but does not exist"); long documentId; try { documentId = Long.parseLong(route[2]); } catch (NumberFormatException e) { - break; + throw new BadRequestException("Exception while parsing " + route[2], e); } if (!user.getOwnedDocuments().contains(documentId) && !user.getSharedDocuments().contains(documentId)) { - break; //user cant do this to documents they don't have access to todo public documents + throw new NotFoundException("User tried to open document they don't have access to"); + //todo public documents } // user has access to the document @@ -197,8 +190,7 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr if (route.length == 3) { // get document or submit new resource to document if (request.method().equals(HttpMethod.GET)) { //todo - send(ctx, request, HttpResponseStatus.NOT_FOUND); - return; + throw new NotFoundException("todo not implemented yet"); /*Resource resource = BackendServerInitializer.getDatabase(ctx).getResource(documentId, documentId); if (resource == null) { //indicates an empty unsaved canvas, so serve that send(ctx, request, Canvas.getEmptyCanvas()); @@ -209,10 +201,9 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr sendChunkedResource(ctx, request, headers, new ChunkedStream(new ByteBufInputStream(resource.getData())), resource.getLastModified());//todo don't fetch entire document from db if not modified*/ } else if (request.method().equals(HttpMethod.POST)) { //todo validation/security for submitted resources Document document = database.getDocument(documentId); - if (document == null) { - Scribbleshare.getLogger(ctx).warning("Document with id " + documentId + " for user " + user + " somehow does not exist"); - break; - } + if (document == null) + throw new NotFoundException("Document with id " + documentId + " for user " + user + " somehow does not exist"); + send(ctx, request, Unpooled.copyLong(database.addResource(document.getId(), new Resource(request.content())))); } else { send(ctx, request, HttpResponseStatus.METHOD_NOT_ALLOWED); @@ -223,20 +214,18 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr try { resourceId = Long.parseLong(route[3]); } catch (NumberFormatException e) { - break; + throw new BadRequestException("Exception while parsing " + route[3], e); } Document document = database.getDocument(documentId); - if (document == null) { - Scribbleshare.getLogger(ctx).warning("Document with id " + documentId + " for user " + user + " somehow does not exist"); - break; - } + if (document == null) + throw new NotFoundException("Document with id " + documentId + " for user " + user + " somehow does not exist"); if (request.method().equals(HttpMethod.GET)) { // get resource, resource must exist on the document Resource resource = database.getResource(resourceId, documentId); if (resource == null) { - break; + throw new NotFoundException("Resource does not exist"); } HttpHeaders headers = new DefaultHttpHeaders(); @@ -248,9 +237,9 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr } return; } + default: + throw new NotFoundException("Bad route"); } - send(ctx, request, HttpResponseStatus.NOT_FOUND); - return; } } @@ -426,7 +415,7 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr sendFile(ctx, request, headers, file, mimeTypes.getMimeType(file)); } - private Long authenticate(ChannelHandlerContext ctx, FullHttpRequest request) { + private Long authenticate(ChannelHandlerContext ctx, FullHttpRequest request) throws UnauthorizedException { HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); if (cookie != null) { HttpUserSession httpSession = database.getHttpSession(cookie); @@ -442,7 +431,7 @@ private Long authenticate(ChannelHandlerContext ctx, FullHttpRequest request) { Scribbleshare.getLogger(ctx).info("No authentication"); } - return null; + throw new UnauthorizedException("Bad authentication"); } private void logIn(ChannelHandlerContext ctx, HttpConfig config, FullHttpRequest request, HttpHeaders headers) throws SQLException { diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/HttpException.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/HttpException.java index 65c0eaee..029cc19b 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/HttpException.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/HttpException.java @@ -7,7 +7,7 @@ protected HttpException(String message) { super(message); } - protected HttpException(String message, HttpException cause) { + protected HttpException(String message, Throwable cause) { super(message, cause); } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/BadRequestException.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/BadRequestException.java index 63f20f5c..2ae74e85 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/BadRequestException.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/BadRequestException.java @@ -8,6 +8,10 @@ public BadRequestException(String message) { super(message); } + public BadRequestException(String message, Throwable cause) { + super(message, cause); + } + @Override public HttpResponseStatus responseStatus() { return HttpResponseStatus.BAD_REQUEST; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/NotFoundException.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/NotFoundException.java index da8298d3..b6935208 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/NotFoundException.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/NotFoundException.java @@ -8,7 +8,7 @@ public NotFoundException(String message) { super(message); } - public NotFoundException(String message, HttpException cause) { + public NotFoundException(String message, Throwable cause) { super(message, cause); } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/UnauthorizedException.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/UnauthorizedException.java new file mode 100644 index 00000000..2d306b10 --- /dev/null +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/UnauthorizedException.java @@ -0,0 +1,15 @@ +package net.stzups.scribbleshare.backend.server.http.exception.exceptions; + +import io.netty.handler.codec.http.HttpResponseStatus; +import net.stzups.scribbleshare.backend.server.http.exception.HttpException; + +public class UnauthorizedException extends HttpException { + public UnauthorizedException(String message) { + super(message); + } + + @Override + public HttpResponseStatus responseStatus() { + return HttpResponseStatus.UNAUTHORIZED; + } +} From 56c6e387660469fd50a35b18cc147c763a95c015 Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 15:52:20 -0400 Subject: [PATCH 050/144] move around classes and methods --- .../server/http/HttpServerHandler.java | 63 +++---------------- .../scribbleshare}/server/http/Form.java | 6 +- .../scribbleshare/server/http/HttpUtils.java | 58 +++++++++++++++++ .../server/http/exception/HttpException.java | 2 +- .../exceptions/BadRequestException.java | 4 +- .../exceptions/NotFoundException.java | 4 +- .../exceptions/UnauthorizedException.java | 4 +- 7 files changed, 77 insertions(+), 64 deletions(-) rename {scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend => scribbleshare-commons/src/main/java/net/stzups/scribbleshare}/server/http/Form.java (85%) rename {scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend => scribbleshare-commons/src/main/java/net/stzups/scribbleshare}/server/http/exception/HttpException.java (84%) rename {scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend => scribbleshare-commons/src/main/java/net/stzups/scribbleshare}/server/http/exception/exceptions/BadRequestException.java (73%) rename {scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend => scribbleshare-commons/src/main/java/net/stzups/scribbleshare}/server/http/exception/exceptions/NotFoundException.java (72%) rename {scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend => scribbleshare-commons/src/main/java/net/stzups/scribbleshare}/server/http/exception/exceptions/UnauthorizedException.java (67%) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index e8087dbd..6bef1995 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -14,10 +14,12 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.stream.ChunkedStream; import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.backend.server.http.exception.HttpException; -import net.stzups.scribbleshare.backend.server.http.exception.exceptions.BadRequestException; -import net.stzups.scribbleshare.backend.server.http.exception.exceptions.NotFoundException; -import net.stzups.scribbleshare.backend.server.http.exception.exceptions.UnauthorizedException; +import net.stzups.scribbleshare.server.http.Form; +import net.stzups.scribbleshare.server.http.HttpUtils; +import net.stzups.scribbleshare.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; +import net.stzups.scribbleshare.server.http.exception.exceptions.UnauthorizedException; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.Resource; @@ -32,7 +34,6 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import java.lang.ref.WeakReference; import java.nio.charset.StandardCharsets; import java.sql.SQLException; import java.util.Collections; @@ -60,11 +61,6 @@ public interface Config extends HttpConfig { private static final String DEFAULT_FILE = "index.html"; // / -> /index.html private static final String DEFAULT_FILE_EXTENSION = ".html"; // /index -> index.html - // /index?key=value&otherKey=value - private static final String QUERY_DELIMITER = "?"; - private static final String QUERY_SEPARATOR = "&"; - private static final String QUERY_PAIR_SEPARATOR = "="; - private static final String QUERY_REGEX = QUERY_DELIMITER + QUERY_SEPARATOR + QUERY_PAIR_SEPARATOR; // abc-ABC_123.file private static final String FILE_NAME_REGEX = "a-zA-Z0-9-_"; @@ -146,10 +142,10 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr String[] route; try { uri = getUri(request.uri()); - splitQuery = splitQuery(uri); + splitQuery = HttpUtils.splitQuery(uri); path = splitQuery[0]; rawQuery = splitQuery[1]; - queries = parseQuery(rawQuery); + queries = HttpUtils.parseQuery(rawQuery); route = getRoute(path); } catch (BadRequestException e) { throw new NotFoundException("Exception while parsing URI", e); @@ -491,7 +487,7 @@ private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders header - private static final Pattern ALLOWED_CHARACTERS = Pattern.compile("^[/." + QUERY_REGEX + FILE_NAME_REGEX + "]+$"); + private static final Pattern ALLOWED_CHARACTERS = Pattern.compile("^[/." + HttpUtils.QUERY_REGEX + FILE_NAME_REGEX + "]+$"); /** Sanitizes uri */ public static String getUri(String uri) throws BadRequestException { @@ -536,46 +532,5 @@ private static String getFilePath(String path) throws BadRequestException { } - /** - * Returns String array with length of 2, with the first element as the path and the second element as the raw query - * Example: - * /index.html?key=value&otherKey=otherValue -> [ /index.html, key=value&otherKey=otherValue ] - */ - public static String[] splitQuery(String uri) throws BadRequestException { - int index = uri.lastIndexOf(QUERY_DELIMITER); - if (index <= 0) { // check for a query - if (uri.contains(QUERY_SEPARATOR) || uri.contains(QUERY_PAIR_SEPARATOR)) { - throw new BadRequestException("Empty query contains illegal characters"); - } else { - return new String[] {uri, ""}; - } - } else if (uri.indexOf(QUERY_DELIMITER) != index) { - throw new BadRequestException("Encountered multiple " + QUERY_DELIMITER + " in uri, there should only be one"); - } else { - return new String[] {uri.substring(0, index), uri.substring(index + 1)}; - } - } - /** - * Parses key=value&otherKey=otherValue&keyWithEmptyValue to a Map of key-value pairs - */ - public static Map parseQuery(String query) throws BadRequestException { - if (query.isEmpty()) - return Collections.emptyMap(); // no query to parse - - Map queries = new HashMap<>(); - String[] keyValuePairs = query.split(QUERY_SEPARATOR); - for (String keyValuePair : keyValuePairs) { - String[] split = keyValuePair.split(QUERY_PAIR_SEPARATOR, 3); // a limit of 2 (expected) would not detect malformed queries such as ?key==, so we need to go one more - if (split.length == 1) { // key with no value, such as ?key - queries.put(split[0], ""); - } else if (split.length != 2) { - throw new BadRequestException("Each key should have one value of query " + query); - } else { - queries.put(split[0], split[1]); - } - } - - return queries; - } } \ No newline at end of file diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/Form.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Form.java similarity index 85% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/Form.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Form.java index 8e618243..97feeaf3 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/Form.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Form.java @@ -1,9 +1,9 @@ -package net.stzups.scribbleshare.backend.server.http; +package net.stzups.scribbleshare.server.http; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpHeaderValues; -import net.stzups.scribbleshare.backend.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import java.nio.charset.StandardCharsets; import java.util.Map; @@ -22,7 +22,7 @@ public Form(FullHttpRequest request) throws BadRequestException { //todo check host/origin/referer to make sure they originate from LOGIN_PAGE - this.form = HttpServerHandler.parseQuery(request.content().toString(StandardCharsets.UTF_8)); + this.form = HttpUtils.parseQuery(request.content().toString(StandardCharsets.UTF_8)); } public String getText(String field) throws BadRequestException { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java index 9013110a..c7e597fd 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java @@ -23,6 +23,7 @@ import io.netty.handler.stream.ChunkedFile; import io.netty.handler.stream.ChunkedInput; import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import java.io.File; import java.io.FileNotFoundException; @@ -31,8 +32,11 @@ import java.text.SimpleDateFormat; import java.time.Instant; import java.util.Calendar; +import java.util.Collections; import java.util.GregorianCalendar; +import java.util.HashMap; import java.util.Locale; +import java.util.Map; import java.util.TimeZone; public class HttpUtils { @@ -177,4 +181,58 @@ public static void sendFile(ChannelHandlerContext ctx, FullHttpRequest request, public static void setCookie(HttpHeaders headers, Cookie cookie) { headers.add(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.STRICT.encode(cookie)); } + + + + + // /index?key=value&otherKey=value + private static final String QUERY_DELIMITER = "?"; + private static final String QUERY_SEPARATOR = "&"; + private static final String QUERY_PAIR_SEPARATOR = "="; + + public static final String QUERY_REGEX = QUERY_DELIMITER + QUERY_SEPARATOR + QUERY_PAIR_SEPARATOR; + + + /** + * Returns String array with length of 2, with the first element as the path and the second element as the raw query + * Example: + * /index.html?key=value&otherKey=otherValue -> [ /index.html, key=value&otherKey=otherValue ] + */ + public static String[] splitQuery(String uri) throws BadRequestException { + int index = uri.lastIndexOf(QUERY_DELIMITER); + if (index <= 0) { // check for a query + if (uri.contains(QUERY_SEPARATOR) || uri.contains(QUERY_PAIR_SEPARATOR)) { + throw new BadRequestException("Empty query contains illegal characters"); + } else { + return new String[] {uri, ""}; + } + } else if (uri.indexOf(QUERY_DELIMITER) != index) { + throw new BadRequestException("Encountered multiple " + QUERY_DELIMITER + " in uri, there should only be one"); + } else { + return new String[] {uri.substring(0, index), uri.substring(index + 1)}; + } + } + + /** + * Parses key=value&otherKey=otherValue&keyWithEmptyValue to a Map of key-value pairs + */ + public static Map parseQuery(String query) throws BadRequestException { + if (query.isEmpty()) + return Collections.emptyMap(); // no query to parse + + Map queries = new HashMap<>(); + String[] keyValuePairs = query.split(QUERY_SEPARATOR); + for (String keyValuePair : keyValuePairs) { + String[] split = keyValuePair.split(QUERY_PAIR_SEPARATOR, 3); // a limit of 2 (expected) would not detect malformed queries such as ?key==, so we need to go one more + if (split.length == 1) { // key with no value, such as ?key + queries.put(split[0], ""); + } else if (split.length != 2) { + throw new BadRequestException("Each key should have one value of query " + query); + } else { + queries.put(split[0], split[1]); + } + } + + return queries; + } } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/HttpException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/HttpException.java similarity index 84% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/HttpException.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/HttpException.java index 029cc19b..76a880d2 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/HttpException.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/HttpException.java @@ -1,4 +1,4 @@ -package net.stzups.scribbleshare.backend.server.http.exception; +package net.stzups.scribbleshare.server.http.exception; import io.netty.handler.codec.http.HttpResponseStatus; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/BadRequestException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/BadRequestException.java similarity index 73% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/BadRequestException.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/BadRequestException.java index 2ae74e85..0ca90995 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/BadRequestException.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/BadRequestException.java @@ -1,7 +1,7 @@ -package net.stzups.scribbleshare.backend.server.http.exception.exceptions; +package net.stzups.scribbleshare.server.http.exception.exceptions; import io.netty.handler.codec.http.HttpResponseStatus; -import net.stzups.scribbleshare.backend.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.exception.HttpException; public class BadRequestException extends HttpException { public BadRequestException(String message) { diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/NotFoundException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/NotFoundException.java similarity index 72% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/NotFoundException.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/NotFoundException.java index b6935208..9803eda5 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/NotFoundException.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/NotFoundException.java @@ -1,7 +1,7 @@ -package net.stzups.scribbleshare.backend.server.http.exception.exceptions; +package net.stzups.scribbleshare.server.http.exception.exceptions; import io.netty.handler.codec.http.HttpResponseStatus; -import net.stzups.scribbleshare.backend.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.exception.HttpException; public class NotFoundException extends HttpException { public NotFoundException(String message) { diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/UnauthorizedException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/UnauthorizedException.java similarity index 67% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/UnauthorizedException.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/UnauthorizedException.java index 2d306b10..4b0b91a9 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/exception/exceptions/UnauthorizedException.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/UnauthorizedException.java @@ -1,7 +1,7 @@ -package net.stzups.scribbleshare.backend.server.http.exception.exceptions; +package net.stzups.scribbleshare.server.http.exception.exceptions; import io.netty.handler.codec.http.HttpResponseStatus; -import net.stzups.scribbleshare.backend.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.exception.HttpException; public class UnauthorizedException extends HttpException { public UnauthorizedException(String message) { From 8192898ee55a3c16449f47d6fc7069d9313cb6e5 Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 16:09:44 -0400 Subject: [PATCH 051/144] start to rework query/request --- .../server/http/HttpServerHandler.java | 75 +++++----------- .../scribbleshare/server/http/HttpUtils.java | 49 +---------- .../scribbleshare/server/http/Query.java | 87 +++++++++++++++++++ .../scribbleshare/server/http/Route.java | 4 + .../stzups/scribbleshare/server/http/Uri.java | 48 ++++++++++ 5 files changed, 162 insertions(+), 101 deletions(-) create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Query.java create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Route.java create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Uri.java diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 6bef1995..174f3e36 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -15,7 +15,9 @@ import io.netty.handler.stream.ChunkedStream; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.server.http.Form; -import net.stzups.scribbleshare.server.http.HttpUtils; +import net.stzups.scribbleshare.server.http.Query; +import net.stzups.scribbleshare.server.http.Route; +import net.stzups.scribbleshare.server.http.Uri; import net.stzups.scribbleshare.server.http.exception.HttpException; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; @@ -36,11 +38,7 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.sql.SQLException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; import java.util.logging.Level; -import java.util.regex.Pattern; import static net.stzups.scribbleshare.server.http.HttpUtils.send; import static net.stzups.scribbleshare.server.http.HttpUtils.sendChunkedResource; @@ -62,8 +60,7 @@ public interface Config extends HttpConfig { private static final String DEFAULT_FILE_EXTENSION = ".html"; // /index -> index.html - // abc-ABC_123.file - private static final String FILE_NAME_REGEX = "a-zA-Z0-9-_"; + @@ -134,19 +131,11 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) { } private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { - final String uri; - final String[] splitQuery; - final String path; - final String rawQuery; - Map queries; - String[] route; + final Query query; + final Route route; try { - uri = getUri(request.uri()); - splitQuery = HttpUtils.splitQuery(uri); - path = splitQuery[0]; - rawQuery = splitQuery[1]; - queries = HttpUtils.parseQuery(rawQuery); - route = getRoute(path); + query = new Query(request.uri()); + route = getRoute(query); } catch (BadRequestException e) { throw new NotFoundException("Exception while parsing URI", e); } @@ -244,7 +233,7 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr if (request.method().equals(HttpMethod.POST)) { //todo validate for extra fields that should not happen - if (uri.equals(LOGIN_PATH)) { + if (query.path().equals(LOGIN_PATH)) { Form form = new Form(request); String username = form.getText("username"); @@ -277,7 +266,7 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr } sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); return; - } else if (uri.equals(REGISTER_PATH)) { + } else if (query.path().equals(REGISTER_PATH)) { Form form = new Form(request); // validate @@ -318,7 +307,7 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr sendRedirect(ctx, request, REGISTER_SUCCESS); return; - } else if (uri.equals(LOGOUT_PAGE)) { + } else if (query.path().equals(LOGOUT_PAGE)) { Form form = new Form(request);//todo necessary? HttpHeaders headers = new DefaultHttpHeaders(); @@ -368,37 +357,39 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr } // redirects - if (path.endsWith(DEFAULT_FILE)) { // /index.html -> / - sendRedirect(ctx, request, path.substring(0, path.length() - DEFAULT_FILE.length()) + rawQuery); + if (query.path().endsWith(DEFAULT_FILE)) { // /index.html -> / + sendRedirect(ctx, request, query.path().substring(0, query.path().length() - DEFAULT_FILE.length()) + query.rawQuery()); return; - } else if ((path + DEFAULT_FILE_EXTENSION).endsWith(DEFAULT_FILE)) { // /index -> / - sendRedirect(ctx, request, path.substring(0, path.length() - (DEFAULT_FILE.length() - DEFAULT_FILE_EXTENSION.length())) + rawQuery); + } else if ((query.path() + DEFAULT_FILE_EXTENSION).endsWith(DEFAULT_FILE)) { // /index -> / + sendRedirect(ctx, request, query.path().substring(0, query.path().length() - (DEFAULT_FILE.length() - DEFAULT_FILE_EXTENSION.length())) + query.rawQuery()); return; - } else if (path.endsWith(DEFAULT_FILE_EXTENSION)) { // /page.html -> /page - sendRedirect(ctx, request, path.substring(0, path.length() - DEFAULT_FILE_EXTENSION.length()) + rawQuery); + } else if (query.path().endsWith(DEFAULT_FILE_EXTENSION)) { // /page.html -> /page + sendRedirect(ctx, request, query.path().substring(0, query.path().length() - DEFAULT_FILE_EXTENSION.length()) + query.rawQuery()); return; } // get filesystem filePath from provided filePath final String filePath; try { - filePath = getFilePath(path); + filePath = getFilePath(query.path()); } catch (BadRequestException e) { throw new NotFoundException("Exception while getting file path for http request", e); } + //todo this is mostly for debug File root; if (filePath.endsWith(".js")) { root = jsRoot; } else { root = httpRoot; } + File file = new File(root, filePath); if (file.isHidden() || !file.exists() || file.isDirectory() || !file.isFile()) { if (new File(httpRoot, filePath.substring(0, filePath.length() - DEFAULT_FILE_EXTENSION.length())).isDirectory()) { // /test -> /test/ if test is a valid directory and /test.html does not exist - sendRedirect(ctx, request, path + "/" + rawQuery); + sendRedirect(ctx, request, query.path() + "/" + query.rawQuery()); } else { - send(ctx, request, HttpResponseStatus.NOT_FOUND); + throw new NotFoundException("File at path " + filePath + " not found"); } return; } @@ -487,29 +478,7 @@ private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders header - private static final Pattern ALLOWED_CHARACTERS = Pattern.compile("^[/." + HttpUtils.QUERY_REGEX + FILE_NAME_REGEX + "]+$"); - - /** Sanitizes uri */ - public static String getUri(String uri) throws BadRequestException { - if (!ALLOWED_CHARACTERS.matcher(uri).matches()) - throw new BadRequestException("URI contains illegal characters"); - - return uri; - } - - private static final Pattern ALLOWED_PATH = Pattern.compile("^[\\\\" + File.separator + "." + FILE_NAME_REGEX + "]+$"); - - private static String[] getRoute(String path) throws BadRequestException { - if (!path.startsWith("/")) - throw new BadRequestException("Route must start with a /"); - String[] route = path.substring(1).split("/"); - if (route.length == 0) { - return new String[] {""}; - } else { - return route; - } - } /** Converts uri to filesystem path */ private static String getFilePath(String path) throws BadRequestException { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java index c7e597fd..c6943159 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java @@ -185,54 +185,7 @@ public static void setCookie(HttpHeaders headers, Cookie cookie) { - // /index?key=value&otherKey=value - private static final String QUERY_DELIMITER = "?"; - private static final String QUERY_SEPARATOR = "&"; - private static final String QUERY_PAIR_SEPARATOR = "="; - - public static final String QUERY_REGEX = QUERY_DELIMITER + QUERY_SEPARATOR + QUERY_PAIR_SEPARATOR; - - - /** - * Returns String array with length of 2, with the first element as the path and the second element as the raw query - * Example: - * /index.html?key=value&otherKey=otherValue -> [ /index.html, key=value&otherKey=otherValue ] - */ - public static String[] splitQuery(String uri) throws BadRequestException { - int index = uri.lastIndexOf(QUERY_DELIMITER); - if (index <= 0) { // check for a query - if (uri.contains(QUERY_SEPARATOR) || uri.contains(QUERY_PAIR_SEPARATOR)) { - throw new BadRequestException("Empty query contains illegal characters"); - } else { - return new String[] {uri, ""}; - } - } else if (uri.indexOf(QUERY_DELIMITER) != index) { - throw new BadRequestException("Encountered multiple " + QUERY_DELIMITER + " in uri, there should only be one"); - } else { - return new String[] {uri.substring(0, index), uri.substring(index + 1)}; - } - } - /** - * Parses key=value&otherKey=otherValue&keyWithEmptyValue to a Map of key-value pairs - */ - public static Map parseQuery(String query) throws BadRequestException { - if (query.isEmpty()) - return Collections.emptyMap(); // no query to parse - - Map queries = new HashMap<>(); - String[] keyValuePairs = query.split(QUERY_SEPARATOR); - for (String keyValuePair : keyValuePairs) { - String[] split = keyValuePair.split(QUERY_PAIR_SEPARATOR, 3); // a limit of 2 (expected) would not detect malformed queries such as ?key==, so we need to go one more - if (split.length == 1) { // key with no value, such as ?key - queries.put(split[0], ""); - } else if (split.length != 2) { - throw new BadRequestException("Each key should have one value of query " + query); - } else { - queries.put(split[0], split[1]); - } - } - return queries; - } + } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Query.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Query.java new file mode 100644 index 00000000..180f6c93 --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Query.java @@ -0,0 +1,87 @@ +package net.stzups.scribbleshare.server.http; + +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class Query { + + // /index?key=value&otherKey=value + private static final String QUERY_DELIMITER = "?"; + private static final String QUERY_SEPARATOR = "&"; + private static final String QUERY_PAIR_SEPARATOR = "="; + + public static final String QUERY_REGEX = QUERY_DELIMITER + QUERY_SEPARATOR + QUERY_PAIR_SEPARATOR; + + private final String path; + private final String rawQuery; + private final Map queries; + + public Query(String uri) throws BadRequestException { + String[] splitQuery = splitQuery(uri); + path = splitQuery[0]; + rawQuery = splitQuery[1]; + queries = parseQuery(rawQuery); + } + + public String getQuery(String key) throws BadRequestException { + String query = queries.get(key); + if (query == null) + throw new BadRequestException("Missing query for key " + key); + + return query; + } + + public String path() { + return path; + } + + public String rawQuery() { + return rawQuery; + } + + /** + * Returns String array with length of 2, with the first element as the path and the second element as the raw query + * Example: + * /index.html?key=value&otherKey=otherValue -> [ /index.html, key=value&otherKey=otherValue ] + */ + public static String[] splitQuery(String uri) throws BadRequestException { + int index = uri.lastIndexOf(QUERY_DELIMITER); + if (index <= 0) { // check for a query + if (uri.contains(QUERY_SEPARATOR) || uri.contains(QUERY_PAIR_SEPARATOR)) { + throw new BadRequestException("Empty query contains illegal characters"); + } else { + return new String[] {uri, ""}; + } + } else if (uri.indexOf(QUERY_DELIMITER) != index) { + throw new BadRequestException("Encountered multiple " + QUERY_DELIMITER + " in uri, there should only be one"); + } else { + return new String[] {uri.substring(0, index), uri.substring(index + 1)}; + } + } + + /** + * Parses key=value&otherKey=otherValue&keyWithEmptyValue to a Map of key-value pairs + */ + public static Map parseQuery(String query) throws BadRequestException { + if (query.isEmpty()) + return Collections.emptyMap(); // no query to parse + + Map queries = new HashMap<>(); + String[] keyValuePairs = query.split(QUERY_SEPARATOR); + for (String keyValuePair : keyValuePairs) { + String[] split = keyValuePair.split(QUERY_PAIR_SEPARATOR, 3); // a limit of 2 (expected) would not detect malformed queries such as ?key==, so we need to go one more + if (split.length == 1) { // key with no value, such as ?key + queries.put(split[0], ""); + } else if (split.length != 2) { + throw new BadRequestException("Each key should have one value of query " + query); + } else { + queries.put(split[0], split[1]); + } + } + + return queries; + } +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Route.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Route.java new file mode 100644 index 00000000..df98d769 --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Route.java @@ -0,0 +1,4 @@ +package net.stzups.scribbleshare.server.http; + +public class Route { +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Uri.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Uri.java new file mode 100644 index 00000000..9a9454ee --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Uri.java @@ -0,0 +1,48 @@ +package net.stzups.scribbleshare.server.http; + +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; + +import java.io.File; +import java.util.regex.Pattern; + +public class Uri { + // abc-ABC_123.file + private static final String FILE_NAME_REGEX = "a-zA-Z0-9-_"; + private static final Pattern ALLOWED_CHARACTERS = Pattern.compile("^[/." + Query.QUERY_REGEX + FILE_NAME_REGEX + "]+$"); + + final String uri; + + public Uri(String uri) throws BadRequestException { + this.uri = getUri(uri); + } + + public String getUri() { + return uri; + } + + /** Sanitizes uri */ + public static String getUri(String uri) throws BadRequestException { + if (!ALLOWED_CHARACTERS.matcher(uri).matches()) + throw new BadRequestException("URI contains illegal characters"); + + return uri; + } + + private static final Pattern ALLOWED_PATH = Pattern.compile("^[\\\\" + File.separator + "." + FILE_NAME_REGEX + "]+$"); + + private static String[] getRoute(String path) throws BadRequestException { + if (!path.startsWith("/")) + throw new BadRequestException("Route must start with a /"); + + String[] route = path.substring(1).split("/"); + if (route.length == 0) { + return new String[] {""}; + } else { + return route; + } + } + + public boolean equals(String string) { + return uri.equals(string); + } +} From 85d8e259d8acb93eb764326b89969acbe90634ed Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 16:22:28 -0400 Subject: [PATCH 052/144] implemented Route --- .../server/http/HttpServerHandler.java | 50 ++++++++----------- .../scribbleshare/server/http/Query.java | 5 +- .../scribbleshare/server/http/Route.java | 43 +++++++++++++++- .../stzups/scribbleshare/server/http/Uri.java | 28 ++--------- 4 files changed, 70 insertions(+), 56 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 174f3e36..46d6c8ee 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -15,7 +15,6 @@ import io.netty.handler.stream.ChunkedStream; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.server.http.Form; -import net.stzups.scribbleshare.server.http.Query; import net.stzups.scribbleshare.server.http.Route; import net.stzups.scribbleshare.server.http.Uri; import net.stzups.scribbleshare.server.http.exception.HttpException; @@ -39,6 +38,7 @@ import java.nio.charset.StandardCharsets; import java.sql.SQLException; import java.util.logging.Level; +import java.util.regex.Pattern; import static net.stzups.scribbleshare.server.http.HttpUtils.send; import static net.stzups.scribbleshare.server.http.HttpUtils.sendChunkedResource; @@ -131,27 +131,19 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) { } private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { - final Query query; final Route route; try { - query = new Query(request.uri()); - route = getRoute(query); + route = new Route(request.uri()); } catch (BadRequestException e) { throw new NotFoundException("Exception while parsing URI", e); } // check if this is a special request - switch (route[0]) { + switch (route.get(0)) { case "api": { - if (route.length < 2) - throw new NotFoundException("No route for api"); - - switch (route[1]) { + switch (route.get(1)) { case "document": { - if (route.length != 3 && route.length != 4) - throw new NotFoundException("Incorrect route length"); - Long userId = authenticate(ctx, request); User user = database.getUser(userId); @@ -160,9 +152,9 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr long documentId; try { - documentId = Long.parseLong(route[2]); + documentId = Long.parseLong(route.get(2)); } catch (NumberFormatException e) { - throw new BadRequestException("Exception while parsing " + route[2], e); + throw new BadRequestException("Exception while parsing " + route.get(2), e); } if (!user.getOwnedDocuments().contains(documentId) && !user.getSharedDocuments().contains(documentId)) { @@ -172,7 +164,7 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr // user has access to the document - if (route.length == 3) { // get document or submit new resource to document + if (route.length() == 3) { // get document or submit new resource to document if (request.method().equals(HttpMethod.GET)) { //todo throw new NotFoundException("todo not implemented yet"); @@ -197,9 +189,9 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr // does the document have this resource? long resourceId; try { - resourceId = Long.parseLong(route[3]); + resourceId = Long.parseLong(route.get(3)); } catch (NumberFormatException e) { - throw new BadRequestException("Exception while parsing " + route[3], e); + throw new BadRequestException("Exception while parsing " + route.get(3), e); } Document document = database.getDocument(documentId); @@ -233,7 +225,7 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr if (request.method().equals(HttpMethod.POST)) { //todo validate for extra fields that should not happen - if (query.path().equals(LOGIN_PATH)) { + if (route.path().equals(LOGIN_PATH)) { Form form = new Form(request); String username = form.getText("username"); @@ -266,7 +258,7 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr } sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); return; - } else if (query.path().equals(REGISTER_PATH)) { + } else if (route.path().equals(REGISTER_PATH)) { Form form = new Form(request); // validate @@ -307,7 +299,7 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr sendRedirect(ctx, request, REGISTER_SUCCESS); return; - } else if (query.path().equals(LOGOUT_PAGE)) { + } else if (route.path().equals(LOGOUT_PAGE)) { Form form = new Form(request);//todo necessary? HttpHeaders headers = new DefaultHttpHeaders(); @@ -357,21 +349,21 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr } // redirects - if (query.path().endsWith(DEFAULT_FILE)) { // /index.html -> / - sendRedirect(ctx, request, query.path().substring(0, query.path().length() - DEFAULT_FILE.length()) + query.rawQuery()); + if (route.path().endsWith(DEFAULT_FILE)) { // /index.html -> / + sendRedirect(ctx, request, route.path().substring(0, route.path().length() - DEFAULT_FILE.length()) + route.rawQuery()); return; - } else if ((query.path() + DEFAULT_FILE_EXTENSION).endsWith(DEFAULT_FILE)) { // /index -> / - sendRedirect(ctx, request, query.path().substring(0, query.path().length() - (DEFAULT_FILE.length() - DEFAULT_FILE_EXTENSION.length())) + query.rawQuery()); + } else if ((route.path() + DEFAULT_FILE_EXTENSION).endsWith(DEFAULT_FILE)) { // /index -> / + sendRedirect(ctx, request, route.path().substring(0, route.path().length() - (DEFAULT_FILE.length() - DEFAULT_FILE_EXTENSION.length())) + route.rawQuery()); return; - } else if (query.path().endsWith(DEFAULT_FILE_EXTENSION)) { // /page.html -> /page - sendRedirect(ctx, request, query.path().substring(0, query.path().length() - DEFAULT_FILE_EXTENSION.length()) + query.rawQuery()); + } else if (route.path().endsWith(DEFAULT_FILE_EXTENSION)) { // /page.html -> /page + sendRedirect(ctx, request, route.path().substring(0, route.path().length() - DEFAULT_FILE_EXTENSION.length()) + route.rawQuery()); return; } // get filesystem filePath from provided filePath final String filePath; try { - filePath = getFilePath(query.path()); + filePath = getFilePath(route.path()); } catch (BadRequestException e) { throw new NotFoundException("Exception while getting file path for http request", e); } @@ -387,7 +379,7 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr File file = new File(root, filePath); if (file.isHidden() || !file.exists() || file.isDirectory() || !file.isFile()) { if (new File(httpRoot, filePath.substring(0, filePath.length() - DEFAULT_FILE_EXTENSION.length())).isDirectory()) { // /test -> /test/ if test is a valid directory and /test.html does not exist - sendRedirect(ctx, request, query.path() + "/" + query.rawQuery()); + sendRedirect(ctx, request, route.path() + "/" + route.rawQuery()); } else { throw new NotFoundException("File at path " + filePath + " not found"); } @@ -478,7 +470,7 @@ private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders header - + private static final Pattern ALLOWED_PATH = Pattern.compile("^[\\\\" + File.separator + "." + Uri.FILE_NAME_REGEX + "]+$"); /** Converts uri to filesystem path */ private static String getFilePath(String path) throws BadRequestException { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Query.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Query.java index 180f6c93..0d002d6d 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Query.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Query.java @@ -6,7 +6,7 @@ import java.util.HashMap; import java.util.Map; -public class Query { +public class Query extends Uri { // /index?key=value&otherKey=value private static final String QUERY_DELIMITER = "?"; @@ -20,13 +20,14 @@ public class Query { private final Map queries; public Query(String uri) throws BadRequestException { + super(uri); String[] splitQuery = splitQuery(uri); path = splitQuery[0]; rawQuery = splitQuery[1]; queries = parseQuery(rawQuery); } - public String getQuery(String key) throws BadRequestException { + public String get(String key) throws BadRequestException { String query = queries.get(key); if (query == null) throw new BadRequestException("Missing query for key " + key); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Route.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Route.java index df98d769..953ab45c 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Route.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Route.java @@ -1,4 +1,45 @@ package net.stzups.scribbleshare.server.http; -public class Route { +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; + +import java.io.File; +import java.util.regex.Pattern; + +public class Route extends Query { + + + private final String[] route; + + public Route(String uri) throws BadRequestException { + super(uri); + if (!path().startsWith("/")) + throw new BadRequestException("Route must start with a /"); + + String[] route = path().substring(1).split("/"); + if (route.length == 0) { + this.route = new String[] {""}; + } else { + this.route = route; + } + } + + /** get route at index */ + public String get(int index) throws BadRequestException { + if (!length(index)) { + throw new BadRequestException("Route not long enough"); + } + + return route[index]; + } + + /** get length */ + public int length() { + return route.length; + } + + /** true if length is long enough */ + public boolean length(int index) { + return route.length >= index; + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Uri.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Uri.java index 9a9454ee..92f7f01b 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Uri.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Uri.java @@ -2,44 +2,24 @@ import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; -import java.io.File; import java.util.regex.Pattern; public class Uri { // abc-ABC_123.file - private static final String FILE_NAME_REGEX = "a-zA-Z0-9-_"; + public static final String FILE_NAME_REGEX = "a-zA-Z0-9-_"; private static final Pattern ALLOWED_CHARACTERS = Pattern.compile("^[/." + Query.QUERY_REGEX + FILE_NAME_REGEX + "]+$"); final String uri; public Uri(String uri) throws BadRequestException { - this.uri = getUri(uri); - } - - public String getUri() { - return uri; - } - - /** Sanitizes uri */ - public static String getUri(String uri) throws BadRequestException { if (!ALLOWED_CHARACTERS.matcher(uri).matches()) throw new BadRequestException("URI contains illegal characters"); - return uri; + this.uri = uri; } - private static final Pattern ALLOWED_PATH = Pattern.compile("^[\\\\" + File.separator + "." + FILE_NAME_REGEX + "]+$"); - - private static String[] getRoute(String path) throws BadRequestException { - if (!path.startsWith("/")) - throw new BadRequestException("Route must start with a /"); - - String[] route = path.substring(1).split("/"); - if (route.length == 0) { - return new String[] {""}; - } else { - return route; - } + public String uri() { + return uri; } public boolean equals(String string) { From 9dd91a720ead048039887b93d7d5ea80459aab36 Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 16:54:51 -0400 Subject: [PATCH 053/144] compiles --- .../main/java/net/stzups/scribbleshare/server/http/Form.java | 2 +- .../main/java/net/stzups/scribbleshare/server/http/Query.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Form.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Form.java index 97feeaf3..6c35720f 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Form.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Form.java @@ -22,7 +22,7 @@ public Form(FullHttpRequest request) throws BadRequestException { //todo check host/origin/referer to make sure they originate from LOGIN_PAGE - this.form = HttpUtils.parseQuery(request.content().toString(StandardCharsets.UTF_8)); + this.form = Query.parseQuery(request.content().toString(StandardCharsets.UTF_8)); } public String getText(String field) throws BadRequestException { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Query.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Query.java index 0d002d6d..13df8c94 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Query.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Query.java @@ -48,7 +48,7 @@ public String rawQuery() { * Example: * /index.html?key=value&otherKey=otherValue -> [ /index.html, key=value&otherKey=otherValue ] */ - public static String[] splitQuery(String uri) throws BadRequestException { + private String[] splitQuery(String uri) throws BadRequestException { int index = uri.lastIndexOf(QUERY_DELIMITER); if (index <= 0) { // check for a query if (uri.contains(QUERY_SEPARATOR) || uri.contains(QUERY_PAIR_SEPARATOR)) { From 5419d44c98ed4c2626da259cd0d82bb24a3beba1 Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 16:56:56 -0400 Subject: [PATCH 054/144] clean up --- .../backend/server/http/HttpServerHandler.java | 14 +++++++------- .../server/http/HttpServerInitializer.java | 3 +++ .../scribbleshare/server/http/HttpUtils.java | 4 ---- .../server/http/{ => handlers}/DebugLog.java | 2 +- .../http/{ => handlers}/HttpAuthenticator.java | 2 +- .../http/{ => handlers}/HttpExceptionHandler.java | 3 ++- .../server/http/{ => handlers}/HttpHandler.java | 2 +- .../server/http/{ => objects}/Form.java | 2 +- .../server/http/{ => objects}/Query.java | 2 +- .../server/http/{ => objects}/Route.java | 6 +----- .../server/http/{ => objects}/Uri.java | 2 +- .../room/server/RoomHttpServerInitializer.java | 2 +- .../server/websocket/ClientMessageHandler.java | 2 +- 13 files changed, 21 insertions(+), 25 deletions(-) rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/{ => handlers}/DebugLog.java (91%) rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/{ => handlers}/HttpAuthenticator.java (98%) rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/{ => handlers}/HttpExceptionHandler.java (85%) rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/{ => handlers}/HttpHandler.java (96%) rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/{ => objects}/Form.java (96%) rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/{ => objects}/Query.java (98%) rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/{ => objects}/Route.java (84%) rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/{ => objects}/Uri.java (93%) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 46d6c8ee..3d35f0d6 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -14,13 +14,6 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.stream.ChunkedStream; import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.server.http.Form; -import net.stzups.scribbleshare.server.http.Route; -import net.stzups.scribbleshare.server.http.Uri; -import net.stzups.scribbleshare.server.http.exception.HttpException; -import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; -import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; -import net.stzups.scribbleshare.server.http.exception.exceptions.UnauthorizedException; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.Resource; @@ -30,6 +23,13 @@ import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; import net.stzups.scribbleshare.data.objects.authentication.login.Login; +import net.stzups.scribbleshare.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; +import net.stzups.scribbleshare.server.http.exception.exceptions.UnauthorizedException; +import net.stzups.scribbleshare.server.http.objects.Form; +import net.stzups.scribbleshare.server.http.objects.Route; +import net.stzups.scribbleshare.server.http.objects.Uri; import java.io.File; import java.io.FileInputStream; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java index cf6b7836..6a25abb1 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java @@ -10,6 +10,9 @@ import io.netty.handler.traffic.GlobalTrafficShapingHandler; import io.netty.handler.traffic.TrafficCounter; import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.server.http.handlers.DebugLog; +import net.stzups.scribbleshare.server.http.handlers.HttpExceptionHandler; +import net.stzups.scribbleshare.server.http.handlers.HttpHandler; import javax.net.ssl.SSLException; import java.io.File; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java index c6943159..00e982f2 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java @@ -23,7 +23,6 @@ import io.netty.handler.stream.ChunkedFile; import io.netty.handler.stream.ChunkedInput; import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import java.io.File; import java.io.FileNotFoundException; @@ -32,11 +31,8 @@ import java.text.SimpleDateFormat; import java.time.Instant; import java.util.Calendar; -import java.util.Collections; import java.util.GregorianCalendar; -import java.util.HashMap; import java.util.Locale; -import java.util.Map; import java.util.TimeZone; public class HttpUtils { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/DebugLog.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/DebugLog.java similarity index 91% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/DebugLog.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/DebugLog.java index 3d1793e8..4fb41c27 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/DebugLog.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/DebugLog.java @@ -1,4 +1,4 @@ -package net.stzups.scribbleshare.server.http; +package net.stzups.scribbleshare.server.http.handlers; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpAuthenticator.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java similarity index 98% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpAuthenticator.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java index eb79065c..e4438fc5 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpAuthenticator.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java @@ -1,4 +1,4 @@ -package net.stzups.scribbleshare.server.http; +package net.stzups.scribbleshare.server.http.handlers; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpExceptionHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpExceptionHandler.java similarity index 85% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpExceptionHandler.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpExceptionHandler.java index 64f08551..678da796 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpExceptionHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpExceptionHandler.java @@ -1,10 +1,11 @@ -package net.stzups.scribbleshare.server.http; +package net.stzups.scribbleshare.server.http.handlers; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.HttpResponseStatus; import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.server.http.HttpUtils; import java.util.logging.Level; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpHandler.java similarity index 96% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpHandler.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpHandler.java index 06151435..16fcaf69 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpHandler.java @@ -1,4 +1,4 @@ -package net.stzups.scribbleshare.server.http; +package net.stzups.scribbleshare.server.http.handlers; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Form.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Form.java similarity index 96% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Form.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Form.java index 6c35720f..e12f985f 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Form.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Form.java @@ -1,4 +1,4 @@ -package net.stzups.scribbleshare.server.http; +package net.stzups.scribbleshare.server.http.objects; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaderNames; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Query.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Query.java similarity index 98% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Query.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Query.java index 13df8c94..0bf79072 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Query.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Query.java @@ -1,4 +1,4 @@ -package net.stzups.scribbleshare.server.http; +package net.stzups.scribbleshare.server.http.objects; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Route.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Route.java similarity index 84% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Route.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Route.java index 953ab45c..3edd9c8e 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Route.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Route.java @@ -1,10 +1,6 @@ -package net.stzups.scribbleshare.server.http; +package net.stzups.scribbleshare.server.http.objects; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; -import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; - -import java.io.File; -import java.util.regex.Pattern; public class Route extends Query { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Uri.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Uri.java similarity index 93% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Uri.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Uri.java index 92f7f01b..64d78457 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/Uri.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Uri.java @@ -1,4 +1,4 @@ -package net.stzups.scribbleshare.server.http; +package net.stzups.scribbleshare.server.http.objects; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java index f5658cac..418c7182 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java @@ -10,8 +10,8 @@ import net.stzups.scribbleshare.room.server.websocket.ClientMessageHandler; import net.stzups.scribbleshare.room.server.websocket.protocol.ClientMessageDecoder; import net.stzups.scribbleshare.room.server.websocket.protocol.ServerMessageEncoder; -import net.stzups.scribbleshare.server.http.HttpAuthenticator; import net.stzups.scribbleshare.server.http.HttpServerInitializer; +import net.stzups.scribbleshare.server.http.handlers.HttpAuthenticator; import javax.net.ssl.SSLException; diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java index 55dc25bc..f5d24ccb 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java @@ -10,7 +10,7 @@ import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessage; import net.stzups.scribbleshare.room.server.websocket.state.State; import net.stzups.scribbleshare.room.server.websocket.state.states.InitialState; -import net.stzups.scribbleshare.server.http.HttpAuthenticator; +import net.stzups.scribbleshare.server.http.handlers.HttpAuthenticator; import java.util.logging.Level; From 1f4526cc6d9c04da7298051d1ceff92e601220ed Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 16:57:45 -0400 Subject: [PATCH 055/144] fix path --- .../scribbleshare/backend/server/http/HttpServerHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 3d35f0d6..7373322c 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -299,7 +299,7 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr sendRedirect(ctx, request, REGISTER_SUCCESS); return; - } else if (route.path().equals(LOGOUT_PAGE)) { + } else if (route.path().equals(LOGOUT_PATH)) { Form form = new Form(request);//todo necessary? HttpHeaders headers = new DefaultHttpHeaders(); From 580acda4e70419fe8c337f316f3d6cf019150688 Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 17:06:49 -0400 Subject: [PATCH 056/144] fix registering while logged in --- .../backend/server/http/HttpServerHandler.java | 13 ++++++++++++- .../net/stzups/scribbleshare/data/objects/User.java | 4 ++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 7373322c..e041b395 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -279,7 +279,15 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr if (cookie != null) { HttpUserSession httpSession = database.getHttpSession(cookie); if (httpSession != null) { - user = database.getUser(httpSession.getUser()); + User u = database.getUser(httpSession.getUser()); + if (u.isRegistered()) { + Scribbleshare.getLogger(ctx).info("Registered user is creating a new account"); + user = new User(username); + database.addUser(user); + } else { + Scribbleshare.getLogger(ctx).info("Temporary user is registering"); + user = u; + } } else { user = new User(username); database.addUser(user); @@ -288,6 +296,9 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr user = new User(username); database.addUser(user); } + + assert !user.isRegistered(); + Login login = new Login(user, password.getBytes(StandardCharsets.UTF_8)); if (!database.addLogin(login)) { Scribbleshare.getLogger(ctx).info("Tried to register with duplicate username " + username); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/User.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/User.java index b2fa15a8..d3d44032 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/User.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/User.java @@ -38,6 +38,10 @@ public Set getSharedDocuments() { return sharedDocuments; } + public boolean isRegistered() { + return !username.equals(""); + } + public String getUsername() { return username; } From 54acb1fa922b4ffa1c8ea2b545b46bcf554ec21b Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 17:29:40 -0400 Subject: [PATCH 057/144] improve login --- .../data/database/implementations/PostgresDatabase.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index 32ec3dd4..47e48161 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -56,7 +56,12 @@ public boolean addLogin(Login login) { preparedStatement.setBinaryStream(3, new ByteArrayInputStream(login.getHashedPassword())); preparedStatement.execute(); } catch (SQLException e) { - return false; + if (e.getSQLState().equals("23505")) { // PostgreSQL error code unique_violation + return false; + } else { + e.printStackTrace(); + return false; + } } return true; From 918727777aab9715e4cd1dfc3b1b8f76c644c800 Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 22:59:05 -0400 Subject: [PATCH 058/144] add proper database exceptions, needs testing --- .../server/http/HttpServerHandler.java | 52 ++++++++++++++----- .../data/database/ScribbleshareDatabase.java | 3 +- .../databases/HttpSessionDatabase.java | 7 ++- .../PersistentHttpSessionDatabase.java | 7 ++- .../database/exception/DatabaseException.java | 7 +++ .../exception/exceptions/FailedException.java | 9 ++++ .../implementations/PostgresDatabase.java | 24 ++++++--- .../scribbleshare/server/http/HttpUtils.java | 15 ++++-- .../exceptions/InternalServerException.java | 16 ++++++ 9 files changed, 106 insertions(+), 34 deletions(-) create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/DatabaseException.java create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/exceptions/FailedException.java create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/InternalServerException.java diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index e041b395..5ade8dbc 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -15,6 +15,7 @@ import io.netty.handler.stream.ChunkedStream; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; +import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.Resource; import net.stzups.scribbleshare.data.objects.User; @@ -25,6 +26,7 @@ import net.stzups.scribbleshare.data.objects.authentication.login.Login; import net.stzups.scribbleshare.server.http.exception.HttpException; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; import net.stzups.scribbleshare.server.http.exception.exceptions.UnauthorizedException; import net.stzups.scribbleshare.server.http.objects.Form; @@ -36,7 +38,6 @@ import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; -import java.sql.SQLException; import java.util.logging.Level; import java.util.regex.Pattern; @@ -124,13 +125,10 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) { } catch (HttpException e) { Scribbleshare.getLogger(ctx).log(Level.WARNING, "Exception while handling HTTP request", e); send(ctx, request, e.responseStatus()); - } catch (Exception e) { - Scribbleshare.getLogger(ctx).log(Level.WARNING, "Exception while handling HTTP request", e); - send(ctx, request, HttpResponseStatus.INTERNAL_SERVER_ERROR); } } - private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { + private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { final Route route; try { route = new Route(request.uri()); @@ -251,10 +249,18 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr HttpHeaders httpHeaders = new DefaultHttpHeaders(); HttpUserSession userSession = new HttpUserSession(config, database.getUser(login.getId()), httpHeaders); - database.addHttpSession(userSession); + try { + database.addHttpSession(userSession); + } catch (FailedException e) { + throw new InternalServerException("Exception while adding http session to database", e); + } if (remember) { PersistentHttpUserSession persistentHttpUserSession = new PersistentHttpUserSession(config, userSession, httpHeaders); - database.addPersistentHttpUserSession(persistentHttpUserSession); + try { + database.addPersistentHttpUserSession(persistentHttpUserSession); + } catch (FailedException e) { + throw new InternalServerException("Exception while adding persistent http session to database", e); + } } sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); return; @@ -300,7 +306,13 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr assert !user.isRegistered(); Login login = new Login(user, password.getBytes(StandardCharsets.UTF_8)); - if (!database.addLogin(login)) { + boolean loginAdded; + try { + loginAdded = database.addLogin(login); + } catch (FailedException e) { + throw new InternalServerException("Exception while adding login for user " + login.getId() + " with username " + login.getUsername(), e); + } + if (!loginAdded) { Scribbleshare.getLogger(ctx).info("Tried to register with duplicate username " + username); sendRedirect(ctx, request, REGISTER_PAGE); return; @@ -319,8 +331,13 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr HttpUserSession httpUserSession = database.getHttpSession(cookie); if (httpUserSession != null) { if (httpUserSession.validate(cookie)) { - database.expireHttpSession(httpUserSession); httpUserSession.clearCookie(config, headers); + try { + database.expireHttpSession(httpUserSession); + } catch (FailedException e) { + //todo still send clear cookie + throw new InternalServerException("Failed to log out user", e); + } } else { Scribbleshare.getLogger(ctx).warning("Tried to log out of existing session with bad authentication"); } @@ -334,8 +351,13 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr PersistentHttpUserSession persistentHttpUserSession = database.getPersistentHttpUserSession(persistentCookie); if (persistentHttpUserSession != null) { if (persistentHttpUserSession.validate(persistentCookie)) { - database.expirePersistentHttpUserSession(persistentHttpUserSession); persistentHttpUserSession.clearCookie(config, headers); + try { + database.expirePersistentHttpUserSession(persistentHttpUserSession); + } catch (FailedException e) { + //todo still send clear cookie + throw new InternalServerException("Failed to log out user", e); + } } else { Scribbleshare.getLogger(ctx).warning("Tried to log out of existing persistent session with bad authentication"); //todo error @@ -402,7 +424,11 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr logIn(ctx, config, request, headers); }*/ headers.set(HttpHeaderNames.CACHE_CONTROL, "public,max-age=" + httpCacheSeconds);//cache but revalidate if stale todo set to private cache for resources behind authentication - sendFile(ctx, request, headers, file, mimeTypes.getMimeType(file)); + try { + sendFile(ctx, request, headers, file, mimeTypes.getMimeType(file)); + } catch (IOException e) { + throw new InternalServerException("Exception while sending file", e); + } } private Long authenticate(ChannelHandlerContext ctx, FullHttpRequest request) throws UnauthorizedException { @@ -424,7 +450,7 @@ private Long authenticate(ChannelHandlerContext ctx, FullHttpRequest request) th throw new UnauthorizedException("Bad authentication"); } - private void logIn(ChannelHandlerContext ctx, HttpConfig config, FullHttpRequest request, HttpHeaders headers) throws SQLException { + private void logIn(ChannelHandlerContext ctx, HttpConfig config, FullHttpRequest request, HttpHeaders headers) throws FailedException { if (!logIn(config, request, headers)) { Scribbleshare.getLogger(ctx).warning("Bad authentication"); send(ctx, request, HttpResponseStatus.UNAUTHORIZED); @@ -434,7 +460,7 @@ private void logIn(ChannelHandlerContext ctx, HttpConfig config, FullHttpRequest } } - private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders headers) throws SQLException { + private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders headers) throws FailedException { HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); if (cookie == null) { User user; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java index 86dcf7f6..7bf1bb7a 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java @@ -3,6 +3,7 @@ import net.stzups.scribbleshare.data.database.databases.HttpSessionDatabase; import net.stzups.scribbleshare.data.database.databases.PersistentHttpSessionDatabase; import net.stzups.scribbleshare.data.database.databases.ResourceDatabase; +import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.InviteCode; import net.stzups.scribbleshare.data.objects.User; @@ -22,5 +23,5 @@ public interface ScribbleshareDatabase extends PersistentHttpSessionDatabase, Re InviteCode getInviteCode(Document document); Login getLogin(String username); /** false if the username already existed */ - boolean addLogin(Login login); + boolean addLogin(Login login) throws FailedException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java index 8fb34152..5c5bf7ca 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java @@ -1,10 +1,9 @@ package net.stzups.scribbleshare.data.database.databases; +import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; -import java.sql.SQLException; - public interface HttpSessionDatabase { /** * Get existing {@link HttpUserSession}, or null if it does not exist @@ -14,10 +13,10 @@ public interface HttpSessionDatabase { /** * Add new {@link HttpUserSession} */ - void addHttpSession(HttpUserSession httpUserSession) throws SQLException; + void addHttpSession(HttpUserSession httpUserSession) throws FailedException; /** * Expire existing {@link HttpUserSession} */ - void expireHttpSession(HttpUserSession httpUserSession) throws SQLException; + void expireHttpSession(HttpUserSession httpUserSession) throws FailedException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java index 37fa122f..3d599cd5 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java @@ -1,10 +1,9 @@ package net.stzups.scribbleshare.data.database.databases; +import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; -import java.sql.SQLException; - public interface PersistentHttpSessionDatabase { /** * Get existing {@link PersistentHttpUserSession}, or null if it does exist @@ -14,10 +13,10 @@ public interface PersistentHttpSessionDatabase { /** * Add new {@link PersistentHttpUserSession} */ - void addPersistentHttpUserSession(PersistentHttpUserSession persistentHttpSession) throws SQLException; + void addPersistentHttpUserSession(PersistentHttpUserSession persistentHttpSession) throws FailedException; /** * Expire existing {@link PersistentHttpUserSession} */ - void expirePersistentHttpUserSession(PersistentHttpUserSession persistentHttpUserSession) throws SQLException; + void expirePersistentHttpUserSession(PersistentHttpUserSession persistentHttpUserSession) throws FailedException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/DatabaseException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/DatabaseException.java new file mode 100644 index 00000000..c8c35e79 --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/DatabaseException.java @@ -0,0 +1,7 @@ +package net.stzups.scribbleshare.data.database.exception; + +public class DatabaseException extends Exception { + protected DatabaseException(Throwable cause) { + super(cause); + } +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/exceptions/FailedException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/exceptions/FailedException.java new file mode 100644 index 00000000..8c20087f --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/exceptions/FailedException.java @@ -0,0 +1,9 @@ +package net.stzups.scribbleshare.data.database.exception.exceptions; + +import net.stzups.scribbleshare.data.database.exception.DatabaseException; + +public class FailedException extends DatabaseException { + public FailedException(Throwable cause) { + super(cause); + } +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index 47e48161..6970f359 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -5,6 +5,7 @@ import io.netty.buffer.Unpooled; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; +import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.InviteCode; import net.stzups.scribbleshare.data.objects.Resource; @@ -49,7 +50,7 @@ public Login getLogin(String username) { } @Override - public boolean addLogin(Login login) { + public boolean addLogin(Login login) throws FailedException { try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO logins(username, user_id, hashed_password) VALUES(?, ?, ?)")) { preparedStatement.setString(1, login.getUsername()); preparedStatement.setLong(2, login.getId()); @@ -59,8 +60,7 @@ public boolean addLogin(Login login) { if (e.getSQLState().equals("23505")) { // PostgreSQL error code unique_violation return false; } else { - e.printStackTrace(); - return false; + throw new FailedException(e); } } @@ -260,7 +260,7 @@ public InviteCode getInviteCode(Document document) {//gets an invite code for a } @Override - public void addPersistentHttpUserSession(PersistentHttpUserSession persistentHttpSession) throws SQLException { + public void addPersistentHttpUserSession(PersistentHttpUserSession persistentHttpSession) throws FailedException { try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO persistent_user_sessions(id, created, expired, user_id, data) VALUES (?, ?, ?, ?, ?)")) { preparedStatement.setLong(1, persistentHttpSession.getId()); preparedStatement.setTimestamp(2, persistentHttpSession.getCreated()); @@ -273,6 +273,8 @@ public void addPersistentHttpUserSession(PersistentHttpUserSession persistentHtt byteBuf.release(); preparedStatement.execute(); + } catch (SQLException e) { + throw new FailedException(e); } } @@ -299,7 +301,7 @@ public HttpUserSession getHttpSession(HttpSessionCookie cookie) { } @Override - public void addHttpSession(HttpUserSession httpUserSession) throws SQLException { + public void addHttpSession(HttpUserSession httpUserSession) throws FailedException { try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO user_sessions(id, created, expired, user_id, data) VALUES (?, ?, ?, ?, ?)")) { preparedStatement.setLong(1, httpUserSession.getId()); preparedStatement.setTimestamp(2, httpUserSession.getCreated()); @@ -312,15 +314,19 @@ public void addHttpSession(HttpUserSession httpUserSession) throws SQLException byteBuf.release(); preparedStatement.execute(); + } catch (SQLException e) { + throw new FailedException(e); } } @Override - public void expireHttpSession(HttpUserSession httpUserSession) throws SQLException { + public void expireHttpSession(HttpUserSession httpUserSession) throws FailedException { try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE user_sessions SET expired=? WHERE id=?")) { preparedStatement.setTimestamp(1, Timestamp.from(Instant.now())); preparedStatement.setLong(2, httpUserSession.getUser()); preparedStatement.execute(); + } catch (SQLException e) { + throw new FailedException(e); } } @@ -339,7 +345,7 @@ private void addResource(long id, long owner, Resource resource) { preparedStatement.setBinaryStream(4, new ByteBufInputStream(resource.getData())); preparedStatement.execute(); } catch (SQLException e) { - throw new RuntimeException(e); + throw new RuntimeException(e);//todo } } @@ -401,10 +407,12 @@ public PersistentHttpUserSession getPersistentHttpUserSession(HttpSessionCookie } @Override - public void expirePersistentHttpUserSession(PersistentHttpUserSession session) throws SQLException { + public void expirePersistentHttpUserSession(PersistentHttpUserSession session) throws FailedException { try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE persistent_user_sessions SET expired=? WHERE id=?; ")) { preparedStatement.setTimestamp(1, Timestamp.from(Instant.now())); preparedStatement.setLong(2, session.getId()); + } catch (SQLException e) { + throw new FailedException(e); } } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java index 00e982f2..084d1c76 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java @@ -23,11 +23,14 @@ import io.netty.handler.stream.ChunkedFile; import io.netty.handler.stream.ChunkedInput; import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import java.io.File; import java.io.FileNotFoundException; +import java.io.IOException; import java.io.RandomAccessFile; import java.sql.Timestamp; +import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.Instant; import java.util.Calendar; @@ -47,13 +50,17 @@ public static void send(ChannelHandlerContext ctx, FullHttpRequest request, Byte send(ctx, request, response); } - public static boolean isModifiedSince(FullHttpRequest request, Timestamp lastModified) throws Exception { + public static boolean isModifiedSince(FullHttpRequest request, Timestamp lastModified) throws BadRequestException { String ifModifiedSince = request.headers().get(HttpHeaderNames.IF_MODIFIED_SINCE); if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) { SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);//todo //round lastModified to nearest second and compare - return Instant.ofEpochSecond(lastModified.getTime() / 1000).isAfter(dateFormatter.parse(ifModifiedSince).toInstant()); + try { + return Instant.ofEpochSecond(lastModified.getTime() / 1000).isAfter(dateFormatter.parse(ifModifiedSince).toInstant()); + } catch (ParseException e) { + throw new BadRequestException("Exception while parsing date " + ifModifiedSince, e); + } } return true; @@ -135,7 +142,7 @@ public static void send(ChannelHandlerContext ctx, FullHttpRequest request, Http } /** sends if stale, otherwise sends not modified */ - public static void sendChunkedResource(ChannelHandlerContext ctx, FullHttpRequest request, HttpHeaders headers, ChunkedInput chunkedInput, Timestamp lastModified) throws Exception { + public static void sendChunkedResource(ChannelHandlerContext ctx, FullHttpRequest request, HttpHeaders headers, ChunkedInput chunkedInput, Timestamp lastModified) throws BadRequestException { setDateAndLastModified(headers, lastModified); if (isModifiedSince(request, lastModified)) { Scribbleshare.getLogger(ctx).info("Uncached"); @@ -158,7 +165,7 @@ public static void sendChunkedResource(ChannelHandlerContext ctx, FullHttpReques } /** make sure the file being sent is valid */ - public static void sendFile(ChannelHandlerContext ctx, FullHttpRequest request, HttpHeaders headers, File file, String mimeType) throws Exception { + public static void sendFile(ChannelHandlerContext ctx, FullHttpRequest request, HttpHeaders headers, File file, String mimeType) throws IOException, BadRequestException { try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r")) { long fileLength = randomAccessFile.length(); if (mimeType == null) { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/InternalServerException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/InternalServerException.java new file mode 100644 index 00000000..8b514ee2 --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/InternalServerException.java @@ -0,0 +1,16 @@ +package net.stzups.scribbleshare.server.http.exception.exceptions; + + +import io.netty.handler.codec.http.HttpResponseStatus; +import net.stzups.scribbleshare.server.http.exception.HttpException; + +public class InternalServerException extends HttpException { + public InternalServerException(String message, Throwable cause) { + super(message, cause); + } + + @Override + public HttpResponseStatus responseStatus() { + return HttpResponseStatus.INTERNAL_SERVER_ERROR; + } +} From c0f45a74474c88beacf73889ea0b277c79d74f47 Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 23:04:12 -0400 Subject: [PATCH 059/144] update CHANGELOG.md --- CHANGELOG.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 641f9a10..804f2448 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -145,7 +145,7 @@ Canvas manipulation did a bunch of commits on master -### v0.6 +## v0.6 Rework project architecture ### v0.6.0 @@ -155,3 +155,12 @@ Typescript refactor ### v0.6.1 Fix build system - Rework rollup with typescript and environment variables + +## v0.7 +HTTP improvements + +### v0.7.0 +Rework authentication +- Robust exception handling +- Password based authentication schemes +- Log in, log out, registration pages \ No newline at end of file From fdd1730b9475f34634e6759944f7c1caca28518f Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 23:08:26 -0400 Subject: [PATCH 060/144] simplify login --- .../backend/server/http/HttpServerHandler.java | 3 +-- .../data/objects/authentication/login/Login.java | 9 ++------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 5ade8dbc..9309872b 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -234,8 +234,7 @@ private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) thr System.out.println(username + ", " + password + ", " + remember); Login login = database.getLogin(username); - Long id = Login.verify(login, password.getBytes(StandardCharsets.UTF_8)); - if (id == null) { + if (Login.verify(login, password.getBytes(StandardCharsets.UTF_8))) { //todo rate limit and generic error handling if (login == null) { Scribbleshare.getLogger(ctx).info("Bad username " + username); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java index 11f1a9da..a8b51320 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java @@ -45,7 +45,7 @@ public byte[] getHashedPassword() { return hashedPassword; } - public static Long verify(Login login, byte[] plaintext) { + public static boolean verify(Login login, byte[] plaintext) { byte[] hashedPassword; if (login == null) { hashedPassword = DUMMY; // still verify hash even when we know it will fail to protect against timing attack @@ -60,11 +60,6 @@ public static Long verify(Login login, byte[] plaintext) { Arrays.fill(hashedPassword, (byte) 0); } - if (verified) { - assert login != null; - return login.id; - } else { - return null; - } + return verified; } } From 4809f7dcfd2ecce993677f278d78f61aa28ce600 Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 23 May 2021 23:14:29 -0400 Subject: [PATCH 061/144] better exception handling in HttpAuthenticator --- .../server/http/HttpServerHandler.java | 4 +-- .../http/handlers/HttpAuthenticator.java | 29 ++++++++++++------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 9309872b..379a9aaa 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -121,14 +121,14 @@ public HttpServerHandler(Config config, ScribbleshareDatabase database) { public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) { Scribbleshare.getLogger(ctx).info(request.method() + " " + request.uri()); try { - channelRead(ctx, request); + handle(ctx, request); } catch (HttpException e) { Scribbleshare.getLogger(ctx).log(Level.WARNING, "Exception while handling HTTP request", e); send(ctx, request, e.responseStatus()); } } - private void channelRead(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { + private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { final Route route; try { route = new Route(request.uri()); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java index e4438fc5..3c41733b 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java @@ -4,14 +4,17 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToMessageDecoder; import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.util.AttributeKey; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.data.database.databases.HttpSessionDatabase; import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; +import net.stzups.scribbleshare.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; +import net.stzups.scribbleshare.server.http.exception.exceptions.UnauthorizedException; import java.util.List; +import java.util.logging.Level; import static net.stzups.scribbleshare.server.http.HttpUtils.send; @@ -35,16 +38,23 @@ public HttpAuthenticator(HttpSessionDatabase httpSessionDatabase, String uri) { } @Override - protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List out) throws Exception { + protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List out) { + try { + handle(ctx, request); + } catch (HttpException e) { + Scribbleshare.getLogger(ctx).log(Level.WARNING, "Exception while handling HTTP request", e); + send(ctx, request, e.responseStatus()); + } + out.add(request.retain()); + } + + private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { if (uri != null && !request.uri().equals(uri)) { - send(ctx, request, HttpResponseStatus.NOT_FOUND); - Scribbleshare.getLogger(ctx).warning("Bad uri"); - return; + throw new NotFoundException("Bad uri"); } Long user = ctx.channel().attr(USER).get(); if (user != null) { - out.add(request.retain()); return; } @@ -54,16 +64,13 @@ protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List Date: Sun, 23 May 2021 23:19:19 -0400 Subject: [PATCH 062/144] add exceptions to HttpHandler --- .../server/http/handlers/HttpHandler.java | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpHandler.java index 16fcaf69..46fc3956 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpHandler.java @@ -6,9 +6,13 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; import java.net.InetSocketAddress; import java.util.List; +import java.util.logging.Level; import static net.stzups.scribbleshare.server.http.HttpUtils.send; @@ -16,26 +20,32 @@ public class HttpHandler extends MessageToMessageDecoder { @Override protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List out) { + try { + if (!handle(ctx, request)) { + out.add(request.retain()); + } + } catch (HttpException e) { + Scribbleshare.getLogger(ctx).log(Level.WARNING, "Exception while handling HTTP request", e); + send(ctx, request, e.responseStatus()); + } + } + + private boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { Scribbleshare.getLogger(ctx).info(request.method() + " " + request.uri()); - if (request.decoderResult().isFailure()) { - send(ctx, request, HttpResponseStatus.BAD_REQUEST); - Scribbleshare.getLogger(ctx).info("Bad request"); - return; - } + if (request.decoderResult().isFailure()) + throw new BadRequestException("Bad request"); if (request.uri().equals("/healthcheck")) { if (!((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().isLoopbackAddress()) { - send(ctx, request, HttpResponseStatus.NOT_FOUND); - Scribbleshare.getLogger(ctx).warning("Healthcheck request from address which is not a loopback address"); + throw new NotFoundException("Healthcheck request from address which is not a loopback address"); } else { send(ctx, request, HttpResponseStatus.OK); Scribbleshare.getLogger(ctx).info("Good healthcheck response"); + return true; } - - return; } - out.add(request.retain()); + return false; } } From d6d8763a909ad9f3af1445845ead964c461a977d Mon Sep 17 00:00:00 2001 From: stzups Date: Mon, 24 May 2021 08:40:04 -0400 Subject: [PATCH 063/144] more exception handling --- .../backend/server/http/HttpServerHandler.java | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 379a9aaa..7d5a3db1 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -419,8 +419,12 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H } HttpHeaders headers = new DefaultHttpHeaders(); -/* if (path.equals(AUTHENTICATE_PAGE)) { - logIn(ctx, config, request, headers); + /*if (route.equals(AUTHENTICATE_PAGE)) { + try { + logIn(config, request, headers); + } catch (FailedException e) { + throw new InternalServerException("Exception while logging user in", e); + } }*/ headers.set(HttpHeaderNames.CACHE_CONTROL, "public,max-age=" + httpCacheSeconds);//cache but revalidate if stale todo set to private cache for resources behind authentication try { @@ -449,16 +453,6 @@ private Long authenticate(ChannelHandlerContext ctx, FullHttpRequest request) th throw new UnauthorizedException("Bad authentication"); } - private void logIn(ChannelHandlerContext ctx, HttpConfig config, FullHttpRequest request, HttpHeaders headers) throws FailedException { - if (!logIn(config, request, headers)) { - Scribbleshare.getLogger(ctx).warning("Bad authentication"); - send(ctx, request, HttpResponseStatus.UNAUTHORIZED); - //todo rate limiting strategies - } else { - Scribbleshare.getLogger(ctx).info("Good authentication"); - } - } - private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders headers) throws FailedException { HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); if (cookie == null) { From 34a7840ae13f4307ca15f94f1bfb40e6a3ff9407 Mon Sep 17 00:00:00 2001 From: stzups Date: Mon, 24 May 2021 12:14:40 -0400 Subject: [PATCH 064/144] move authentication to HttpUserSession --- .../server/http/HttpServerHandler.java | 83 +++--------- .../data/database/ScribbleshareDatabase.java | 4 +- .../implementations/PostgresDatabase.java | 8 +- .../exceptions/InternalServerException.java | 4 + .../http/handlers/HttpAuthenticator.java | 126 +++++++++++++++--- .../state/states/HandshakeState.java | 8 +- 6 files changed, 142 insertions(+), 91 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 7d5a3db1..c3856319 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -10,7 +10,6 @@ import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.stream.ChunkedStream; import net.stzups.scribbleshare.Scribbleshare; @@ -288,18 +287,30 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H if (u.isRegistered()) { Scribbleshare.getLogger(ctx).info("Registered user is creating a new account"); user = new User(username); - database.addUser(user); + try { + database.addUser(user); + } catch (FailedException e) { + throw new InternalServerException("todo", e); + } } else { Scribbleshare.getLogger(ctx).info("Temporary user is registering"); user = u; } } else { user = new User(username); - database.addUser(user); + try { + database.addUser(user); + } catch (FailedException e) { + throw new InternalServerException("todo", e); + } } } else { user = new User(username); - database.addUser(user); + try { + database.addUser(user); + } catch (FailedException e) { + throw new InternalServerException("todo", e); + } } assert !user.isRegistered(); @@ -434,70 +445,6 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H } } - private Long authenticate(ChannelHandlerContext ctx, FullHttpRequest request) throws UnauthorizedException { - HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); - if (cookie != null) { - HttpUserSession httpSession = database.getHttpSession(cookie); - if (httpSession != null && httpSession.validate(cookie)) { - Scribbleshare.getLogger(ctx).info("Authenticated with id " + httpSession.getUser()); - return httpSession.getUser(); - } else { - Scribbleshare.getLogger(ctx).warning("Bad authentication"); - //bad authentication attempt - //todo rate limit timeout server a proper response??? - } - } else { - Scribbleshare.getLogger(ctx).info("No authentication"); - } - - throw new UnauthorizedException("Bad authentication"); - } - - private boolean logIn(HttpConfig config, HttpRequest request, HttpHeaders headers) throws FailedException { - HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); - if (cookie == null) { - User user; - HttpSessionCookie cookiePersistent = HttpSessionCookie.getHttpSessionCookie(request, PersistentHttpUserSession.COOKIE_NAME); - if (cookiePersistent != null) { - PersistentHttpUserSession persistentHttpSession = database.getPersistentHttpUserSession(cookiePersistent); - if (persistentHttpSession != null && persistentHttpSession.validate(cookiePersistent)) { - user = database.getUser(persistentHttpSession.getUser()); - } else { - //return false; todo - user = new User(); - database.addUser(user); - } - } else { - user = new User(); - database.addUser(user); - } - - HttpUserSession httpSession = new HttpUserSession(config, user, headers); - database.addHttpSession(httpSession); - - //this is single use and always refreshed - PersistentHttpUserSession persistentHttpSession = new PersistentHttpUserSession(config, httpSession, headers); - database.addPersistentHttpUserSession(persistentHttpSession); - return true; - } else { - HttpUserSession httpSession = database.getHttpSession(cookie); - if (httpSession != null && httpSession.validate(cookie)) { - return true; - } else { - //todo copied and bad - User user = new User(); - database.addUser(user); - httpSession = new HttpUserSession(config, user, headers); - database.addHttpSession(httpSession); - - //this is single use and always refreshed - PersistentHttpUserSession persistentHttpSession = new PersistentHttpUserSession(config, httpSession, headers); - database.addPersistentHttpUserSession(persistentHttpSession); - return true; - } - } - } - private static final Pattern ALLOWED_PATH = Pattern.compile("^[\\\\" + File.separator + "." + Uri.FILE_NAME_REGEX + "]+$"); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java index 7bf1bb7a..a696cacf 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java @@ -10,9 +10,9 @@ import net.stzups.scribbleshare.data.objects.authentication.login.Login; public interface ScribbleshareDatabase extends PersistentHttpSessionDatabase, ResourceDatabase, HttpSessionDatabase { - void addUser(User user); + void addUser(User user) throws FailedException; User getUser(long id); - void updateUser(User user); + void updateUser(User user) throws FailedException; Document createDocument(User owner); Document getDocument(long id); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index 6970f359..bd29235a 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -101,7 +101,7 @@ public void close() throws SQLException { } @Override - public void addUser(User user) { + public void addUser(User user) throws FailedException { try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO users(id, owned_documents, shared_documents, username) VALUES (?, ?, ?, ?)")) { preparedStatement.setLong(1, user.getId()); preparedStatement.setArray(2, connection.createArrayOf("bigint", user.getOwnedDocuments().toArray())); @@ -109,7 +109,7 @@ public void addUser(User user) { preparedStatement.setString(4, user.getUsername()); preparedStatement.execute(); } catch (SQLException e) { - e.printStackTrace(); + throw new FailedException(e); } } @@ -134,14 +134,14 @@ public User getUser(long id) { } @Override - public void updateUser(User user) { + public void updateUser(User user) throws FailedException { try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE users SET owned_documents=?, shared_documents=? WHERE id=?")){ preparedStatement.setArray(1, connection.createArrayOf("bigint", user.getOwnedDocuments().toArray())); preparedStatement.setArray(2, connection.createArrayOf("bigint", user.getSharedDocuments().toArray())); preparedStatement.setLong(3, user.getId()); preparedStatement.execute(); } catch (SQLException e) { - e.printStackTrace(); + throw new FailedException(e); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/InternalServerException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/InternalServerException.java index 8b514ee2..8c2b8a4e 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/InternalServerException.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/InternalServerException.java @@ -5,6 +5,10 @@ import net.stzups.scribbleshare.server.http.exception.HttpException; public class InternalServerException extends HttpException { + public InternalServerException(String message) { + super(message); + } + public InternalServerException(String message, Throwable cause) { super(message, cause); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java index 3c41733b..7b9b8b65 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java @@ -4,12 +4,20 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToMessageDecoder; import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaders; import io.netty.util.AttributeKey; import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.database.databases.HttpSessionDatabase; +import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; +import net.stzups.scribbleshare.data.objects.User; +import net.stzups.scribbleshare.data.objects.authentication.AuthenticatedUserSession; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; +import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; import net.stzups.scribbleshare.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; import net.stzups.scribbleshare.server.http.exception.exceptions.UnauthorizedException; @@ -26,14 +34,16 @@ public static Long getUser(ChannelHandlerContext ctx) { } private final HttpSessionDatabase httpSessionDatabase; + private final HttpConfig httpConfig; private final String uri; - public HttpAuthenticator(HttpSessionDatabase httpSessionDatabase) { - this(httpSessionDatabase, null); + public HttpAuthenticator(HttpSessionDatabase httpSessionDatabase, HttpConfig httpConfig) { + this(httpSessionDatabase, httpConfig, null); } - public HttpAuthenticator(HttpSessionDatabase httpSessionDatabase, String uri) { + public HttpAuthenticator(HttpSessionDatabase httpSessionDatabase, HttpConfig httpConfig, String uri) { this.httpSessionDatabase = httpSessionDatabase; + this.httpConfig = httpConfig; this.uri = uri; } @@ -58,19 +68,103 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H return; } - HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); - if (cookie != null) { - HttpUserSession httpSession = httpSessionDatabase.getHttpSession(cookie); - if (httpSession != null && httpSession.validate(cookie)) { - Scribbleshare.getLogger(ctx).info("Authenticated with id " + httpSession.getUser()); - ctx.channel().attr(USER).set(httpSession.getUser()); - } else { - //bad authentication attempt - //todo rate limit timeout server a proper response??? - throw new UnauthorizedException("Bad authentication"); - } - } else { - throw new UnauthorizedException("No authentication"); + ctx.channel().attr(USER).set(authenticateHttpUserSession(request, httpSessionDatabase)); + } + + /** authenticates */ + public static AuthenticatedUserSession authenticateHttpUserSession(FullHttpRequest request, HttpSessionDatabase database) throws UnauthorizedException { + HttpSessionCookie sessionCookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); + if (sessionCookie == null) { + return null; + } + + HttpUserSession userSession = database.getHttpSession(sessionCookie); + if (userSession == null) { + throw new UnauthorizedException("Bad authentication (bad id)"); + } + + if (!userSession.validate(sessionCookie)) { + throw new UnauthorizedException("Bad authentication (bad validation)"); } + + return userSession; + } + + /** create session and persistent session for user */ + private static HttpUserSession createHttpSession(User user, HttpConfig httpConfig, ScribbleshareDatabase database, HttpHeaders httpHeaders) throws InternalServerException { + // create session + HttpUserSession httpUserSession = new HttpUserSession(httpConfig, user, httpHeaders); + try { + database.addHttpSession(httpUserSession); + } catch (FailedException e) { + throw new InternalServerException("Failed to add http session", e); + } + + // create new persistent session + PersistentHttpUserSession a = new PersistentHttpUserSession(httpConfig, httpUserSession, httpHeaders); + try { + database.addPersistentHttpUserSession(a); + } catch (FailedException e) { + throw new InternalServerException("Failed to add persistent http session", e); + } + + return httpUserSession; + } + + /** logs in if not authenticated */ + public static HttpUserSession logInHttpSession(FullHttpRequest request, ScribbleshareDatabase database, HttpHeaders httpHeaders, HttpConfig httpConfig) throws UnauthorizedException, InternalServerException { + HttpUserSession session = authenticateHttpUserSession(request, database); + if (session != null) { + return session; + } + + // check for persistent login + HttpSessionCookie sessionCookie = HttpSessionCookie.getHttpSessionCookie(request, PersistentHttpUserSession.COOKIE_NAME); + if (sessionCookie == null) { + return null; + } + + // use persistent login + PersistentHttpUserSession persistentHttpUserSession = database.getPersistentHttpUserSession(sessionCookie); + if (persistentHttpUserSession == null) { + throw new UnauthorizedException("Bad authentication (bad id)"); + } + + // expire persistent login + try { + database.expirePersistentHttpUserSession(persistentHttpUserSession); + } catch (FailedException e) { + throw new InternalServerException("Failed to expire persistent http session", e); + } + + // validate persistent login + if (!persistentHttpUserSession.validate(sessionCookie)) { + throw new UnauthorizedException("Bad authentication (bad validation)"); + } + // now logged in + + User user = database.getUser(persistentHttpUserSession.getId()); + if (user == null) { + throw new InternalServerException("User somehow does not exist " + persistentHttpUserSession.getUser()); + } + + return createHttpSession(user, httpConfig, database, httpHeaders); + } + + /** creates new user if not logged in or authenticated */ + public static HttpUserSession createHttpSession(FullHttpRequest request, ScribbleshareDatabase database, HttpConfig httpConfig, HttpHeaders httpHeaders) throws UnauthorizedException, InternalServerException { + HttpUserSession session = logInHttpSession(request, database, httpHeaders, httpConfig); + if (session != null) { + return session; + } + + User user = new User(); + try { + database.addUser(user); + } catch (FailedException e) { + throw new InternalServerException("Failed to add user", e); + } + + return createHttpSession(user, httpConfig, database, httpHeaders); } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java index 6a010f59..42524960 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java @@ -2,6 +2,7 @@ import io.netty.channel.ChannelHandlerContext; import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.InviteCode; import net.stzups.scribbleshare.data.objects.User; @@ -45,7 +46,12 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro //if this isn't the user's own document and this isn't part of the user's shared documents then add and update if (document.getOwner() != client.getUser().getId()) { if (client.getUser().getSharedDocuments().add(document.getId())) { - RoomHttpServerInitializer.getDatabase(ctx).updateUser(client.getUser()); + try { + RoomHttpServerInitializer.getDatabase(ctx).updateUser(client.getUser()); + } catch (FailedException e) { + e.printStackTrace(); + //todo + } } } try { From 17e001fd6429695594b1f585a97114fce10f51d1 Mon Sep 17 00:00:00 2001 From: stzups Date: Mon, 24 May 2021 13:12:24 -0400 Subject: [PATCH 065/144] start to rework http cookie --- .../http/HttpSessionCookie.java | 83 +++++++++++++++---- 1 file changed, 67 insertions(+), 16 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java index 6cb65fdb..63ded16b 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java @@ -4,9 +4,15 @@ import io.netty.buffer.Unpooled; import io.netty.handler.codec.base64.Base64; import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.cookie.Cookie; +import io.netty.handler.codec.http.cookie.CookieHeaderNames; +import io.netty.handler.codec.http.cookie.DefaultCookie; import io.netty.handler.codec.http.cookie.ServerCookieDecoder; +import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; +import net.stzups.scribbleshare.server.http.HttpUtils; +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import java.nio.charset.StandardCharsets; import java.util.Set; @@ -15,10 +21,14 @@ public class HttpSessionCookie { private final long id; private final byte[] token; - HttpSessionCookie(ByteBuf byteBuf) { - id = byteBuf.readLong(); - token = new byte[UserSession.TOKEN_LENGTH]; - byteBuf.readBytes(token); + HttpSessionCookie(ByteBuf byteBuf, int tokenLength) throws DeserializationException { + try { + id = byteBuf.readLong(); + token = new byte[tokenLength]; + byteBuf.readBytes(token); + } catch (IndexOutOfBoundsException e) { + throw new DeserializationException("Exception while deserializing HttpSessionCookie", e); + } } public long getId() { @@ -29,21 +39,62 @@ public byte[] getToken() { return token; } - public static HttpSessionCookie getHttpSessionCookie(HttpRequest request, String name) { + private static void setCookie(HttpConfig config, DefaultCookie cookie) { + cookie.setDomain(config.getDomain()); + if (config.getSSL()) cookie.setSecure(true); + cookie.setHttpOnly(true); + cookie.setSameSite(CookieHeaderNames.SameSite.Strict); + } + + public void setCookie(HttpConfig config, String name, HttpHeaders headers, long id, byte[] token) { + ByteBuf tokenBuffer = Unpooled.buffer(); + tokenBuffer.writeLong(id); + tokenBuffer.writeBytes(token); + ByteBuf tokenBase64 = Base64.encode(tokenBuffer); + tokenBuffer.release(); + + DefaultCookie cookie = new DefaultCookie(name, tokenBase64.toString(StandardCharsets.UTF_8)); + tokenBase64.release(); + + setCookie(config, cookie); + + HttpUtils.setCookie(headers, cookie); + } + + public static void clearCookie(HttpConfig config, String name, HttpHeaders headers) { + DefaultCookie cookie = new DefaultCookie(name, ""); + + setCookie(config, cookie); + cookie.setMaxAge(0); + + HttpUtils.setCookie(headers, cookie); + } + + public static HttpSessionCookie getCookie(HttpRequest request, String name, int tokenLength) throws BadRequestException { String cookiesHeader = request.headers().get(HttpHeaderNames.COOKIE); - if (cookiesHeader != null) { - Set cookies = ServerCookieDecoder.STRICT.decode(cookiesHeader); - for (Cookie cookie : cookies) { - if (cookie.name().equals(name)) { - ByteBuf tokenBase64 = Unpooled.wrappedBuffer(cookie.value().getBytes(StandardCharsets.UTF_8)); - ByteBuf token = Base64.decode(tokenBase64); - tokenBase64.release(); - HttpSessionCookie c = new HttpSessionCookie(token); - token.release(); - return c; - } + if (cookiesHeader == null) + return null; + + Set cookies = ServerCookieDecoder.STRICT.decode(cookiesHeader); + for (Cookie cookie : cookies) { + if (!cookie.name().equals(name)) { + continue; + } + + ByteBuf tokenBase64 = Unpooled.wrappedBuffer(cookie.value().getBytes(StandardCharsets.UTF_8)); + ByteBuf token = Base64.decode(tokenBase64); + tokenBase64.release(); + HttpSessionCookie httpSessionCookie; + try { + httpSessionCookie = new HttpSessionCookie(token, tokenLength); + } catch (DeserializationException e) { + throw new BadRequestException("Malformed cookie content", e); + } finally { + token.release(); } + return httpSessionCookie; } + return null; } } \ No newline at end of file From aa26cace47b3765382a10eb5cc0927ab84ff84dd Mon Sep 17 00:00:00 2001 From: stzups Date: Mon, 24 May 2021 23:52:14 -0400 Subject: [PATCH 066/144] start to refactor all the cookies --- .../implementations/PostgresDatabase.java | 6 +- .../AuthenticatedUserSession.java | 13 +++++ .../AuthenticationException.java | 7 +++ .../{http => }/UserSession.java | 14 +++-- .../http/HttpSessionCookie.java | 34 ++++++----- .../authentication/http/HttpUserSession.java | 46 +++------------ .../http/HttpUserSessionCookie.java | 38 +++++++++++++ .../http/PersistentHttpUserSession.java | 31 +++------- .../http/PersistentHttpUserSessionCookie.java | 48 ++++++++++++++++ .../exceptions/UnauthorizedException.java | 4 ++ .../http/handlers/HttpAuthenticator.java | 56 ++++++++++++------- 11 files changed, 192 insertions(+), 105 deletions(-) create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticatedUserSession.java create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticationException.java rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/{http => }/UserSession.java (81%) create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSessionCookie.java create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index bd29235a..4e51d93d 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -160,7 +160,11 @@ public Document createDocument(User owner) { } addResource(document.getId(), document.getId(), new Resource(Canvas.getEmptyCanvas())); owner.getOwnedDocuments().add(document.getId()); - updateUser(owner);//todo + try { + updateUser(owner);//todo + } catch (FailedException e) { + e.printStackTrace(); + } return document; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticatedUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticatedUserSession.java new file mode 100644 index 00000000..c98231ac --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticatedUserSession.java @@ -0,0 +1,13 @@ +package net.stzups.scribbleshare.data.objects.authentication; + +public class AuthenticatedUserSession { + private final long userId; + + public AuthenticatedUserSession(long userId) { + this.userId = userId; + } + + public long getUserId() { + return userId; + } +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticationException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticationException.java new file mode 100644 index 00000000..6ae401e9 --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticationException.java @@ -0,0 +1,7 @@ +package net.stzups.scribbleshare.data.objects.authentication; + +public class AuthenticationException extends Exception { + public AuthenticationException(String message) { + super(message); + } +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/UserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/UserSession.java similarity index 81% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/UserSession.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/UserSession.java index 5149bf57..a25d2ce5 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/UserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/UserSession.java @@ -1,6 +1,7 @@ -package net.stzups.scribbleshare.data.objects.authentication.http; +package net.stzups.scribbleshare.data.objects.authentication; import io.netty.buffer.ByteBuf; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -10,7 +11,6 @@ import java.util.Arrays; public class UserSession { - protected static final int TOKEN_LENGTH = 16; private static final int HASHED_TOKEN_LENGTH = 32; private static final SecureRandom secureRandom = new SecureRandom(); @@ -46,7 +46,7 @@ public UserSession(long id, Timestamp created, Timestamp expired, long userId, B } protected byte[] generateToken() { - byte[] token = new byte[TOKEN_LENGTH]; + byte[] token = new byte[HttpSessionCookie.TOKEN_LENGTH]; secureRandom.nextBytes(token); System.arraycopy(messageDigest.digest(token), 0, hashedToken, 0, hashedToken.length); @@ -73,8 +73,12 @@ public byte[] getHashedToken() { return hashedToken; } - protected boolean validate(byte[] token) { - return Arrays.equals(messageDigest.digest(token), this.hashedToken) && created.equals(expired); + protected void validate(byte[] token) throws AuthenticationException { + if (!Arrays.equals(messageDigest.digest(token), this.hashedToken)) + throw new AuthenticationException("Bad token"); + + if (!created.equals(expired)) + throw new AuthenticationException("Expired session"); } public void serialize(ByteBuf byteBuf) { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java index 63ded16b..6730bdf3 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java @@ -12,25 +12,31 @@ import io.netty.handler.codec.http.cookie.ServerCookieDecoder; import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; import net.stzups.scribbleshare.server.http.HttpUtils; -import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import java.nio.charset.StandardCharsets; import java.util.Set; public class HttpSessionCookie { + public static final int TOKEN_LENGTH = 16; + private final long id; private final byte[] token; - HttpSessionCookie(ByteBuf byteBuf, int tokenLength) throws DeserializationException { + HttpSessionCookie(ByteBuf byteBuf) throws DeserializationException { try { id = byteBuf.readLong(); - token = new byte[tokenLength]; + token = new byte[TOKEN_LENGTH]; byteBuf.readBytes(token); } catch (IndexOutOfBoundsException e) { throw new DeserializationException("Exception while deserializing HttpSessionCookie", e); } } + HttpSessionCookie(long id, byte[] token) { + this.id = id; + this.token = token; + } + public long getId() { return id; } @@ -39,14 +45,14 @@ public byte[] getToken() { return token; } - private static void setCookie(HttpConfig config, DefaultCookie cookie) { + protected static void setCookie(HttpConfig config, DefaultCookie cookie) { cookie.setDomain(config.getDomain()); if (config.getSSL()) cookie.setSecure(true); cookie.setHttpOnly(true); cookie.setSameSite(CookieHeaderNames.SameSite.Strict); } - public void setCookie(HttpConfig config, String name, HttpHeaders headers, long id, byte[] token) { + public void setCookie(HttpConfig config, String name, HttpHeaders headers) { ByteBuf tokenBuffer = Unpooled.buffer(); tokenBuffer.writeLong(id); tokenBuffer.writeBytes(token); @@ -70,7 +76,7 @@ public static void clearCookie(HttpConfig config, String name, HttpHeaders heade HttpUtils.setCookie(headers, cookie); } - public static HttpSessionCookie getCookie(HttpRequest request, String name, int tokenLength) throws BadRequestException { + public static ByteBuf getCookie(HttpRequest request, String name) { String cookiesHeader = request.headers().get(HttpHeaderNames.COOKIE); if (cookiesHeader == null) return null; @@ -81,18 +87,10 @@ public static HttpSessionCookie getCookie(HttpRequest request, String name, int continue; } - ByteBuf tokenBase64 = Unpooled.wrappedBuffer(cookie.value().getBytes(StandardCharsets.UTF_8)); - ByteBuf token = Base64.decode(tokenBase64); - tokenBase64.release(); - HttpSessionCookie httpSessionCookie; - try { - httpSessionCookie = new HttpSessionCookie(token, tokenLength); - } catch (DeserializationException e) { - throw new BadRequestException("Malformed cookie content", e); - } finally { - token.release(); - } - return httpSessionCookie; + ByteBuf valueBase64 = Unpooled.wrappedBuffer(cookie.value().getBytes(StandardCharsets.UTF_8)); + ByteBuf value = Base64.decode(valueBase64); + valueBase64.release(); + return value; } return null; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java index c5779f8a..7f03b4c3 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java @@ -1,16 +1,12 @@ package net.stzups.scribbleshare.data.objects.authentication.http; import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.handler.codec.base64.Base64; import io.netty.handler.codec.http.HttpHeaders; -import io.netty.handler.codec.http.cookie.Cookie; -import io.netty.handler.codec.http.cookie.CookieHeaderNames; -import io.netty.handler.codec.http.cookie.DefaultCookie; import net.stzups.scribbleshare.data.objects.User; -import net.stzups.scribbleshare.server.http.HttpUtils; +import net.stzups.scribbleshare.data.objects.authentication.AuthenticatedUserSession; +import net.stzups.scribbleshare.data.objects.authentication.AuthenticationException; +import net.stzups.scribbleshare.data.objects.authentication.UserSession; -import java.nio.charset.StandardCharsets; import java.sql.Timestamp; import java.time.Duration; import java.time.Instant; @@ -18,49 +14,25 @@ public class HttpUserSession extends UserSession { private static final Duration MAX_AGE = Duration.ofDays(1); - public static final String COOKIE_NAME = "session"; - protected HttpUserSession(long user) { super(user); } public HttpUserSession(HttpConfig config, User user, HttpHeaders headers) { super(user.getId()); - HttpUtils.setCookie(headers, getCookie(config)); + new HttpUserSessionCookie(getId(), generateToken()).setCookie(config, headers); } public HttpUserSession(long id, Timestamp creation, Timestamp expiration, long userId, ByteBuf byteBuf) { super(id, creation, expiration, userId, byteBuf); } - protected String getCookieName() { - return COOKIE_NAME; - } - - public DefaultCookie getCookie(HttpConfig config) { - ByteBuf token = Unpooled.buffer(); - token.writeLong(getId()); - token.writeBytes(super.generateToken()); - ByteBuf tokenBase64 = Base64.encode(token); - DefaultCookie cookie = new DefaultCookie(getCookieName(), tokenBase64.toString(StandardCharsets.UTF_8)); - tokenBase64.release(); - token.release(); - - cookie.setDomain(config.getDomain()); - if (config.getSSL()) cookie.setSecure(true); - cookie.setHttpOnly(true); - cookie.setSameSite(CookieHeaderNames.SameSite.Strict); + public AuthenticatedUserSession validate(HttpSessionCookie cookie) throws AuthenticationException { + if (!Instant.now().isBefore(getCreated().toInstant().plus(MAX_AGE))) + throw new AuthenticationException("Session is expired"); - return cookie; - } - - public void clearCookie(HttpConfig config, HttpHeaders headers) { - Cookie cookie = getCookie(config); - cookie.setMaxAge(0); - HttpUtils.setCookie(headers, cookie); - } + validate(cookie.getToken()); - public boolean validate(HttpSessionCookie cookie) { - return validate(cookie.getToken()) && Instant.now().isBefore(getCreated().toInstant().plus(MAX_AGE)); + return new AuthenticatedUserSession(getUser()); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSessionCookie.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSessionCookie.java new file mode 100644 index 00000000..a6e5e35c --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSessionCookie.java @@ -0,0 +1,38 @@ +package net.stzups.scribbleshare.data.objects.authentication.http; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpRequest; +import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; + +public class HttpUserSessionCookie extends HttpSessionCookie { + private static final String COOKIE_NAME = "session"; + + public HttpUserSessionCookie(ByteBuf byteBuf) throws DeserializationException { + super(byteBuf); + } + + public HttpUserSessionCookie(long id, byte[] token) { + super(id, token); + } + + public void setCookie(HttpConfig config, HttpHeaders headers) { + setCookie(config, COOKIE_NAME, headers); + } + + public static HttpUserSessionCookie getHttpUserSessionCookie(HttpRequest request) throws BadRequestException { + ByteBuf byteBuf = HttpSessionCookie.getCookie(request, COOKIE_NAME); + if (byteBuf != null) { + try { + return new HttpUserSessionCookie(byteBuf); + } catch (DeserializationException e) { + throw new BadRequestException("Malformed cookie", e); + } finally { + byteBuf.release(); + } + } + + return null; + } +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java index 307b32b5..fad670d7 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java @@ -2,46 +2,31 @@ import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.HttpHeaders; -import io.netty.handler.codec.http.cookie.DefaultCookie; -import net.stzups.scribbleshare.server.http.HttpUtils; +import net.stzups.scribbleshare.data.objects.authentication.AuthenticationException; +import net.stzups.scribbleshare.data.objects.authentication.UserSession; import java.sql.Timestamp; import java.time.Duration; import java.time.Instant; -import java.time.temporal.ChronoUnit; -public class PersistentHttpUserSession extends HttpUserSession { +public class PersistentHttpUserSession extends UserSession { private static final Duration MAX_AGE = Duration.ofDays(90); - public static final String COOKIE_NAME = "persistent_session"; public static final String LOGIN_PATH = "/login"; - public PersistentHttpUserSession(HttpConfig config, HttpUserSession httpSession, HttpHeaders headers) { super(httpSession.getUser()); - HttpUtils.setCookie(headers, getCookie(config)); + new PersistentHttpUserSessionCookie(getId(), generateToken()).setCookie(config, headers); } public PersistentHttpUserSession(long id, Timestamp creation, Timestamp expiration, long userId, ByteBuf byteBuf) { super(id, creation, expiration, userId, byteBuf); } - @Override - protected String getCookieName() { - return COOKIE_NAME; - } - - @Override - public DefaultCookie getCookie(HttpConfig config) { - DefaultCookie cookie = super.getCookie(config); - - cookie.setMaxAge(MAX_AGE.get(ChronoUnit.SECONDS)); //persistent cookie - - return cookie; - } + public void validate(HttpSessionCookie cookie) throws AuthenticationException { + if (!Instant.now().isBefore(getCreated().toInstant().plus(MAX_AGE))) + throw new AuthenticationException("Session is too old"); - @Override - public boolean validate(HttpSessionCookie cookie) { - return validate(cookie.getToken()) && Instant.now().isBefore(getCreated().toInstant().plus(MAX_AGE)); + validate(cookie.getToken()); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java new file mode 100644 index 00000000..5fc79dec --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java @@ -0,0 +1,48 @@ +package net.stzups.scribbleshare.data.objects.authentication.http; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.cookie.DefaultCookie; +import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; + +import java.time.Duration; +import java.time.temporal.ChronoUnit; + +public class PersistentHttpUserSessionCookie extends HttpSessionCookie { + private static final String COOKIE_NAME = "persistent_session"; + private static final Duration MAX_AGE = Duration.ofDays(90); + + PersistentHttpUserSessionCookie(ByteBuf byteBuf) throws DeserializationException { + super(byteBuf); + } + + PersistentHttpUserSessionCookie(long id, byte[] token) { + super(id, token); + } + + protected static void setCookie(HttpConfig config, DefaultCookie cookie) { + HttpUserSessionCookie.setCookie(config, cookie); + cookie.setMaxAge(MAX_AGE.get(ChronoUnit.SECONDS)); //persistent cookie + } + + public void setCookie(HttpConfig config, HttpHeaders headers) { + setCookie(config, COOKIE_NAME, headers); + } + + public HttpUserSessionCookie getHttpUserSessionCookie(HttpRequest request) throws BadRequestException { + ByteBuf byteBuf = HttpSessionCookie.getCookie(request, COOKIE_NAME); + if (byteBuf != null) { + try { + return new HttpUserSessionCookie(byteBuf); + } catch (DeserializationException e) { + throw new BadRequestException("Malformed cookie", e); + } finally { + byteBuf.release(); + } + } + + return null; + } +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/UnauthorizedException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/UnauthorizedException.java index 4b0b91a9..88c41721 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/UnauthorizedException.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/UnauthorizedException.java @@ -8,6 +8,10 @@ public UnauthorizedException(String message) { super(message); } + public UnauthorizedException(String message, Exception e) { + super(message, e); + } + @Override public HttpResponseStatus responseStatus() { return HttpResponseStatus.UNAUTHORIZED; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java index 7b9b8b65..9c5b5727 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java @@ -12,11 +12,14 @@ import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; import net.stzups.scribbleshare.data.objects.User; import net.stzups.scribbleshare.data.objects.authentication.AuthenticatedUserSession; +import net.stzups.scribbleshare.data.objects.authentication.AuthenticationException; import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; import net.stzups.scribbleshare.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; import net.stzups.scribbleshare.server.http.exception.exceptions.UnauthorizedException; @@ -28,8 +31,8 @@ @ChannelHandler.Sharable public class HttpAuthenticator extends MessageToMessageDecoder { - private static final AttributeKey USER = AttributeKey.valueOf(HttpAuthenticator.class, "USER"); - public static Long getUser(ChannelHandlerContext ctx) { + private static final AttributeKey USER = AttributeKey.valueOf(HttpAuthenticator.class, "USER"); + public static AuthenticatedUserSession getUser(ChannelHandlerContext ctx) { return ctx.channel().attr(USER).get(); } @@ -63,7 +66,7 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H throw new NotFoundException("Bad uri"); } - Long user = ctx.channel().attr(USER).get(); + AuthenticatedUserSession user = ctx.channel().attr(USER).get(); if (user != null) { return; } @@ -71,9 +74,15 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H ctx.channel().attr(USER).set(authenticateHttpUserSession(request, httpSessionDatabase)); } - /** authenticates */ + /** authenticates, or null if no authentication */ public static AuthenticatedUserSession authenticateHttpUserSession(FullHttpRequest request, HttpSessionDatabase database) throws UnauthorizedException { - HttpSessionCookie sessionCookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); + HttpSessionCookie sessionCookie; + try { + sessionCookie = HttpUserSessionCookie.getHttpUserSessionCookie(request); + } catch (BadRequestException e) { + throw new UnauthorizedException("Malformed cookie", e); + } + if (sessionCookie == null) { return null; } @@ -83,15 +92,17 @@ public static AuthenticatedUserSession authenticateHttpUserSession(FullHttpReque throw new UnauthorizedException("Bad authentication (bad id)"); } - if (!userSession.validate(sessionCookie)) { - throw new UnauthorizedException("Bad authentication (bad validation)"); + try { + userSession.validate(sessionCookie); + } catch (AuthenticationException e) { + throw new UnauthorizedException("Bad authentication", e); } - return userSession; + return new AuthenticatedUserSession(userSession.getUser()); } /** create session and persistent session for user */ - private static HttpUserSession createHttpSession(User user, HttpConfig httpConfig, ScribbleshareDatabase database, HttpHeaders httpHeaders) throws InternalServerException { + private static AuthenticatedUserSession createHttpSession(User user, HttpConfig httpConfig, ScribbleshareDatabase database, HttpHeaders httpHeaders) throws InternalServerException { // create session HttpUserSession httpUserSession = new HttpUserSession(httpConfig, user, httpHeaders); try { @@ -108,37 +119,40 @@ private static HttpUserSession createHttpSession(User user, HttpConfig httpConfi throw new InternalServerException("Failed to add persistent http session", e); } - return httpUserSession; + return new AuthenticatedUserSession(httpUserSession.getUser()); } - /** logs in if not authenticated */ - public static HttpUserSession logInHttpSession(FullHttpRequest request, ScribbleshareDatabase database, HttpHeaders httpHeaders, HttpConfig httpConfig) throws UnauthorizedException, InternalServerException { - HttpUserSession session = authenticateHttpUserSession(request, database); + /** logs in if not authenticated, or null if no auth */ + public static AuthenticatedUserSession logInHttpSession(FullHttpRequest request, ScribbleshareDatabase database, HttpHeaders httpHeaders, HttpConfig httpConfig) throws UnauthorizedException, InternalServerException { + AuthenticatedUserSession session = authenticateHttpUserSession(request, database); if (session != null) { return session; } - // check for persistent login - HttpSessionCookie sessionCookie = HttpSessionCookie.getHttpSessionCookie(request, PersistentHttpUserSession.COOKIE_NAME); + HttpSessionCookie sessionCookie; + try { + sessionCookie = HttpUserSessionCookie.getHttpUserSessionCookie(request); + } catch (BadRequestException e) { + throw new UnauthorizedException("Malformed cookie", e); + } if (sessionCookie == null) { return null; } - // use persistent login PersistentHttpUserSession persistentHttpUserSession = database.getPersistentHttpUserSession(sessionCookie); if (persistentHttpUserSession == null) { throw new UnauthorizedException("Bad authentication (bad id)"); } - // expire persistent login try { database.expirePersistentHttpUserSession(persistentHttpUserSession); } catch (FailedException e) { throw new InternalServerException("Failed to expire persistent http session", e); } - // validate persistent login - if (!persistentHttpUserSession.validate(sessionCookie)) { + try { + persistentHttpUserSession.validate(sessionCookie); + } catch (AuthenticationException e) { throw new UnauthorizedException("Bad authentication (bad validation)"); } // now logged in @@ -152,8 +166,8 @@ public static HttpUserSession logInHttpSession(FullHttpRequest request, Scribble } /** creates new user if not logged in or authenticated */ - public static HttpUserSession createHttpSession(FullHttpRequest request, ScribbleshareDatabase database, HttpConfig httpConfig, HttpHeaders httpHeaders) throws UnauthorizedException, InternalServerException { - HttpUserSession session = logInHttpSession(request, database, httpHeaders, httpConfig); + public static AuthenticatedUserSession createHttpSession(FullHttpRequest request, ScribbleshareDatabase database, HttpConfig httpConfig, HttpHeaders httpHeaders) throws UnauthorizedException, InternalServerException { + AuthenticatedUserSession session = logInHttpSession(request, database, httpHeaders, httpConfig); if (session != null) { return session; } From b7079531c0113b7f2d418c73b50c5b3e4b1247a3 Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 25 May 2021 09:56:54 -0400 Subject: [PATCH 067/144] use AuthenticationResult instead of exceptions --- .../server/http/HttpServerHandler.java | 25 ++++++++----- .../AuthenticatedUserSession.java | 12 +++--- .../authentication/AuthenticationResult.java | 8 ++++ .../objects/authentication/UserSession.java | 8 ++-- .../http/HttpSessionCookie.java | 6 +-- .../authentication/http/HttpUserSession.java | 11 ++---- .../http/PersistentHttpUserSession.java | 8 ++-- .../http/PersistentHttpUserSessionCookie.java | 4 +- .../http/handlers/HttpAuthenticator.java | 37 +++++++++---------- .../server/RoomHttpServerInitializer.java | 2 +- .../websocket/ClientMessageHandler.java | 9 +---- .../websocket/state/states/InitialState.java | 8 ++-- 12 files changed, 72 insertions(+), 66 deletions(-) create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticationResult.java diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index c3856319..e7991ad7 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -18,9 +18,11 @@ import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.Resource; import net.stzups.scribbleshare.data.objects.User; +import net.stzups.scribbleshare.data.objects.authentication.AuthenticatedUserSession; import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; import net.stzups.scribbleshare.data.objects.authentication.login.Login; import net.stzups.scribbleshare.server.http.exception.HttpException; @@ -28,6 +30,7 @@ import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; import net.stzups.scribbleshare.server.http.exception.exceptions.UnauthorizedException; +import net.stzups.scribbleshare.server.http.handlers.HttpAuthenticator; import net.stzups.scribbleshare.server.http.objects.Form; import net.stzups.scribbleshare.server.http.objects.Route; import net.stzups.scribbleshare.server.http.objects.Uri; @@ -141,11 +144,13 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H case "api": { switch (route.get(1)) { case "document": { - Long userId = authenticate(ctx, request); + AuthenticatedUserSession session = HttpAuthenticator.authenticateHttpUserSession(request, database); - User user = database.getUser(userId); - if (user == null) //todo - throw new UnauthorizedException("User with " + userId + " authenticated but does not exist"); + if (session == null) { + throw new UnauthorizedException("No authentication"); + } + + User user = session.getUser(); long documentId; try { @@ -279,7 +284,7 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H } User user; - HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); + HttpSessionCookie cookie = HttpUserSessionCookie.getHttpUserSessionCookie(request); if (cookie != null) { HttpUserSession httpSession = database.getHttpSession(cookie); if (httpSession != null) { @@ -336,8 +341,8 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H Form form = new Form(request);//todo necessary? HttpHeaders headers = new DefaultHttpHeaders(); - HttpSessionCookie cookie = HttpSessionCookie.getHttpSessionCookie(request, HttpUserSession.COOKIE_NAME); - if (cookie != null) { + HttpSessionCookie cookie = HttpUserSessionCookie.getHttpUserSessionCookie(request); +/* if (cookie != null) { HttpUserSession httpUserSession = database.getHttpSession(cookie); if (httpUserSession != null) { if (httpUserSession.validate(cookie)) { @@ -356,12 +361,12 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H } } - HttpSessionCookie persistentCookie = HttpSessionCookie.getHttpSessionCookie(request, PersistentHttpUserSession.COOKIE_NAME); + PersistentHttpUserSessionCookie persistentCookie = PersistentHttpUserSessionCookie.getHttpUserSessionCookie(request); if (persistentCookie != null) { PersistentHttpUserSession persistentHttpUserSession = database.getPersistentHttpUserSession(persistentCookie); if (persistentHttpUserSession != null) { if (persistentHttpUserSession.validate(persistentCookie)) { - persistentHttpUserSession.clearCookie(config, headers); + persistentCookie.clearCookie(config, headers); try { database.expirePersistentHttpUserSession(persistentHttpUserSession); } catch (FailedException e) { @@ -376,7 +381,7 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H Scribbleshare.getLogger(ctx).warning("Tried to log out of non existent persistent session"); //todo error } - } + }*/ sendRedirect(ctx, request, headers, LOGOUT_SUCCESS); return; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticatedUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticatedUserSession.java index c98231ac..6ef2ec5e 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticatedUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticatedUserSession.java @@ -1,13 +1,15 @@ package net.stzups.scribbleshare.data.objects.authentication; +import net.stzups.scribbleshare.data.objects.User; + public class AuthenticatedUserSession { - private final long userId; + private final User user; - public AuthenticatedUserSession(long userId) { - this.userId = userId; + public AuthenticatedUserSession(User user) { + this.user = user; } - public long getUserId() { - return userId; + public User getUser() { + return user; } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticationResult.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticationResult.java new file mode 100644 index 00000000..423d1949 --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticationResult.java @@ -0,0 +1,8 @@ +package net.stzups.scribbleshare.data.objects.authentication; + +public enum AuthenticationResult { + SUCCESS, + EXPIRED, + BAD_TOKEN, + STALE +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/UserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/UserSession.java index a25d2ce5..066488da 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/UserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/UserSession.java @@ -73,12 +73,14 @@ public byte[] getHashedToken() { return hashedToken; } - protected void validate(byte[] token) throws AuthenticationException { + protected AuthenticationResult validate(byte[] token) { if (!Arrays.equals(messageDigest.digest(token), this.hashedToken)) - throw new AuthenticationException("Bad token"); + return AuthenticationResult.BAD_TOKEN; if (!created.equals(expired)) - throw new AuthenticationException("Expired session"); + return AuthenticationResult.EXPIRED; + + return AuthenticationResult.SUCCESS; } public void serialize(ByteBuf byteBuf) { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java index 6730bdf3..3e1a8938 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java @@ -52,7 +52,7 @@ protected static void setCookie(HttpConfig config, DefaultCookie cookie) { cookie.setSameSite(CookieHeaderNames.SameSite.Strict); } - public void setCookie(HttpConfig config, String name, HttpHeaders headers) { + protected void setCookie(HttpConfig config, String name, HttpHeaders headers) { ByteBuf tokenBuffer = Unpooled.buffer(); tokenBuffer.writeLong(id); tokenBuffer.writeBytes(token); @@ -67,7 +67,7 @@ public void setCookie(HttpConfig config, String name, HttpHeaders headers) { HttpUtils.setCookie(headers, cookie); } - public static void clearCookie(HttpConfig config, String name, HttpHeaders headers) { + protected static void clearCookie(HttpConfig config, String name, HttpHeaders headers) { DefaultCookie cookie = new DefaultCookie(name, ""); setCookie(config, cookie); @@ -76,7 +76,7 @@ public static void clearCookie(HttpConfig config, String name, HttpHeaders heade HttpUtils.setCookie(headers, cookie); } - public static ByteBuf getCookie(HttpRequest request, String name) { + protected static ByteBuf getCookie(HttpRequest request, String name) { String cookiesHeader = request.headers().get(HttpHeaderNames.COOKIE); if (cookiesHeader == null) return null; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java index 7f03b4c3..b5cf1f03 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java @@ -3,8 +3,7 @@ import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.HttpHeaders; import net.stzups.scribbleshare.data.objects.User; -import net.stzups.scribbleshare.data.objects.authentication.AuthenticatedUserSession; -import net.stzups.scribbleshare.data.objects.authentication.AuthenticationException; +import net.stzups.scribbleshare.data.objects.authentication.AuthenticationResult; import net.stzups.scribbleshare.data.objects.authentication.UserSession; import java.sql.Timestamp; @@ -27,12 +26,10 @@ public HttpUserSession(long id, Timestamp creation, Timestamp expiration, long u super(id, creation, expiration, userId, byteBuf); } - public AuthenticatedUserSession validate(HttpSessionCookie cookie) throws AuthenticationException { + public AuthenticationResult validate(HttpSessionCookie cookie) { if (!Instant.now().isBefore(getCreated().toInstant().plus(MAX_AGE))) - throw new AuthenticationException("Session is expired"); + return AuthenticationResult.STALE; - validate(cookie.getToken()); - - return new AuthenticatedUserSession(getUser()); + return validate(cookie.getToken()); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java index fad670d7..88e5d6aa 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java @@ -2,7 +2,7 @@ import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.HttpHeaders; -import net.stzups.scribbleshare.data.objects.authentication.AuthenticationException; +import net.stzups.scribbleshare.data.objects.authentication.AuthenticationResult; import net.stzups.scribbleshare.data.objects.authentication.UserSession; import java.sql.Timestamp; @@ -23,10 +23,10 @@ public PersistentHttpUserSession(long id, Timestamp creation, Timestamp expirati super(id, creation, expiration, userId, byteBuf); } - public void validate(HttpSessionCookie cookie) throws AuthenticationException { + public AuthenticationResult validate(HttpSessionCookie cookie) { if (!Instant.now().isBefore(getCreated().toInstant().plus(MAX_AGE))) - throw new AuthenticationException("Session is too old"); + return AuthenticationResult.STALE; - validate(cookie.getToken()); + return validate(cookie.getToken()); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java index 5fc79dec..60095341 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java @@ -31,11 +31,11 @@ public void setCookie(HttpConfig config, HttpHeaders headers) { setCookie(config, COOKIE_NAME, headers); } - public HttpUserSessionCookie getHttpUserSessionCookie(HttpRequest request) throws BadRequestException { + public static PersistentHttpUserSessionCookie getHttpUserSessionCookie(HttpRequest request) throws BadRequestException { ByteBuf byteBuf = HttpSessionCookie.getCookie(request, COOKIE_NAME); if (byteBuf != null) { try { - return new HttpUserSessionCookie(byteBuf); + return new PersistentHttpUserSessionCookie(byteBuf); } catch (DeserializationException e) { throw new BadRequestException("Malformed cookie", e); } finally { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java index 9c5b5727..afcf04d5 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java @@ -8,11 +8,10 @@ import io.netty.util.AttributeKey; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; -import net.stzups.scribbleshare.data.database.databases.HttpSessionDatabase; import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; import net.stzups.scribbleshare.data.objects.User; import net.stzups.scribbleshare.data.objects.authentication.AuthenticatedUserSession; -import net.stzups.scribbleshare.data.objects.authentication.AuthenticationException; +import net.stzups.scribbleshare.data.objects.authentication.AuthenticationResult; import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; @@ -36,17 +35,15 @@ public static AuthenticatedUserSession getUser(ChannelHandlerContext ctx) { return ctx.channel().attr(USER).get(); } - private final HttpSessionDatabase httpSessionDatabase; - private final HttpConfig httpConfig; + private final ScribbleshareDatabase httpSessionDatabase; private final String uri; - public HttpAuthenticator(HttpSessionDatabase httpSessionDatabase, HttpConfig httpConfig) { - this(httpSessionDatabase, httpConfig, null); + public HttpAuthenticator(ScribbleshareDatabase httpSessionDatabase) { + this(httpSessionDatabase, null); } - public HttpAuthenticator(HttpSessionDatabase httpSessionDatabase, HttpConfig httpConfig, String uri) { + public HttpAuthenticator(ScribbleshareDatabase httpSessionDatabase, String uri) { this.httpSessionDatabase = httpSessionDatabase; - this.httpConfig = httpConfig; this.uri = uri; } @@ -75,7 +72,7 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H } /** authenticates, or null if no authentication */ - public static AuthenticatedUserSession authenticateHttpUserSession(FullHttpRequest request, HttpSessionDatabase database) throws UnauthorizedException { + public static AuthenticatedUserSession authenticateHttpUserSession(FullHttpRequest request, ScribbleshareDatabase database) throws UnauthorizedException, InternalServerException { HttpSessionCookie sessionCookie; try { sessionCookie = HttpUserSessionCookie.getHttpUserSessionCookie(request); @@ -92,13 +89,16 @@ public static AuthenticatedUserSession authenticateHttpUserSession(FullHttpReque throw new UnauthorizedException("Bad authentication (bad id)"); } - try { - userSession.validate(sessionCookie); - } catch (AuthenticationException e) { - throw new UnauthorizedException("Bad authentication", e); + AuthenticationResult result = userSession.validate(sessionCookie); + if (result != AuthenticationResult.SUCCESS) { + throw new UnauthorizedException("Bad authentication " + result); } - return new AuthenticatedUserSession(userSession.getUser()); + User user = database.getUser(userSession.getUser()); + if (user == null) + throw new InternalServerException("Unknown user for authentication"); + + return new AuthenticatedUserSession(user); } /** create session and persistent session for user */ @@ -119,7 +119,7 @@ private static AuthenticatedUserSession createHttpSession(User user, HttpConfig throw new InternalServerException("Failed to add persistent http session", e); } - return new AuthenticatedUserSession(httpUserSession.getUser()); + return new AuthenticatedUserSession(user); } /** logs in if not authenticated, or null if no auth */ @@ -150,10 +150,9 @@ public static AuthenticatedUserSession logInHttpSession(FullHttpRequest request, throw new InternalServerException("Failed to expire persistent http session", e); } - try { - persistentHttpUserSession.validate(sessionCookie); - } catch (AuthenticationException e) { - throw new UnauthorizedException("Bad authentication (bad validation)"); + AuthenticationResult result = persistentHttpUserSession.validate(sessionCookie); + if (result != AuthenticationResult.SUCCESS) { + throw new UnauthorizedException("Bad authentication " + result); } // now logged in diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java index 418c7182..aed00252 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java @@ -39,7 +39,7 @@ public RoomHttpServerInitializer(Config config, ScribbleshareDatabase database) super(config); this.config = config; this.database = database; - clientMessageHandler = new ClientMessageHandler(database); + clientMessageHandler = new ClientMessageHandler(); httpAuthenticator = new HttpAuthenticator(database); } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java index f5d24ccb..aa2073ec 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java @@ -6,7 +6,6 @@ import io.netty.util.Attribute; import io.netty.util.AttributeKey; import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessage; import net.stzups.scribbleshare.room.server.websocket.state.State; import net.stzups.scribbleshare.room.server.websocket.state.states.InitialState; @@ -22,15 +21,9 @@ public static Attribute getState(ChannelHandlerContext ctx) { return ctx.channel().attr(STATE); } - private final ScribbleshareDatabase database; - - public ClientMessageHandler(ScribbleshareDatabase database) { - this.database = database; - } - @Override public void channelActive(ChannelHandlerContext ctx) { - State.setState(ctx, new InitialState(database.getUser(HttpAuthenticator.getUser(ctx)))); + State.setState(ctx, new InitialState(HttpAuthenticator.getUser(ctx))); } @Override diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java index a810c83a..599418c3 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java @@ -3,14 +3,14 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.data.objects.User; +import net.stzups.scribbleshare.data.objects.authentication.AuthenticatedUserSession; import net.stzups.scribbleshare.room.server.websocket.state.State; public class InitialState extends State { - private final User user; + private final AuthenticatedUserSession session; - public InitialState(User user) { - this.user = user; + public InitialState(AuthenticatedUserSession session) { + this.session = session; } @Override From 23d1feb69637699ffdcd383abaf4f3ee8b568e71 Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 25 May 2021 10:07:57 -0400 Subject: [PATCH 068/144] add tons of interfaces for database, idk if this is good --- .../data/database/ScribbleshareDatabase.java | 26 +++++------------ .../database/databases/DocumentDatabase.java | 11 ++++++++ .../databases/InviteCodeDatabase.java | 9 ++++++ .../database/databases/LoginDatabase.java | 10 +++++++ .../data/database/databases/UserDatabase.java | 10 +++++++ .../http/handlers/HttpAuthenticator.java | 28 +++++++++++-------- 6 files changed, 64 insertions(+), 30 deletions(-) create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/InviteCodeDatabase.java create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java index a696cacf..43a380ab 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java @@ -1,27 +1,15 @@ package net.stzups.scribbleshare.data.database; +import net.stzups.scribbleshare.data.database.databases.DocumentDatabase; import net.stzups.scribbleshare.data.database.databases.HttpSessionDatabase; +import net.stzups.scribbleshare.data.database.databases.InviteCodeDatabase; +import net.stzups.scribbleshare.data.database.databases.LoginDatabase; import net.stzups.scribbleshare.data.database.databases.PersistentHttpSessionDatabase; import net.stzups.scribbleshare.data.database.databases.ResourceDatabase; -import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; -import net.stzups.scribbleshare.data.objects.Document; -import net.stzups.scribbleshare.data.objects.InviteCode; -import net.stzups.scribbleshare.data.objects.User; -import net.stzups.scribbleshare.data.objects.authentication.login.Login; +import net.stzups.scribbleshare.data.database.databases.UserDatabase; +import net.stzups.scribbleshare.server.http.handlers.HttpAuthenticator; -public interface ScribbleshareDatabase extends PersistentHttpSessionDatabase, ResourceDatabase, HttpSessionDatabase { - void addUser(User user) throws FailedException; - User getUser(long id); - void updateUser(User user) throws FailedException; +public interface ScribbleshareDatabase extends PersistentHttpSessionDatabase, ResourceDatabase, HttpSessionDatabase, UserDatabase, DocumentDatabase, InviteCodeDatabase, LoginDatabase, + HttpAuthenticator.Database { - Document createDocument(User owner); - Document getDocument(long id); - void updateDocument(Document document); - void deleteDocument(Document document); - - InviteCode getInviteCode(String code); - InviteCode getInviteCode(Document document); - Login getLogin(String username); - /** false if the username already existed */ - boolean addLogin(Login login) throws FailedException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java new file mode 100644 index 00000000..19a27301 --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java @@ -0,0 +1,11 @@ +package net.stzups.scribbleshare.data.database.databases; + +import net.stzups.scribbleshare.data.objects.Document; +import net.stzups.scribbleshare.data.objects.User; + +public interface DocumentDatabase { + Document createDocument(User owner); + Document getDocument(long id); + void updateDocument(Document document); + void deleteDocument(Document document); +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/InviteCodeDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/InviteCodeDatabase.java new file mode 100644 index 00000000..ac4352b1 --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/InviteCodeDatabase.java @@ -0,0 +1,9 @@ +package net.stzups.scribbleshare.data.database.databases; + +import net.stzups.scribbleshare.data.objects.Document; +import net.stzups.scribbleshare.data.objects.InviteCode; + +public interface InviteCodeDatabase { + InviteCode getInviteCode(String code); + InviteCode getInviteCode(Document document); +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java new file mode 100644 index 00000000..afbd16ad --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java @@ -0,0 +1,10 @@ +package net.stzups.scribbleshare.data.database.databases; + +import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; +import net.stzups.scribbleshare.data.objects.authentication.login.Login; + +public interface LoginDatabase { + Login getLogin(String username); + /** false if the username already existed */ + boolean addLogin(Login login) throws FailedException; +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java new file mode 100644 index 00000000..127032b6 --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java @@ -0,0 +1,10 @@ +package net.stzups.scribbleshare.data.database.databases; + +import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; +import net.stzups.scribbleshare.data.objects.User; + +public interface UserDatabase { + void addUser(User user) throws FailedException; + User getUser(long id); + void updateUser(User user) throws FailedException; +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java index afcf04d5..c0e110da 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java @@ -7,7 +7,9 @@ import io.netty.handler.codec.http.HttpHeaders; import io.netty.util.AttributeKey; import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; +import net.stzups.scribbleshare.data.database.databases.HttpSessionDatabase; +import net.stzups.scribbleshare.data.database.databases.PersistentHttpSessionDatabase; +import net.stzups.scribbleshare.data.database.databases.UserDatabase; import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; import net.stzups.scribbleshare.data.objects.User; import net.stzups.scribbleshare.data.objects.authentication.AuthenticatedUserSession; @@ -35,15 +37,19 @@ public static AuthenticatedUserSession getUser(ChannelHandlerContext ctx) { return ctx.channel().attr(USER).get(); } - private final ScribbleshareDatabase httpSessionDatabase; + public interface Database extends HttpSessionDatabase, PersistentHttpSessionDatabase, UserDatabase { + + } + + private final Database database; private final String uri; - public HttpAuthenticator(ScribbleshareDatabase httpSessionDatabase) { - this(httpSessionDatabase, null); + public HttpAuthenticator(Database database) { + this(database, null); } - public HttpAuthenticator(ScribbleshareDatabase httpSessionDatabase, String uri) { - this.httpSessionDatabase = httpSessionDatabase; + public HttpAuthenticator(Database database, String uri) { + this.database = database; this.uri = uri; } @@ -68,11 +74,11 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H return; } - ctx.channel().attr(USER).set(authenticateHttpUserSession(request, httpSessionDatabase)); + ctx.channel().attr(USER).set(authenticateHttpUserSession(request, database)); } /** authenticates, or null if no authentication */ - public static AuthenticatedUserSession authenticateHttpUserSession(FullHttpRequest request, ScribbleshareDatabase database) throws UnauthorizedException, InternalServerException { + public static AuthenticatedUserSession authenticateHttpUserSession(FullHttpRequest request, Database database) throws UnauthorizedException, InternalServerException { HttpSessionCookie sessionCookie; try { sessionCookie = HttpUserSessionCookie.getHttpUserSessionCookie(request); @@ -102,7 +108,7 @@ public static AuthenticatedUserSession authenticateHttpUserSession(FullHttpReque } /** create session and persistent session for user */ - private static AuthenticatedUserSession createHttpSession(User user, HttpConfig httpConfig, ScribbleshareDatabase database, HttpHeaders httpHeaders) throws InternalServerException { + private static AuthenticatedUserSession createHttpSession(User user, HttpConfig httpConfig, Database database, HttpHeaders httpHeaders) throws InternalServerException { // create session HttpUserSession httpUserSession = new HttpUserSession(httpConfig, user, httpHeaders); try { @@ -123,7 +129,7 @@ private static AuthenticatedUserSession createHttpSession(User user, HttpConfig } /** logs in if not authenticated, or null if no auth */ - public static AuthenticatedUserSession logInHttpSession(FullHttpRequest request, ScribbleshareDatabase database, HttpHeaders httpHeaders, HttpConfig httpConfig) throws UnauthorizedException, InternalServerException { + public static AuthenticatedUserSession logInHttpSession(FullHttpRequest request, Database database, HttpHeaders httpHeaders, HttpConfig httpConfig) throws UnauthorizedException, InternalServerException { AuthenticatedUserSession session = authenticateHttpUserSession(request, database); if (session != null) { return session; @@ -165,7 +171,7 @@ public static AuthenticatedUserSession logInHttpSession(FullHttpRequest request, } /** creates new user if not logged in or authenticated */ - public static AuthenticatedUserSession createHttpSession(FullHttpRequest request, ScribbleshareDatabase database, HttpConfig httpConfig, HttpHeaders httpHeaders) throws UnauthorizedException, InternalServerException { + public static AuthenticatedUserSession createHttpSession(FullHttpRequest request, Database database, HttpConfig httpConfig, HttpHeaders httpHeaders) throws UnauthorizedException, InternalServerException { AuthenticatedUserSession session = logInHttpSession(request, database, httpHeaders, httpConfig); if (session != null) { return session; From bd34f047ea57f1b796142dfddfc1318cc9e45f5e Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 25 May 2021 10:09:14 -0400 Subject: [PATCH 069/144] compiles --- .../websocket/state/states/HandshakeState.java | 12 ++++++------ .../server/websocket/state/states/InitialState.java | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java index 42524960..392cae26 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java @@ -5,7 +5,7 @@ import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.InviteCode; -import net.stzups.scribbleshare.data.objects.User; +import net.stzups.scribbleshare.data.objects.authentication.AuthenticatedUserSession; import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; import net.stzups.scribbleshare.room.server.RoomHttpServerInitializer; import net.stzups.scribbleshare.room.server.websocket.Client; @@ -19,10 +19,10 @@ import net.stzups.scribbleshare.room.server.websocket.state.State; public class HandshakeState extends State { - private final User user; + private final AuthenticatedUserSession session; - public HandshakeState(User user) { - this.user = user; + public HandshakeState(AuthenticatedUserSession session) { + this.session = session; } @Override @@ -32,9 +32,9 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro case HANDSHAKE: { ClientMessageHandshake clientPacketHandshake = (ClientMessageHandshake) clientMessage; - Scribbleshare.getLogger(ctx).info("Handshake with invite " + clientPacketHandshake.getCode() + ", " + user); + Scribbleshare.getLogger(ctx).info("Handshake with invite " + clientPacketHandshake.getCode() + ", " + session); - Client client = new Client(user, ctx.channel()); + Client client = new Client(session.getUser(), ctx.channel()); client.queueMessage(new ServerMessageHandshake(client)); InviteCode inviteCode = RoomHttpServerInitializer.getDatabase(ctx).getInviteCode(clientPacketHandshake.getCode()); diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java index 599418c3..d09ff7f7 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java @@ -17,7 +17,7 @@ public InitialState(AuthenticatedUserSession session) { public void userEventTriggered(ChannelHandlerContext ctx, Object event) { if (event instanceof WebSocketServerProtocolHandler.HandshakeComplete) { Scribbleshare.getLogger(ctx).info("WebSocket connection initialized"); - setState(ctx, new HandshakeState(user)); + setState(ctx, new HandshakeState(session)); return; } From 148cea243db65ed52bb48b47a2e74a32d87be8ad Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 25 May 2021 10:09:31 -0400 Subject: [PATCH 070/144] remove unused AuthenticationException.java --- .../objects/authentication/AuthenticationException.java | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticationException.java diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticationException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticationException.java deleted file mode 100644 index 6ae401e9..00000000 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticationException.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.stzups.scribbleshare.data.objects.authentication; - -public class AuthenticationException extends Exception { - public AuthenticationException(String message) { - super(message); - } -} From 038057662654a2a363638c1b8ceeb84773dc56fb Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 25 May 2021 10:12:16 -0400 Subject: [PATCH 071/144] refactor to switch --- .../server/http/HttpServerHandler.java | 161 +++++++++--------- 1 file changed, 83 insertions(+), 78 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index e7991ad7..45dd5019 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -227,79 +227,89 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H if (request.method().equals(HttpMethod.POST)) { //todo validate for extra fields that should not happen - if (route.path().equals(LOGIN_PATH)) { - Form form = new Form(request); + switch (route.path()) { + case LOGIN_PATH: { + Form form = new Form(request); - String username = form.getText("username"); - String password = form.getText("password"); - boolean remember = form.getCheckbox("remember"); + String username = form.getText("username"); + String password = form.getText("password"); + boolean remember = form.getCheckbox("remember"); - System.out.println(username + ", " + password + ", " + remember); + System.out.println(username + ", " + password + ", " + remember); - Login login = database.getLogin(username); - if (Login.verify(login, password.getBytes(StandardCharsets.UTF_8))) { - //todo rate limit and generic error handling - if (login == null) { - Scribbleshare.getLogger(ctx).info("Bad username " + username); - } else { - Scribbleshare.getLogger(ctx).info("Bad password for username " + username); - } + Login login = database.getLogin(username); + if (Login.verify(login, password.getBytes(StandardCharsets.UTF_8))) { + //todo rate limit and generic error handling + if (login == null) { + Scribbleshare.getLogger(ctx).info("Bad username " + username); + } else { + Scribbleshare.getLogger(ctx).info("Bad password for username " + username); + } - sendRedirect(ctx, request, LOGIN_PAGE); - return; - } + sendRedirect(ctx, request, LOGIN_PAGE); + return; + } - HttpHeaders httpHeaders = new DefaultHttpHeaders(); - HttpUserSession userSession = new HttpUserSession(config, database.getUser(login.getId()), httpHeaders); - try { - database.addHttpSession(userSession); - } catch (FailedException e) { - throw new InternalServerException("Exception while adding http session to database", e); - } - if (remember) { - PersistentHttpUserSession persistentHttpUserSession = new PersistentHttpUserSession(config, userSession, httpHeaders); + HttpHeaders httpHeaders = new DefaultHttpHeaders(); + HttpUserSession userSession = new HttpUserSession(config, database.getUser(login.getId()), httpHeaders); try { - database.addPersistentHttpUserSession(persistentHttpUserSession); + database.addHttpSession(userSession); } catch (FailedException e) { - throw new InternalServerException("Exception while adding persistent http session to database", e); + throw new InternalServerException("Exception while adding http session to database", e); + } + if (remember) { + PersistentHttpUserSession persistentHttpUserSession = new PersistentHttpUserSession(config, userSession, httpHeaders); + try { + database.addPersistentHttpUserSession(persistentHttpUserSession); + } catch (FailedException e) { + throw new InternalServerException("Exception while adding persistent http session to database", e); + } } + sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); + return; } - sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); - return; - } else if (route.path().equals(REGISTER_PATH)) { - Form form = new Form(request); + case REGISTER_PATH: { + Form form = new Form(request); - // validate + // validate - String username = form.getText("username"); - String password = form.getText("password"); + String username = form.getText("username"); + String password = form.getText("password"); - //todo validate - if (false) { - //todo rate limit and generic error handling + //todo validate + if (false) { + //todo rate limit and generic error handling - sendRedirect(ctx, request, REGISTER_PAGE); - return; - } + sendRedirect(ctx, request, REGISTER_PAGE); + return; + } - User user; - HttpSessionCookie cookie = HttpUserSessionCookie.getHttpUserSessionCookie(request); - if (cookie != null) { - HttpUserSession httpSession = database.getHttpSession(cookie); - if (httpSession != null) { - User u = database.getUser(httpSession.getUser()); - if (u.isRegistered()) { - Scribbleshare.getLogger(ctx).info("Registered user is creating a new account"); + User user; + HttpSessionCookie cookie = HttpUserSessionCookie.getHttpUserSessionCookie(request); + if (cookie != null) { + HttpUserSession httpSession = database.getHttpSession(cookie); + if (httpSession != null) { + User u = database.getUser(httpSession.getUser()); + if (u.isRegistered()) { + Scribbleshare.getLogger(ctx).info("Registered user is creating a new account"); + user = new User(username); + try { + database.addUser(user); + } catch (FailedException e) { + throw new InternalServerException("todo", e); + } + } else { + Scribbleshare.getLogger(ctx).info("Temporary user is registering"); + user = u; + } + } else { user = new User(username); try { database.addUser(user); } catch (FailedException e) { throw new InternalServerException("todo", e); } - } else { - Scribbleshare.getLogger(ctx).info("Temporary user is registering"); - user = u; } } else { user = new User(username); @@ -309,39 +319,33 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H throw new InternalServerException("todo", e); } } - } else { - user = new User(username); + + assert !user.isRegistered(); + + Login login = new Login(user, password.getBytes(StandardCharsets.UTF_8)); + boolean loginAdded; try { - database.addUser(user); + loginAdded = database.addLogin(login); } catch (FailedException e) { - throw new InternalServerException("todo", e); + throw new InternalServerException("Exception while adding login for user " + login.getId() + " with username " + login.getUsername(), e); + } + if (!loginAdded) { + Scribbleshare.getLogger(ctx).info("Tried to register with duplicate username " + username); + sendRedirect(ctx, request, REGISTER_PAGE); + return; } - } - assert !user.isRegistered(); + Scribbleshare.getLogger(ctx).info("Registered with username " + username); - Login login = new Login(user, password.getBytes(StandardCharsets.UTF_8)); - boolean loginAdded; - try { - loginAdded = database.addLogin(login); - } catch (FailedException e) { - throw new InternalServerException("Exception while adding login for user " + login.getId() + " with username " + login.getUsername(), e); - } - if (!loginAdded) { - Scribbleshare.getLogger(ctx).info("Tried to register with duplicate username " + username); - sendRedirect(ctx, request, REGISTER_PAGE); + sendRedirect(ctx, request, REGISTER_SUCCESS); return; } + case LOGOUT_PATH: { + Form form = new Form(request);//todo necessary? - Scribbleshare.getLogger(ctx).info("Registered with username " + username); - - sendRedirect(ctx, request, REGISTER_SUCCESS); - return; - } else if (route.path().equals(LOGOUT_PATH)) { - Form form = new Form(request);//todo necessary? - HttpHeaders headers = new DefaultHttpHeaders(); - HttpSessionCookie cookie = HttpUserSessionCookie.getHttpUserSessionCookie(request); + HttpHeaders headers = new DefaultHttpHeaders(); + HttpSessionCookie cookie = HttpUserSessionCookie.getHttpUserSessionCookie(request); /* if (cookie != null) { HttpUserSession httpUserSession = database.getHttpSession(cookie); if (httpUserSession != null) { @@ -383,8 +387,9 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H } }*/ - sendRedirect(ctx, request, headers, LOGOUT_SUCCESS); - return; + sendRedirect(ctx, request, headers, LOGOUT_SUCCESS); + return; + } } } From 046baf9bf0f269b1313005b6b282ac480209ef8d Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 25 May 2021 10:57:42 -0400 Subject: [PATCH 072/144] remove FailedException.java, replace with DatabaseException --- .../server/http/HttpServerHandler.java | 20 +++++++++++-------- .../database/databases/DocumentDatabase.java | 7 ++++--- .../databases/HttpSessionDatabase.java | 6 +++--- .../database/databases/LoginDatabase.java | 4 ++-- .../PersistentHttpSessionDatabase.java | 6 +++--- .../database/databases/ResourceDatabase.java | 5 +++-- .../data/database/databases/UserDatabase.java | 6 +++--- .../database/exception/DatabaseException.java | 5 ++++- .../exception/exceptions/FailedException.java | 9 --------- .../server/http/exception/HttpException.java | 4 ++++ .../exceptions/InternalServerException.java | 4 ++++ .../http/handlers/HttpAuthenticator.java | 10 +++++----- .../room/server/websocket/Room.java | 8 +++++++- .../state/states/HandshakeState.java | 12 ++++++++--- .../websocket/state/states/ReadyState.java | 11 +++++++++- .../websocket/state/states/RoomState.java | 17 ++++++++++++++-- 16 files changed, 88 insertions(+), 46 deletions(-) delete mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/exceptions/FailedException.java diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 45dd5019..2e0b3670 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -14,7 +14,7 @@ import io.netty.handler.stream.ChunkedStream; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; -import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; +import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.Resource; import net.stzups.scribbleshare.data.objects.User; @@ -183,7 +183,11 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H if (document == null) throw new NotFoundException("Document with id " + documentId + " for user " + user + " somehow does not exist"); - send(ctx, request, Unpooled.copyLong(database.addResource(document.getId(), new Resource(request.content())))); + try { + send(ctx, request, Unpooled.copyLong(database.addResource(document.getId(), new Resource(request.content())))); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } } else { send(ctx, request, HttpResponseStatus.METHOD_NOT_ALLOWED); } @@ -255,14 +259,14 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H HttpUserSession userSession = new HttpUserSession(config, database.getUser(login.getId()), httpHeaders); try { database.addHttpSession(userSession); - } catch (FailedException e) { + } catch (DatabaseException e) { throw new InternalServerException("Exception while adding http session to database", e); } if (remember) { PersistentHttpUserSession persistentHttpUserSession = new PersistentHttpUserSession(config, userSession, httpHeaders); try { database.addPersistentHttpUserSession(persistentHttpUserSession); - } catch (FailedException e) { + } catch (DatabaseException e) { throw new InternalServerException("Exception while adding persistent http session to database", e); } } @@ -296,7 +300,7 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H user = new User(username); try { database.addUser(user); - } catch (FailedException e) { + } catch (DatabaseException e) { throw new InternalServerException("todo", e); } } else { @@ -307,7 +311,7 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H user = new User(username); try { database.addUser(user); - } catch (FailedException e) { + } catch (DatabaseException e) { throw new InternalServerException("todo", e); } } @@ -315,7 +319,7 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H user = new User(username); try { database.addUser(user); - } catch (FailedException e) { + } catch (DatabaseException e) { throw new InternalServerException("todo", e); } } @@ -326,7 +330,7 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H boolean loginAdded; try { loginAdded = database.addLogin(login); - } catch (FailedException e) { + } catch (DatabaseException e) { throw new InternalServerException("Exception while adding login for user " + login.getId() + " with username " + login.getUsername(), e); } if (!loginAdded) { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java index 19a27301..08e1698c 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java @@ -1,11 +1,12 @@ package net.stzups.scribbleshare.data.database.databases; +import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.User; public interface DocumentDatabase { - Document createDocument(User owner); + Document createDocument(User owner) throws DatabaseException; Document getDocument(long id); - void updateDocument(Document document); - void deleteDocument(Document document); + void updateDocument(Document document) throws DatabaseException; + void deleteDocument(Document document) throws DatabaseException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java index 5c5bf7ca..eaa20e63 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java @@ -1,6 +1,6 @@ package net.stzups.scribbleshare.data.database.databases; -import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; +import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; @@ -13,10 +13,10 @@ public interface HttpSessionDatabase { /** * Add new {@link HttpUserSession} */ - void addHttpSession(HttpUserSession httpUserSession) throws FailedException; + void addHttpSession(HttpUserSession httpUserSession) throws DatabaseException; /** * Expire existing {@link HttpUserSession} */ - void expireHttpSession(HttpUserSession httpUserSession) throws FailedException; + void expireHttpSession(HttpUserSession httpUserSession) throws DatabaseException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java index afbd16ad..fd97fd9f 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java @@ -1,10 +1,10 @@ package net.stzups.scribbleshare.data.database.databases; -import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; +import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.authentication.login.Login; public interface LoginDatabase { Login getLogin(String username); /** false if the username already existed */ - boolean addLogin(Login login) throws FailedException; + boolean addLogin(Login login) throws DatabaseException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java index 3d599cd5..47c157c0 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java @@ -1,6 +1,6 @@ package net.stzups.scribbleshare.data.database.databases; -import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; +import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; @@ -13,10 +13,10 @@ public interface PersistentHttpSessionDatabase { /** * Add new {@link PersistentHttpUserSession} */ - void addPersistentHttpUserSession(PersistentHttpUserSession persistentHttpSession) throws FailedException; + void addPersistentHttpUserSession(PersistentHttpUserSession persistentHttpSession) throws DatabaseException; /** * Expire existing {@link PersistentHttpUserSession} */ - void expirePersistentHttpUserSession(PersistentHttpUserSession persistentHttpUserSession) throws FailedException; + void expirePersistentHttpUserSession(PersistentHttpUserSession persistentHttpUserSession) throws DatabaseException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/ResourceDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/ResourceDatabase.java index aad37835..c778e6cc 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/ResourceDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/ResourceDatabase.java @@ -1,15 +1,16 @@ package net.stzups.scribbleshare.data.database.databases; +import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.Resource; public interface ResourceDatabase { /** * Add resource to database and return the corresponding id for the new resource */ - long addResource(long owner, Resource resource); + long addResource(long owner, Resource resource) throws DatabaseException; /** update resource */ - void updateResource(long id, long owner, Resource resource); + void updateResource(long id, long owner, Resource resource) throws DatabaseException; /** * Gets resource, or null if the resource does not exist diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java index 127032b6..843e79ea 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java @@ -1,10 +1,10 @@ package net.stzups.scribbleshare.data.database.databases; -import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; +import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.User; public interface UserDatabase { - void addUser(User user) throws FailedException; + void addUser(User user) throws DatabaseException; User getUser(long id); - void updateUser(User user) throws FailedException; + void updateUser(User user) throws DatabaseException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/DatabaseException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/DatabaseException.java index c8c35e79..b15f5ea5 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/DatabaseException.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/DatabaseException.java @@ -1,7 +1,10 @@ package net.stzups.scribbleshare.data.database.exception; public class DatabaseException extends Exception { - protected DatabaseException(Throwable cause) { + public DatabaseException(String message, Throwable cause) { + super(message, cause); + } + public DatabaseException(Throwable cause) { super(cause); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/exceptions/FailedException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/exceptions/FailedException.java deleted file mode 100644 index 8c20087f..00000000 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/exceptions/FailedException.java +++ /dev/null @@ -1,9 +0,0 @@ -package net.stzups.scribbleshare.data.database.exception.exceptions; - -import net.stzups.scribbleshare.data.database.exception.DatabaseException; - -public class FailedException extends DatabaseException { - public FailedException(Throwable cause) { - super(cause); - } -} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/HttpException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/HttpException.java index 76a880d2..82815374 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/HttpException.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/HttpException.java @@ -7,6 +7,10 @@ protected HttpException(String message) { super(message); } + protected HttpException(Throwable cause) { + super(cause); + } + protected HttpException(String message, Throwable cause) { super(message, cause); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/InternalServerException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/InternalServerException.java index 8c2b8a4e..ba26f59f 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/InternalServerException.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/InternalServerException.java @@ -9,6 +9,10 @@ public InternalServerException(String message) { super(message); } + public InternalServerException(Throwable cause) { + super(cause); + } + public InternalServerException(String message, Throwable cause) { super(message, cause); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java index c0e110da..6123a5d0 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java @@ -10,7 +10,7 @@ import net.stzups.scribbleshare.data.database.databases.HttpSessionDatabase; import net.stzups.scribbleshare.data.database.databases.PersistentHttpSessionDatabase; import net.stzups.scribbleshare.data.database.databases.UserDatabase; -import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; +import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.User; import net.stzups.scribbleshare.data.objects.authentication.AuthenticatedUserSession; import net.stzups.scribbleshare.data.objects.authentication.AuthenticationResult; @@ -113,7 +113,7 @@ private static AuthenticatedUserSession createHttpSession(User user, HttpConfig HttpUserSession httpUserSession = new HttpUserSession(httpConfig, user, httpHeaders); try { database.addHttpSession(httpUserSession); - } catch (FailedException e) { + } catch (DatabaseException e) { throw new InternalServerException("Failed to add http session", e); } @@ -121,7 +121,7 @@ private static AuthenticatedUserSession createHttpSession(User user, HttpConfig PersistentHttpUserSession a = new PersistentHttpUserSession(httpConfig, httpUserSession, httpHeaders); try { database.addPersistentHttpUserSession(a); - } catch (FailedException e) { + } catch (DatabaseException e) { throw new InternalServerException("Failed to add persistent http session", e); } @@ -152,7 +152,7 @@ public static AuthenticatedUserSession logInHttpSession(FullHttpRequest request, try { database.expirePersistentHttpUserSession(persistentHttpUserSession); - } catch (FailedException e) { + } catch (DatabaseException e) { throw new InternalServerException("Failed to expire persistent http session", e); } @@ -180,7 +180,7 @@ public static AuthenticatedUserSession createHttpSession(FullHttpRequest request User user = new User(); try { database.addUser(user); - } catch (FailedException e) { + } catch (DatabaseException e) { throw new InternalServerException("Failed to add user", e); } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java index a983a2ab..9a651ad7 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java @@ -4,6 +4,7 @@ import io.netty.buffer.Unpooled; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; +import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.Resource; import net.stzups.scribbleshare.data.objects.canvas.Canvas; @@ -20,6 +21,7 @@ import java.util.Set; import java.util.Timer; import java.util.TimerTask; +import java.util.logging.Level; public class Room { private static final int SEND_PERIOD = 1000; @@ -64,7 +66,11 @@ public void end() { if (canvas.isDirty()) { ByteBuf byteBuf = Unpooled.buffer(); canvas.serialize(byteBuf); - database.updateResource(document.getId(), document.getId(), new Resource(byteBuf));//todo autosave? + try { + database.updateResource(document.getId(), document.getId(), new Resource(byteBuf));//todo autosave? + } catch (DatabaseException e) { + Scribbleshare.getLogger().log(Level.WARNING, "Failed to save canvas to database", e); + } } //todo Scribbleshare.getLogger().info("Ended room " + this); diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java index 392cae26..44bd22cd 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java @@ -2,7 +2,7 @@ import io.netty.channel.ChannelHandlerContext; import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; +import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.InviteCode; import net.stzups.scribbleshare.data.objects.authentication.AuthenticatedUserSession; @@ -18,6 +18,8 @@ import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageUpdateDocument; import net.stzups.scribbleshare.room.server.websocket.state.State; +import java.util.logging.Level; + public class HandshakeState extends State { private final AuthenticatedUserSession session; @@ -48,7 +50,7 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro if (client.getUser().getSharedDocuments().add(document.getId())) { try { RoomHttpServerInitializer.getDatabase(ctx).updateUser(client.getUser()); - } catch (FailedException e) { + } catch (DatabaseException e) { e.printStackTrace(); //todo } @@ -64,7 +66,11 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro } } else { if (client.getUser().getOwnedDocuments().size() == 0) { - RoomHttpServerInitializer.getDatabase(ctx).createDocument(client.getUser()); + try { + RoomHttpServerInitializer.getDatabase(ctx).createDocument(client.getUser()); + } catch (DatabaseException e) { + Scribbleshare.getLogger().log(Level.WARNING, "Failed to create document for new user with no documents", e); + } } } client.getUser().getOwnedDocuments().removeIf((id) -> { diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java index c6709115..1d22240c 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java @@ -2,6 +2,7 @@ import io.netty.channel.ChannelHandlerContext; import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; import net.stzups.scribbleshare.room.server.RoomHttpServerInitializer; @@ -13,6 +14,8 @@ import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageUpdateDocument; import net.stzups.scribbleshare.room.server.websocket.state.State; +import java.util.logging.Level; + public class ReadyState extends State { private final Client client; @@ -44,7 +47,13 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro } case CREATE_DOCUMENT: { //create - Document document = RoomHttpServerInitializer.getDatabase(ctx).createDocument(client.getUser()); + Document document; + try { + document = RoomHttpServerInitializer.getDatabase(ctx).createDocument(client.getUser()); + } catch (DatabaseException e) { + Scribbleshare.getLogger().log(Level.WARNING, "Failed to create document for client that requested it", e);//todo this will probably break the client + return;//todo throw server exception + } client.sendMessage(new ServerMessageUpdateDocument(document)); //open Room room; diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java index 82d9ce9f..1f5649ce 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java @@ -2,6 +2,7 @@ import io.netty.channel.ChannelHandlerContext; import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.CanvasUpdateException; import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.CanvasUpdates; import net.stzups.scribbleshare.room.server.RoomHttpServerInitializer; @@ -16,6 +17,8 @@ import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageDeleteDocument; import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageUpdateDocument; +import java.util.logging.Level; + public class RoomState extends ReadyState { private final Client client; private final Room room; @@ -58,7 +61,12 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro Scribbleshare.getLogger(ctx).info("Deleting live document " + room.getDocument()); room.sendMessage(new ServerMessageDeleteDocument(room.getDocument())); room.end(); - RoomHttpServerInitializer.getDatabase(ctx).deleteDocument(room.getDocument()); + try { + RoomHttpServerInitializer.getDatabase(ctx).deleteDocument(room.getDocument()); + } catch (DatabaseException e) { + Scribbleshare.getLogger().log(Level.WARNING, "Failed to delete document", e); + //todo + } break; } else { throw new ClientMessageException(clientMessage, "Tried to delete document which is not currently open"); @@ -82,7 +90,12 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro } room.getDocument().setName(clientMessageUpdateDocument.getName()); room.queueMessageExcept(new ServerMessageUpdateDocument(room.getDocument()), client); - RoomHttpServerInitializer.getDatabase(ctx).updateDocument(room.getDocument()); + try { + RoomHttpServerInitializer.getDatabase(ctx).updateDocument(room.getDocument()); + } catch (DatabaseException e) { + Scribbleshare.getLogger(ctx).log(Level.WARNING, "Failed to update document", e); + //todo + } break;//todo better update logic } default: From 6928ae48a7cc3435d4e6c1b9c195c8f44d3150eb Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 25 May 2021 11:03:59 -0400 Subject: [PATCH 073/144] better exceptions and logging for db --- .../exception/ConnectionException.java | 7 ++ .../implementations/PostgresDatabase.java | 100 +++++++++--------- 2 files changed, 59 insertions(+), 48 deletions(-) create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/ConnectionException.java diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/ConnectionException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/ConnectionException.java new file mode 100644 index 00000000..59c9b4e4 --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/ConnectionException.java @@ -0,0 +1,7 @@ +package net.stzups.scribbleshare.data.database.exception; + +public class ConnectionException extends DatabaseException { + public ConnectionException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index 4e51d93d..d3cd0b0f 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -5,7 +5,8 @@ import io.netty.buffer.Unpooled; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; -import net.stzups.scribbleshare.data.database.exception.exceptions.FailedException; +import net.stzups.scribbleshare.data.database.exception.ConnectionException; +import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.InviteCode; import net.stzups.scribbleshare.data.objects.Resource; @@ -15,7 +16,6 @@ import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; import net.stzups.scribbleshare.data.objects.authentication.login.Login; import net.stzups.scribbleshare.data.objects.canvas.Canvas; -import org.postgresql.util.PSQLException; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -30,6 +30,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Random; +import java.util.logging.Level; public class PostgresDatabase implements AutoCloseable, ScribbleshareDatabase { @Override @@ -44,13 +45,13 @@ public Login getLogin(String username) { } } } catch (SQLException e) { - e.printStackTrace(); + Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting login for username " + username, e); return null; } } @Override - public boolean addLogin(Login login) throws FailedException { + public boolean addLogin(Login login) throws DatabaseException { try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO logins(username, user_id, hashed_password) VALUES(?, ?, ?)")) { preparedStatement.setString(1, login.getUsername()); preparedStatement.setLong(2, login.getId()); @@ -60,7 +61,7 @@ public boolean addLogin(Login login) throws FailedException { if (e.getSQLState().equals("23505")) { // PostgreSQL error code unique_violation return false; } else { - throw new FailedException(e); + throw new DatabaseException(e); } } @@ -79,17 +80,21 @@ public interface Config { private final Map documents = new HashMap<>(); - public PostgresDatabase(PostgresDatabase.Config config) throws Exception { - Class.forName("org.postgresql.Driver"); + public PostgresDatabase(PostgresDatabase.Config config) throws ConnectionException { + try { + Class.forName("org.postgresql.Driver"); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Exception while finding PostgreSQL JDBC driver", e); + } int retries = 0; while (connection == null) { try { connection = DriverManager.getConnection(config.getUrl(), config.getUser(), config.getPassword()); - } catch (PSQLException e) { + } catch (SQLException e) { if (e.getCause() instanceof ConnectException && (config.getMaxRetries() < 0 || retries < config.getMaxRetries())) { Scribbleshare.getLogger().info("Retrying PostgreSQL database connection (" + ++retries + "/" + config.getMaxRetries() + " retries)"); } else { - throw e; + throw new ConnectionException("Exception while establishing connection to PostgreSQL database", e); } } } @@ -101,7 +106,7 @@ public void close() throws SQLException { } @Override - public void addUser(User user) throws FailedException { + public void addUser(User user) throws DatabaseException { try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO users(id, owned_documents, shared_documents, username) VALUES (?, ?, ?, ?)")) { preparedStatement.setLong(1, user.getId()); preparedStatement.setArray(2, connection.createArrayOf("bigint", user.getOwnedDocuments().toArray())); @@ -109,7 +114,7 @@ public void addUser(User user) throws FailedException { preparedStatement.setString(4, user.getUsername()); preparedStatement.execute(); } catch (SQLException e) { - throw new FailedException(e); + throw new DatabaseException(e); } } @@ -128,25 +133,25 @@ public User getUser(long id) { } } } catch (SQLException e) { - e.printStackTrace(); + Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + User.class.getSimpleName() + " with id " + id, e); return null; } } @Override - public void updateUser(User user) throws FailedException { + public void updateUser(User user) throws DatabaseException { try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE users SET owned_documents=?, shared_documents=? WHERE id=?")){ preparedStatement.setArray(1, connection.createArrayOf("bigint", user.getOwnedDocuments().toArray())); preparedStatement.setArray(2, connection.createArrayOf("bigint", user.getSharedDocuments().toArray())); preparedStatement.setLong(3, user.getId()); preparedStatement.execute(); } catch (SQLException e) { - throw new FailedException(e); + throw new DatabaseException(e); } } @Override - public Document createDocument(User owner) { + public Document createDocument(User owner) throws DatabaseException { Document document = new Document(owner); try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO documents(id, owner, name) VALUES (?, ?, ?)")){ preparedStatement.setLong(1, document.getId()); @@ -155,16 +160,11 @@ public Document createDocument(User owner) { preparedStatement.execute(); documents.put(document.getId(), document); } catch (SQLException e) { - e.printStackTrace(); - return null; + throw new DatabaseException("Exception while creating new " + Document.class.getSimpleName() + " with owner " + owner, e); } addResource(document.getId(), document.getId(), new Resource(Canvas.getEmptyCanvas())); owner.getOwnedDocuments().add(document.getId()); - try { - updateUser(owner);//todo - } catch (FailedException e) { - e.printStackTrace(); - } + updateUser(owner);//todo return document; } @@ -181,12 +181,12 @@ public Document getDocument(long id) { resultSet.getString("name")); documents.put(document.getId(), document); } else { - System.out.println("Document with id " + id + " does not exist"); + System.out.println(Document.class.getSimpleName() + " with id " + id + " does not exist"); return null; } } } catch (SQLException e) { - e.printStackTrace(); + Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + Document.class.getSimpleName() + " with id " + id, e); return null; } } @@ -194,18 +194,18 @@ public Document getDocument(long id) { } @Override - public void updateDocument(Document document) { + public void updateDocument(Document document) throws DatabaseException { try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE documents SET name=? WHERE id=?")) { preparedStatement.setString(1, document.getName()); preparedStatement.setLong(2, document.getId()); preparedStatement.execute(); } catch (SQLException e) { - e.printStackTrace(); + throw new DatabaseException("Exception while updating " + document, e); } } @Override - public void deleteDocument(Document document) {//todo + public void deleteDocument(Document document) throws DatabaseException {//todo documents.remove(document.getId()); try (PreparedStatement preparedStatement = connection.prepareStatement("DELETE FROM documents WHERE id=?; DELETE FROM resources WHERE owner=?; DELETE FROM invite_codes WHERE document=?;")) { preparedStatement.setLong(1, document.getId()); @@ -213,7 +213,7 @@ public void deleteDocument(Document document) {//todo preparedStatement.setLong(3, document.getId()); preparedStatement.execute(); } catch (SQLException e) { - e.printStackTrace(); + throw new DatabaseException("Exception while deleting " + document, e); } } @@ -231,7 +231,7 @@ public InviteCode getInviteCode(String code) {//gets a document for an existing return new InviteCode(code, resultSet.getLong(1)); } } catch (SQLException e) { - e.printStackTrace(); + Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + InviteCode.class.getSimpleName() + " code " + code, e); return null; } } @@ -247,7 +247,7 @@ public InviteCode getInviteCode(Document document) {//gets an invite code for a } } } catch (SQLException e) { - e.printStackTrace(); + Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + InviteCode.class.getSimpleName() + " code for " + document, e); return null; } //invite code does not already exist, so a new one must be made @@ -258,13 +258,13 @@ public InviteCode getInviteCode(Document document) {//gets an invite code for a preparedStatement.execute(); return inviteCode; } catch (SQLException e) { - e.printStackTrace(); + Scribbleshare.getLogger().log(Level.WARNING, "Exception while inserting new " + inviteCode + " for " + document, e); return null; } } @Override - public void addPersistentHttpUserSession(PersistentHttpUserSession persistentHttpSession) throws FailedException { + public void addPersistentHttpUserSession(PersistentHttpUserSession persistentHttpSession) throws DatabaseException { try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO persistent_user_sessions(id, created, expired, user_id, data) VALUES (?, ?, ?, ?, ?)")) { preparedStatement.setLong(1, persistentHttpSession.getId()); preparedStatement.setTimestamp(2, persistentHttpSession.getCreated()); @@ -278,7 +278,7 @@ public void addPersistentHttpUserSession(PersistentHttpUserSession persistentHtt preparedStatement.execute(); } catch (SQLException e) { - throw new FailedException(e); + throw new DatabaseException(e); } } @@ -299,13 +299,13 @@ public HttpUserSession getHttpSession(HttpSessionCookie cookie) { Unpooled.wrappedBuffer(resultSet.getBinaryStream("data").readAllBytes())); } } catch (SQLException | IOException e) { - e.printStackTrace(); + Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + HttpUserSession.class.getSimpleName() + " for " + cookie, e); return null; } } @Override - public void addHttpSession(HttpUserSession httpUserSession) throws FailedException { + public void addHttpSession(HttpUserSession httpUserSession) throws DatabaseException { try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO user_sessions(id, created, expired, user_id, data) VALUES (?, ?, ?, ?, ?)")) { preparedStatement.setLong(1, httpUserSession.getId()); preparedStatement.setTimestamp(2, httpUserSession.getCreated()); @@ -319,29 +319,29 @@ public void addHttpSession(HttpUserSession httpUserSession) throws FailedExcepti preparedStatement.execute(); } catch (SQLException e) { - throw new FailedException(e); + throw new DatabaseException(e); } } @Override - public void expireHttpSession(HttpUserSession httpUserSession) throws FailedException { + public void expireHttpSession(HttpUserSession httpUserSession) throws DatabaseException { try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE user_sessions SET expired=? WHERE id=?")) { preparedStatement.setTimestamp(1, Timestamp.from(Instant.now())); preparedStatement.setLong(2, httpUserSession.getUser()); preparedStatement.execute(); } catch (SQLException e) { - throw new FailedException(e); + throw new DatabaseException(e); } } @Override - public long addResource(long owner, Resource resource) { + public long addResource(long owner, Resource resource) throws DatabaseException { long id = RANDOM.nextLong(); addResource(id, owner, resource); return id; } - private void addResource(long id, long owner, Resource resource) { + private void addResource(long id, long owner, Resource resource) throws DatabaseException { try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO resources(id, owner, last_modified, data) VALUES (?, ?, ?, ?)")) { preparedStatement.setLong(1, id); preparedStatement.setLong(2, owner); @@ -349,12 +349,12 @@ private void addResource(long id, long owner, Resource resource) { preparedStatement.setBinaryStream(4, new ByteBufInputStream(resource.getData())); preparedStatement.execute(); } catch (SQLException e) { - throw new RuntimeException(e);//todo + throw new DatabaseException("Exception while adding " + Resource.class.getSimpleName() + " with id " + id, e); } } @Override - public void updateResource(long id, long owner, Resource data) { + public void updateResource(long id, long owner, Resource data) throws DatabaseException { try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE resources SET last_modified=?, data=? WHERE id=? AND owner=?")) { preparedStatement.setTimestamp(1, Timestamp.from(Instant.now())); preparedStatement.setBinaryStream(2, new ByteBufInputStream(data.getData())); @@ -362,7 +362,7 @@ public void updateResource(long id, long owner, Resource data) { preparedStatement.setLong(4, owner); preparedStatement.execute(); } catch (SQLException e) { - e.printStackTrace(); + throw new DatabaseException("Exception while updating " + Resource.class.getSimpleName() + " with id " + id, e); } } @@ -378,8 +378,12 @@ public Resource getResource(long id, long owner) { return null; } } - } catch (SQLException | IOException e) { - throw new RuntimeException(e);//todo error handling?? + } catch (IOException e) { + Scribbleshare.getLogger().log(Level.WARNING, "Unexpected exception while getting " + Resource.class.getSimpleName() + " with id " + id, e); + return null; + } catch (SQLException e) { + Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + Resource.class.getSimpleName() + " with id " + id, e); + return null; } } @@ -403,7 +407,7 @@ public PersistentHttpUserSession getPersistentHttpUserSession(HttpSessionCookie } } } catch (SQLException | IOException e) { - e.printStackTrace(); + Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + PersistentHttpUserSession.class.getSimpleName() + " for " + cookie); return null; } @@ -411,12 +415,12 @@ public PersistentHttpUserSession getPersistentHttpUserSession(HttpSessionCookie } @Override - public void expirePersistentHttpUserSession(PersistentHttpUserSession session) throws FailedException { + public void expirePersistentHttpUserSession(PersistentHttpUserSession session) throws DatabaseException { try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE persistent_user_sessions SET expired=? WHERE id=?; ")) { preparedStatement.setTimestamp(1, Timestamp.from(Instant.now())); preparedStatement.setLong(2, session.getId()); } catch (SQLException e) { - throw new FailedException(e); + throw new DatabaseException("Exception while expiring " + session, e); } } } From ea8f6ecf66a681fb94dcf0609304f6f32fcb3b08 Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 25 May 2021 20:30:16 -0400 Subject: [PATCH 074/144] start to add nullable, documentation --- scribbleshare-commons/build.gradle | 1 + .../database/databases/DocumentDatabase.java | 10 ++++++++- .../databases/HttpSessionDatabase.java | 10 ++++----- .../databases/InviteCodeDatabase.java | 14 ++++++++++-- .../database/databases/LoginDatabase.java | 8 +++++-- .../PersistentHttpSessionDatabase.java | 9 ++++---- .../database/databases/ResourceDatabase.java | 8 +++---- .../data/database/databases/UserDatabase.java | 8 ++++++- .../implementations/PostgresDatabase.java | 22 ++++++++++--------- 9 files changed, 60 insertions(+), 30 deletions(-) diff --git a/scribbleshare-commons/build.gradle b/scribbleshare-commons/build.gradle index 454a11cb..8bc06697 100644 --- a/scribbleshare-commons/build.gradle +++ b/scribbleshare-commons/build.gradle @@ -11,4 +11,5 @@ dependencies { implementation 'redis.clients:jedis:3.5.2' implementation 'at.favre.lib:bcrypt:0.9.0' api 'com.github.stzups:config:master-SNAPSHOT' + implementation 'org.jetbrains:annotations:16.0.2' } \ No newline at end of file diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java index 08e1698c..bc220aba 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java @@ -3,10 +3,18 @@ import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.User; +import org.jetbrains.annotations.Nullable; public interface DocumentDatabase { Document createDocument(User owner) throws DatabaseException; - Document getDocument(long id); + + /** + * @param id of document + * @return null if {@link Document} does not exist + */ + @Nullable Document getDocument(long id); + void updateDocument(Document document) throws DatabaseException; + //todo fail silently or throw exception if document does not exist? void deleteDocument(Document document) throws DatabaseException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java index eaa20e63..7d1c777d 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java @@ -3,20 +3,20 @@ import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; +import org.jetbrains.annotations.Nullable; public interface HttpSessionDatabase { /** - * Get existing {@link HttpUserSession}, or null if it does not exist + * @param cookie of {@link HttpUserSession} + * @return null if the {@link HttpUserSession} does not exist */ - HttpUserSession getHttpSession(HttpSessionCookie cookie); + @Nullable HttpUserSession getHttpSession(HttpSessionCookie cookie); - /** - * Add new {@link HttpUserSession} - */ void addHttpSession(HttpUserSession httpUserSession) throws DatabaseException; /** * Expire existing {@link HttpUserSession} + * todo fail if does not exist? */ void expireHttpSession(HttpUserSession httpUserSession) throws DatabaseException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/InviteCodeDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/InviteCodeDatabase.java index ac4352b1..de5f6e8e 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/InviteCodeDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/InviteCodeDatabase.java @@ -2,8 +2,18 @@ import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.InviteCode; +import org.jetbrains.annotations.Nullable; public interface InviteCodeDatabase { - InviteCode getInviteCode(String code); - InviteCode getInviteCode(Document document); + /** + * @param code {@link InviteCode} + * @return null if the {@link InviteCode} does not exist for + */ + @Nullable InviteCode getInviteCode(String code); + + /** + * @param document {@link Document} + * @return null if the {@link InviteCode} does not exist + */ + @Nullable InviteCode getInviteCode(Document document); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java index fd97fd9f..07088ebc 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java @@ -2,9 +2,13 @@ import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.authentication.login.Login; +import org.jetbrains.annotations.Nullable; public interface LoginDatabase { - Login getLogin(String username); - /** false if the username already existed */ + @Nullable Login getLogin(String username); + + /** + * @return false if the login with duplicate username already exists + */ boolean addLogin(Login login) throws DatabaseException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java index 47c157c0..78dd4a9d 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java @@ -3,20 +3,19 @@ import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; +import org.jetbrains.annotations.Nullable; public interface PersistentHttpSessionDatabase { /** - * Get existing {@link PersistentHttpUserSession}, or null if it does exist + * @return null if {@link PersistentHttpUserSession} does not exist for {@param cookie} */ - PersistentHttpUserSession getPersistentHttpUserSession(HttpSessionCookie cookie); + @Nullable PersistentHttpUserSession getPersistentHttpUserSession(HttpSessionCookie cookie); - /** - * Add new {@link PersistentHttpUserSession} - */ void addPersistentHttpUserSession(PersistentHttpUserSession persistentHttpSession) throws DatabaseException; /** * Expire existing {@link PersistentHttpUserSession} + * todo fail silently or loudly if the persistent http user session does not exist? */ void expirePersistentHttpUserSession(PersistentHttpUserSession persistentHttpUserSession) throws DatabaseException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/ResourceDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/ResourceDatabase.java index c778e6cc..3db9d1af 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/ResourceDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/ResourceDatabase.java @@ -2,18 +2,18 @@ import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.Resource; +import org.jetbrains.annotations.Nullable; public interface ResourceDatabase { /** - * Add resource to database and return the corresponding id for the new resource + * @return id for the newly added {@link Resource} */ long addResource(long owner, Resource resource) throws DatabaseException; - /** update resource */ void updateResource(long id, long owner, Resource resource) throws DatabaseException; /** - * Gets resource, or null if the resource does not exist + * @return null if the {@link Resource} does not exist for {@param id} and {@param owner} */ - Resource getResource(long id, long owner); + @Nullable Resource getResource(long id, long owner); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java index 843e79ea..b61f3b3a 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java @@ -2,9 +2,15 @@ import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.User; +import org.jetbrains.annotations.Nullable; public interface UserDatabase { void addUser(User user) throws DatabaseException; - User getUser(long id); + + /** + * @return null if the {@link User} does not exist for {@param id} + */ + @Nullable User getUser(long id); + void updateUser(User user) throws DatabaseException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index d3cd0b0f..8fd93f33 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -16,6 +16,7 @@ import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; import net.stzups.scribbleshare.data.objects.authentication.login.Login; import net.stzups.scribbleshare.data.objects.canvas.Canvas; +import org.jetbrains.annotations.Nullable; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -36,14 +37,15 @@ public class PostgresDatabase implements AutoCloseable, ScribbleshareDatabase { @Override public Login getLogin(String username) { try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM logins WHERE username=?")) { - preparedStatement.setString(1, username); - try (ResultSet resultSet = preparedStatement.executeQuery()) { + throw new SQLException("poggers"); + //preparedStatement.setString(1, username); +/* try (ResultSet resultSet = preparedStatement.executeQuery()) { if (resultSet.next()) { return new Login(username, resultSet.getLong("user_id"), resultSet.getBytes("hashed_password")); } else { return null; } - } + }*/ } catch (SQLException e) { Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting login for username " + username, e); return null; @@ -102,7 +104,7 @@ public PostgresDatabase(PostgresDatabase.Config config) throws ConnectionExcepti @Override public void close() throws SQLException { - connection.close(); + connection.close(); } @Override @@ -119,7 +121,7 @@ public void addUser(User user) throws DatabaseException { } @Override - public User getUser(long id) { + public @Nullable User getUser(long id) { try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM users WHERE id=?")) { preparedStatement.setLong(1, id); try (ResultSet resultSet = preparedStatement.executeQuery()) { @@ -169,7 +171,7 @@ public Document createDocument(User owner) throws DatabaseException { } @Override - public Document getDocument(long id) { + public @Nullable Document getDocument(long id) { Document document = documents.get(id); if (document == null) { try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM documents WHERE id=?")) { @@ -237,7 +239,7 @@ public InviteCode getInviteCode(String code) {//gets a document for an existing } @Override - public InviteCode getInviteCode(Document document) {//gets an invite code for a document + public @Nullable InviteCode getInviteCode(Document document) {//gets an invite code for a document //check if invite code already exists, otherwise generate a new one try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT code FROM invite_codes WHERE document=?")) { preparedStatement.setLong(1, document.getId()); @@ -283,7 +285,7 @@ public void addPersistentHttpUserSession(PersistentHttpUserSession persistentHtt } @Override - public HttpUserSession getHttpSession(HttpSessionCookie cookie) { + public @Nullable HttpUserSession getHttpSession(HttpSessionCookie cookie) { try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM user_sessions WHERE id=?")) { preparedStatement.setLong(1, cookie.getId()); try (ResultSet resultSet = preparedStatement.executeQuery()) { @@ -367,7 +369,7 @@ public void updateResource(long id, long owner, Resource data) throws DatabaseEx } @Override - public Resource getResource(long id, long owner) { + public @Nullable Resource getResource(long id, long owner) { try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM resources WHERE id=? AND owner=?")) { preparedStatement.setLong(1, id); preparedStatement.setLong(2, owner); @@ -388,7 +390,7 @@ public Resource getResource(long id, long owner) { } @Override - public PersistentHttpUserSession getPersistentHttpUserSession(HttpSessionCookie cookie) {//todo combine + public @Nullable PersistentHttpUserSession getPersistentHttpUserSession(HttpSessionCookie cookie) {//todo combine PersistentHttpUserSession persistentHttpSession; try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM persistent_user_sessions WHERE id=?")) { From 761e866fb57076c2508c6f433d516a8933fc843d Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 25 May 2021 20:44:38 -0400 Subject: [PATCH 075/144] probably improve javadoc, still need to figure out a style/format --- .../data/database/databases/DocumentDatabase.java | 2 +- .../data/database/databases/HttpSessionDatabase.java | 2 +- .../data/database/databases/InviteCodeDatabase.java | 6 +++--- .../data/database/databases/LoginDatabase.java | 4 ++++ .../database/databases/PersistentHttpSessionDatabase.java | 3 ++- .../data/database/databases/ResourceDatabase.java | 7 +++++-- .../data/database/databases/UserDatabase.java | 3 ++- 7 files changed, 18 insertions(+), 9 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java index bc220aba..c1299989 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java @@ -9,7 +9,7 @@ public interface DocumentDatabase { Document createDocument(User owner) throws DatabaseException; /** - * @param id of document + * @param id id of document * @return null if {@link Document} does not exist */ @Nullable Document getDocument(long id); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java index 7d1c777d..3e819cb8 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java @@ -7,7 +7,7 @@ public interface HttpSessionDatabase { /** - * @param cookie of {@link HttpUserSession} + * @param cookie cookie of {@link HttpUserSession} * @return null if the {@link HttpUserSession} does not exist */ @Nullable HttpUserSession getHttpSession(HttpSessionCookie cookie); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/InviteCodeDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/InviteCodeDatabase.java index de5f6e8e..c5b05031 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/InviteCodeDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/InviteCodeDatabase.java @@ -6,13 +6,13 @@ public interface InviteCodeDatabase { /** - * @param code {@link InviteCode} - * @return null if the {@link InviteCode} does not exist for + * @param code code of {@link InviteCode} + * @return null if the {@link InviteCode} does not exist */ @Nullable InviteCode getInviteCode(String code); /** - * @param document {@link Document} + * @param document {@link Document} of {@link InviteCode} * @return null if the {@link InviteCode} does not exist */ @Nullable InviteCode getInviteCode(Document document); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java index 07088ebc..d8e5bbd3 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java @@ -5,6 +5,10 @@ import org.jetbrains.annotations.Nullable; public interface LoginDatabase { + /** + * @param username username of {@link Login} + * @return null if {@link Login} does not exist + */ @Nullable Login getLogin(String username); /** diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java index 78dd4a9d..ca1efb00 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java @@ -7,7 +7,8 @@ public interface PersistentHttpSessionDatabase { /** - * @return null if {@link PersistentHttpUserSession} does not exist for {@param cookie} + * @param cookie {@link HttpSessionCookie} of {@link PersistentHttpUserSession} + * @return null if {@link PersistentHttpUserSession} does not exist */ @Nullable PersistentHttpUserSession getPersistentHttpUserSession(HttpSessionCookie cookie); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/ResourceDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/ResourceDatabase.java index 3db9d1af..9c001360 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/ResourceDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/ResourceDatabase.java @@ -6,14 +6,17 @@ public interface ResourceDatabase { /** - * @return id for the newly added {@link Resource} + * @param owner owner of new {@link Resource} + * @return id of the newly added {@link Resource} */ long addResource(long owner, Resource resource) throws DatabaseException; void updateResource(long id, long owner, Resource resource) throws DatabaseException; /** - * @return null if the {@link Resource} does not exist for {@param id} and {@param owner} + * @param id id of {@link Resource} + * @param owner owner of {@link Resource} + * @return null if the {@link Resource} does not exist */ @Nullable Resource getResource(long id, long owner); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java index b61f3b3a..7d7b80cd 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java @@ -8,7 +8,8 @@ public interface UserDatabase { void addUser(User user) throws DatabaseException; /** - * @return null if the {@link User} does not exist for {@param id} + * @param id id of {@link User} + * @return null if the {@link User} does not exist */ @Nullable User getUser(long id); From bc59e73500254d87bbebaafbc6eaefaafbee99a9 Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 25 May 2021 21:12:52 -0400 Subject: [PATCH 076/144] javadoc, unexpected exceptions throw runtime exceptions --- .../database/exception/ConnectionException.java | 4 ++++ .../data/database/exception/DatabaseException.java | 3 +++ .../database/implementations/PostgresDatabase.java | 14 +++++++++----- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/ConnectionException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/ConnectionException.java index 59c9b4e4..485fb851 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/ConnectionException.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/ConnectionException.java @@ -1,5 +1,9 @@ package net.stzups.scribbleshare.data.database.exception; +/** + * Thrown when an exception occurs while establishing a connection to the database + * Should only be thrown when the database is initialized. If the database connections fails later, it should throw a {@link DatabaseException} + */ public class ConnectionException extends DatabaseException { public ConnectionException(String message, Throwable cause) { super(message, cause); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/DatabaseException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/DatabaseException.java index b15f5ea5..d5cb6d7c 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/DatabaseException.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/DatabaseException.java @@ -1,5 +1,8 @@ package net.stzups.scribbleshare.data.database.exception; +/** + * Thrown when there is any exception while handling a database transaction. + */ public class DatabaseException extends Exception { public DatabaseException(String message, Throwable cause) { super(message, cause); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index 8fd93f33..5017d2c6 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -72,8 +72,11 @@ public boolean addLogin(Login login) throws DatabaseException { public interface Config { String getUrl(); + String getUser(); + String getPassword(); + int getMaxRetries(); } @@ -142,7 +145,7 @@ public void addUser(User user) throws DatabaseException { @Override public void updateUser(User user) throws DatabaseException { - try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE users SET owned_documents=?, shared_documents=? WHERE id=?")){ + try (PreparedStatement preparedStatement = connection.prepareStatement("UPDATE users SET owned_documents=?, shared_documents=? WHERE id=?")) { preparedStatement.setArray(1, connection.createArrayOf("bigint", user.getOwnedDocuments().toArray())); preparedStatement.setArray(2, connection.createArrayOf("bigint", user.getSharedDocuments().toArray())); preparedStatement.setLong(3, user.getId()); @@ -155,7 +158,7 @@ public void updateUser(User user) throws DatabaseException { @Override public Document createDocument(User owner) throws DatabaseException { Document document = new Document(owner); - try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO documents(id, owner, name) VALUES (?, ?, ?)")){ + try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO documents(id, owner, name) VALUES (?, ?, ?)")) { preparedStatement.setLong(1, document.getId()); preparedStatement.setLong(2, document.getOwner()); preparedStatement.setString(3, document.getName()); @@ -381,8 +384,7 @@ public void updateResource(long id, long owner, Resource data) throws DatabaseEx } } } catch (IOException e) { - Scribbleshare.getLogger().log(Level.WARNING, "Unexpected exception while getting " + Resource.class.getSimpleName() + " with id " + id, e); - return null; + throw new RuntimeException("Unexpected exception while getting " + Resource.class.getSimpleName() + " with id " + id, e); } catch (SQLException e) { Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + Resource.class.getSimpleName() + " with id " + id, e); return null; @@ -408,7 +410,9 @@ public void updateResource(long id, long owner, Resource data) throws DatabaseEx return null; } } - } catch (SQLException | IOException e) { + } catch (IOException e) { + throw new RuntimeException("Unexpected exception while getting " + Resource.class.getSimpleName() + " for " + cookie, e); + } catch (SQLException e) { Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + PersistentHttpUserSession.class.getSimpleName() + " for " + cookie); return null; } From 4d0b82a272936ec158698da3446ba0159d717097 Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 25 May 2021 21:23:44 -0400 Subject: [PATCH 077/144] missed one --- .../data/database/implementations/PostgresDatabase.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index 5017d2c6..13ebe9cd 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -303,7 +303,9 @@ public void addPersistentHttpUserSession(PersistentHttpUserSession persistentHtt resultSet.getLong("user_id"), Unpooled.wrappedBuffer(resultSet.getBinaryStream("data").readAllBytes())); } - } catch (SQLException | IOException e) { + } catch (IOException e) { + throw new RuntimeException("Exception while getting " + HttpUserSession.class.getSimpleName() + " for " + cookie, e); + } catch (SQLException e) { Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + HttpUserSession.class.getSimpleName() + " for " + cookie, e); return null; } @@ -384,7 +386,7 @@ public void updateResource(long id, long owner, Resource data) throws DatabaseEx } } } catch (IOException e) { - throw new RuntimeException("Unexpected exception while getting " + Resource.class.getSimpleName() + " with id " + id, e); + throw new RuntimeException("Exception while getting " + Resource.class.getSimpleName() + " with id " + id, e); } catch (SQLException e) { Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + Resource.class.getSimpleName() + " with id " + id, e); return null; @@ -411,7 +413,7 @@ public void updateResource(long id, long owner, Resource data) throws DatabaseEx } } } catch (IOException e) { - throw new RuntimeException("Unexpected exception while getting " + Resource.class.getSimpleName() + " for " + cookie, e); + throw new RuntimeException("Exception while getting " + Resource.class.getSimpleName() + " for " + cookie, e); } catch (SQLException e) { Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + PersistentHttpUserSession.class.getSimpleName() + " for " + cookie); return null; From 1011ccf181835f15b7dd5f4d0d79a5f06edcc775 Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 25 May 2021 21:29:09 -0400 Subject: [PATCH 078/144] spacing and stuff --- .../database/exception/DatabaseException.java | 3 ++ .../implementations/PostgresDatabase.java | 51 +++++++++---------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/DatabaseException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/DatabaseException.java index d5cb6d7c..f3fcfb08 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/DatabaseException.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/DatabaseException.java @@ -7,6 +7,9 @@ public class DatabaseException extends Exception { public DatabaseException(String message, Throwable cause) { super(message, cause); } + public DatabaseException(String message) { + super(message); + } public DatabaseException(Throwable cause) { super(cause); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index 13ebe9cd..3d06126c 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -91,6 +91,7 @@ public PostgresDatabase(PostgresDatabase.Config config) throws ConnectionExcepti } catch (ClassNotFoundException e) { throw new RuntimeException("Exception while finding PostgreSQL JDBC driver", e); } + int retries = 0; while (connection == null) { try { @@ -128,14 +129,14 @@ public void addUser(User user) throws DatabaseException { try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM users WHERE id=?")) { preparedStatement.setLong(1, id); try (ResultSet resultSet = preparedStatement.executeQuery()) { - if (resultSet.next()) { - return new User(id, - (Long[]) (resultSet.getArray("owned_documents").getArray()), - (Long[]) (resultSet.getArray("shared_documents").getArray()), - resultSet.getString("username")); - } else { + if (!resultSet.next()) { return null; } + + return new User(id, + (Long[]) (resultSet.getArray("owned_documents").getArray()), + (Long[]) (resultSet.getArray("shared_documents").getArray()), + resultSet.getString("username")); } } catch (SQLException e) { Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + User.class.getSimpleName() + " with id " + id, e); @@ -180,15 +181,13 @@ public Document createDocument(User owner) throws DatabaseException { try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM documents WHERE id=?")) { preparedStatement.setLong(1, id); try (ResultSet resultSet = preparedStatement.executeQuery()) { - if (resultSet.next()) { - document = new Document(id, - resultSet.getLong("owner"), - resultSet.getString("name")); - documents.put(document.getId(), document); - } else { - System.out.println(Document.class.getSimpleName() + " with id " + id + " does not exist"); + if (!resultSet.next()) { return null; } + document = new Document(id, + resultSet.getLong("owner"), + resultSet.getString("name")); + documents.put(document.getId(), document); } } catch (SQLException e) { Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + Document.class.getSimpleName() + " with id " + id, e); @@ -233,6 +232,7 @@ public InviteCode getInviteCode(String code) {//gets a document for an existing if (!resultSet.next()) { return null; } + return new InviteCode(code, resultSet.getLong(1)); } } catch (SQLException e) { @@ -293,7 +293,7 @@ public void addPersistentHttpUserSession(PersistentHttpUserSession persistentHtt preparedStatement.setLong(1, cookie.getId()); try (ResultSet resultSet = preparedStatement.executeQuery()) { if (!resultSet.next()) { - return null; // does not exist + return null; } return new HttpUserSession( @@ -379,11 +379,11 @@ public void updateResource(long id, long owner, Resource data) throws DatabaseEx preparedStatement.setLong(1, id); preparedStatement.setLong(2, owner); try (ResultSet resultSet = preparedStatement.executeQuery()) { - if (resultSet.next()) { - return new Resource(resultSet.getTimestamp("last_modified"), Unpooled.wrappedBuffer(resultSet.getBinaryStream("data").readAllBytes())); - } else { + if (!resultSet.next()) { return null; } + + return new Resource(resultSet.getTimestamp("last_modified"), Unpooled.wrappedBuffer(resultSet.getBinaryStream("data").readAllBytes())); } } catch (IOException e) { throw new RuntimeException("Exception while getting " + Resource.class.getSimpleName() + " with id " + id, e); @@ -400,17 +400,16 @@ public void updateResource(long id, long owner, Resource data) throws DatabaseEx try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM persistent_user_sessions WHERE id=?")) { preparedStatement.setLong(1, cookie.getId()); try (ResultSet resultSet = preparedStatement.executeQuery()) { - if (resultSet.next()) { - persistentHttpSession = new PersistentHttpUserSession( - resultSet.getLong("id"), - resultSet.getTimestamp("created"), - resultSet.getTimestamp("expired"), - resultSet.getLong("user_id"), - Unpooled.wrappedBuffer(resultSet.getBinaryStream("data").readAllBytes())); - } else { - //todo + if (!resultSet.next()) { return null; } + + persistentHttpSession = new PersistentHttpUserSession( + resultSet.getLong("id"), + resultSet.getTimestamp("created"), + resultSet.getTimestamp("expired"), + resultSet.getLong("user_id"), + Unpooled.wrappedBuffer(resultSet.getBinaryStream("data").readAllBytes())); } } catch (IOException e) { throw new RuntimeException("Exception while getting " + Resource.class.getSimpleName() + " for " + cookie, e); From 62202f5158111408e0d83ec9b7c572eae4f24107 Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 25 May 2021 21:50:12 -0400 Subject: [PATCH 079/144] start to implement nullable properly, improve login assertions --- .../backend/server/http/HttpServerHandler.java | 9 ++++++++- .../data/database/databases/LoginDatabase.java | 1 + .../data/objects/authentication/login/Login.java | 9 +++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 2e0b3670..cadb0db7 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -255,8 +255,15 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H return; } + assert login != null : "Verified logins should never be null"; + HttpHeaders httpHeaders = new DefaultHttpHeaders(); - HttpUserSession userSession = new HttpUserSession(config, database.getUser(login.getId()), httpHeaders); + User user = database.getUser(login.getId()); + if (user == null) { + throw new InternalServerException("No user for id " + login.getId()); + } + + HttpUserSession userSession = new HttpUserSession(config, user, httpHeaders); try { database.addHttpSession(userSession); } catch (DatabaseException e) { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java index d8e5bbd3..2eb76f10 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java @@ -6,6 +6,7 @@ public interface LoginDatabase { /** + * It is important when verifying logins that the operation takes the same amount of time regardless of whether a {@link Login} exists for a provided username, or the result of the verification of the login. * @param username username of {@link Login} * @return null if {@link Login} does not exist */ diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java index a8b51320..1d288255 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java @@ -55,11 +55,20 @@ public static boolean verify(Login login, byte[] plaintext) { boolean verified = VERIFIER.verify(plaintext, hashedPassword).verified; + // might as well clear the tokens after using them, as they should only be verified once and discarded Arrays.fill(plaintext, (byte) 0); if (hashedPassword != DUMMY) { // don't clear dummy, it will be reused Arrays.fill(hashedPassword, (byte) 0); } + if (login == null) { + assert !verified : "Null logins should never be verified"; + } + + if (hashedPassword == DUMMY) { + assert !verified : "Dummy logins should never be verified"; + } + return verified; } } From 4ca4dd6b270381393c38a48ef4bcc5652e0c5798 Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 25 May 2021 21:57:46 -0400 Subject: [PATCH 080/144] nullable is properly handled --- .../server/http/HttpServerHandler.java | 12 +++--- .../room/server/websocket/Room.java | 11 ++++-- .../state/states/HandshakeState.java | 39 ++++++++++--------- .../websocket/state/states/ReadyState.java | 5 ++- 4 files changed, 38 insertions(+), 29 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index cadb0db7..ab0081b2 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -302,6 +302,9 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H HttpUserSession httpSession = database.getHttpSession(cookie); if (httpSession != null) { User u = database.getUser(httpSession.getUser()); + if (u == null) { + throw new InternalServerException("User somehow does not exist for " + httpSession); + } if (u.isRegistered()) { Scribbleshare.getLogger(ctx).info("Registered user is creating a new account"); user = new User(username); @@ -352,12 +355,12 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H return; } case LOGOUT_PATH: { - Form form = new Form(request);//todo necessary? +/* Form form = new Form(request);//todo necessary? HttpHeaders headers = new DefaultHttpHeaders(); HttpSessionCookie cookie = HttpUserSessionCookie.getHttpUserSessionCookie(request); -/* if (cookie != null) { + if (cookie != null) { HttpUserSession httpUserSession = database.getHttpSession(cookie); if (httpUserSession != null) { if (httpUserSession.validate(cookie)) { @@ -396,10 +399,9 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H Scribbleshare.getLogger(ctx).warning("Tried to log out of non existent persistent session"); //todo error } - }*/ - + } sendRedirect(ctx, request, headers, LOGOUT_SUCCESS); - return; + return;*/ } } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java index 9a651ad7..079f3c44 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java @@ -14,6 +14,7 @@ import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageAddUser; import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageOpenDocument; import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageRemoveClient; +import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; import java.util.HashMap; import java.util.HashSet; @@ -44,16 +45,20 @@ public void run() { private final Document document; private final Canvas canvas; - Room(ScribbleshareDatabase database, Document document) throws DeserializationException { + Room(ScribbleshareDatabase database, Document document) throws DeserializationException, InternalServerException { this.database = database; this.document = document; - ByteBuf canvas = database.getResource(document.getId(), document.getId()).getData(); + Resource resource = database.getResource(document.getId(), document.getId()); + if (resource == null) { + throw new InternalServerException("Somehow there is no resource for " + document); + } + ByteBuf canvas = resource.getData(); this.canvas = new Canvas(canvas); rooms.put(document, this); Scribbleshare.getLogger().info("Started " + this); } - public static Room getRoom(ScribbleshareDatabase database, Document document) throws DeserializationException { + public static Room getRoom(ScribbleshareDatabase database, Document document) throws DeserializationException, InternalServerException { Room room = rooms.get(document); if (room == null) { return new Room(database, document); diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java index 44bd22cd..2dd44b17 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java @@ -17,6 +17,7 @@ import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageHandshake; import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageUpdateDocument; import net.stzups.scribbleshare.room.server.websocket.state.State; +import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; import java.util.logging.Level; @@ -44,25 +45,25 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro //figure out which document to open first if (inviteCode != null) { Document document = RoomHttpServerInitializer.getDatabase(ctx).getDocument(inviteCode.getDocument()); - if (document != null) { - //if this isn't the user's own document and this isn't part of the user's shared documents then add and update - if (document.getOwner() != client.getUser().getId()) { - if (client.getUser().getSharedDocuments().add(document.getId())) { - try { - RoomHttpServerInitializer.getDatabase(ctx).updateUser(client.getUser()); - } catch (DatabaseException e) { - e.printStackTrace(); - //todo - } + if (document == null) { + throw new ClientMessageException(clientMessage, "Somehow used invite code for non existent document"); + } + + //if this isn't the user's own document and this isn't part of the user's shared documents then add and update + if (document.getOwner() != client.getUser().getId()) { + if (client.getUser().getSharedDocuments().add(document.getId())) { + try { + RoomHttpServerInitializer.getDatabase(ctx).updateUser(client.getUser()); + } catch (DatabaseException e) { + e.printStackTrace(); + //todo } } - try { - room = Room.getRoom(RoomHttpServerInitializer.getDatabase(ctx), document); - } catch (DeserializationException e) { - throw new ClientMessageException(clientMessage, e); - } - } else { - throw new ClientMessageException(clientMessage, "Somehow used invite code for non existent document"); + } + try { + room = Room.getRoom(RoomHttpServerInitializer.getDatabase(ctx), document); + } catch (DeserializationException | InternalServerException e) { + throw new ClientMessageException(clientMessage, e); } } else { if (client.getUser().getOwnedDocuments().size() == 0) { @@ -78,7 +79,7 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro if (document == null) { return true; } else { - client.queueMessage(new ServerMessageUpdateDocument(RoomHttpServerInitializer.getDatabase(ctx).getDocument(id))); + client.queueMessage(new ServerMessageUpdateDocument(document)); return false; } });//todo this is bad @@ -87,7 +88,7 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro if (document == null) { return true; } else { - client.queueMessage(new ServerMessageUpdateDocument(RoomHttpServerInitializer.getDatabase(ctx).getDocument(id))); + client.queueMessage(new ServerMessageUpdateDocument(document)); return false; } }); diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java index 1d22240c..c6214b5b 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java @@ -13,6 +13,7 @@ import net.stzups.scribbleshare.room.server.websocket.protocol.client.messages.ClientMessageOpenDocument; import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageUpdateDocument; import net.stzups.scribbleshare.room.server.websocket.state.State; +import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; import java.util.logging.Level; @@ -35,7 +36,7 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro Room room; try { room = Room.getRoom(RoomHttpServerInitializer.getDatabase(ctx), document); - } catch (DeserializationException e) { + } catch (DeserializationException | InternalServerException e) { throw new ClientMessageException(clientMessage, e); } room.addClient(client); @@ -59,7 +60,7 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro Room room; try { room = Room.getRoom(RoomHttpServerInitializer.getDatabase(ctx), document); - } catch (DeserializationException e) { + } catch (DeserializationException | InternalServerException e) { throw new ClientMessageException(clientMessage, e); } room.addClient(client); From a37610e55c84744ebe9b93c9e57dbd4e87549a9b Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 25 May 2021 22:04:10 -0400 Subject: [PATCH 081/144] fix logins not verified :/, remove debug, assertions are used properly --- .../backend/server/http/HttpServerHandler.java | 6 +++--- .../data/database/implementations/PostgresDatabase.java | 7 +++---- .../data/objects/authentication/login/Login.java | 6 +----- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index ab0081b2..821cbed4 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -243,12 +243,12 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H System.out.println(username + ", " + password + ", " + remember); Login login = database.getLogin(username); - if (Login.verify(login, password.getBytes(StandardCharsets.UTF_8))) { + if (!Login.verify(login, password.getBytes(StandardCharsets.UTF_8))) { //todo rate limit and generic error handling if (login == null) { - Scribbleshare.getLogger(ctx).info("Bad username " + username); + Scribbleshare.getLogger(ctx).info("Failed login attempt with bad username " + username); } else { - Scribbleshare.getLogger(ctx).info("Bad password for username " + username); + Scribbleshare.getLogger(ctx).info("Failed login attempt with bad password for username " + username); } sendRedirect(ctx, request, LOGIN_PAGE); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index 3d06126c..17f531c1 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -37,15 +37,14 @@ public class PostgresDatabase implements AutoCloseable, ScribbleshareDatabase { @Override public Login getLogin(String username) { try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM logins WHERE username=?")) { - throw new SQLException("poggers"); - //preparedStatement.setString(1, username); -/* try (ResultSet resultSet = preparedStatement.executeQuery()) { + preparedStatement.setString(1, username); + try (ResultSet resultSet = preparedStatement.executeQuery()) { if (resultSet.next()) { return new Login(username, resultSet.getLong("user_id"), resultSet.getBytes("hashed_password")); } else { return null; } - }*/ + } } catch (SQLException e) { Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting login for username " + username, e); return null; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java index 1d288255..3e74e4a0 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java @@ -62,11 +62,7 @@ public static boolean verify(Login login, byte[] plaintext) { } if (login == null) { - assert !verified : "Null logins should never be verified"; - } - - if (hashedPassword == DUMMY) { - assert !verified : "Dummy logins should never be verified"; + return false; } return verified; From 470697ffbe6a92b1af16a8e05a9b162d3d2c6e21 Mon Sep 17 00:00:00 2001 From: stzups Date: Tue, 25 May 2021 22:07:06 -0400 Subject: [PATCH 082/144] fix assertions --- .../data/objects/authentication/login/Login.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java index 3e74e4a0..b24f5bc0 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java @@ -11,9 +11,10 @@ public class Login { private static final BCrypt.Hasher HASHER = BCrypt.withDefaults(); private static final BCrypt.Verifyer VERIFIER = BCrypt.verifyer(); - private static final byte[] DUMMY; + private static final byte[] DUMMY = new byte[0]; + private static final byte[] HASHED_DUMMY; static { - DUMMY = HASHER.hash(COST, new byte[0]); // todo new byte[0] - use a different dummy plaintext? + HASHED_DUMMY = HASHER.hash(COST, DUMMY); // todo new byte[0] - use a different dummy plaintext? } private final String username; @@ -48,20 +49,27 @@ public byte[] getHashedPassword() { public static boolean verify(Login login, byte[] plaintext) { byte[] hashedPassword; if (login == null) { - hashedPassword = DUMMY; // still verify hash even when we know it will fail to protect against timing attack + hashedPassword = HASHED_DUMMY; // still verify hash even when we know it will fail to protect against timing attack } else { hashedPassword = login.hashedPassword; } boolean verified = VERIFIER.verify(plaintext, hashedPassword).verified; + if (Arrays.equals(plaintext, DUMMY)) { + assert !verified : "Dummy should be unverified"; + return false; + } + // might as well clear the tokens after using them, as they should only be verified once and discarded Arrays.fill(plaintext, (byte) 0); - if (hashedPassword != DUMMY) { // don't clear dummy, it will be reused + if (hashedPassword != HASHED_DUMMY) { // don't clear dummy, it will be reused Arrays.fill(hashedPassword, (byte) 0); } + if (login == null) { + assert !verified : "Null login should be unverified"; return false; } From 8db6deb58847496475fb984ec778911b9b87ee40 Mon Sep 17 00:00:00 2001 From: stzups Date: Wed, 26 May 2021 13:29:41 -0400 Subject: [PATCH 083/144] getters can throw --- .../server/http/HttpServerHandler.java | 60 ++++++++++---- .../database/databases/DocumentDatabase.java | 2 +- .../databases/HttpSessionDatabase.java | 2 +- .../databases/InviteCodeDatabase.java | 5 +- .../database/databases/LoginDatabase.java | 2 +- .../PersistentHttpSessionDatabase.java | 2 +- .../database/databases/ResourceDatabase.java | 2 +- .../data/database/databases/UserDatabase.java | 2 +- .../exception/ConnectionException.java | 3 + .../implementations/PostgresDatabase.java | 42 ++++------ .../exceptions/UnauthorizedException.java | 8 +- .../http/handlers/HttpAuthenticator.java | 83 ++++++++++--------- .../websocket/ClientMessageHandler.java | 13 ++- .../room/server/websocket/Room.java | 7 +- .../room/server/websocket/state/State.java | 3 +- .../state/states/HandshakeState.java | 32 +++++-- .../websocket/state/states/ReadyState.java | 18 ++-- .../websocket/state/states/RoomState.java | 11 +-- 18 files changed, 183 insertions(+), 114 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 821cbed4..4a083e55 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -179,7 +179,12 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H headers.set(HttpHeaderNames.CACHE_CONTROL, "private,max-age=0");//cache but always revalidate sendChunkedResource(ctx, request, headers, new ChunkedStream(new ByteBufInputStream(resource.getData())), resource.getLastModified());//todo don't fetch entire document from db if not modified*/ } else if (request.method().equals(HttpMethod.POST)) { //todo validation/security for submitted resources - Document document = database.getDocument(documentId); + Document document; + try { + document = database.getDocument(documentId); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } if (document == null) throw new NotFoundException("Document with id " + documentId + " for user " + user + " somehow does not exist"); @@ -200,13 +205,23 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H throw new BadRequestException("Exception while parsing " + route.get(3), e); } - Document document = database.getDocument(documentId); + Document document; + try { + document = database.getDocument(documentId); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } if (document == null) throw new NotFoundException("Document with id " + documentId + " for user " + user + " somehow does not exist"); if (request.method().equals(HttpMethod.GET)) { // get resource, resource must exist on the document - Resource resource = database.getResource(resourceId, documentId); + Resource resource; + try { + resource = database.getResource(resourceId, documentId); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } if (resource == null) { throw new NotFoundException("Resource does not exist"); } @@ -239,10 +254,12 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H String password = form.getText("password"); boolean remember = form.getCheckbox("remember"); - - System.out.println(username + ", " + password + ", " + remember); - - Login login = database.getLogin(username); + Login login; + try { + login = database.getLogin(username); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } if (!Login.verify(login, password.getBytes(StandardCharsets.UTF_8))) { //todo rate limit and generic error handling if (login == null) { @@ -258,7 +275,12 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H assert login != null : "Verified logins should never be null"; HttpHeaders httpHeaders = new DefaultHttpHeaders(); - User user = database.getUser(login.getId()); + User user; + try { + user = database.getUser(login.getId()); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } if (user == null) { throw new InternalServerException("No user for id " + login.getId()); } @@ -267,14 +289,14 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H try { database.addHttpSession(userSession); } catch (DatabaseException e) { - throw new InternalServerException("Exception while adding http session to database", e); + throw new InternalServerException(e); } if (remember) { PersistentHttpUserSession persistentHttpUserSession = new PersistentHttpUserSession(config, userSession, httpHeaders); try { database.addPersistentHttpUserSession(persistentHttpUserSession); } catch (DatabaseException e) { - throw new InternalServerException("Exception while adding persistent http session to database", e); + throw new InternalServerException(e); } } sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); @@ -299,9 +321,19 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H User user; HttpSessionCookie cookie = HttpUserSessionCookie.getHttpUserSessionCookie(request); if (cookie != null) { - HttpUserSession httpSession = database.getHttpSession(cookie); + HttpUserSession httpSession; + try { + httpSession = database.getHttpSession(cookie); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } if (httpSession != null) { - User u = database.getUser(httpSession.getUser()); + User u; + try { + u = database.getUser(httpSession.getUser()); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } if (u == null) { throw new InternalServerException("User somehow does not exist for " + httpSession); } @@ -322,7 +354,7 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H try { database.addUser(user); } catch (DatabaseException e) { - throw new InternalServerException("todo", e); + throw new InternalServerException(e); } } } else { @@ -330,7 +362,7 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H try { database.addUser(user); } catch (DatabaseException e) { - throw new InternalServerException("todo", e); + throw new InternalServerException(e); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java index c1299989..e40bda8a 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/DocumentDatabase.java @@ -12,7 +12,7 @@ public interface DocumentDatabase { * @param id id of document * @return null if {@link Document} does not exist */ - @Nullable Document getDocument(long id); + @Nullable Document getDocument(long id) throws DatabaseException; void updateDocument(Document document) throws DatabaseException; //todo fail silently or throw exception if document does not exist? diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java index 3e819cb8..b1b9edc1 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/HttpSessionDatabase.java @@ -10,7 +10,7 @@ public interface HttpSessionDatabase { * @param cookie cookie of {@link HttpUserSession} * @return null if the {@link HttpUserSession} does not exist */ - @Nullable HttpUserSession getHttpSession(HttpSessionCookie cookie); + @Nullable HttpUserSession getHttpSession(HttpSessionCookie cookie) throws DatabaseException; void addHttpSession(HttpUserSession httpUserSession) throws DatabaseException; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/InviteCodeDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/InviteCodeDatabase.java index c5b05031..a0ba6f82 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/InviteCodeDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/InviteCodeDatabase.java @@ -1,5 +1,6 @@ package net.stzups.scribbleshare.data.database.databases; +import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.data.objects.InviteCode; import org.jetbrains.annotations.Nullable; @@ -9,11 +10,11 @@ public interface InviteCodeDatabase { * @param code code of {@link InviteCode} * @return null if the {@link InviteCode} does not exist */ - @Nullable InviteCode getInviteCode(String code); + @Nullable InviteCode getInviteCode(String code) throws DatabaseException; /** * @param document {@link Document} of {@link InviteCode} * @return null if the {@link InviteCode} does not exist */ - @Nullable InviteCode getInviteCode(Document document); + @Nullable InviteCode getInviteCode(Document document) throws DatabaseException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java index 2eb76f10..8dfd0079 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/LoginDatabase.java @@ -10,7 +10,7 @@ public interface LoginDatabase { * @param username username of {@link Login} * @return null if {@link Login} does not exist */ - @Nullable Login getLogin(String username); + @Nullable Login getLogin(String username) throws DatabaseException; /** * @return false if the login with duplicate username already exists diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java index ca1efb00..bb3d3008 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/PersistentHttpSessionDatabase.java @@ -10,7 +10,7 @@ public interface PersistentHttpSessionDatabase { * @param cookie {@link HttpSessionCookie} of {@link PersistentHttpUserSession} * @return null if {@link PersistentHttpUserSession} does not exist */ - @Nullable PersistentHttpUserSession getPersistentHttpUserSession(HttpSessionCookie cookie); + @Nullable PersistentHttpUserSession getPersistentHttpUserSession(HttpSessionCookie cookie) throws DatabaseException; void addPersistentHttpUserSession(PersistentHttpUserSession persistentHttpSession) throws DatabaseException; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/ResourceDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/ResourceDatabase.java index 9c001360..757e8060 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/ResourceDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/ResourceDatabase.java @@ -18,5 +18,5 @@ public interface ResourceDatabase { * @param owner owner of {@link Resource} * @return null if the {@link Resource} does not exist */ - @Nullable Resource getResource(long id, long owner); + @Nullable Resource getResource(long id, long owner) throws DatabaseException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java index 7d7b80cd..e85b918a 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/databases/UserDatabase.java @@ -11,7 +11,7 @@ public interface UserDatabase { * @param id id of {@link User} * @return null if the {@link User} does not exist */ - @Nullable User getUser(long id); + @Nullable User getUser(long id) throws DatabaseException; void updateUser(User user) throws DatabaseException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/ConnectionException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/ConnectionException.java index 485fb851..98b34d04 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/ConnectionException.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/exception/ConnectionException.java @@ -5,6 +5,9 @@ * Should only be thrown when the database is initialized. If the database connections fails later, it should throw a {@link DatabaseException} */ public class ConnectionException extends DatabaseException { + public ConnectionException(Throwable cause) { + super(cause); + } public ConnectionException(String message, Throwable cause) { super(message, cause); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index 17f531c1..73923c7c 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -35,7 +35,7 @@ public class PostgresDatabase implements AutoCloseable, ScribbleshareDatabase { @Override - public Login getLogin(String username) { + public Login getLogin(String username) throws DatabaseException { try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM logins WHERE username=?")) { preparedStatement.setString(1, username); try (ResultSet resultSet = preparedStatement.executeQuery()) { @@ -99,7 +99,7 @@ public PostgresDatabase(PostgresDatabase.Config config) throws ConnectionExcepti if (e.getCause() instanceof ConnectException && (config.getMaxRetries() < 0 || retries < config.getMaxRetries())) { Scribbleshare.getLogger().info("Retrying PostgreSQL database connection (" + ++retries + "/" + config.getMaxRetries() + " retries)"); } else { - throw new ConnectionException("Exception while establishing connection to PostgreSQL database", e); + throw new ConnectionException(e); } } } @@ -119,12 +119,12 @@ public void addUser(User user) throws DatabaseException { preparedStatement.setString(4, user.getUsername()); preparedStatement.execute(); } catch (SQLException e) { - throw new DatabaseException(e); + throw new DatabaseException("Exception while getting " + user, e); } } @Override - public @Nullable User getUser(long id) { + public @Nullable User getUser(long id) throws DatabaseException { try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM users WHERE id=?")) { preparedStatement.setLong(1, id); try (ResultSet resultSet = preparedStatement.executeQuery()) { @@ -151,7 +151,7 @@ public void updateUser(User user) throws DatabaseException { preparedStatement.setLong(3, user.getId()); preparedStatement.execute(); } catch (SQLException e) { - throw new DatabaseException(e); + throw new DatabaseException("Exception while updating user " + user, e); } } @@ -174,7 +174,7 @@ public Document createDocument(User owner) throws DatabaseException { } @Override - public @Nullable Document getDocument(long id) { + public @Nullable Document getDocument(long id) throws DatabaseException { Document document = documents.get(id); if (document == null) { try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM documents WHERE id=?")) { @@ -189,8 +189,7 @@ public Document createDocument(User owner) throws DatabaseException { documents.put(document.getId(), document); } } catch (SQLException e) { - Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + Document.class.getSimpleName() + " with id " + id, e); - return null; + throw new DatabaseException("Exception while getting " + Document.class.getSimpleName() + " with id " + id, e); } } return document; @@ -221,7 +220,7 @@ public void deleteDocument(Document document) throws DatabaseException {//todo } @Override - public InviteCode getInviteCode(String code) {//gets a document for an existing invite code + public InviteCode getInviteCode(String code) throws DatabaseException {//gets a document for an existing invite code if (code.length() != InviteCode.INVITE_CODE_LENGTH) { return null; } @@ -235,13 +234,12 @@ public InviteCode getInviteCode(String code) {//gets a document for an existing return new InviteCode(code, resultSet.getLong(1)); } } catch (SQLException e) { - Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + InviteCode.class.getSimpleName() + " code " + code, e); - return null; + throw new DatabaseException("Exception while getting " + InviteCode.class.getSimpleName() + " with code " + code, e); } } @Override - public @Nullable InviteCode getInviteCode(Document document) {//gets an invite code for a document + public @Nullable InviteCode getInviteCode(Document document) throws DatabaseException {//gets an invite code for a document //check if invite code already exists, otherwise generate a new one try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT code FROM invite_codes WHERE document=?")) { preparedStatement.setLong(1, document.getId()); @@ -262,8 +260,7 @@ public InviteCode getInviteCode(String code) {//gets a document for an existing preparedStatement.execute(); return inviteCode; } catch (SQLException e) { - Scribbleshare.getLogger().log(Level.WARNING, "Exception while inserting new " + inviteCode + " for " + document, e); - return null; + throw new DatabaseException("Exception while inserting new " + inviteCode + " for " + document, e); } } @@ -287,7 +284,7 @@ public void addPersistentHttpUserSession(PersistentHttpUserSession persistentHtt } @Override - public @Nullable HttpUserSession getHttpSession(HttpSessionCookie cookie) { + public @Nullable HttpUserSession getHttpSession(HttpSessionCookie cookie) throws DatabaseException { try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM user_sessions WHERE id=?")) { preparedStatement.setLong(1, cookie.getId()); try (ResultSet resultSet = preparedStatement.executeQuery()) { @@ -305,8 +302,7 @@ public void addPersistentHttpUserSession(PersistentHttpUserSession persistentHtt } catch (IOException e) { throw new RuntimeException("Exception while getting " + HttpUserSession.class.getSimpleName() + " for " + cookie, e); } catch (SQLException e) { - Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + HttpUserSession.class.getSimpleName() + " for " + cookie, e); - return null; + throw new DatabaseException("Exception while getting " + HttpUserSession.class.getSimpleName() + " for " + cookie, e); } } @@ -325,7 +321,7 @@ public void addHttpSession(HttpUserSession httpUserSession) throws DatabaseExcep preparedStatement.execute(); } catch (SQLException e) { - throw new DatabaseException(e); + throw new DatabaseException("Exception while adding " + httpUserSession, e); } } @@ -373,7 +369,7 @@ public void updateResource(long id, long owner, Resource data) throws DatabaseEx } @Override - public @Nullable Resource getResource(long id, long owner) { + public @Nullable Resource getResource(long id, long owner) throws DatabaseException { try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM resources WHERE id=? AND owner=?")) { preparedStatement.setLong(1, id); preparedStatement.setLong(2, owner); @@ -387,13 +383,12 @@ public void updateResource(long id, long owner, Resource data) throws DatabaseEx } catch (IOException e) { throw new RuntimeException("Exception while getting " + Resource.class.getSimpleName() + " with id " + id, e); } catch (SQLException e) { - Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + Resource.class.getSimpleName() + " with id " + id, e); - return null; + throw new DatabaseException("Exception while getting " + Resource.class.getSimpleName() + " with id " + id, e); } } @Override - public @Nullable PersistentHttpUserSession getPersistentHttpUserSession(HttpSessionCookie cookie) {//todo combine + public @Nullable PersistentHttpUserSession getPersistentHttpUserSession(HttpSessionCookie cookie) throws DatabaseException {//todo combine PersistentHttpUserSession persistentHttpSession; try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM persistent_user_sessions WHERE id=?")) { @@ -413,8 +408,7 @@ public void updateResource(long id, long owner, Resource data) throws DatabaseEx } catch (IOException e) { throw new RuntimeException("Exception while getting " + Resource.class.getSimpleName() + " for " + cookie, e); } catch (SQLException e) { - Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + PersistentHttpUserSession.class.getSimpleName() + " for " + cookie); - return null; + throw new DatabaseException("Exception while getting " + PersistentHttpUserSession.class.getSimpleName() + " for " + cookie); } return persistentHttpSession; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/UnauthorizedException.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/UnauthorizedException.java index 88c41721..e770b618 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/UnauthorizedException.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/exception/exceptions/UnauthorizedException.java @@ -8,8 +8,12 @@ public UnauthorizedException(String message) { super(message); } - public UnauthorizedException(String message, Exception e) { - super(message, e); + public UnauthorizedException(Throwable cause) { + super(cause); + } + + public UnauthorizedException(String message, Throwable cause) { + super(message, cause); } @Override diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java index 6123a5d0..22bdc04d 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java @@ -85,44 +85,45 @@ public static AuthenticatedUserSession authenticateHttpUserSession(FullHttpReque } catch (BadRequestException e) { throw new UnauthorizedException("Malformed cookie", e); } - if (sessionCookie == null) { return null; } - HttpUserSession userSession = database.getHttpSession(sessionCookie); - if (userSession == null) { - throw new UnauthorizedException("Bad authentication (bad id)"); - } - - AuthenticationResult result = userSession.validate(sessionCookie); - if (result != AuthenticationResult.SUCCESS) { - throw new UnauthorizedException("Bad authentication " + result); + User user; + try { + HttpUserSession userSession = database.getHttpSession(sessionCookie); + if (userSession == null) { + throw new UnauthorizedException("Bad authentication (bad id)"); + } + + AuthenticationResult result = userSession.validate(sessionCookie); + if (result != AuthenticationResult.SUCCESS) { + throw new UnauthorizedException("Bad authentication " + result); + } + + user = database.getUser(userSession.getUser()); + if (user == null) { + throw new InternalServerException("Unknown user for authentication"); + } + } catch (DatabaseException e) { + throw new InternalServerException(e); } - User user = database.getUser(userSession.getUser()); - if (user == null) - throw new InternalServerException("Unknown user for authentication"); - return new AuthenticatedUserSession(user); } /** create session and persistent session for user */ private static AuthenticatedUserSession createHttpSession(User user, HttpConfig httpConfig, Database database, HttpHeaders httpHeaders) throws InternalServerException { - // create session - HttpUserSession httpUserSession = new HttpUserSession(httpConfig, user, httpHeaders); try { + // create session + HttpUserSession httpUserSession = new HttpUserSession(httpConfig, user, httpHeaders); database.addHttpSession(httpUserSession); - } catch (DatabaseException e) { - throw new InternalServerException("Failed to add http session", e); - } - // create new persistent session - PersistentHttpUserSession a = new PersistentHttpUserSession(httpConfig, httpUserSession, httpHeaders); - try { + // create new persistent session + PersistentHttpUserSession a = new PersistentHttpUserSession(httpConfig, httpUserSession, httpHeaders); database.addPersistentHttpUserSession(a); } catch (DatabaseException e) { - throw new InternalServerException("Failed to add persistent http session", e); + throw new InternalServerException(e); } return new AuthenticatedUserSession(user); @@ -139,32 +140,34 @@ public static AuthenticatedUserSession logInHttpSession(FullHttpRequest request, try { sessionCookie = HttpUserSessionCookie.getHttpUserSessionCookie(request); } catch (BadRequestException e) { - throw new UnauthorizedException("Malformed cookie", e); + throw new UnauthorizedException(e); } if (sessionCookie == null) { return null; } - PersistentHttpUserSession persistentHttpUserSession = database.getPersistentHttpUserSession(sessionCookie); - if (persistentHttpUserSession == null) { - throw new UnauthorizedException("Bad authentication (bad id)"); - } - + User user; try { + PersistentHttpUserSession persistentHttpUserSession = database.getPersistentHttpUserSession(sessionCookie); + if (persistentHttpUserSession == null) { + throw new UnauthorizedException("Bad authentication (bad id)"); + } + database.expirePersistentHttpUserSession(persistentHttpUserSession); - } catch (DatabaseException e) { - throw new InternalServerException("Failed to expire persistent http session", e); - } - AuthenticationResult result = persistentHttpUserSession.validate(sessionCookie); - if (result != AuthenticationResult.SUCCESS) { - throw new UnauthorizedException("Bad authentication " + result); - } - // now logged in + AuthenticationResult result = persistentHttpUserSession.validate(sessionCookie); + if (result != AuthenticationResult.SUCCESS) { + throw new UnauthorizedException("Bad authentication " + result); + } + // now logged in - User user = database.getUser(persistentHttpUserSession.getId()); - if (user == null) { - throw new InternalServerException("User somehow does not exist " + persistentHttpUserSession.getUser()); + user = database.getUser(persistentHttpUserSession.getId()); + if (user == null) { + throw new InternalServerException("User somehow does not exist " + persistentHttpUserSession.getUser()); + } + + } catch (DatabaseException e) { + throw new InternalServerException(e); } return createHttpSession(user, httpConfig, database, httpHeaders); @@ -181,7 +184,7 @@ public static AuthenticatedUserSession createHttpSession(FullHttpRequest request try { database.addUser(user); } catch (DatabaseException e) { - throw new InternalServerException("Failed to add user", e); + throw new InternalServerException(e); } return createHttpSession(user, httpConfig, database, httpHeaders); diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java index aa2073ec..cc213960 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java @@ -9,6 +9,7 @@ import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessage; import net.stzups.scribbleshare.room.server.websocket.state.State; import net.stzups.scribbleshare.room.server.websocket.state.states.InitialState; +import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; import net.stzups.scribbleshare.server.http.handlers.HttpAuthenticator; import java.util.logging.Level; @@ -38,11 +39,17 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object event) { @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - Scribbleshare.getLogger(ctx).log(Level.WARNING, "Unhandled exception while in connection state " + getState(ctx).get(), cause); + Scribbleshare.getLogger(ctx).log(Level.WARNING, "Unhandled exception while in " + getState(ctx).get(), cause); } @Override - protected void channelRead0(ChannelHandlerContext ctx, ClientMessage message) throws ClientMessageException { - ctx.channel().attr(STATE).get().message(ctx, message); + protected void channelRead0(ChannelHandlerContext ctx, ClientMessage message) { + try { + ctx.channel().attr(STATE).get().message(ctx, message); + } catch (ClientMessageException | InternalServerException e) { + Scribbleshare.getLogger(ctx).log(Level.WARNING, "Exception while handling message while in " + getState(ctx), e); + //todo write exception + //todo toString for state + } } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java index 079f3c44..2436d416 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java @@ -48,7 +48,12 @@ public void run() { Room(ScribbleshareDatabase database, Document document) throws DeserializationException, InternalServerException { this.database = database; this.document = document; - Resource resource = database.getResource(document.getId(), document.getId()); + Resource resource; + try { + resource = database.getResource(document.getId(), document.getId()); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } if (resource == null) { throw new InternalServerException("Somehow there is no resource for " + document); } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/State.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/State.java index 327fdf31..9274b286 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/State.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/State.java @@ -5,6 +5,7 @@ import net.stzups.scribbleshare.room.server.websocket.ClientMessageException; import net.stzups.scribbleshare.room.server.websocket.ClientMessageHandler; import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessage; +import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; public abstract class State { public static void setState(ChannelHandlerContext ctx, State state) { @@ -20,7 +21,7 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object event) { throw new UnsupportedOperationException("Unhandled Netty userEventTriggered " + event); } - public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) throws ClientMessageException { + public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) throws ClientMessageException, InternalServerException { throw new UnsupportedOperationException("Unhandled ClientMessage " + clientMessage.getClass().getSimpleName()); } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java index 2dd44b17..e35279ef 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java @@ -29,7 +29,7 @@ public HandshakeState(AuthenticatedUserSession session) { } @Override - public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) throws ClientMessageException { + public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) throws ClientMessageException, InternalServerException { Room room = null;//todo switch (clientMessage.getMessageType()) { case HANDSHAKE: { @@ -40,11 +40,21 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro Client client = new Client(session.getUser(), ctx.channel()); client.queueMessage(new ServerMessageHandshake(client)); - InviteCode inviteCode = RoomHttpServerInitializer.getDatabase(ctx).getInviteCode(clientPacketHandshake.getCode()); + InviteCode inviteCode; + try { + inviteCode = RoomHttpServerInitializer.getDatabase(ctx).getInviteCode(clientPacketHandshake.getCode()); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } client.queueMessage(new ServerMessageAddUser(client.getUser())); //figure out which document to open first if (inviteCode != null) { - Document document = RoomHttpServerInitializer.getDatabase(ctx).getDocument(inviteCode.getDocument()); + Document document; + try { + document = RoomHttpServerInitializer.getDatabase(ctx).getDocument(inviteCode.getDocument()); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } if (document == null) { throw new ClientMessageException(clientMessage, "Somehow used invite code for non existent document"); } @@ -62,7 +72,7 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro } try { room = Room.getRoom(RoomHttpServerInitializer.getDatabase(ctx), document); - } catch (DeserializationException | InternalServerException e) { + } catch (DeserializationException e) { throw new ClientMessageException(clientMessage, e); } } else { @@ -75,7 +85,12 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro } } client.getUser().getOwnedDocuments().removeIf((id) -> { - Document document = RoomHttpServerInitializer.getDatabase(ctx).getDocument(id); + Document document; + try { + document = RoomHttpServerInitializer.getDatabase(ctx).getDocument(id); + } catch (DatabaseException e) { + throw new RuntimeException(new InternalServerException(e));//todo + } if (document == null) { return true; } else { @@ -84,7 +99,12 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro } });//todo this is bad client.getUser().getSharedDocuments().removeIf((id) -> { - Document document = RoomHttpServerInitializer.getDatabase(ctx).getDocument(id); + Document document; + try { + document = RoomHttpServerInitializer.getDatabase(ctx).getDocument(id); + } catch (DatabaseException e) { + throw new RuntimeException(new InternalServerException(e));//todo + } if (document == null) { return true; } else { diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java index c6214b5b..eccb5c3d 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java @@ -15,8 +15,6 @@ import net.stzups.scribbleshare.room.server.websocket.state.State; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; -import java.util.logging.Level; - public class ReadyState extends State { private final Client client; @@ -25,18 +23,23 @@ public class ReadyState extends State { } @Override - public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) throws ClientMessageException { + public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) throws ClientMessageException, InternalServerException { switch (clientMessage.getMessageType()) { case OPEN_DOCUMENT: { ClientMessageOpenDocument clientPacketOpenDocument = (ClientMessageOpenDocument) clientMessage; - Document document = RoomHttpServerInitializer.getDatabase(ctx).getDocument(clientPacketOpenDocument.getId()); + Document document; + try { + document = RoomHttpServerInitializer.getDatabase(ctx).getDocument(clientPacketOpenDocument.getId()); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } if (document != null) { //open Room room; try { room = Room.getRoom(RoomHttpServerInitializer.getDatabase(ctx), document); - } catch (DeserializationException | InternalServerException e) { + } catch (DeserializationException e) { throw new ClientMessageException(clientMessage, e); } room.addClient(client); @@ -52,15 +55,14 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro try { document = RoomHttpServerInitializer.getDatabase(ctx).createDocument(client.getUser()); } catch (DatabaseException e) { - Scribbleshare.getLogger().log(Level.WARNING, "Failed to create document for client that requested it", e);//todo this will probably break the client - return;//todo throw server exception + throw new InternalServerException("Exception while creating document for client " + client + " that request it", e); } client.sendMessage(new ServerMessageUpdateDocument(document)); //open Room room; try { room = Room.getRoom(RoomHttpServerInitializer.getDatabase(ctx), document); - } catch (DeserializationException | InternalServerException e) { + } catch (DeserializationException e) { throw new ClientMessageException(clientMessage, e); } room.addClient(client); diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java index 1f5649ce..1be11300 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java @@ -16,8 +16,7 @@ import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageCanvasUpdate; import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageDeleteDocument; import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageUpdateDocument; - -import java.util.logging.Level; +import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; public class RoomState extends ReadyState { private final Client client; @@ -36,7 +35,7 @@ public void channelInactive(ChannelHandlerContext ctx) { } @Override - public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) throws ClientMessageException { + public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) throws ClientMessageException, InternalServerException { switch (clientMessage.getMessageType()) { case CANVAS_UPDATE: { @@ -64,8 +63,7 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro try { RoomHttpServerInitializer.getDatabase(ctx).deleteDocument(room.getDocument()); } catch (DatabaseException e) { - Scribbleshare.getLogger().log(Level.WARNING, "Failed to delete document", e); - //todo + throw new InternalServerException(e); } break; } else { @@ -93,8 +91,7 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro try { RoomHttpServerInitializer.getDatabase(ctx).updateDocument(room.getDocument()); } catch (DatabaseException e) { - Scribbleshare.getLogger(ctx).log(Level.WARNING, "Failed to update document", e); - //todo + throw new InternalServerException(e); } break;//todo better update logic } From b641d3f41543a2e38dc771a1a4c939207bcfd87d Mon Sep 17 00:00:00 2001 From: stzups Date: Wed, 26 May 2021 13:38:02 -0400 Subject: [PATCH 084/144] start to improve toString of ScribbleshareRoom --- .../stzups/scribbleshare/room/server/websocket/Client.java | 2 +- .../room/server/websocket/ClientMessageHandler.java | 3 +-- .../scribbleshare/room/server/websocket/MouseMove.java | 5 +++++ .../net/stzups/scribbleshare/room/server/websocket/Room.java | 2 +- .../room/server/websocket/state/states/HandshakeState.java | 5 +++++ .../room/server/websocket/state/states/InitialState.java | 5 +++++ .../room/server/websocket/state/states/ReadyState.java | 5 +++++ .../room/server/websocket/state/states/RoomState.java | 5 +++++ 8 files changed, 28 insertions(+), 4 deletions(-) diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Client.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Client.java index 83c47a49..b7331f72 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Client.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Client.java @@ -72,7 +72,7 @@ public void serialize(ByteBuf byteBuf) { @Override public String toString() { - return "Client{user=" + user + ",address=" + channel.remoteAddress() + "}"; + return Client.class.getSimpleName() + "[" + user + ",address=" + channel.remoteAddress() + ",id=" + id + "]"; } @Override diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java index cc213960..c8bb8ee5 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java @@ -48,8 +48,7 @@ protected void channelRead0(ChannelHandlerContext ctx, ClientMessage message) { ctx.channel().attr(STATE).get().message(ctx, message); } catch (ClientMessageException | InternalServerException e) { Scribbleshare.getLogger(ctx).log(Level.WARNING, "Exception while handling message while in " + getState(ctx), e); - //todo write exception - //todo toString for state + //todo send exception to client } } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java index 6c1b1860..59102283 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java @@ -18,4 +18,9 @@ public void serialize(ByteBuf byteBuf) { byteBuf.writeShort(x); byteBuf.writeShort(y); } + + @Override + public String toString() { + return MouseMove.class.getSimpleName() + "[dt=" + dt + ",x=" + x + ",y=" + y + "}"; + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java index 2436d416..06503e98 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java @@ -180,6 +180,6 @@ private void update() { @Override public String toString() { - return "Room{document=" + document + "}"; + return Room.class.getSimpleName() + "[" + document + "," + canvas + ",clients[" + clients.size() + "]]"; } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java index e35279ef..343e44e4 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java @@ -121,4 +121,9 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro super.message(ctx, clientMessage); } } + + @Override + public String toString() { + return HandshakeState.class.getSimpleName() + "{" + session + "}"; + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java index d09ff7f7..b04c1b9b 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java @@ -25,4 +25,9 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object event) { super.userEventTriggered(ctx, event); } + + @Override + public String toString() { + return InitialState.class.getSimpleName() + "{" + session + "}"; + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java index eccb5c3d..9e75b368 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java @@ -106,4 +106,9 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro super.message(ctx, clientMessage); } } + + @Override + public String toString() { + return ReadyState.class.getSimpleName() + "{" + client + "}"; + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java index 1be11300..a3ded107 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java @@ -99,4 +99,9 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro super.message(ctx, clientMessage); } } + + @Override + public String toString() { + return RoomState.class.getSimpleName() + "[" + client + "," + room + "]"; + } } From 9b1bdcdf2c737696d9cb18495146c6f991ddbecd Mon Sep 17 00:00:00 2001 From: stzups Date: Wed, 26 May 2021 13:43:01 -0400 Subject: [PATCH 085/144] change #toString formatting --- .../net/stzups/scribbleshare/room/server/websocket/Client.java | 2 +- .../stzups/scribbleshare/room/server/websocket/MouseMove.java | 2 +- .../net/stzups/scribbleshare/room/server/websocket/Room.java | 2 +- .../room/server/websocket/state/states/HandshakeState.java | 2 +- .../room/server/websocket/state/states/InitialState.java | 2 +- .../room/server/websocket/state/states/ReadyState.java | 2 +- .../room/server/websocket/state/states/RoomState.java | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Client.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Client.java index b7331f72..abde5350 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Client.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Client.java @@ -72,7 +72,7 @@ public void serialize(ByteBuf byteBuf) { @Override public String toString() { - return Client.class.getSimpleName() + "[" + user + ",address=" + channel.remoteAddress() + ",id=" + id + "]"; + return Client.class.getSimpleName() + "{user=" + user + ",address=" + channel.remoteAddress() + ",id=" + id + "}"; } @Override diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java index 59102283..0be0a580 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java @@ -21,6 +21,6 @@ public void serialize(ByteBuf byteBuf) { @Override public String toString() { - return MouseMove.class.getSimpleName() + "[dt=" + dt + ",x=" + x + ",y=" + y + "}"; + return MouseMove.class.getSimpleName() + "{dt=" + dt + ",x=" + x + ",y=" + y + "}"; } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java index 06503e98..f8f5da8e 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java @@ -180,6 +180,6 @@ private void update() { @Override public String toString() { - return Room.class.getSimpleName() + "[" + document + "," + canvas + ",clients[" + clients.size() + "]]"; + return Room.class.getSimpleName() + "{" + document + "," + canvas + ",clients=[" + clients.size() + "]}"; } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java index 343e44e4..631686bb 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java @@ -124,6 +124,6 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro @Override public String toString() { - return HandshakeState.class.getSimpleName() + "{" + session + "}"; + return HandshakeState.class.getSimpleName() + "{session=" + session + "}"; } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java index b04c1b9b..79160293 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java @@ -28,6 +28,6 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object event) { @Override public String toString() { - return InitialState.class.getSimpleName() + "{" + session + "}"; + return InitialState.class.getSimpleName() + "{session=" + session + "}"; } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java index 9e75b368..54767ab5 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java @@ -109,6 +109,6 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro @Override public String toString() { - return ReadyState.class.getSimpleName() + "{" + client + "}"; + return ReadyState.class.getSimpleName() + "{client=" + client + "}"; } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java index a3ded107..6adbe6ce 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java @@ -102,6 +102,6 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro @Override public String toString() { - return RoomState.class.getSimpleName() + "[" + client + "," + room + "]"; + return RoomState.class.getSimpleName() + "{client=" + client + ",room=" + room + "}"; } } From e01653925182cefe192a57442eaf512aaba08c02 Mon Sep 17 00:00:00 2001 From: stzups Date: Wed, 26 May 2021 13:43:25 -0400 Subject: [PATCH 086/144] fix HttpAuthenticator passing along unauthenticated requests --- .../scribbleshare/server/http/handlers/HttpAuthenticator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java index 22bdc04d..68cef11c 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java @@ -60,6 +60,7 @@ protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List Date: Wed, 26 May 2021 13:44:37 -0400 Subject: [PATCH 087/144] disable verbose console output --- .../java/net/stzups/scribbleshare/server/http/HttpUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java index 084d1c76..8af47767 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java @@ -145,10 +145,10 @@ public static void send(ChannelHandlerContext ctx, FullHttpRequest request, Http public static void sendChunkedResource(ChannelHandlerContext ctx, FullHttpRequest request, HttpHeaders headers, ChunkedInput chunkedInput, Timestamp lastModified) throws BadRequestException { setDateAndLastModified(headers, lastModified); if (isModifiedSince(request, lastModified)) { - Scribbleshare.getLogger(ctx).info("Uncached"); + //Scribbleshare.getLogger(ctx).info("Uncached"); sendChunkedResource(ctx, request, headers, chunkedInput); } else { - Scribbleshare.getLogger(ctx).info("Cached"); + //Scribbleshare.getLogger(ctx).info("Cached"); FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_MODIFIED, Unpooled.EMPTY_BUFFER); response.headers().set(headers); From 46d0d1a5a50858e4a9d1147d5ca2be139412b93f Mon Sep 17 00:00:00 2001 From: stzups Date: Wed, 26 May 2021 14:12:28 -0400 Subject: [PATCH 088/144] fix duplicate log --- .../scribbleshare/backend/server/http/HttpServerHandler.java | 1 - 1 file changed, 1 deletion(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 4a083e55..40035f0d 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -121,7 +121,6 @@ public HttpServerHandler(Config config, ScribbleshareDatabase database) { @Override public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) { - Scribbleshare.getLogger(ctx).info(request.method() + " " + request.uri()); try { handle(ctx, request); } catch (HttpException e) { From d8730bb4c85e5fe43796fb2d64bb1c1bb7f549ff Mon Sep 17 00:00:00 2001 From: stzups Date: Wed, 26 May 2021 14:16:05 -0400 Subject: [PATCH 089/144] fix npe --- .../room/server/websocket/ClientMessageHandler.java | 3 +-- .../server/websocket/state/states/InitialState.java | 11 +++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java index c8bb8ee5..df3f0bc9 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/ClientMessageHandler.java @@ -10,7 +10,6 @@ import net.stzups.scribbleshare.room.server.websocket.state.State; import net.stzups.scribbleshare.room.server.websocket.state.states.InitialState; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; -import net.stzups.scribbleshare.server.http.handlers.HttpAuthenticator; import java.util.logging.Level; @@ -24,7 +23,7 @@ public static Attribute getState(ChannelHandlerContext ctx) { @Override public void channelActive(ChannelHandlerContext ctx) { - State.setState(ctx, new InitialState(HttpAuthenticator.getUser(ctx))); + State.setState(ctx, new InitialState()); } @Override diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java index 79160293..95afd594 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java @@ -3,21 +3,20 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.data.objects.authentication.AuthenticatedUserSession; import net.stzups.scribbleshare.room.server.websocket.state.State; +import net.stzups.scribbleshare.server.http.handlers.HttpAuthenticator; public class InitialState extends State { - private final AuthenticatedUserSession session; - public InitialState(AuthenticatedUserSession session) { - this.session = session; + public InitialState() { + } @Override public void userEventTriggered(ChannelHandlerContext ctx, Object event) { if (event instanceof WebSocketServerProtocolHandler.HandshakeComplete) { Scribbleshare.getLogger(ctx).info("WebSocket connection initialized"); - setState(ctx, new HandshakeState(session)); + setState(ctx, new HandshakeState(HttpAuthenticator.getUser(ctx))); return; } @@ -28,6 +27,6 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object event) { @Override public String toString() { - return InitialState.class.getSimpleName() + "{session=" + session + "}"; + return InitialState.class.getSimpleName(); } } From 8e271fa00e2e9d5ea21beca03d8ded1c43b7e618 Mon Sep 17 00:00:00 2001 From: stzups Date: Wed, 26 May 2021 14:21:10 -0400 Subject: [PATCH 090/144] toString for authentication package --- .../objects/authentication/AuthenticatedUserSession.java | 5 +++++ .../data/objects/authentication/UserSession.java | 2 +- .../data/objects/authentication/http/HttpSessionCookie.java | 5 +++++ .../data/objects/authentication/http/HttpUserSession.java | 5 +++++ .../objects/authentication/http/HttpUserSessionCookie.java | 5 +++++ .../authentication/http/PersistentHttpUserSession.java | 5 +++++ .../authentication/http/PersistentHttpUserSessionCookie.java | 5 +++++ .../data/objects/authentication/login/Login.java | 5 +++++ 8 files changed, 36 insertions(+), 1 deletion(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticatedUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticatedUserSession.java index 6ef2ec5e..b60cd0c2 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticatedUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticatedUserSession.java @@ -12,4 +12,9 @@ public AuthenticatedUserSession(User user) { public User getUser() { return user; } + + @Override + public String toString() { + return AuthenticatedUserSession.class.getSimpleName() + "{user=" + user + "}"; + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/UserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/UserSession.java index 066488da..c48ba4f1 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/UserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/UserSession.java @@ -89,7 +89,7 @@ public void serialize(ByteBuf byteBuf) { @Override public String toString() { - return "Session{id=" + id + ",userId" + userId + ",created=" + created + ",expires=" + expired + "}"; + return UserSession.class.getSimpleName() + "{id=" + id + ",userId" + userId + ",created=" + created + ",expires=" + expired + "}"; } @Override diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java index 3e1a8938..55c05b94 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java @@ -95,4 +95,9 @@ protected static ByteBuf getCookie(HttpRequest request, String name) { return null; } + + @Override + public String toString() { + return HttpSessionCookie.class.getSimpleName() + "{id=" + id + "}"; + } } \ No newline at end of file diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java index b5cf1f03..ff6b853d 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java @@ -32,4 +32,9 @@ public AuthenticationResult validate(HttpSessionCookie cookie) { return validate(cookie.getToken()); } + + @Override + public String toString() { + return HttpUserSession.class.getSimpleName() + "{" + super.toString() + "}"; + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSessionCookie.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSessionCookie.java index a6e5e35c..fd73ef07 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSessionCookie.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSessionCookie.java @@ -35,4 +35,9 @@ public static HttpUserSessionCookie getHttpUserSessionCookie(HttpRequest request return null; } + + @Override + public String toString() { + return HttpUserSessionCookie.class.getSimpleName() + "{" + super.toString() + "}"; + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java index 88e5d6aa..66f918fc 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java @@ -29,4 +29,9 @@ public AuthenticationResult validate(HttpSessionCookie cookie) { return validate(cookie.getToken()); } + + @Override + public String toString() { + return PersistentHttpUserSession.class.getSimpleName() + "{" + super.toString() + "}"; + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java index 60095341..acc765a8 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java @@ -45,4 +45,9 @@ public static PersistentHttpUserSessionCookie getHttpUserSessionCookie(HttpReque return null; } + + @Override + public String toString() { + return PersistentHttpUserSessionCookie.class.getSimpleName() + "{" + super.toString() + "}"; + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java index b24f5bc0..dd1fe090 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java @@ -75,4 +75,9 @@ public static boolean verify(Login login, byte[] plaintext) { return verified; } + + @Override + public String toString() { + return Login.class.getSimpleName() + "{username=" + username + ",id=" + id + "}"; + } } From aaed473c1b10c3d8fefc993c5b765f620d25d91b Mon Sep 17 00:00:00 2001 From: stzups Date: Wed, 26 May 2021 14:47:43 -0400 Subject: [PATCH 091/144] add DebugString, start to refactor toString methods --- .../data/objects/InviteCode.java | 9 +++ .../scribbleshare/data/objects/Resource.java | 5 ++ .../scribbleshare/util/DebugString.java | 73 +++++++++++++++++++ .../room/server/websocket/MouseMove.java | 7 +- .../state/states/HandshakeState.java | 5 +- .../websocket/state/states/InitialState.java | 4 +- .../websocket/state/states/ReadyState.java | 5 +- .../websocket/state/states/RoomState.java | 6 +- 8 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/InviteCode.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/InviteCode.java index 5fccc7bf..b6f04f69 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/InviteCode.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/InviteCode.java @@ -1,5 +1,6 @@ package net.stzups.scribbleshare.data.objects; +import net.stzups.scribbleshare.util.DebugString; import net.stzups.scribbleshare.util.RandomString; public class InviteCode { @@ -24,4 +25,12 @@ public String getCode() { public long getDocument() { return document; } + + @Override + public String toString() { + return new DebugString(this) + .add("code", code) + .add("document", document) + .toString(); + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/Resource.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/Resource.java index 32cfccf9..6f3a39d0 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/Resource.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/Resource.java @@ -27,4 +27,9 @@ public Timestamp getLastModified() { public ByteBuf getData() { return data; } + + @Override + public String toString() { + return Resource.class.getSimpleName() + "{lastModified=" + lastModified + ",data=" + data + "}"; + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java new file mode 100644 index 00000000..a5d347ed --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java @@ -0,0 +1,73 @@ +package net.stzups.scribbleshare.util; + +import java.util.ArrayList; +import java.util.List; + +/** + * Used to format a String returned by a toString override. Use the following mock Car class as an example + *
+ *     public class Car {
+ *         private String make;
+ *         private int year;
+ *
+ *         ...
+ *
+ *         public String toString() {
+ *             return new DebugString(this)
+ *                 .add("make", make)
+ *                 .add("year", year)
+ *                 .toString();
+ *         }
+ *     }
+ * 
+ * + * Now the toString method will return Car{model=Toyota,year=1999} + */ +public class DebugString { + private static class Property { + private final String name; + private final Object value; + + private Property(String name, Object value) { + this.name = name; + this.value = value; + } + + @Override + public String toString() { + return name + "=" + value; + } + } + + private final Class clazz; + private List properties; // will be lazily allocated if needed + + public DebugString(Object object) { + this(object.getClass()); + } + + public DebugString(Class clazz) { + this.clazz = clazz; + } + + public DebugString add(String name, Object value) { + if (properties == null) { + properties = new ArrayList<>(); + } + properties.add(new Property(name, value)); + return this; + } + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder(clazz.getSimpleName()); + if (properties != null) { + stringBuilder.append("{"); + for (Property property : properties) { + stringBuilder.append(property); + } + stringBuilder.append("}"); + } + return stringBuilder.toString(); + } +} diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java index 0be0a580..7abfa3d2 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java @@ -1,6 +1,7 @@ package net.stzups.scribbleshare.room.server.websocket; import io.netty.buffer.ByteBuf; +import net.stzups.scribbleshare.util.DebugString; public class MouseMove { private final byte dt; @@ -21,6 +22,10 @@ public void serialize(ByteBuf byteBuf) { @Override public String toString() { - return MouseMove.class.getSimpleName() + "{dt=" + dt + ",x=" + x + ",y=" + y + "}"; + return new DebugString(this) + .add("dt", dt) + .add("x", x) + .add("y", y) + .toString(); } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java index 631686bb..1760a9b9 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java @@ -18,6 +18,7 @@ import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageUpdateDocument; import net.stzups.scribbleshare.room.server.websocket.state.State; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; +import net.stzups.scribbleshare.util.DebugString; import java.util.logging.Level; @@ -124,6 +125,8 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro @Override public String toString() { - return HandshakeState.class.getSimpleName() + "{session=" + session + "}"; + return new DebugString(this) + .add("session", session) + .toString(); } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java index 95afd594..73b826d9 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java @@ -5,6 +5,7 @@ import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.room.server.websocket.state.State; import net.stzups.scribbleshare.server.http.handlers.HttpAuthenticator; +import net.stzups.scribbleshare.util.DebugString; public class InitialState extends State { @@ -27,6 +28,7 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object event) { @Override public String toString() { - return InitialState.class.getSimpleName(); + return new DebugString(this) + .toString(); } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java index 54767ab5..616415fc 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java @@ -14,6 +14,7 @@ import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageUpdateDocument; import net.stzups.scribbleshare.room.server.websocket.state.State; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; +import net.stzups.scribbleshare.util.DebugString; public class ReadyState extends State { private final Client client; @@ -109,6 +110,8 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro @Override public String toString() { - return ReadyState.class.getSimpleName() + "{client=" + client + "}"; + return new DebugString(this) + .add("client", client) + .toString(); } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java index 6adbe6ce..02f886d1 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java @@ -17,6 +17,7 @@ import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageDeleteDocument; import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageUpdateDocument; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; +import net.stzups.scribbleshare.util.DebugString; public class RoomState extends ReadyState { private final Client client; @@ -102,6 +103,9 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro @Override public String toString() { - return RoomState.class.getSimpleName() + "{client=" + client + ",room=" + room + "}"; + return new DebugString(this) + .add("client", client) + .add("room", room) + .toString(); } } From ef082a6a83bdaee21922c5551ab0e9643f4c23d6 Mon Sep 17 00:00:00 2001 From: stzups Date: Wed, 26 May 2021 17:56:11 -0400 Subject: [PATCH 092/144] refactor with slick factory method --- .../scribbleshare/data/objects/InviteCode.java | 2 +- .../stzups/scribbleshare/util/DebugString.java | 15 ++++++++++++--- .../room/server/websocket/MouseMove.java | 2 +- .../scribbleshare/room/server/websocket/Room.java | 7 ++++++- .../websocket/state/states/HandshakeState.java | 2 +- .../websocket/state/states/InitialState.java | 2 +- .../server/websocket/state/states/ReadyState.java | 2 +- .../server/websocket/state/states/RoomState.java | 2 +- 8 files changed, 24 insertions(+), 10 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/InviteCode.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/InviteCode.java index b6f04f69..c22bd6d4 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/InviteCode.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/InviteCode.java @@ -28,7 +28,7 @@ public long getDocument() { @Override public String toString() { - return new DebugString(this) + return DebugString.get(this) .add("code", code) .add("document", document) .toString(); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java index a5d347ed..084cdcb4 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java @@ -13,7 +13,7 @@ * ... * * public String toString() { - * return new DebugString(this) + * return DebugString.get(this) * .add("make", make) * .add("year", year) * .toString(); @@ -42,11 +42,11 @@ public String toString() { private final Class clazz; private List properties; // will be lazily allocated if needed - public DebugString(Object object) { + private DebugString(Object object) { this(object.getClass()); } - public DebugString(Class clazz) { + private DebugString(Class clazz) { this.clazz = clazz; } @@ -70,4 +70,13 @@ public String toString() { } return stringBuilder.toString(); } + + // useless factory methods that are easier to type than new DebugLog + public static DebugString get(Object object) { + return new DebugString(object); + } + + public static DebugString get(Class clazz) { + return new DebugString(clazz); + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java index 7abfa3d2..cbecebea 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java @@ -22,7 +22,7 @@ public void serialize(ByteBuf byteBuf) { @Override public String toString() { - return new DebugString(this) + return DebugString.get(this) .add("dt", dt) .add("x", x) .add("y", y) diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java index f8f5da8e..c012925b 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java @@ -15,6 +15,7 @@ import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageOpenDocument; import net.stzups.scribbleshare.room.server.websocket.protocol.server.messages.ServerMessageRemoveClient; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; +import net.stzups.scribbleshare.util.DebugString; import java.util.HashMap; import java.util.HashSet; @@ -180,6 +181,10 @@ private void update() { @Override public String toString() { - return Room.class.getSimpleName() + "{" + document + "," + canvas + ",clients=[" + clients.size() + "]}"; + return DebugString.get(this) + .add("document", document) + .add("canvas", canvas) + .add("clients", clients) + .toString(); } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java index 1760a9b9..e0b056b8 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java @@ -125,7 +125,7 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro @Override public String toString() { - return new DebugString(this) + return DebugString.get(this) .add("session", session) .toString(); } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java index 73b826d9..0966b5f2 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java @@ -28,7 +28,7 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object event) { @Override public String toString() { - return new DebugString(this) + return DebugString.get(this) .toString(); } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java index 616415fc..60f5e2b7 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java @@ -110,7 +110,7 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro @Override public String toString() { - return new DebugString(this) + return DebugString.get(this) .add("client", client) .toString(); } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java index 02f886d1..58009c3a 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java @@ -103,7 +103,7 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro @Override public String toString() { - return new DebugString(this) + return DebugString.get(this) .add("client", client) .add("room", room) .toString(); From 107a3458505090702a3f495848570053d459041e Mon Sep 17 00:00:00 2001 From: stzups Date: Wed, 26 May 2021 18:14:04 -0400 Subject: [PATCH 093/144] change to queue, put symbols in variables --- .../scribbleshare/util/DebugString.java | 46 ++++++++++++------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java index 084cdcb4..99d4c5da 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java @@ -1,7 +1,10 @@ package net.stzups.scribbleshare.util; -import java.util.ArrayList; -import java.util.List; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayDeque; +import java.util.Iterator; +import java.util.Queue; /** * Used to format a String returned by a toString override. Use the following mock Car class as an example @@ -24,6 +27,11 @@ * Now the toString method will return Car{model=Toyota,year=1999} */ public class DebugString { + private static final String OPEN = "{"; + private static final String CLOSE = "}"; + private static final String SEPARATOR = ","; + private static final String EQUALS = "="; + private static class Property { private final String name; private final Object value; @@ -35,24 +43,28 @@ private Property(String name, Object value) { @Override public String toString() { - return name + "=" + value; + if (name == null) { + return value.toString(); + } else { + return name + EQUALS + value; + } } } private final Class clazz; - private List properties; // will be lazily allocated if needed + private Queue properties; // will be lazily allocated if needed private DebugString(Object object) { - this(object.getClass()); + this.clazz = object.getClass(); } - private DebugString(Class clazz) { - this.clazz = clazz; + public DebugString add(Object value) { + return add(null, value); } - public DebugString add(String name, Object value) { + public DebugString add(@Nullable String name, Object value) { if (properties == null) { - properties = new ArrayList<>(); + properties = new ArrayDeque<>(); } properties.add(new Property(name, value)); return this; @@ -62,11 +74,15 @@ public DebugString add(String name, Object value) { public String toString() { StringBuilder stringBuilder = new StringBuilder(clazz.getSimpleName()); if (properties != null) { - stringBuilder.append("{"); - for (Property property : properties) { - stringBuilder.append(property); + stringBuilder.append(OPEN); + Iterator iterator = properties.iterator(); + while (iterator.hasNext()) { + stringBuilder.append(iterator.next()); + if (iterator.hasNext()) { + stringBuilder.append(SEPARATOR); + } } - stringBuilder.append("}"); + stringBuilder.append(CLOSE); } return stringBuilder.toString(); } @@ -75,8 +91,4 @@ public String toString() { public static DebugString get(Object object) { return new DebugString(object); } - - public static DebugString get(Class clazz) { - return new DebugString(clazz); - } } From f46eccfb6c808982e54a58a757d60e2118e2b5a9 Mon Sep 17 00:00:00 2001 From: stzups Date: Wed, 26 May 2021 19:46:37 -0400 Subject: [PATCH 094/144] improve DebugString formatting --- .../data/objects/InviteCode.java | 2 +- .../http/HttpSessionCookie.java | 5 ++++- .../server/http/objects/Form.java | 9 +++++++++ .../server/http/objects/Query.java | 10 ++++++++++ .../server/http/objects/Route.java | 9 +++++++++ .../server/http/objects/Uri.java | 8 ++++++++ .../scribbleshare/util/DebugString.java | 20 +++++++++++++------ .../room/server/websocket/Client.java | 7 ++++++- .../room/server/websocket/MouseMove.java | 2 +- .../room/server/websocket/Room.java | 2 +- .../state/states/HandshakeState.java | 2 +- .../websocket/state/states/InitialState.java | 2 +- .../websocket/state/states/ReadyState.java | 2 +- .../websocket/state/states/RoomState.java | 2 +- 14 files changed, 67 insertions(+), 15 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/InviteCode.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/InviteCode.java index c22bd6d4..e0124fdd 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/InviteCode.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/InviteCode.java @@ -28,7 +28,7 @@ public long getDocument() { @Override public String toString() { - return DebugString.get(this) + return DebugString.get(InviteCode.class) .add("code", code) .add("document", document) .toString(); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java index 55c05b94..e95ba935 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpSessionCookie.java @@ -12,6 +12,7 @@ import io.netty.handler.codec.http.cookie.ServerCookieDecoder; import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; import net.stzups.scribbleshare.server.http.HttpUtils; +import net.stzups.scribbleshare.util.DebugString; import java.nio.charset.StandardCharsets; import java.util.Set; @@ -98,6 +99,8 @@ protected static ByteBuf getCookie(HttpRequest request, String name) { @Override public String toString() { - return HttpSessionCookie.class.getSimpleName() + "{id=" + id + "}"; + return DebugString.get(HttpSessionCookie.class) + .add("id", id) + .toString(); } } \ No newline at end of file diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Form.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Form.java index e12f985f..7eeec2ea 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Form.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Form.java @@ -4,6 +4,7 @@ import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpHeaderValues; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.util.DebugString; import java.nio.charset.StandardCharsets; import java.util.Map; @@ -44,4 +45,12 @@ public boolean getCheckbox(String field) throws BadRequestException { throw new BadRequestException("Malformed value for " + field); } } + + @Override + public String toString() { + return DebugString.get(Form.class) + .add("form", form) + .add(super.toString()) + .toString(); + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Query.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Query.java index 0bf79072..89ed844f 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Query.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Query.java @@ -1,6 +1,7 @@ package net.stzups.scribbleshare.server.http.objects; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.util.DebugString; import java.util.Collections; import java.util.HashMap; @@ -85,4 +86,13 @@ public static Map parseQuery(String query) throws BadRequestExce return queries; } + + @Override + public String toString() { + return DebugString.get(Query.class) + .add("path", path) + .add("rawQuery", rawQuery) + .add("queries", queries) + .toString(); + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Route.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Route.java index 3edd9c8e..34e8b12f 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Route.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Route.java @@ -1,6 +1,7 @@ package net.stzups.scribbleshare.server.http.objects; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.util.DebugString; public class Route extends Query { @@ -38,4 +39,12 @@ public int length() { public boolean length(int index) { return route.length >= index; } + + @Override + public String toString() { + return DebugString.get(Route.class) + .add("route", route) + .add(super.toString()) + .toString(); + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Uri.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Uri.java index 64d78457..3dd173cd 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Uri.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Uri.java @@ -1,6 +1,7 @@ package net.stzups.scribbleshare.server.http.objects; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.util.DebugString; import java.util.regex.Pattern; @@ -25,4 +26,11 @@ public String uri() { public boolean equals(String string) { return uri.equals(string); } + + @Override + public String toString() { + return DebugString.get(Uri.class) + .add("uri", uri) + .toString(); + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java index 99d4c5da..c857860e 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java @@ -3,6 +3,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayDeque; +import java.util.Arrays; import java.util.Iterator; import java.util.Queue; @@ -29,7 +30,7 @@ public class DebugString { private static final String OPEN = "{"; private static final String CLOSE = "}"; - private static final String SEPARATOR = ","; + private static final String SEPARATOR = ", "; private static final String EQUALS = "="; private static class Property { @@ -43,8 +44,15 @@ private Property(String name, Object value) { @Override public String toString() { + String value; + if (this.value.getClass().isArray()) { + value = Arrays.toString((Object[]) this.value); + } else { + value = this.value.toString(); + } + if (name == null) { - return value.toString(); + return value; } else { return name + EQUALS + value; } @@ -54,8 +62,8 @@ public String toString() { private final Class clazz; private Queue properties; // will be lazily allocated if needed - private DebugString(Object object) { - this.clazz = object.getClass(); + private DebugString(Class clazz) { + this.clazz = clazz; } public DebugString add(Object value) { @@ -88,7 +96,7 @@ public String toString() { } // useless factory methods that are easier to type than new DebugLog - public static DebugString get(Object object) { - return new DebugString(object); + public static DebugString get(Class clazz) { + return new DebugString(clazz); } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Client.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Client.java index abde5350..4161cc88 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Client.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Client.java @@ -4,6 +4,7 @@ import io.netty.channel.Channel; import net.stzups.scribbleshare.data.objects.User; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessage; +import net.stzups.scribbleshare.util.DebugString; import java.util.ArrayList; import java.util.Collections; @@ -72,7 +73,11 @@ public void serialize(ByteBuf byteBuf) { @Override public String toString() { - return Client.class.getSimpleName() + "{user=" + user + ",address=" + channel.remoteAddress() + ",id=" + id + "}"; + return DebugString.get(Client.class) + .add("user", user) + .add("address", channel.remoteAddress()) + .add("id", id) + .toString(); } @Override diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java index cbecebea..418b4cb0 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java @@ -22,7 +22,7 @@ public void serialize(ByteBuf byteBuf) { @Override public String toString() { - return DebugString.get(this) + return DebugString.get(MouseMove.class) .add("dt", dt) .add("x", x) .add("y", y) diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java index c012925b..0833f423 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/Room.java @@ -181,7 +181,7 @@ private void update() { @Override public String toString() { - return DebugString.get(this) + return DebugString.get(Room.class) .add("document", document) .add("canvas", canvas) .add("clients", clients) diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java index e0b056b8..7bdfe05a 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/HandshakeState.java @@ -125,7 +125,7 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro @Override public String toString() { - return DebugString.get(this) + return DebugString.get(HandshakeState.class) .add("session", session) .toString(); } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java index 0966b5f2..423f5cd6 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java @@ -28,7 +28,7 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object event) { @Override public String toString() { - return DebugString.get(this) + return DebugString.get(InitialState.class) .toString(); } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java index 60f5e2b7..6d29f4e3 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java @@ -110,7 +110,7 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro @Override public String toString() { - return DebugString.get(this) + return DebugString.get(ReadyState.class) .add("client", client) .toString(); } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java index 58009c3a..c3c3d1fc 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/RoomState.java @@ -103,7 +103,7 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro @Override public String toString() { - return DebugString.get(this) + return DebugString.get(RoomState.class) .add("client", client) .add("room", room) .toString(); From 9f3ce1c039e48a217f4d9ff5d8b44dfcf1a8a1ed Mon Sep 17 00:00:00 2001 From: stzups Date: Thu, 27 May 2021 08:32:25 -0400 Subject: [PATCH 095/144] toString for pretty much all of scribbleshare-commoons --- .../server/http/HttpServerHandler.java | 4 +-- .../scribbleshare/data/objects/Document.java | 7 ++++- .../scribbleshare/data/objects/Resource.java | 5 ++- .../scribbleshare/data/objects/User.java | 8 ++++- .../AuthenticatedUserSession.java | 5 ++- .../objects/authentication/UserSession.java | 8 ++++- .../authentication/http/HttpUserSession.java | 5 ++- .../http/HttpUserSessionCookie.java | 5 ++- .../http/PersistentHttpUserSession.java | 5 ++- .../http/PersistentHttpUserSessionCookie.java | 5 ++- .../objects/authentication/login/Login.java | 6 +++- .../data/objects/canvas/Canvas.java | 5 ++- .../data/objects/canvas/Color.java | 31 +++++++++++++++++++ .../canvas/canvasObject/CanvasObject.java | 9 ++++++ .../canvasObject/EntityCanvasObject.java | 10 ++++++ .../canvasObjects/CanvasImage.java | 9 ++++++ .../canvasObjects/CanvasMouse.java | 8 +++++ .../canvasObject/canvasObjects/Line.java | 30 ++++++++++++------ .../canvasObject/canvasObjects/Shape.java | 22 +++++++------ .../canvas/canvasUpdate/CanvasUpdate.java | 8 +++++ .../canvas/canvasUpdate/CanvasUpdates.java | 9 ++++++ .../canvasUpdates/CanvasUpdateDelete.java | 9 +++++- .../canvasUpdates/CanvasUpdateInsert.java | 8 +++++ .../canvasUpdates/CanvasUpdateMove.java | 8 +++++ .../scribbleshare/util/DebugString.java | 17 ++++++++-- .../websocket/state/states/ReadyState.java | 2 +- 26 files changed, 212 insertions(+), 36 deletions(-) create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/Color.java diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 40035f0d..2a746c93 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -242,7 +242,7 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H } //login - + System.out.println(route); if (request.method().equals(HttpMethod.POST)) { //todo validate for extra fields that should not happen switch (route.path()) { @@ -372,7 +372,7 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H try { loginAdded = database.addLogin(login); } catch (DatabaseException e) { - throw new InternalServerException("Exception while adding login for user " + login.getId() + " with username " + login.getUsername(), e); + throw new InternalServerException(e); } if (!loginAdded) { Scribbleshare.getLogger(ctx).info("Tried to register with duplicate username " + username); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/Document.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/Document.java index 4ec13a10..4bc28a6d 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/Document.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/Document.java @@ -1,5 +1,7 @@ package net.stzups.scribbleshare.data.objects; +import net.stzups.scribbleshare.util.DebugString; + import java.util.Random; public class Document { @@ -46,7 +48,10 @@ public void setName(String name) { @Override public String toString() { - return "Document{id=" + id + ",name=" + name + "}"; + return DebugString.get(Document.class) + .add("id", id) + .add("name", name) + .toString(); } @Override diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/Resource.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/Resource.java index 6f3a39d0..b2774bd2 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/Resource.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/Resource.java @@ -1,6 +1,7 @@ package net.stzups.scribbleshare.data.objects; import io.netty.buffer.ByteBuf; +import net.stzups.scribbleshare.util.DebugString; import java.sql.Timestamp; import java.time.Instant; @@ -30,6 +31,8 @@ public ByteBuf getData() { @Override public String toString() { - return Resource.class.getSimpleName() + "{lastModified=" + lastModified + ",data=" + data + "}"; + return DebugString.get(Resource.class) + .add("lastModifed", lastModified) + .toString(); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/User.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/User.java index d3d44032..bb658ef4 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/User.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/User.java @@ -1,5 +1,7 @@ package net.stzups.scribbleshare.data.objects; +import net.stzups.scribbleshare.util.DebugString; + import java.util.Arrays; import java.util.HashSet; import java.util.Random; @@ -48,7 +50,11 @@ public String getUsername() { @Override public String toString() { - return "User{id=" + id + ",ownedDocuments=" + ownedDocuments + ",sharedDocuments=" + sharedDocuments + "}"; + return DebugString.get(User.class) + .add("id", id) + .add("ownedDocuments", ownedDocuments) + .add("sharedDocuments", sharedDocuments) + .toString(); } @Override diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticatedUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticatedUserSession.java index b60cd0c2..22cbacd4 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticatedUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/AuthenticatedUserSession.java @@ -1,6 +1,7 @@ package net.stzups.scribbleshare.data.objects.authentication; import net.stzups.scribbleshare.data.objects.User; +import net.stzups.scribbleshare.util.DebugString; public class AuthenticatedUserSession { private final User user; @@ -15,6 +16,8 @@ public User getUser() { @Override public String toString() { - return AuthenticatedUserSession.class.getSimpleName() + "{user=" + user + "}"; + return DebugString.get(AuthenticatedUserSession.class) + .add("user", user) + .toString(); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/UserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/UserSession.java index c48ba4f1..c47fa149 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/UserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/UserSession.java @@ -2,6 +2,7 @@ import io.netty.buffer.ByteBuf; import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; +import net.stzups.scribbleshare.util.DebugString; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -89,7 +90,12 @@ public void serialize(ByteBuf byteBuf) { @Override public String toString() { - return UserSession.class.getSimpleName() + "{id=" + id + ",userId" + userId + ",created=" + created + ",expires=" + expired + "}"; + return DebugString.get(UserSession.class) + .add("id", id) + .add("userId", userId) + .add("created", created) + .add("expires", expired) + .toString(); } @Override diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java index ff6b853d..5b4876c9 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java @@ -5,6 +5,7 @@ import net.stzups.scribbleshare.data.objects.User; import net.stzups.scribbleshare.data.objects.authentication.AuthenticationResult; import net.stzups.scribbleshare.data.objects.authentication.UserSession; +import net.stzups.scribbleshare.util.DebugString; import java.sql.Timestamp; import java.time.Duration; @@ -35,6 +36,8 @@ public AuthenticationResult validate(HttpSessionCookie cookie) { @Override public String toString() { - return HttpUserSession.class.getSimpleName() + "{" + super.toString() + "}"; + return DebugString.get(HttpUserSession.class) + .add(super.toString()) + .toString(); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSessionCookie.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSessionCookie.java index fd73ef07..d8e6799c 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSessionCookie.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSessionCookie.java @@ -5,6 +5,7 @@ import io.netty.handler.codec.http.HttpRequest; import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.util.DebugString; public class HttpUserSessionCookie extends HttpSessionCookie { private static final String COOKIE_NAME = "session"; @@ -38,6 +39,8 @@ public static HttpUserSessionCookie getHttpUserSessionCookie(HttpRequest request @Override public String toString() { - return HttpUserSessionCookie.class.getSimpleName() + "{" + super.toString() + "}"; + return DebugString.get(HttpUserSessionCookie.class) + .add(super.toString()) + .toString(); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java index 66f918fc..349f53c9 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java @@ -4,6 +4,7 @@ import io.netty.handler.codec.http.HttpHeaders; import net.stzups.scribbleshare.data.objects.authentication.AuthenticationResult; import net.stzups.scribbleshare.data.objects.authentication.UserSession; +import net.stzups.scribbleshare.util.DebugString; import java.sql.Timestamp; import java.time.Duration; @@ -32,6 +33,8 @@ public AuthenticationResult validate(HttpSessionCookie cookie) { @Override public String toString() { - return PersistentHttpUserSession.class.getSimpleName() + "{" + super.toString() + "}"; + return DebugString.get(PersistentHttpUserSession.class) + .add(super.toString()) + .toString(); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java index acc765a8..3902b7a1 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java @@ -6,6 +6,7 @@ import io.netty.handler.codec.http.cookie.DefaultCookie; import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.util.DebugString; import java.time.Duration; import java.time.temporal.ChronoUnit; @@ -48,6 +49,8 @@ public static PersistentHttpUserSessionCookie getHttpUserSessionCookie(HttpReque @Override public String toString() { - return PersistentHttpUserSessionCookie.class.getSimpleName() + "{" + super.toString() + "}"; + return DebugString.get(PersistentHttpUserSessionCookie.class) + .add(super.toString()) + .toString(); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java index dd1fe090..85a19bb1 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/login/Login.java @@ -2,6 +2,7 @@ import at.favre.lib.crypto.bcrypt.BCrypt; import net.stzups.scribbleshare.data.objects.User; +import net.stzups.scribbleshare.util.DebugString; import java.util.Arrays; @@ -78,6 +79,9 @@ public static boolean verify(Login login, byte[] plaintext) { @Override public String toString() { - return Login.class.getSimpleName() + "{username=" + username + ",id=" + id + "}"; + return DebugString.get(Login.class) + .add("username", username) + .add("id", id) + .toString(); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/Canvas.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/Canvas.java index 8c59a9f3..6917a068 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/Canvas.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/Canvas.java @@ -8,6 +8,7 @@ import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.CanvasUpdates; import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; import net.stzups.scribbleshare.data.objects.exceptions.DeserializationLengthException; +import net.stzups.scribbleshare.util.DebugString; import java.util.HashMap; import java.util.Map; @@ -95,6 +96,8 @@ public boolean equals(Object object) { @Override public String toString() { - return "Canvas{canvasObjects=" + canvasObjects.size() + "}"; + return DebugString.get(Canvas.class) + .add("canvasObjects", canvasObjects) + .toString(); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/Color.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/Color.java new file mode 100644 index 00000000..a8ffcd97 --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/Color.java @@ -0,0 +1,31 @@ +package net.stzups.scribbleshare.data.objects.canvas; + +import io.netty.buffer.ByteBuf; +import net.stzups.scribbleshare.util.DebugString; + +public class Color { + private final byte red; + private final byte green; + private final byte blue; + + public Color(ByteBuf byteBuf) { + red = byteBuf.readByte(); + green = byteBuf.readByte(); + blue = byteBuf.readByte(); + } + + public void serialize(ByteBuf byteBuf) { + byteBuf.writeByte(red); + byteBuf.writeByte(green); + byteBuf.writeByte(blue); + } + + @Override + public String toString() { + return DebugString.get(Color.class) + .add("red", red & 0xff) + .add("green", green & 0xff) + .add("blue", blue & 0xff) + .toString(); + } +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/CanvasObject.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/CanvasObject.java index e7d1c997..95470fe0 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/CanvasObject.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/CanvasObject.java @@ -6,6 +6,7 @@ import net.stzups.scribbleshare.data.objects.canvas.canvasObject.canvasObjects.Line; import net.stzups.scribbleshare.data.objects.canvas.canvasObject.canvasObjects.Shape; import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; +import net.stzups.scribbleshare.util.DebugString; public class CanvasObject {//todo make abstract? private short x; @@ -30,6 +31,14 @@ public void serialize(ByteBuf byteBuf) { byteBuf.writeShort(y); } + @Override + public String toString() { + return DebugString.get(CanvasMouse.class) + .add("x", x) + .add("y", y) + .toString(); + } + public static CanvasObject deserialize(CanvasObjectType type, ByteBuf byteBuf) throws DeserializationException { CanvasObject canvasObject; switch (type) { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/EntityCanvasObject.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/EntityCanvasObject.java index 730855d7..774f865c 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/EntityCanvasObject.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/EntityCanvasObject.java @@ -1,6 +1,7 @@ package net.stzups.scribbleshare.data.objects.canvas.canvasObject; import io.netty.buffer.ByteBuf; +import net.stzups.scribbleshare.util.DebugString; public class EntityCanvasObject extends CanvasObject { private final short width; @@ -21,4 +22,13 @@ public void serialize(ByteBuf byteBuf) { byteBuf.writeShort(height); byteBuf.writeByte(rotation); } + + @Override + public String toString() { + return DebugString.get(EntityCanvasObject.class, super.toString()) + .add("width", width) + .add("height", height) + .add("rotation", rotation) + .toString(); + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/CanvasImage.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/CanvasImage.java index 56193310..b6c76d83 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/CanvasImage.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/CanvasImage.java @@ -3,6 +3,7 @@ import io.netty.buffer.ByteBuf; import net.stzups.scribbleshare.data.objects.canvas.canvasObject.CanvasObjectType; import net.stzups.scribbleshare.data.objects.canvas.canvasObject.EntityCanvasObject; +import net.stzups.scribbleshare.util.DebugString; public class CanvasImage extends EntityCanvasObject { private final long id; @@ -22,4 +23,12 @@ public void serialize(ByteBuf byteBuf) { super.serialize(byteBuf); byteBuf.writeLong(id); } + + @Override + public String toString() { + return DebugString.get(CanvasImage.class, super.toString()) + .add("id", id) + .add(super.toString()) + .toString(); + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/CanvasMouse.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/CanvasMouse.java index 5e6a44ce..941e5d53 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/CanvasMouse.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/CanvasMouse.java @@ -3,6 +3,7 @@ import io.netty.buffer.ByteBuf; import net.stzups.scribbleshare.data.objects.canvas.canvasObject.CanvasObject; import net.stzups.scribbleshare.data.objects.canvas.canvasObject.CanvasObjectType; +import net.stzups.scribbleshare.util.DebugString; public class CanvasMouse extends CanvasObject { public CanvasMouse(ByteBuf byteBuf) { @@ -18,4 +19,11 @@ public CanvasObjectType getCanvasObjectType() { public void serialize(ByteBuf byteBuf) { super.serialize(byteBuf); } + + @Override + public String toString() { + return DebugString.get(CanvasMouse.class, super.toString()) + .add(super.toString()) + .toString(); + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/Line.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/Line.java index ab60f854..d4744967 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/Line.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/Line.java @@ -1,8 +1,10 @@ package net.stzups.scribbleshare.data.objects.canvas.canvasObject.canvasObjects; import io.netty.buffer.ByteBuf; +import net.stzups.scribbleshare.data.objects.canvas.Color; import net.stzups.scribbleshare.data.objects.canvas.canvasObject.CanvasObject; import net.stzups.scribbleshare.data.objects.canvas.canvasObject.CanvasObjectType; +import net.stzups.scribbleshare.util.DebugString; import java.util.ArrayList; import java.util.List; @@ -21,18 +23,22 @@ private void serialize(ByteBuf byteBuf) { byteBuf.writeShort(x); byteBuf.writeShort(y); } + + @Override + public String toString() { + return DebugString.get(Point.class) + .add("x", x) + .add("y", y) + .toString(); + } } private final List points = new ArrayList<>(); - private final byte red; - private final byte green; - private final byte blue; + private final Color color; public Line(ByteBuf byteBuf) { super(byteBuf); - this.red = byteBuf.readByte(); - this.green = byteBuf.readByte(); - this.blue = byteBuf.readByte(); + color = new Color(byteBuf); int length = byteBuf.readUnsignedByte(); for (int i = 0; i < length; i++) { points.add(new Point(byteBuf)); @@ -47,12 +53,18 @@ public CanvasObjectType getCanvasObjectType() { @Override public void serialize(ByteBuf byteBuf) { super.serialize(byteBuf); - byteBuf.writeByte(red); - byteBuf.writeByte(green); - byteBuf.writeByte(blue); + color.serialize(byteBuf); byteBuf.writeByte((byte) points.size()); for (Point point : points) { point.serialize(byteBuf); } } + + @Override + public String toString() { + return DebugString.get(Line.class, super.toString()) + .add("points", points) + .add("color", color) + .toString(); + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/Shape.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/Shape.java index 293f1b3b..4a2479a4 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/Shape.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/Shape.java @@ -2,10 +2,12 @@ import io.netty.buffer.ByteBuf; import io.netty.util.collection.IntObjectHashMap; +import net.stzups.scribbleshare.data.objects.canvas.Color; import net.stzups.scribbleshare.data.objects.canvas.canvasObject.CanvasObjectType; import net.stzups.scribbleshare.data.objects.canvas.canvasObject.EntityCanvasObject; import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; import net.stzups.scribbleshare.data.objects.exceptions.DeserializationTypeException; +import net.stzups.scribbleshare.util.DebugString; import java.util.EnumSet; import java.util.Map; @@ -41,16 +43,12 @@ public static Type deserialize(ByteBuf byteBuf) throws DeserializationException } private final Type type; - private final byte red; - private final byte green; - private final byte blue; + private final Color color; public Shape(ByteBuf byteBuf) throws DeserializationException { super(byteBuf); this.type = Type.deserialize(byteBuf); - this.red = byteBuf.readByte(); - this.green = byteBuf.readByte(); - this.blue = byteBuf.readByte(); + color = new Color(byteBuf); } @Override @@ -61,8 +59,14 @@ public CanvasObjectType getCanvasObjectType() { public void serialize(ByteBuf byteBuf) { super.serialize(byteBuf); byteBuf.writeByte((byte) type.id); - byteBuf.writeByte(red); - byteBuf.writeByte(green); - byteBuf.writeByte(blue); + color.serialize(byteBuf); + } + + @Override + public String toString() { + return DebugString.get(Shape.class, super.toString()) + .add("type", type) + .add("color", color) + .toString(); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/CanvasUpdate.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/CanvasUpdate.java index 33da4f54..9d9caef7 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/CanvasUpdate.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/CanvasUpdate.java @@ -7,6 +7,7 @@ import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.canvasUpdates.CanvasUpdateMove; import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; import net.stzups.scribbleshare.data.objects.exceptions.DeserializationTypeException; +import net.stzups.scribbleshare.util.DebugString; public abstract class CanvasUpdate { private final byte dt; @@ -23,6 +24,13 @@ public void serialize(ByteBuf byteBuf) { byteBuf.writeByte(dt); } + @Override + public String toString() { + return DebugString.get(CanvasUpdate.class) + .add("dt", dt) + .toString(); + } + static CanvasUpdate deserialize(CanvasUpdateType type, ByteBuf byteBuf) throws DeserializationException { CanvasUpdate canvasUpdate; switch (type) { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/CanvasUpdates.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/CanvasUpdates.java index bd3a1ffb..0b69c020 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/CanvasUpdates.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/CanvasUpdates.java @@ -4,6 +4,7 @@ import net.stzups.scribbleshare.data.objects.canvas.Canvas; import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; import net.stzups.scribbleshare.data.objects.exceptions.DeserializationLengthException; +import net.stzups.scribbleshare.util.DebugString; public class CanvasUpdates { private final short id; @@ -40,4 +41,12 @@ public void serialize(ByteBuf byteBuf) { canvasUpdates.serialize(byteBuf); } } + + @Override + public String toString() { + return DebugString.get(CanvasUpdate.class) + .add("id", id) + .add("canvasUpdates", canvasUpdates) + .toString(); + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/canvasUpdates/CanvasUpdateDelete.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/canvasUpdates/CanvasUpdateDelete.java index 89794c87..c06c1723 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/canvasUpdates/CanvasUpdateDelete.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/canvasUpdates/CanvasUpdateDelete.java @@ -1,10 +1,11 @@ package net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.canvasUpdates; import io.netty.buffer.ByteBuf; -import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.CanvasUpdateException; import net.stzups.scribbleshare.data.objects.canvas.Canvas; import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.CanvasUpdate; +import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.CanvasUpdateException; import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.CanvasUpdateType; +import net.stzups.scribbleshare.util.DebugString; public class CanvasUpdateDelete extends CanvasUpdate { public CanvasUpdateDelete(ByteBuf byteBuf) { @@ -23,6 +24,12 @@ public void update(Canvas canvas, short id) throws CanvasUpdateException { } } + @Override + public String toString() { + return DebugString.get(CanvasUpdateDelete.class, super.toString()) + .toString(); + } + @Override public void serialize(ByteBuf byteBuf) { super.serialize(byteBuf); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/canvasUpdates/CanvasUpdateInsert.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/canvasUpdates/CanvasUpdateInsert.java index 1e3e00e4..5b10abcf 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/canvasUpdates/CanvasUpdateInsert.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/canvasUpdates/CanvasUpdateInsert.java @@ -8,6 +8,7 @@ import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.CanvasUpdateException; import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.CanvasUpdateType; import net.stzups.scribbleshare.data.objects.exceptions.DeserializationException; +import net.stzups.scribbleshare.util.DebugString; public class CanvasUpdateInsert extends CanvasUpdate { private final CanvasObject canvasObject; @@ -35,4 +36,11 @@ public void serialize(ByteBuf byteBuf) { canvasObject.getCanvasObjectType().serialize(byteBuf); canvasObject.serialize(byteBuf); } + + @Override + public String toString() { + return DebugString.get(CanvasUpdateInsert.class, super.toString()) + .add("canvasObject", canvasObject) + .toString(); + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/canvasUpdates/CanvasUpdateMove.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/canvasUpdates/CanvasUpdateMove.java index 3eaeb001..fe6291d5 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/canvasUpdates/CanvasUpdateMove.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasUpdate/canvasUpdates/CanvasUpdateMove.java @@ -6,6 +6,7 @@ import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.CanvasUpdate; import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.CanvasUpdateException; import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.CanvasUpdateType; +import net.stzups.scribbleshare.util.DebugString; public class CanvasUpdateMove extends CanvasUpdate { private final CanvasObject canvasObject; @@ -34,4 +35,11 @@ public void serialize(ByteBuf byteBuf) { super.serialize(byteBuf); canvasObject.serialize(byteBuf); } + + @Override + public String toString() { + return DebugString.get(CanvasUpdateMove.class, super.toString()) + .add("canvasObject", canvasObject) + .toString(); + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java index c857860e..b1fef663 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java @@ -1,7 +1,5 @@ package net.stzups.scribbleshare.util; -import org.jetbrains.annotations.Nullable; - import java.util.ArrayDeque; import java.util.Arrays; import java.util.Iterator; @@ -60,17 +58,23 @@ public String toString() { } private final Class clazz; + private final String string; private Queue properties; // will be lazily allocated if needed private DebugString(Class clazz) { + this(clazz, null); + } + + private DebugString(Class clazz, String string) { this.clazz = clazz; + this.string = string; } public DebugString add(Object value) { return add(null, value); } - public DebugString add(@Nullable String name, Object value) { + public DebugString add(String name, Object value) { if (properties == null) { properties = new ArrayDeque<>(); } @@ -90,6 +94,9 @@ public String toString() { stringBuilder.append(SEPARATOR); } } + if (string != null) { + stringBuilder.append(string); + } stringBuilder.append(CLOSE); } return stringBuilder.toString(); @@ -99,4 +106,8 @@ public String toString() { public static DebugString get(Class clazz) { return new DebugString(clazz); } + + public static DebugString get(Class clazz, String string) { + return new DebugString(clazz, string); + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java index 6d29f4e3..56446c52 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/ReadyState.java @@ -56,7 +56,7 @@ public void message(ChannelHandlerContext ctx, ClientMessage clientMessage) thro try { document = RoomHttpServerInitializer.getDatabase(ctx).createDocument(client.getUser()); } catch (DatabaseException e) { - throw new InternalServerException("Exception while creating document for client " + client + " that request it", e); + throw new InternalServerException(e); } client.sendMessage(new ServerMessageUpdateDocument(document)); //open From 644eeba5374792329b5b274c1512842f262739da Mon Sep 17 00:00:00 2001 From: stzups Date: Thu, 27 May 2021 08:33:11 -0400 Subject: [PATCH 096/144] remove unused classw --- .../room/server/websocket/MouseMove.java | 31 ------------------- 1 file changed, 31 deletions(-) delete mode 100644 scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java deleted file mode 100644 index 418b4cb0..00000000 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/MouseMove.java +++ /dev/null @@ -1,31 +0,0 @@ -package net.stzups.scribbleshare.room.server.websocket; - -import io.netty.buffer.ByteBuf; -import net.stzups.scribbleshare.util.DebugString; - -public class MouseMove { - private final byte dt; - private final short x; - private final short y; - - public MouseMove(ByteBuf byteBuf) { - this.dt = byteBuf.readByte(); - this.x = byteBuf.readShort(); - this.y = byteBuf.readShort(); - } - - public void serialize(ByteBuf byteBuf) { - byteBuf.writeByte(dt); - byteBuf.writeShort(x); - byteBuf.writeShort(y); - } - - @Override - public String toString() { - return DebugString.get(MouseMove.class) - .add("dt", dt) - .add("x", x) - .add("y", y) - .toString(); - } -} From f0029ffc7a9dd8cda475238d4ab46bc48086f360 Mon Sep 17 00:00:00 2001 From: stzups Date: Thu, 27 May 2021 08:39:43 -0400 Subject: [PATCH 097/144] add toString to protocol --- .../client/messages/ClientMessageCanvasUpdate.java | 8 ++++++++ .../client/messages/ClientMessageCreateDocument.java | 7 +++++++ .../client/messages/ClientMessageDeleteDocument.java | 8 ++++++++ .../protocol/client/messages/ClientMessageGetInvite.java | 7 +++++++ .../protocol/client/messages/ClientMessageHandshake.java | 8 ++++++++ .../client/messages/ClientMessageOpenDocument.java | 8 ++++++++ .../client/messages/ClientMessageUpdateDocument.java | 9 +++++++++ .../protocol/server/messages/ServerMessageAddClient.java | 8 ++++++++ .../protocol/server/messages/ServerMessageAddUser.java | 8 ++++++++ .../server/messages/ServerMessageCanvasUpdate.java | 8 ++++++++ .../server/messages/ServerMessageDeleteDocument.java | 8 ++++++++ .../protocol/server/messages/ServerMessageGetInvite.java | 8 ++++++++ .../protocol/server/messages/ServerMessageHandshake.java | 8 ++++++++ .../server/messages/ServerMessageOpenDocument.java | 9 +++++++++ .../server/messages/ServerMessageRemoveClient.java | 8 ++++++++ .../server/messages/ServerMessageUpdateDocument.java | 9 +++++++++ 16 files changed, 129 insertions(+) diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageCanvasUpdate.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageCanvasUpdate.java index 4cb67da4..8535c75f 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageCanvasUpdate.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageCanvasUpdate.java @@ -6,6 +6,7 @@ import net.stzups.scribbleshare.data.objects.exceptions.DeserializationLengthException; import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessage; import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessageType; +import net.stzups.scribbleshare.util.DebugString; public class ClientMessageCanvasUpdate extends ClientMessage { private final CanvasUpdates[] canvasUpdatesArray; @@ -26,4 +27,11 @@ public ClientMessageType getMessageType() { public CanvasUpdates[] getCanvasUpdatesArray() { return canvasUpdatesArray; } + + @Override + public String toString() { + return DebugString.get(ClientMessageCanvasUpdate.class) + .add("canvasUpdatesArray", canvasUpdatesArray) + .toString(); + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageCreateDocument.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageCreateDocument.java index 6ccc2f7f..9b57e0b7 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageCreateDocument.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageCreateDocument.java @@ -3,6 +3,7 @@ import io.netty.buffer.ByteBuf; import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessage; import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessageType; +import net.stzups.scribbleshare.util.DebugString; public class ClientMessageCreateDocument extends ClientMessage { public ClientMessageCreateDocument(ByteBuf byteBuf) { @@ -13,4 +14,10 @@ public ClientMessageCreateDocument(ByteBuf byteBuf) { public ClientMessageType getMessageType() { return ClientMessageType.CREATE_DOCUMENT; } + + @Override + public String toString() { + return DebugString.get(ClientMessageCreateDocument.class) + .toString(); + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageDeleteDocument.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageDeleteDocument.java index 977f21ab..03db0a6e 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageDeleteDocument.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageDeleteDocument.java @@ -3,6 +3,7 @@ import io.netty.buffer.ByteBuf; import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessage; import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessageType; +import net.stzups.scribbleshare.util.DebugString; public class ClientMessageDeleteDocument extends ClientMessage { private final long id; @@ -19,4 +20,11 @@ public ClientMessageType getMessageType() { public long getId() { return id; } + + @Override + public String toString() { + return DebugString.get(ClientMessageDeleteDocument.class) + .add("id", id) + .toString(); + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageGetInvite.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageGetInvite.java index 9d232cf8..a38e1284 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageGetInvite.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageGetInvite.java @@ -3,6 +3,7 @@ import io.netty.buffer.ByteBuf; import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessage; import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessageType; +import net.stzups.scribbleshare.util.DebugString; public class ClientMessageGetInvite extends ClientMessage { public ClientMessageGetInvite(ByteBuf byteBuf) { @@ -13,4 +14,10 @@ public ClientMessageGetInvite(ByteBuf byteBuf) { public ClientMessageType getMessageType() { return ClientMessageType.GET_INVITE; } + + @Override + public String toString() { + return DebugString.get(ClientMessageGetInvite.class) + .toString(); + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageHandshake.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageHandshake.java index 3da331b6..ecc618c7 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageHandshake.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageHandshake.java @@ -3,6 +3,7 @@ import io.netty.buffer.ByteBuf; import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessage; import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessageType; +import net.stzups.scribbleshare.util.DebugString; public class ClientMessageHandshake extends ClientMessage { private final String code; @@ -19,4 +20,11 @@ public ClientMessageType getMessageType() { public String getCode() { return code; } + + @Override + public String toString() { + return DebugString.get(ClientMessageHandshake.class) + .add("code", code) + .toString(); + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageOpenDocument.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageOpenDocument.java index 7cc48c75..877fc48c 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageOpenDocument.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageOpenDocument.java @@ -3,6 +3,7 @@ import io.netty.buffer.ByteBuf; import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessage; import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessageType; +import net.stzups.scribbleshare.util.DebugString; public class ClientMessageOpenDocument extends ClientMessage { private final long id; @@ -19,4 +20,11 @@ public ClientMessageType getMessageType() { public long getId() { return id; } + + @Override + public String toString() { + return DebugString.get(ClientMessageOpenDocument.class) + .add("id", id) + .toString(); + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageUpdateDocument.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageUpdateDocument.java index b20ad695..c8fccdd3 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageUpdateDocument.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/client/messages/ClientMessageUpdateDocument.java @@ -3,6 +3,7 @@ import io.netty.buffer.ByteBuf; import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessage; import net.stzups.scribbleshare.room.server.websocket.protocol.client.ClientMessageType; +import net.stzups.scribbleshare.util.DebugString; public class ClientMessageUpdateDocument extends ClientMessage { private final long id; @@ -25,4 +26,12 @@ public long getId() { public String getName() { return name; } + + @Override + public String toString() { + return DebugString.get(ClientMessageUpdateDocument.class) + .add("id", id) + .add("name", name) + .toString(); + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageAddClient.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageAddClient.java index 5035803f..d5f34690 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageAddClient.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageAddClient.java @@ -4,6 +4,7 @@ import net.stzups.scribbleshare.room.server.websocket.Client; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessage; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessageType; +import net.stzups.scribbleshare.util.DebugString; import java.util.Collections; import java.util.Set; @@ -32,4 +33,11 @@ public void serialize(ByteBuf byteBuf) { client.serialize(byteBuf); } } + + @Override + public String toString() { + return DebugString.get(ServerMessageAddClient.class) + .add("clients", clients) + .toString(); + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageAddUser.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageAddUser.java index bd7936ed..046e205a 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageAddUser.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageAddUser.java @@ -4,6 +4,7 @@ import net.stzups.scribbleshare.data.objects.User; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessage; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessageType; +import net.stzups.scribbleshare.util.DebugString; public class ServerMessageAddUser extends ServerMessage { private final User user; @@ -22,4 +23,11 @@ public void serialize(ByteBuf byteBuf) { super.serialize(byteBuf); byteBuf.writeLong(user.getId()); } + + @Override + public String toString() { + return DebugString.get(ServerMessageAddUser.class) + .add("user", user) + .toString(); + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageCanvasUpdate.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageCanvasUpdate.java index 514dacb4..6bdbd1c2 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageCanvasUpdate.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageCanvasUpdate.java @@ -4,6 +4,7 @@ import net.stzups.scribbleshare.data.objects.canvas.canvasUpdate.CanvasUpdates; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessage; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessageType; +import net.stzups.scribbleshare.util.DebugString; public class ServerMessageCanvasUpdate extends ServerMessage { private final CanvasUpdates[] canvasUpdates; @@ -25,4 +26,11 @@ public void serialize(ByteBuf byteBuf) { canvasUpdates.serialize(byteBuf); } } + + @Override + public String toString() { + return DebugString.get(ServerMessageCanvasUpdate.class) + .add("canvasUpdates", canvasUpdates) + .toString(); + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageDeleteDocument.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageDeleteDocument.java index f755d8e1..3bf11b71 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageDeleteDocument.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageDeleteDocument.java @@ -4,6 +4,7 @@ import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessage; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessageType; +import net.stzups.scribbleshare.util.DebugString; public class ServerMessageDeleteDocument extends ServerMessage { private final long id; @@ -22,4 +23,11 @@ public void serialize(ByteBuf byteBuf) { super.serialize(byteBuf); byteBuf.writeLong(id); } + + @Override + public String toString() { + return DebugString.get(ServerMessageDeleteDocument.class) + .add("id", id) + .toString(); + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageGetInvite.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageGetInvite.java index 0e426daf..1dd15364 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageGetInvite.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageGetInvite.java @@ -4,6 +4,7 @@ import net.stzups.scribbleshare.data.objects.InviteCode; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessage; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessageType; +import net.stzups.scribbleshare.util.DebugString; public class ServerMessageGetInvite extends ServerMessage { private final String code; @@ -22,4 +23,11 @@ public void serialize(ByteBuf byteBuf) { super.serialize(byteBuf); writeString(code, byteBuf); } + + @Override + public String toString() { + return DebugString.get(ServerMessageGetInvite.class) + .add("code", code) + .toString(); + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageHandshake.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageHandshake.java index 566f9a46..1e9d79fa 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageHandshake.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageHandshake.java @@ -4,6 +4,7 @@ import net.stzups.scribbleshare.room.server.websocket.Client; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessage; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessageType; +import net.stzups.scribbleshare.util.DebugString; public class ServerMessageHandshake extends ServerMessage { private final Client client; @@ -21,4 +22,11 @@ public void serialize(ByteBuf byteBuf) { super.serialize(byteBuf); byteBuf.writeShort(client.getId()); } + + @Override + public String toString() { + return DebugString.get(ServerMessageHandshake.class) + .add("client", client) + .toString(); + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageOpenDocument.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageOpenDocument.java index c255c596..5ac6a10a 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageOpenDocument.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageOpenDocument.java @@ -5,6 +5,7 @@ import net.stzups.scribbleshare.data.objects.canvas.Canvas; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessage; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessageType; +import net.stzups.scribbleshare.util.DebugString; public class ServerMessageOpenDocument extends ServerMessage { private final Document document; @@ -26,4 +27,12 @@ public void serialize(ByteBuf byteBuf) { byteBuf.writeLong(document.getId()); canvas.serialize(byteBuf); } + + @Override + public String toString() { + return DebugString.get(ServerMessageOpenDocument.class) + .add("document", document) + .add("canvas", canvas) + .toString(); + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageRemoveClient.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageRemoveClient.java index 9cbf4ebe..38b69cc4 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageRemoveClient.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageRemoveClient.java @@ -4,6 +4,7 @@ import net.stzups.scribbleshare.room.server.websocket.Client; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessage; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessageType; +import net.stzups.scribbleshare.util.DebugString; public class ServerMessageRemoveClient extends ServerMessage { private final Client client; @@ -22,4 +23,11 @@ public void serialize(ByteBuf byteBuf) { super.serialize(byteBuf); byteBuf.writeShort(client.getId()); } + + @Override + public String toString() { + return DebugString.get(ServerMessageRemoveClient.class) + .add("client", client) + .toString(); + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageUpdateDocument.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageUpdateDocument.java index 1175c533..e476259a 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageUpdateDocument.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/protocol/server/messages/ServerMessageUpdateDocument.java @@ -4,6 +4,7 @@ import net.stzups.scribbleshare.data.objects.Document; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessage; import net.stzups.scribbleshare.room.server.websocket.protocol.server.ServerMessageType; +import net.stzups.scribbleshare.util.DebugString; public class ServerMessageUpdateDocument extends ServerMessage { private final Document document; @@ -29,4 +30,12 @@ public void serialize(ByteBuf byteBuf) { byteBuf.writeLong(document.getId()); writeString(document.getName(), byteBuf); } + + @Override + public String toString() { + return DebugString.get(ServerMessageUpdateDocument.class) + .add("document", document) + .add("shared", shared) + .toString(); + } } From 34b42fd0c6d13a54868efd444ddbe3aa605f5d35 Mon Sep 17 00:00:00 2001 From: stzups Date: Thu, 27 May 2021 08:40:44 -0400 Subject: [PATCH 098/144] fix super.toString() --- .../data/objects/authentication/http/HttpUserSession.java | 3 +-- .../objects/authentication/http/HttpUserSessionCookie.java | 3 +-- .../objects/authentication/http/PersistentHttpUserSession.java | 3 +-- .../authentication/http/PersistentHttpUserSessionCookie.java | 3 +-- .../objects/canvas/canvasObject/canvasObjects/CanvasImage.java | 1 - .../objects/canvas/canvasObject/canvasObjects/CanvasMouse.java | 1 - .../net/stzups/scribbleshare/server/http/objects/Form.java | 3 +-- .../net/stzups/scribbleshare/server/http/objects/Route.java | 3 +-- 8 files changed, 6 insertions(+), 14 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java index 5b4876c9..e1523f5c 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSession.java @@ -36,8 +36,7 @@ public AuthenticationResult validate(HttpSessionCookie cookie) { @Override public String toString() { - return DebugString.get(HttpUserSession.class) - .add(super.toString()) + return DebugString.get(HttpUserSession.class, super.toString()) .toString(); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSessionCookie.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSessionCookie.java index d8e6799c..a4699ab4 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSessionCookie.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpUserSessionCookie.java @@ -39,8 +39,7 @@ public static HttpUserSessionCookie getHttpUserSessionCookie(HttpRequest request @Override public String toString() { - return DebugString.get(HttpUserSessionCookie.class) - .add(super.toString()) + return DebugString.get(HttpUserSessionCookie.class, super.toString()) .toString(); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java index 349f53c9..976fc236 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSession.java @@ -33,8 +33,7 @@ public AuthenticationResult validate(HttpSessionCookie cookie) { @Override public String toString() { - return DebugString.get(PersistentHttpUserSession.class) - .add(super.toString()) + return DebugString.get(PersistentHttpUserSession.class, super.toString()) .toString(); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java index 3902b7a1..6ebba1bb 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/PersistentHttpUserSessionCookie.java @@ -49,8 +49,7 @@ public static PersistentHttpUserSessionCookie getHttpUserSessionCookie(HttpReque @Override public String toString() { - return DebugString.get(PersistentHttpUserSessionCookie.class) - .add(super.toString()) + return DebugString.get(PersistentHttpUserSessionCookie.class, super.toString()) .toString(); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/CanvasImage.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/CanvasImage.java index b6c76d83..43f4caca 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/CanvasImage.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/CanvasImage.java @@ -28,7 +28,6 @@ public void serialize(ByteBuf byteBuf) { public String toString() { return DebugString.get(CanvasImage.class, super.toString()) .add("id", id) - .add(super.toString()) .toString(); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/CanvasMouse.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/CanvasMouse.java index 941e5d53..73420073 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/CanvasMouse.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/canvas/canvasObject/canvasObjects/CanvasMouse.java @@ -23,7 +23,6 @@ public void serialize(ByteBuf byteBuf) { @Override public String toString() { return DebugString.get(CanvasMouse.class, super.toString()) - .add(super.toString()) .toString(); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Form.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Form.java index 7eeec2ea..eee8dfe8 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Form.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Form.java @@ -48,9 +48,8 @@ public boolean getCheckbox(String field) throws BadRequestException { @Override public String toString() { - return DebugString.get(Form.class) + return DebugString.get(Form.class, super.toString()) .add("form", form) - .add(super.toString()) .toString(); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Route.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Route.java index 34e8b12f..39eab5cc 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Route.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Route.java @@ -42,9 +42,8 @@ public boolean length(int index) { @Override public String toString() { - return DebugString.get(Route.class) + return DebugString.get(Route.class, super.toString()) .add("route", route) - .add(super.toString()) .toString(); } } From 85516f5140c69aa792307537cb865ded18fd8bc0 Mon Sep 17 00:00:00 2001 From: stzups Date: Thu, 27 May 2021 09:27:55 -0400 Subject: [PATCH 099/144] add FormHandler --- .../server/BackendHttpServerInitializer.java | 8 +- .../backend/server/http/FormHandler.java | 21 ++ .../server/http/HttpServerHandler.java | 222 ++---------------- .../http/handlers/LoginFormHandler.java | 91 +++++++ .../http/handlers/LogoutFormHandler.java | 76 ++++++ .../http/handlers/RegisterFormHandler.java | 121 ++++++++++ 6 files changed, 331 insertions(+), 208 deletions(-) create mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/FormHandler.java create mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/LoginFormHandler.java create mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/LogoutFormHandler.java create mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/RegisterFormHandler.java diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java index a028aba0..186b5010 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java @@ -6,6 +6,9 @@ import io.netty.handler.stream.ChunkedWriteHandler; import net.stzups.scribbleshare.backend.ScribbleshareBackendConfig; import net.stzups.scribbleshare.backend.server.http.HttpServerHandler; +import net.stzups.scribbleshare.backend.server.http.handlers.LoginFormHandler; +import net.stzups.scribbleshare.backend.server.http.handlers.LogoutFormHandler; +import net.stzups.scribbleshare.backend.server.http.handlers.RegisterFormHandler; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.server.http.HttpServerInitializer; @@ -17,7 +20,10 @@ public class BackendHttpServerInitializer extends HttpServerInitializer { public BackendHttpServerInitializer(ScribbleshareBackendConfig config, ScribbleshareDatabase database) throws SSLException { super(config); - httpServerHandler = new HttpServerHandler(config, database); + httpServerHandler = new HttpServerHandler(config, database) + .addFormHandler(new LoginFormHandler(config, database)) + .addFormHandler(new LogoutFormHandler(config, database)) + .addFormHandler(new RegisterFormHandler(config, database)); } @Override diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/FormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/FormHandler.java new file mode 100644 index 00000000..3307917a --- /dev/null +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/FormHandler.java @@ -0,0 +1,21 @@ +package net.stzups.scribbleshare.backend.server.http; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.FullHttpRequest; +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; +import net.stzups.scribbleshare.server.http.objects.Form; + +public abstract class FormHandler { + private final String route; + + protected FormHandler(String route) { + this.route = route; + } + + public String getRoute() { + return route; + } + + public abstract void handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form) throws BadRequestException, InternalServerException; +} diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index 2a746c93..f069ebca 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -20,11 +20,6 @@ import net.stzups.scribbleshare.data.objects.User; import net.stzups.scribbleshare.data.objects.authentication.AuthenticatedUserSession; import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; -import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; -import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; -import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSessionCookie; -import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; -import net.stzups.scribbleshare.data.objects.authentication.login.Login; import net.stzups.scribbleshare.server.http.exception.HttpException; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; @@ -39,7 +34,8 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; import java.util.logging.Level; import java.util.regex.Pattern; @@ -69,19 +65,12 @@ public interface Config extends HttpConfig { private static final String AUTHENTICATE_PAGE = "/"; // the page where new users will be automatically created - private static final String LOGIN_PAGE = "/login"; // the login page, where login requests should come from - private static final String LOGIN_PATH = PersistentHttpUserSession.LOGIN_PATH; // where login requests should go - private static final String LOGIN_SUCCESS = "/"; // redirect for a good login, should be the main page - private static final String REGISTER_PAGE = "/register"; // the register page, where register requests should come from - private static final String REGISTER_PATH = "/register"; // where register requests should go - private static final String REGISTER_SUCCESS = LOGIN_PAGE; // redirect for a good register, should be the login page - private static final String LOGOUT_PAGE = "/logout"; // the logout page, where logout requests should come from - private static final String LOGOUT_PATH = "/logout"; // where logout requests should go - private static final String LOGOUT_SUCCESS = LOGIN_PAGE; // redirect for a good logout, should be the login page - private final HttpConfig config; + + + private final ScribbleshareDatabase database; private final File jsRoot; @@ -89,8 +78,9 @@ public interface Config extends HttpConfig { private final int httpCacheSeconds; private final MimeTypes mimeTypes = new MimeTypes(); + private final Map formHandlers = new HashMap<>(); + public HttpServerHandler(Config config, ScribbleshareDatabase database) { - this.config = config; this.database = database; httpRoot = new File(config.getHttpRoot()); @@ -119,6 +109,11 @@ public HttpServerHandler(Config config, ScribbleshareDatabase database) { } } + public HttpServerHandler addFormHandler(FormHandler formHandler) { + formHandlers.put(formHandler.getRoute(), formHandler); + return this; + } + @Override public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) { try { @@ -242,198 +237,11 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H } //login - System.out.println(route); if (request.method().equals(HttpMethod.POST)) { //todo validate for extra fields that should not happen - switch (route.path()) { - case LOGIN_PATH: { - Form form = new Form(request); - - String username = form.getText("username"); - String password = form.getText("password"); - boolean remember = form.getCheckbox("remember"); - - Login login; - try { - login = database.getLogin(username); - } catch (DatabaseException e) { - throw new InternalServerException(e); - } - if (!Login.verify(login, password.getBytes(StandardCharsets.UTF_8))) { - //todo rate limit and generic error handling - if (login == null) { - Scribbleshare.getLogger(ctx).info("Failed login attempt with bad username " + username); - } else { - Scribbleshare.getLogger(ctx).info("Failed login attempt with bad password for username " + username); - } - - sendRedirect(ctx, request, LOGIN_PAGE); - return; - } - - assert login != null : "Verified logins should never be null"; - - HttpHeaders httpHeaders = new DefaultHttpHeaders(); - User user; - try { - user = database.getUser(login.getId()); - } catch (DatabaseException e) { - throw new InternalServerException(e); - } - if (user == null) { - throw new InternalServerException("No user for id " + login.getId()); - } - - HttpUserSession userSession = new HttpUserSession(config, user, httpHeaders); - try { - database.addHttpSession(userSession); - } catch (DatabaseException e) { - throw new InternalServerException(e); - } - if (remember) { - PersistentHttpUserSession persistentHttpUserSession = new PersistentHttpUserSession(config, userSession, httpHeaders); - try { - database.addPersistentHttpUserSession(persistentHttpUserSession); - } catch (DatabaseException e) { - throw new InternalServerException(e); - } - } - sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); - return; - } - case REGISTER_PATH: { - Form form = new Form(request); - - // validate - - String username = form.getText("username"); - String password = form.getText("password"); - - //todo validate - if (false) { - //todo rate limit and generic error handling - - sendRedirect(ctx, request, REGISTER_PAGE); - return; - } - - User user; - HttpSessionCookie cookie = HttpUserSessionCookie.getHttpUserSessionCookie(request); - if (cookie != null) { - HttpUserSession httpSession; - try { - httpSession = database.getHttpSession(cookie); - } catch (DatabaseException e) { - throw new InternalServerException(e); - } - if (httpSession != null) { - User u; - try { - u = database.getUser(httpSession.getUser()); - } catch (DatabaseException e) { - throw new InternalServerException(e); - } - if (u == null) { - throw new InternalServerException("User somehow does not exist for " + httpSession); - } - if (u.isRegistered()) { - Scribbleshare.getLogger(ctx).info("Registered user is creating a new account"); - user = new User(username); - try { - database.addUser(user); - } catch (DatabaseException e) { - throw new InternalServerException("todo", e); - } - } else { - Scribbleshare.getLogger(ctx).info("Temporary user is registering"); - user = u; - } - } else { - user = new User(username); - try { - database.addUser(user); - } catch (DatabaseException e) { - throw new InternalServerException(e); - } - } - } else { - user = new User(username); - try { - database.addUser(user); - } catch (DatabaseException e) { - throw new InternalServerException(e); - } - } - - assert !user.isRegistered(); - - Login login = new Login(user, password.getBytes(StandardCharsets.UTF_8)); - boolean loginAdded; - try { - loginAdded = database.addLogin(login); - } catch (DatabaseException e) { - throw new InternalServerException(e); - } - if (!loginAdded) { - Scribbleshare.getLogger(ctx).info("Tried to register with duplicate username " + username); - sendRedirect(ctx, request, REGISTER_PAGE); - return; - } - - Scribbleshare.getLogger(ctx).info("Registered with username " + username); - - sendRedirect(ctx, request, REGISTER_SUCCESS); - return; - } - case LOGOUT_PATH: { -/* Form form = new Form(request);//todo necessary? - - - HttpHeaders headers = new DefaultHttpHeaders(); - HttpSessionCookie cookie = HttpUserSessionCookie.getHttpUserSessionCookie(request); - if (cookie != null) { - HttpUserSession httpUserSession = database.getHttpSession(cookie); - if (httpUserSession != null) { - if (httpUserSession.validate(cookie)) { - httpUserSession.clearCookie(config, headers); - try { - database.expireHttpSession(httpUserSession); - } catch (FailedException e) { - //todo still send clear cookie - throw new InternalServerException("Failed to log out user", e); - } - } else { - Scribbleshare.getLogger(ctx).warning("Tried to log out of existing session with bad authentication"); - } - } else { - Scribbleshare.getLogger(ctx).warning("Tried to log out of non existent session"); - } - } - - PersistentHttpUserSessionCookie persistentCookie = PersistentHttpUserSessionCookie.getHttpUserSessionCookie(request); - if (persistentCookie != null) { - PersistentHttpUserSession persistentHttpUserSession = database.getPersistentHttpUserSession(persistentCookie); - if (persistentHttpUserSession != null) { - if (persistentHttpUserSession.validate(persistentCookie)) { - persistentCookie.clearCookie(config, headers); - try { - database.expirePersistentHttpUserSession(persistentHttpUserSession); - } catch (FailedException e) { - //todo still send clear cookie - throw new InternalServerException("Failed to log out user", e); - } - } else { - Scribbleshare.getLogger(ctx).warning("Tried to log out of existing persistent session with bad authentication"); - //todo error - } - } else { - Scribbleshare.getLogger(ctx).warning("Tried to log out of non existent persistent session"); - //todo error - } - } - sendRedirect(ctx, request, headers, LOGOUT_SUCCESS); - return;*/ - } + FormHandler handler = formHandlers.get(route.path()); + if (handler != null) { + handler.handle(ctx, request, new Form(request)); } } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/LoginFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/LoginFormHandler.java new file mode 100644 index 00000000..f5469ad0 --- /dev/null +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/LoginFormHandler.java @@ -0,0 +1,91 @@ +package net.stzups.scribbleshare.backend.server.http.handlers; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.DefaultHttpHeaders; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaders; +import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.backend.server.http.FormHandler; +import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; +import net.stzups.scribbleshare.data.database.exception.DatabaseException; +import net.stzups.scribbleshare.data.objects.User; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; +import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; +import net.stzups.scribbleshare.data.objects.authentication.login.Login; +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; +import net.stzups.scribbleshare.server.http.objects.Form; + +import java.nio.charset.StandardCharsets; + +import static net.stzups.scribbleshare.server.http.HttpUtils.sendRedirect; + +public class LoginFormHandler extends FormHandler { + static final String LOGIN_PAGE = "/login"; // the login page, where login requests should come from + private static final String LOGIN_PATH = PersistentHttpUserSession.LOGIN_PATH; // where login requests should go + private static final String LOGIN_SUCCESS = "/"; // redirect for a good login, should be the main page + + private final HttpConfig config; + private final ScribbleshareDatabase database; + + public LoginFormHandler(HttpConfig config, ScribbleshareDatabase database) { + super(LOGIN_PATH); + this.database = database; + this.config = config; + } + + @Override + public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form) throws BadRequestException, InternalServerException { + String username = form.getText("username"); + String password = form.getText("password"); + boolean remember = form.getCheckbox("remember"); + + Login login; + try { + login = database.getLogin(username); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } + if (!Login.verify(login, password.getBytes(StandardCharsets.UTF_8))) { + //todo rate limit and generic error handling + if (login == null) { + Scribbleshare.getLogger(ctx).info("Failed login attempt with bad username " + username); + } else { + Scribbleshare.getLogger(ctx).info("Failed login attempt with bad password for username " + username); + } + + sendRedirect(ctx, request, LOGIN_PAGE); + return; + } + + assert login != null : "Verified logins should never be null"; + + HttpHeaders httpHeaders = new DefaultHttpHeaders(); + User user; + try { + user = database.getUser(login.getId()); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } + if (user == null) { + throw new InternalServerException("No user for id " + login.getId()); + } + + HttpUserSession userSession = new HttpUserSession(config, user, httpHeaders); + try { + database.addHttpSession(userSession); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } + if (remember) { + PersistentHttpUserSession persistentHttpUserSession = new PersistentHttpUserSession(config, userSession, httpHeaders); + try { + database.addPersistentHttpUserSession(persistentHttpUserSession); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } + } + sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); + } +} diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/LogoutFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/LogoutFormHandler.java new file mode 100644 index 00000000..516cfbe6 --- /dev/null +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/LogoutFormHandler.java @@ -0,0 +1,76 @@ +package net.stzups.scribbleshare.backend.server.http.handlers; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.FullHttpRequest; +import net.stzups.scribbleshare.backend.server.http.FormHandler; +import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; +import net.stzups.scribbleshare.server.http.objects.Form; + +public class LogoutFormHandler extends FormHandler { + private static final String LOGOUT_PAGE = "/logout"; // the logout page, where logout requests should come from + private static final String LOGOUT_PATH = "/logout"; // where logout requests should go + private static final String LOGOUT_SUCCESS = LoginFormHandler.LOGIN_PAGE; // redirect for a good logout, should be the login page + + private final HttpConfig config; + private final ScribbleshareDatabase database; + + public LogoutFormHandler(HttpConfig config, ScribbleshareDatabase database) { + super(LOGOUT_PATH); + this.config = config; + this.database = database; + } + + @Override + public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form) throws BadRequestException, InternalServerException { +/* Form form = new Form(request);//todo necessary? + + + HttpHeaders headers = new DefaultHttpHeaders(); + HttpSessionCookie cookie = HttpUserSessionCookie.getHttpUserSessionCookie(request); + if (cookie != null) { + HttpUserSession httpUserSession = database.getHttpSession(cookie); + if (httpUserSession != null) { + if (httpUserSession.validate(cookie)) { + httpUserSession.clearCookie(config, headers); + try { + database.expireHttpSession(httpUserSession); + } catch (FailedException e) { + //todo still send clear cookie + throw new InternalServerException("Failed to log out user", e); + } + } else { + Scribbleshare.getLogger(ctx).warning("Tried to log out of existing session with bad authentication"); + } + } else { + Scribbleshare.getLogger(ctx).warning("Tried to log out of non existent session"); + } + } + + PersistentHttpUserSessionCookie persistentCookie = PersistentHttpUserSessionCookie.getHttpUserSessionCookie(request); + if (persistentCookie != null) { + PersistentHttpUserSession persistentHttpUserSession = database.getPersistentHttpUserSession(persistentCookie); + if (persistentHttpUserSession != null) { + if (persistentHttpUserSession.validate(persistentCookie)) { + persistentCookie.clearCookie(config, headers); + try { + database.expirePersistentHttpUserSession(persistentHttpUserSession); + } catch (FailedException e) { + //todo still send clear cookie + throw new InternalServerException("Failed to log out user", e); + } + } else { + Scribbleshare.getLogger(ctx).warning("Tried to log out of existing persistent session with bad authentication"); + //todo error + } + } else { + Scribbleshare.getLogger(ctx).warning("Tried to log out of non existent persistent session"); + //todo error + } + } + sendRedirect(ctx, request, headers, LOGOUT_SUCCESS); + return;*/ + } +} diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/RegisterFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/RegisterFormHandler.java new file mode 100644 index 00000000..e8175e4e --- /dev/null +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/RegisterFormHandler.java @@ -0,0 +1,121 @@ +package net.stzups.scribbleshare.backend.server.http.handlers; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.FullHttpRequest; +import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.backend.server.http.FormHandler; +import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; +import net.stzups.scribbleshare.data.database.exception.DatabaseException; +import net.stzups.scribbleshare.data.objects.User; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSessionCookie; +import net.stzups.scribbleshare.data.objects.authentication.login.Login; +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; +import net.stzups.scribbleshare.server.http.objects.Form; + +import java.nio.charset.StandardCharsets; + +import static net.stzups.scribbleshare.server.http.HttpUtils.sendRedirect; + +public class RegisterFormHandler extends FormHandler { + private static final String REGISTER_PAGE = "/register"; // the register page, where register requests should come from + private static final String REGISTER_PATH = "/register"; // where register requests should go + private static final String REGISTER_SUCCESS = LoginFormHandler.LOGIN_PAGE; // redirect for a good register, should be the login page + + private final HttpConfig config; + private final ScribbleshareDatabase database; + + public RegisterFormHandler(HttpConfig config, ScribbleshareDatabase database) { + super(REGISTER_PATH); + this.config = config; + this.database = database; + } + + @Override + public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form) throws BadRequestException, InternalServerException { + + // validate + + String username = form.getText("username"); + String password = form.getText("password"); + + //todo validate + if (false) { + //todo rate limit and generic error handling + + sendRedirect(ctx, request, REGISTER_PAGE); + return; + } + + User user; + HttpSessionCookie cookie = HttpUserSessionCookie.getHttpUserSessionCookie(request); + if (cookie != null) { + HttpUserSession httpSession; + try { + httpSession = database.getHttpSession(cookie); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } + if (httpSession != null) { + User u; + try { + u = database.getUser(httpSession.getUser()); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } + if (u == null) { + throw new InternalServerException("User somehow does not exist for " + httpSession); + } + if (u.isRegistered()) { + Scribbleshare.getLogger(ctx).info("Registered user is creating a new account"); + user = new User(username); + try { + database.addUser(user); + } catch (DatabaseException e) { + throw new InternalServerException("todo", e); + } + } else { + Scribbleshare.getLogger(ctx).info("Temporary user is registering"); + user = u; + } + } else { + user = new User(username); + try { + database.addUser(user); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } + } + } else { + user = new User(username); + try { + database.addUser(user); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } + } + + assert !user.isRegistered(); + + Login login = new Login(user, password.getBytes(StandardCharsets.UTF_8)); + boolean loginAdded; + try { + loginAdded = database.addLogin(login); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } + if (!loginAdded) { + Scribbleshare.getLogger(ctx).info("Tried to register with duplicate username " + username); + sendRedirect(ctx, request, REGISTER_PAGE); + return; + } + + Scribbleshare.getLogger(ctx).info("Registered with username " + username); + + sendRedirect(ctx, request, REGISTER_SUCCESS); + return; + } +} From 8bcafec5eb8798845d07bbdf9afc3f7444c8c3e4 Mon Sep 17 00:00:00 2001 From: stzups Date: Thu, 27 May 2021 10:58:47 -0400 Subject: [PATCH 100/144] more handler stuff --- .../server/BackendHttpServerInitializer.java | 14 +- .../backend/server/http/FormHandler.java | 21 --- .../server/http/HttpServerHandler.java | 139 ++---------------- .../server/http/handler/FormHandler.java | 22 +++ .../server/http/handler/HttpHandler.java | 19 +++ .../server/http/handler/RequestHandler.java | 19 +++ .../handlers/DocumentRequestHandler.java | 133 +++++++++++++++++ .../handlers/LoginFormHandler.java | 4 +- .../handlers/LogoutFormHandler.java | 7 +- .../handlers/RegisterFormHandler.java | 4 +- 10 files changed, 217 insertions(+), 165 deletions(-) delete mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/FormHandler.java create mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/FormHandler.java create mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/HttpHandler.java create mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/RequestHandler.java create mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java rename scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/{ => handler}/handlers/LoginFormHandler.java (96%) rename scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/{ => handler}/handlers/LogoutFormHandler.java (95%) rename scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/{ => handler}/handlers/RegisterFormHandler.java (97%) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java index 186b5010..e952231c 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java @@ -6,9 +6,9 @@ import io.netty.handler.stream.ChunkedWriteHandler; import net.stzups.scribbleshare.backend.ScribbleshareBackendConfig; import net.stzups.scribbleshare.backend.server.http.HttpServerHandler; -import net.stzups.scribbleshare.backend.server.http.handlers.LoginFormHandler; -import net.stzups.scribbleshare.backend.server.http.handlers.LogoutFormHandler; -import net.stzups.scribbleshare.backend.server.http.handlers.RegisterFormHandler; +import net.stzups.scribbleshare.backend.server.http.handler.handlers.LoginFormHandler; +import net.stzups.scribbleshare.backend.server.http.handler.handlers.LogoutFormHandler; +import net.stzups.scribbleshare.backend.server.http.handler.handlers.RegisterFormHandler; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.server.http.HttpServerInitializer; @@ -20,10 +20,10 @@ public class BackendHttpServerInitializer extends HttpServerInitializer { public BackendHttpServerInitializer(ScribbleshareBackendConfig config, ScribbleshareDatabase database) throws SSLException { super(config); - httpServerHandler = new HttpServerHandler(config, database) - .addFormHandler(new LoginFormHandler(config, database)) - .addFormHandler(new LogoutFormHandler(config, database)) - .addFormHandler(new RegisterFormHandler(config, database)); + httpServerHandler = new HttpServerHandler(config) + .addHandler(new LoginFormHandler(config, database)) + .addHandler(new LogoutFormHandler(config, database)) + .addHandler(new RegisterFormHandler(config, database)); } @Override diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/FormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/FormHandler.java deleted file mode 100644 index 3307917a..00000000 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/FormHandler.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.stzups.scribbleshare.backend.server.http; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.FullHttpRequest; -import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; -import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; -import net.stzups.scribbleshare.server.http.objects.Form; - -public abstract class FormHandler { - private final String route; - - protected FormHandler(String route) { - this.route = route; - } - - public String getRoute() { - return route; - } - - public abstract void handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form) throws BadRequestException, InternalServerException; -} diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index f069ebca..d5149d4c 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -1,7 +1,5 @@ package net.stzups.scribbleshare.backend.server.http; -import io.netty.buffer.ByteBufInputStream; -import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; @@ -11,22 +9,13 @@ import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.stream.ChunkedStream; import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; -import net.stzups.scribbleshare.data.database.exception.DatabaseException; -import net.stzups.scribbleshare.data.objects.Document; -import net.stzups.scribbleshare.data.objects.Resource; -import net.stzups.scribbleshare.data.objects.User; -import net.stzups.scribbleshare.data.objects.authentication.AuthenticatedUserSession; +import net.stzups.scribbleshare.backend.server.http.handler.HttpHandler; import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.server.http.exception.HttpException; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; -import net.stzups.scribbleshare.server.http.exception.exceptions.UnauthorizedException; -import net.stzups.scribbleshare.server.http.handlers.HttpAuthenticator; -import net.stzups.scribbleshare.server.http.objects.Form; import net.stzups.scribbleshare.server.http.objects.Route; import net.stzups.scribbleshare.server.http.objects.Uri; @@ -40,7 +29,6 @@ import java.util.regex.Pattern; import static net.stzups.scribbleshare.server.http.HttpUtils.send; -import static net.stzups.scribbleshare.server.http.HttpUtils.sendChunkedResource; import static net.stzups.scribbleshare.server.http.HttpUtils.sendFile; import static net.stzups.scribbleshare.server.http.HttpUtils.sendRedirect; @@ -52,7 +40,7 @@ public interface Config extends HttpConfig { String getMimeTypesFilePath(); String getDebugJsRoot(); } - private static final long MAX_AGE_NO_EXPIRE = 31536000;//one year, max age of a cookie + private static final String DEFAULT_FILE = "index.html"; // / -> /index.html @@ -71,18 +59,15 @@ public interface Config extends HttpConfig { - private final ScribbleshareDatabase database; private final File jsRoot; private final File httpRoot; private final int httpCacheSeconds; private final MimeTypes mimeTypes = new MimeTypes(); - private final Map formHandlers = new HashMap<>(); - - public HttpServerHandler(Config config, ScribbleshareDatabase database) { - this.database = database; + private final Map handlers = new HashMap<>(); + public HttpServerHandler(Config config) { httpRoot = new File(config.getHttpRoot()); if (config.getDebugJsRoot().equals("")) { jsRoot = httpRoot; @@ -109,8 +94,8 @@ public HttpServerHandler(Config config, ScribbleshareDatabase database) { } } - public HttpServerHandler addFormHandler(FormHandler formHandler) { - formHandlers.put(formHandler.getRoute(), formHandler); + public HttpServerHandler addHandler(HttpHandler handler) { + handlers.put(handler.getRoute(), handler); return this; } @@ -134,115 +119,9 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H // check if this is a special request - switch (route.get(0)) { - case "api": { - switch (route.get(1)) { - case "document": { - AuthenticatedUserSession session = HttpAuthenticator.authenticateHttpUserSession(request, database); - - if (session == null) { - throw new UnauthorizedException("No authentication"); - } - - User user = session.getUser(); - - long documentId; - try { - documentId = Long.parseLong(route.get(2)); - } catch (NumberFormatException e) { - throw new BadRequestException("Exception while parsing " + route.get(2), e); - } - - if (!user.getOwnedDocuments().contains(documentId) && !user.getSharedDocuments().contains(documentId)) { - throw new NotFoundException("User tried to open document they don't have access to"); - //todo public documents - } - - // user has access to the document - - if (route.length() == 3) { // get document or submit new resource to document - if (request.method().equals(HttpMethod.GET)) { - //todo - throw new NotFoundException("todo not implemented yet"); - /*Resource resource = BackendServerInitializer.getDatabase(ctx).getResource(documentId, documentId); - if (resource == null) { //indicates an empty unsaved canvas, so serve that - send(ctx, request, Canvas.getEmptyCanvas()); - return; - } - HttpHeaders headers = new DefaultHttpHeaders(); - headers.set(HttpHeaderNames.CACHE_CONTROL, "private,max-age=0");//cache but always revalidate - sendChunkedResource(ctx, request, headers, new ChunkedStream(new ByteBufInputStream(resource.getData())), resource.getLastModified());//todo don't fetch entire document from db if not modified*/ - } else if (request.method().equals(HttpMethod.POST)) { //todo validation/security for submitted resources - Document document; - try { - document = database.getDocument(documentId); - } catch (DatabaseException e) { - throw new InternalServerException(e); - } - if (document == null) - throw new NotFoundException("Document with id " + documentId + " for user " + user + " somehow does not exist"); - - try { - send(ctx, request, Unpooled.copyLong(database.addResource(document.getId(), new Resource(request.content())))); - } catch (DatabaseException e) { - throw new InternalServerException(e); - } - } else { - send(ctx, request, HttpResponseStatus.METHOD_NOT_ALLOWED); - } - } else { // route.length == 4, get resource from document - // does the document have this resource? - long resourceId; - try { - resourceId = Long.parseLong(route.get(3)); - } catch (NumberFormatException e) { - throw new BadRequestException("Exception while parsing " + route.get(3), e); - } - - Document document; - try { - document = database.getDocument(documentId); - } catch (DatabaseException e) { - throw new InternalServerException(e); - } - if (document == null) - throw new NotFoundException("Document with id " + documentId + " for user " + user + " somehow does not exist"); - - if (request.method().equals(HttpMethod.GET)) { - // get resource, resource must exist on the document - Resource resource; - try { - resource = database.getResource(resourceId, documentId); - } catch (DatabaseException e) { - throw new InternalServerException(e); - } - if (resource == null) { - throw new NotFoundException("Resource does not exist"); - } - - HttpHeaders headers = new DefaultHttpHeaders(); - headers.add(HttpHeaderNames.CACHE_CONTROL, "private,max-age=" + MAX_AGE_NO_EXPIRE + ",immutable");//cache and never revalidate - permanent - sendChunkedResource(ctx, request, headers, new ChunkedStream(new ByteBufInputStream(resource.getData()))); - } else { - send(ctx, request, HttpResponseStatus.METHOD_NOT_ALLOWED); - } - } - return; - } - default: - throw new NotFoundException("Bad route"); - } - } - - } - - //login - if (request.method().equals(HttpMethod.POST)) { - //todo validate for extra fields that should not happen - FormHandler handler = formHandlers.get(route.path()); - if (handler != null) { - handler.handle(ctx, request, new Form(request)); - } + HttpHandler handler = handlers.get(route.path()); + if (handler != null) { + handler.handle(ctx, request); } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/FormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/FormHandler.java new file mode 100644 index 00000000..ff2a1a88 --- /dev/null +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/FormHandler.java @@ -0,0 +1,22 @@ +package net.stzups.scribbleshare.backend.server.http.handler; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpMethod; +import net.stzups.scribbleshare.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.objects.Form; + +public abstract class FormHandler extends HttpHandler { + protected FormHandler(String route) { + super(route); + } + + @Override + public final void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { + if (request.method().equals(HttpMethod.POST)) { + handle(ctx, request, new Form(request)); + } + } + + public abstract void handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form) throws HttpException; +} diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/HttpHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/HttpHandler.java new file mode 100644 index 00000000..7a247bad --- /dev/null +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/HttpHandler.java @@ -0,0 +1,19 @@ +package net.stzups.scribbleshare.backend.server.http.handler; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.FullHttpRequest; +import net.stzups.scribbleshare.server.http.exception.HttpException; + +public abstract class HttpHandler { + private final String route; + + protected HttpHandler(String route) { + this.route = route; + } + + public String getRoute() { + return route; + } + + public abstract void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException; +} diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/RequestHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/RequestHandler.java new file mode 100644 index 00000000..e7f4c010 --- /dev/null +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/RequestHandler.java @@ -0,0 +1,19 @@ +package net.stzups.scribbleshare.backend.server.http.handler; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.FullHttpRequest; +import net.stzups.scribbleshare.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.objects.Route; + +public abstract class RequestHandler extends HttpHandler { + protected RequestHandler(String route) { + super(route); + } + + @Override + public final void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { + handle(ctx, request, new Route(request.uri())); + } + + public abstract void handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException; +} diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java new file mode 100644 index 00000000..d9d7cd68 --- /dev/null +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java @@ -0,0 +1,133 @@ +package net.stzups.scribbleshare.backend.server.http.handler.handlers; + +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.DefaultHttpHeaders; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.stream.ChunkedStream; +import net.stzups.scribbleshare.backend.server.http.handler.RequestHandler; +import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; +import net.stzups.scribbleshare.data.database.exception.DatabaseException; +import net.stzups.scribbleshare.data.objects.Document; +import net.stzups.scribbleshare.data.objects.Resource; +import net.stzups.scribbleshare.data.objects.User; +import net.stzups.scribbleshare.data.objects.authentication.AuthenticatedUserSession; +import net.stzups.scribbleshare.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; +import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; +import net.stzups.scribbleshare.server.http.exception.exceptions.UnauthorizedException; +import net.stzups.scribbleshare.server.http.handlers.HttpAuthenticator; +import net.stzups.scribbleshare.server.http.objects.Route; + +import static net.stzups.scribbleshare.server.http.HttpUtils.send; +import static net.stzups.scribbleshare.server.http.HttpUtils.sendChunkedResource; + +public class DocumentRequestHandler extends RequestHandler { + private static final long MAX_AGE_NO_EXPIRE = 31536000;//one year, max age of a cookie + + private final ScribbleshareDatabase database; + + protected DocumentRequestHandler(ScribbleshareDatabase database) { + super("document"); + this.database = database; + } + + @Override + public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException { + AuthenticatedUserSession session = HttpAuthenticator.authenticateHttpUserSession(request, database); + + if (session == null) { + throw new UnauthorizedException("No authentication"); + } + + User user = session.getUser(); + + long documentId; + try { + documentId = Long.parseLong(route.get(2)); + } catch (NumberFormatException e) { + throw new BadRequestException("Exception while parsing " + route.get(2), e); + } + + if (!user.getOwnedDocuments().contains(documentId) && !user.getSharedDocuments().contains(documentId)) { + throw new NotFoundException("User tried to open document they don't have access to"); + //todo public documents + } + + // user has access to the document + + if (route.length() == 3) { // get document or submit new resource to document + if (request.method().equals(HttpMethod.GET)) { + //todo + throw new NotFoundException("todo not implemented yet"); + /*Resource resource = BackendServerInitializer.getDatabase(ctx).getResource(documentId, documentId); + if (resource == null) { //indicates an empty unsaved canvas, so serve that + send(ctx, request, Canvas.getEmptyCanvas()); + return; + } + HttpHeaders headers = new DefaultHttpHeaders(); + headers.set(HttpHeaderNames.CACHE_CONTROL, "private,max-age=0");//cache but always revalidate + sendChunkedResource(ctx, request, headers, new ChunkedStream(new ByteBufInputStream(resource.getData())), resource.getLastModified());//todo don't fetch entire document from db if not modified*/ + } else if (request.method().equals(HttpMethod.POST)) { //todo validation/security for submitted resources + Document document; + try { + document = database.getDocument(documentId); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } + if (document == null) + throw new NotFoundException("Document with id " + documentId + " for user " + user + " somehow does not exist"); + + try { + send(ctx, request, Unpooled.copyLong(database.addResource(document.getId(), new Resource(request.content())))); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } + } else { + send(ctx, request, HttpResponseStatus.METHOD_NOT_ALLOWED); + } + } else { // route.length == 4, get resource from document + // does the document have this resource? + long resourceId; + try { + resourceId = Long.parseLong(route.get(3)); + } catch (NumberFormatException e) { + throw new BadRequestException("Exception while parsing " + route.get(3), e); + } + + Document document; + try { + document = database.getDocument(documentId); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } + if (document == null) + throw new NotFoundException("Document with id " + documentId + " for user " + user + " somehow does not exist"); + + if (request.method().equals(HttpMethod.GET)) { + // get resource, resource must exist on the document + Resource resource; + try { + resource = database.getResource(resourceId, documentId); + } catch (DatabaseException e) { + throw new InternalServerException(e); + } + if (resource == null) { + throw new NotFoundException("Resource does not exist"); + } + + HttpHeaders headers = new DefaultHttpHeaders(); + headers.add(HttpHeaderNames.CACHE_CONTROL, "private,max-age=" + MAX_AGE_NO_EXPIRE + ",immutable");//cache and never revalidate - permanent + sendChunkedResource(ctx, request, headers, new ChunkedStream(new ByteBufInputStream(resource.getData()))); + } else { + send(ctx, request, HttpResponseStatus.METHOD_NOT_ALLOWED); + } + } + } +} diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/LoginFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LoginFormHandler.java similarity index 96% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/LoginFormHandler.java rename to scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LoginFormHandler.java index f5469ad0..0a92f5d3 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/LoginFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LoginFormHandler.java @@ -1,11 +1,11 @@ -package net.stzups.scribbleshare.backend.server.http.handlers; +package net.stzups.scribbleshare.backend.server.http.handler.handlers; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.DefaultHttpHeaders; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaders; import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.backend.server.http.FormHandler; +import net.stzups.scribbleshare.backend.server.http.handler.FormHandler; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.User; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/LogoutFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LogoutFormHandler.java similarity index 95% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/LogoutFormHandler.java rename to scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LogoutFormHandler.java index 516cfbe6..537d3106 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/LogoutFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LogoutFormHandler.java @@ -1,8 +1,8 @@ -package net.stzups.scribbleshare.backend.server.http.handlers; +package net.stzups.scribbleshare.backend.server.http.handler.handlers; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; -import net.stzups.scribbleshare.backend.server.http.FormHandler; +import net.stzups.scribbleshare.backend.server.http.handler.FormHandler; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; @@ -71,6 +71,7 @@ public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form } } sendRedirect(ctx, request, headers, LOGOUT_SUCCESS); - return;*/ + return true;*/ + return; } } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/RegisterFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/RegisterFormHandler.java similarity index 97% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/RegisterFormHandler.java rename to scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/RegisterFormHandler.java index e8175e4e..84e461fb 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handlers/RegisterFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/RegisterFormHandler.java @@ -1,9 +1,9 @@ -package net.stzups.scribbleshare.backend.server.http.handlers; +package net.stzups.scribbleshare.backend.server.http.handler.handlers; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.backend.server.http.FormHandler; +import net.stzups.scribbleshare.backend.server.http.handler.FormHandler; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.User; From aafececef853cabb5944691f021dd559dc6776c9 Mon Sep 17 00:00:00 2001 From: stzups Date: Thu, 27 May 2021 12:28:02 -0400 Subject: [PATCH 101/144] FileRequestHandler --- .../backend/ScribbleshareBackendConfig.java | 4 +- .../server/BackendHttpServerInitializer.java | 8 +- .../server/http/HttpServerHandler.java | 183 ++---------------- .../server/http/handler/FormHandler.java | 5 +- .../server/http/handler/HttpHandler.java | 5 +- .../server/http/handler/RequestHandler.java | 3 +- .../handlers/DocumentRequestHandler.java | 4 +- .../handler/handlers/FileRequestHandler.java | 161 +++++++++++++++ 8 files changed, 192 insertions(+), 181 deletions(-) create mode 100644 scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfig.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfig.java index 39e3fc4e..aee199cb 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfig.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfig.java @@ -1,8 +1,8 @@ package net.stzups.scribbleshare.backend; import net.stzups.scribbleshare.ScribbleshareConfig; -import net.stzups.scribbleshare.backend.server.http.HttpServerHandler; +import net.stzups.scribbleshare.backend.server.http.handler.handlers.FileRequestHandler; -public interface ScribbleshareBackendConfig extends ScribbleshareConfig, HttpServerHandler.Config { +public interface ScribbleshareBackendConfig extends ScribbleshareConfig, FileRequestHandler.Config { } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java index e952231c..1c1d6c22 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java @@ -6,6 +6,8 @@ import io.netty.handler.stream.ChunkedWriteHandler; import net.stzups.scribbleshare.backend.ScribbleshareBackendConfig; import net.stzups.scribbleshare.backend.server.http.HttpServerHandler; +import net.stzups.scribbleshare.backend.server.http.handler.handlers.DocumentRequestHandler; +import net.stzups.scribbleshare.backend.server.http.handler.handlers.FileRequestHandler; import net.stzups.scribbleshare.backend.server.http.handler.handlers.LoginFormHandler; import net.stzups.scribbleshare.backend.server.http.handler.handlers.LogoutFormHandler; import net.stzups.scribbleshare.backend.server.http.handler.handlers.RegisterFormHandler; @@ -20,10 +22,12 @@ public class BackendHttpServerInitializer extends HttpServerInitializer { public BackendHttpServerInitializer(ScribbleshareBackendConfig config, ScribbleshareDatabase database) throws SSLException { super(config); - httpServerHandler = new HttpServerHandler(config) + httpServerHandler = new HttpServerHandler() + .addHandler(new DocumentRequestHandler(database)) .addHandler(new LoginFormHandler(config, database)) .addHandler(new LogoutFormHandler(config, database)) - .addHandler(new RegisterFormHandler(config, database)); + .addHandler(new RegisterFormHandler(config, database)) + .addHandler(new FileRequestHandler(config)); } @Override diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java index d5149d4c..e835e774 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java @@ -3,99 +3,32 @@ import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.codec.http.DefaultHttpHeaders; import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpHeaders; -import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.backend.server.http.handler.HttpHandler; -import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.server.http.exception.HttpException; -import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; -import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; -import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; -import net.stzups.scribbleshare.server.http.objects.Route; -import net.stzups.scribbleshare.server.http.objects.Uri; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; +import java.util.ArrayDeque; +import java.util.Queue; import java.util.logging.Level; -import java.util.regex.Pattern; import static net.stzups.scribbleshare.server.http.HttpUtils.send; -import static net.stzups.scribbleshare.server.http.HttpUtils.sendFile; -import static net.stzups.scribbleshare.server.http.HttpUtils.sendRedirect; @ChannelHandler.Sharable public class HttpServerHandler extends SimpleChannelInboundHandler { - public interface Config extends HttpConfig { - String getHttpRoot(); - int getHttpCacheSeconds(); - String getMimeTypesFilePath(); - String getDebugJsRoot(); - } - - - - private static final String DEFAULT_FILE = "index.html"; // / -> /index.html - private static final String DEFAULT_FILE_EXTENSION = ".html"; // /index -> index.html - - - - - - - private static final String AUTHENTICATE_PAGE = "/"; // the page where new users will be automatically created - - - + //private static final String AUTHENTICATE_PAGE = "/"; // the page where new users will be automatically created + private final Queue handlers = new ArrayDeque<>(); + public HttpServerHandler() { - private final File jsRoot; - private final File httpRoot; - private final int httpCacheSeconds; - private final MimeTypes mimeTypes = new MimeTypes(); - - private final Map handlers = new HashMap<>(); - - public HttpServerHandler(Config config) { - httpRoot = new File(config.getHttpRoot()); - if (config.getDebugJsRoot().equals("")) { - jsRoot = httpRoot; - } else { - jsRoot = new File(config.getDebugJsRoot()); - } - httpCacheSeconds = config.getHttpCacheSeconds(); - String path = config.getMimeTypesFilePath(); - // check for mime types in working directory - try (FileInputStream fileInputStream = new FileInputStream(path)) { - mimeTypes.load(fileInputStream); - } catch (IOException e) { - // check for mime types in root of classpath - InputStream inputStream = HttpServerHandler.class.getResourceAsStream(path.startsWith("/") ? "" : "/" + path); - if (inputStream != null) { - try { - mimeTypes.load(inputStream); - } catch (IOException e1) { - e.printStackTrace(); - } - } else { - e.printStackTrace(); // non critical, server will just serve 404 responses - } - } } public HttpServerHandler addHandler(HttpHandler handler) { - handlers.put(handler.getRoute(), handler); + handlers.add(handler); return this; } @@ -110,106 +43,12 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) { } private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { - final Route route; - try { - route = new Route(request.uri()); - } catch (BadRequestException e) { - throw new NotFoundException("Exception while parsing URI", e); - } - - // check if this is a special request - - HttpHandler handler = handlers.get(route.path()); - if (handler != null) { - handler.handle(ctx, request); - } - - - // otherwise try to serve a regular HTTP file resource - - if (!HttpMethod.GET.equals(request.method())) { - send(ctx, request, HttpResponseStatus.METHOD_NOT_ALLOWED); - return; - } - - // redirects - if (route.path().endsWith(DEFAULT_FILE)) { // /index.html -> / - sendRedirect(ctx, request, route.path().substring(0, route.path().length() - DEFAULT_FILE.length()) + route.rawQuery()); - return; - } else if ((route.path() + DEFAULT_FILE_EXTENSION).endsWith(DEFAULT_FILE)) { // /index -> / - sendRedirect(ctx, request, route.path().substring(0, route.path().length() - (DEFAULT_FILE.length() - DEFAULT_FILE_EXTENSION.length())) + route.rawQuery()); - return; - } else if (route.path().endsWith(DEFAULT_FILE_EXTENSION)) { // /page.html -> /page - sendRedirect(ctx, request, route.path().substring(0, route.path().length() - DEFAULT_FILE_EXTENSION.length()) + route.rawQuery()); - return; - } - - // get filesystem filePath from provided filePath - final String filePath; - try { - filePath = getFilePath(route.path()); - } catch (BadRequestException e) { - throw new NotFoundException("Exception while getting file path for http request", e); - } - - //todo this is mostly for debug - File root; - if (filePath.endsWith(".js")) { - root = jsRoot; - } else { - root = httpRoot; - } - - File file = new File(root, filePath); - if (file.isHidden() || !file.exists() || file.isDirectory() || !file.isFile()) { - if (new File(httpRoot, filePath.substring(0, filePath.length() - DEFAULT_FILE_EXTENSION.length())).isDirectory()) { // /test -> /test/ if test is a valid directory and /test.html does not exist - sendRedirect(ctx, request, route.path() + "/" + route.rawQuery()); - } else { - throw new NotFoundException("File at path " + filePath + " not found"); + for (HttpHandler handler : handlers) { + if (request.uri().startsWith(handler.getRoute()) && handler.handle(ctx, request)) { + return; } - return; } - - HttpHeaders headers = new DefaultHttpHeaders(); - /*if (route.equals(AUTHENTICATE_PAGE)) { - try { - logIn(config, request, headers); - } catch (FailedException e) { - throw new InternalServerException("Exception while logging user in", e); - } - }*/ - headers.set(HttpHeaderNames.CACHE_CONTROL, "public,max-age=" + httpCacheSeconds);//cache but revalidate if stale todo set to private cache for resources behind authentication - try { - sendFile(ctx, request, headers, file, mimeTypes.getMimeType(file)); - } catch (IOException e) { - throw new InternalServerException("Exception while sending file", e); - } - } - - - - private static final Pattern ALLOWED_PATH = Pattern.compile("^[\\\\" + File.separator + "." + Uri.FILE_NAME_REGEX + "]+$"); - - /** Converts uri to filesystem path */ - private static String getFilePath(String path) throws BadRequestException { - path = path.replace("/", File.separator); - - if (path.contains(File.separator + '.') // /. - || path.contains('.' + File.separator) // ./ - || path.contains(File.separator + File.separator) // // - || path.charAt(0) == '.' // . - || path.charAt(path.length() - 1) == '.' // /page. - || !ALLOWED_PATH.matcher(path).matches()) - throw new BadRequestException("File path contains illegal characters"); - - if (path.endsWith(File.separator)) { // / -> index.html - path = path + DEFAULT_FILE; - } else if (path.lastIndexOf(File.separator) > path.lastIndexOf(".")) { // /page -> /page.html - path = path + DEFAULT_FILE_EXTENSION; - } - return path; + Scribbleshare.getLogger(ctx).warning("No handler for request, serving 404"); + send(ctx, request, HttpResponseStatus.NOT_FOUND); } - - - } \ No newline at end of file diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/FormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/FormHandler.java index ff2a1a88..1ee1a07e 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/FormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/FormHandler.java @@ -12,9 +12,12 @@ protected FormHandler(String route) { } @Override - public final void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { + public final boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { if (request.method().equals(HttpMethod.POST)) { handle(ctx, request, new Form(request)); + return true; + } else { + return false; } } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/HttpHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/HttpHandler.java index 7a247bad..7c96cd38 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/HttpHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/HttpHandler.java @@ -15,5 +15,8 @@ public String getRoute() { return route; } - public abstract void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException; + /** + * true if the request was handled + */ + public abstract boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException; } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/RequestHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/RequestHandler.java index e7f4c010..fb8018dc 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/RequestHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/RequestHandler.java @@ -11,8 +11,9 @@ protected RequestHandler(String route) { } @Override - public final void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { + public final boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { handle(ctx, request, new Route(request.uri())); + return true; } public abstract void handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java index d9d7cd68..e6699aa4 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java @@ -33,8 +33,8 @@ public class DocumentRequestHandler extends RequestHandler { private final ScribbleshareDatabase database; - protected DocumentRequestHandler(ScribbleshareDatabase database) { - super("document"); + public DocumentRequestHandler(ScribbleshareDatabase database) { + super("/document"); this.database = database; } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java new file mode 100644 index 00000000..873e09e3 --- /dev/null +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java @@ -0,0 +1,161 @@ +package net.stzups.scribbleshare.backend.server.http.handler.handlers; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.DefaultHttpHeaders; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpResponseStatus; +import net.stzups.scribbleshare.backend.server.http.HttpServerHandler; +import net.stzups.scribbleshare.backend.server.http.MimeTypes; +import net.stzups.scribbleshare.backend.server.http.handler.RequestHandler; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; +import net.stzups.scribbleshare.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; +import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; +import net.stzups.scribbleshare.server.http.objects.Route; +import net.stzups.scribbleshare.server.http.objects.Uri; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.regex.Pattern; + +import static net.stzups.scribbleshare.server.http.HttpUtils.send; +import static net.stzups.scribbleshare.server.http.HttpUtils.sendFile; +import static net.stzups.scribbleshare.server.http.HttpUtils.sendRedirect; + +public class FileRequestHandler extends RequestHandler { + public interface Config extends HttpConfig { + String getHttpRoot(); + int getHttpCacheSeconds(); + String getMimeTypesFilePath(); + String getDebugJsRoot(); + } + + private static final String DEFAULT_FILE = "index.html"; // / -> /index.html + private static final String DEFAULT_FILE_EXTENSION = ".html"; // /index -> index.html + + private final File jsRoot; + private final File httpRoot; + private final int httpCacheSeconds; + private final MimeTypes mimeTypes = new MimeTypes(); + + public FileRequestHandler(Config config) { + super("/"); + httpRoot = new File(config.getHttpRoot()); + if (config.getDebugJsRoot().equals("")) { + jsRoot = httpRoot; + } else { + jsRoot = new File(config.getDebugJsRoot()); + } + httpCacheSeconds = config.getHttpCacheSeconds(); + String path = config.getMimeTypesFilePath(); + // check for mime types in working directory + try (FileInputStream fileInputStream = new FileInputStream(path)) { + mimeTypes.load(fileInputStream); + } catch (IOException e) { + // check for mime types in root of classpath + InputStream inputStream = HttpServerHandler.class.getResourceAsStream(path.startsWith("/") ? "" : "/" + path); + if (inputStream != null) { + try { + mimeTypes.load(inputStream); + } catch (IOException e1) { + e.printStackTrace(); + } + } else { + e.printStackTrace(); // non critical, server will just serve 404 responses + } + } + } + + @Override + public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException { + // otherwise try to serve a regular HTTP file resource + + if (!HttpMethod.GET.equals(request.method())) { + send(ctx, request, HttpResponseStatus.METHOD_NOT_ALLOWED); + return; + } + + // redirects + if (route.path().endsWith(DEFAULT_FILE)) { // /index.html -> / + sendRedirect(ctx, request, route.path().substring(0, route.path().length() - DEFAULT_FILE.length()) + route.rawQuery()); + return; + } else if ((route.path() + DEFAULT_FILE_EXTENSION).endsWith(DEFAULT_FILE)) { // /index -> / + sendRedirect(ctx, request, route.path().substring(0, route.path().length() - (DEFAULT_FILE.length() - DEFAULT_FILE_EXTENSION.length())) + route.rawQuery()); + return; + } else if (route.path().endsWith(DEFAULT_FILE_EXTENSION)) { // /page.html -> /page + sendRedirect(ctx, request, route.path().substring(0, route.path().length() - DEFAULT_FILE_EXTENSION.length()) + route.rawQuery()); + return; + } + + // get filesystem filePath from provided filePath + final String filePath; + try { + filePath = getFilePath(route.path()); + } catch (BadRequestException e) { + throw new NotFoundException("Exception while getting file path for http request", e); + } + + //todo this is mostly for debug + File root; + if (filePath.endsWith(".js")) { + root = jsRoot; + } else { + root = httpRoot; + } + + File file = new File(root, filePath); + if (file.isHidden() || !file.exists() || file.isDirectory() || !file.isFile()) { + if (new File(httpRoot, filePath.substring(0, filePath.length() - DEFAULT_FILE_EXTENSION.length())).isDirectory()) { // /test -> /test/ if test is a valid directory and /test.html does not exist + sendRedirect(ctx, request, route.path() + "/" + route.rawQuery()); + } else { + throw new NotFoundException("File at path " + filePath + " not found"); + } + return; + } + + HttpHeaders headers = new DefaultHttpHeaders(); + /*if (route.equals(AUTHENTICATE_PAGE)) { + try { + logIn(config, request, headers); + } catch (FailedException e) { + throw new InternalServerException("Exception while logging user in", e); + } + }*/ + headers.set(HttpHeaderNames.CACHE_CONTROL, "public,max-age=" + httpCacheSeconds);//cache but revalidate if stale todo set to private cache for resources behind authentication + try { + sendFile(ctx, request, headers, file, mimeTypes.getMimeType(file)); + } catch (IOException e) { + throw new InternalServerException("Exception while sending file", e); + } + } + + + + private static final Pattern ALLOWED_PATH = Pattern.compile("^[\\\\" + File.separator + "." + Uri.FILE_NAME_REGEX + "]+$"); + + /** Converts uri to filesystem path */ + private static String getFilePath(String path) throws BadRequestException { + path = path.replace("/", File.separator); + + if (path.contains(File.separator + '.') // /. + || path.contains('.' + File.separator) // ./ + || path.contains(File.separator + File.separator) // // + || path.charAt(0) == '.' // . + || path.charAt(path.length() - 1) == '.' // /page. + || !ALLOWED_PATH.matcher(path).matches()) + throw new BadRequestException("File path contains illegal characters"); + + if (path.endsWith(File.separator)) { // / -> index.html + path = path + DEFAULT_FILE; + } else if (path.lastIndexOf(File.separator) > path.lastIndexOf(".")) { // /page -> /page.html + path = path + DEFAULT_FILE_EXTENSION; + } + return path; + } +} From 8896b215d2662824f7e7ad811dbb11e0a58d1b96 Mon Sep 17 00:00:00 2001 From: stzups Date: Thu, 27 May 2021 14:38:51 -0400 Subject: [PATCH 102/144] move stuff around --- .../server/BackendHttpServerInitializer.java | 5 ++--- .../handlers/DocumentRequestHandler.java | 2 +- .../handler/handlers/FileRequestHandler.java | 6 +++--- .../handler/handlers/LoginFormHandler.java | 2 +- .../handler/handlers/LogoutFormHandler.java | 2 +- .../handler/handlers/RegisterFormHandler.java | 2 +- .../server/http/HttpServerHandler.java | 13 ++++-------- .../server/http/HttpServerInitializer.java | 12 +++-------- .../scribbleshare}/server/http/MimeTypes.java | 2 +- .../{DebugLog.java => DebugOpenCloseLog.java} | 2 +- .../http/handlers/HttpExceptionHandler.java | 20 ------------------- .../server/http/httphandler}/HttpHandler.java | 4 ++-- .../httphandlers}/FormHandler.java | 3 ++- .../httphandlers}/RequestHandler.java | 3 ++- 14 files changed, 24 insertions(+), 54 deletions(-) rename {scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend => scribbleshare-commons/src/main/java/net/stzups/scribbleshare}/server/http/HttpServerHandler.java (76%) rename {scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend => scribbleshare-commons/src/main/java/net/stzups/scribbleshare}/server/http/MimeTypes.java (97%) rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/{DebugLog.java => DebugOpenCloseLog.java} (90%) delete mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpExceptionHandler.java rename {scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler => scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler}/HttpHandler.java (78%) rename {scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler => scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/httphandlers}/FormHandler.java (85%) rename {scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler => scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/httphandlers}/RequestHandler.java (83%) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java index 1c1d6c22..a84c2195 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java @@ -5,13 +5,13 @@ import io.netty.handler.codec.http.HttpContentCompressor; import io.netty.handler.stream.ChunkedWriteHandler; import net.stzups.scribbleshare.backend.ScribbleshareBackendConfig; -import net.stzups.scribbleshare.backend.server.http.HttpServerHandler; import net.stzups.scribbleshare.backend.server.http.handler.handlers.DocumentRequestHandler; import net.stzups.scribbleshare.backend.server.http.handler.handlers.FileRequestHandler; import net.stzups.scribbleshare.backend.server.http.handler.handlers.LoginFormHandler; import net.stzups.scribbleshare.backend.server.http.handler.handlers.LogoutFormHandler; import net.stzups.scribbleshare.backend.server.http.handler.handlers.RegisterFormHandler; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; +import net.stzups.scribbleshare.server.http.HttpServerHandler; import net.stzups.scribbleshare.server.http.HttpServerInitializer; import javax.net.ssl.SSLException; @@ -37,7 +37,6 @@ protected void initChannel(SocketChannel channel) { channel.pipeline() .addLast(new HttpContentCompressor()) .addLast(new ChunkedWriteHandler()) - .addLast(httpServerHandler) - .addLast(httpExceptionHandler()); + .addLast(httpServerHandler); } } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java index e6699aa4..45a3591d 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java @@ -10,7 +10,6 @@ import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.stream.ChunkedStream; -import net.stzups.scribbleshare.backend.server.http.handler.RequestHandler; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.Document; @@ -23,6 +22,7 @@ import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; import net.stzups.scribbleshare.server.http.exception.exceptions.UnauthorizedException; import net.stzups.scribbleshare.server.http.handlers.HttpAuthenticator; +import net.stzups.scribbleshare.server.http.httphandler.httphandlers.RequestHandler; import net.stzups.scribbleshare.server.http.objects.Route; import static net.stzups.scribbleshare.server.http.HttpUtils.send; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java index 873e09e3..5efdc59a 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java @@ -7,14 +7,14 @@ import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; -import net.stzups.scribbleshare.backend.server.http.HttpServerHandler; -import net.stzups.scribbleshare.backend.server.http.MimeTypes; -import net.stzups.scribbleshare.backend.server.http.handler.RequestHandler; import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; +import net.stzups.scribbleshare.server.http.HttpServerHandler; +import net.stzups.scribbleshare.server.http.MimeTypes; import net.stzups.scribbleshare.server.http.exception.HttpException; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; +import net.stzups.scribbleshare.server.http.httphandler.httphandlers.RequestHandler; import net.stzups.scribbleshare.server.http.objects.Route; import net.stzups.scribbleshare.server.http.objects.Uri; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LoginFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LoginFormHandler.java index 0a92f5d3..6313dab0 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LoginFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LoginFormHandler.java @@ -5,7 +5,6 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaders; import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.backend.server.http.handler.FormHandler; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.User; @@ -15,6 +14,7 @@ import net.stzups.scribbleshare.data.objects.authentication.login.Login; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; +import net.stzups.scribbleshare.server.http.httphandler.httphandlers.FormHandler; import net.stzups.scribbleshare.server.http.objects.Form; import java.nio.charset.StandardCharsets; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LogoutFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LogoutFormHandler.java index 537d3106..e8f0f237 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LogoutFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LogoutFormHandler.java @@ -2,11 +2,11 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; -import net.stzups.scribbleshare.backend.server.http.handler.FormHandler; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; +import net.stzups.scribbleshare.server.http.httphandler.httphandlers.FormHandler; import net.stzups.scribbleshare.server.http.objects.Form; public class LogoutFormHandler extends FormHandler { diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/RegisterFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/RegisterFormHandler.java index 84e461fb..37e93ece 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/RegisterFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/RegisterFormHandler.java @@ -3,7 +3,6 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.backend.server.http.handler.FormHandler; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.User; @@ -14,6 +13,7 @@ import net.stzups.scribbleshare.data.objects.authentication.login.Login; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; +import net.stzups.scribbleshare.server.http.httphandler.httphandlers.FormHandler; import net.stzups.scribbleshare.server.http.objects.Form; import java.nio.charset.StandardCharsets; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java similarity index 76% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java index e835e774..32d2eeb6 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/HttpServerHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java @@ -1,13 +1,13 @@ -package net.stzups.scribbleshare.backend.server.http; +package net.stzups.scribbleshare.server.http; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.HttpResponseStatus; import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.backend.server.http.handler.HttpHandler; import net.stzups.scribbleshare.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; +import net.stzups.scribbleshare.server.http.httphandler.HttpHandler; import java.util.ArrayDeque; import java.util.Queue; @@ -17,10 +17,6 @@ @ChannelHandler.Sharable public class HttpServerHandler extends SimpleChannelInboundHandler { - - //private static final String AUTHENTICATE_PAGE = "/"; // the page where new users will be automatically created - - private final Queue handlers = new ArrayDeque<>(); public HttpServerHandler() { @@ -48,7 +44,6 @@ private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws H return; } } - Scribbleshare.getLogger(ctx).warning("No handler for request, serving 404"); - send(ctx, request, HttpResponseStatus.NOT_FOUND); + throw new NotFoundException("No " + HttpHandler.class + " for request"); } } \ No newline at end of file diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java index 6a25abb1..8fabd430 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java @@ -10,8 +10,7 @@ import io.netty.handler.traffic.GlobalTrafficShapingHandler; import io.netty.handler.traffic.TrafficCounter; import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.server.http.handlers.DebugLog; -import net.stzups.scribbleshare.server.http.handlers.HttpExceptionHandler; +import net.stzups.scribbleshare.server.http.handlers.DebugOpenCloseLog; import net.stzups.scribbleshare.server.http.handlers.HttpHandler; import javax.net.ssl.SSLException; @@ -29,9 +28,8 @@ public interface Config { private final Config config; private final SslContext sslContext; - private final DebugLog debugLog = new DebugLog(); + private final DebugOpenCloseLog debugOpenCloseLog = new DebugOpenCloseLog(); private final HttpHandler httpHandler = new HttpHandler(); - private final HttpExceptionHandler httpExceptionHandler = new HttpExceptionHandler(); protected HttpServerInitializer(Config config) throws SSLException { this.config = config; @@ -46,15 +44,11 @@ protected HttpServerInitializer(Config config) throws SSLException { } } - protected HttpExceptionHandler httpExceptionHandler() { - return httpExceptionHandler; - } - @Override protected void initChannel(SocketChannel channel) { Scribbleshare.setLogger(channel); - channel.pipeline().addLast(debugLog); + channel.pipeline().addLast(debugOpenCloseLog); if (config.getDebugLogTraffic()) channel.pipeline().addLast(new GlobalTrafficShapingHandler(channel.eventLoop(), 0, 0, 1000) { @Override protected void doAccounting(TrafficCounter counter) { diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/MimeTypes.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/MimeTypes.java similarity index 97% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/MimeTypes.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/MimeTypes.java index ce641225..6e5bbc91 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/MimeTypes.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/MimeTypes.java @@ -1,4 +1,4 @@ -package net.stzups.scribbleshare.backend.server.http; +package net.stzups.scribbleshare.server.http; import java.io.BufferedReader; import java.io.File; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/DebugLog.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/DebugOpenCloseLog.java similarity index 90% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/DebugLog.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/DebugOpenCloseLog.java index 4fb41c27..a5352109 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/DebugLog.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/DebugOpenCloseLog.java @@ -6,7 +6,7 @@ import net.stzups.scribbleshare.Scribbleshare; @ChannelHandler.Sharable -public class DebugLog extends ChannelDuplexHandler { +public class DebugOpenCloseLog extends ChannelDuplexHandler { @Override public void channelActive(ChannelHandlerContext ctx) { Scribbleshare.getLogger(ctx).info("Connection opened"); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpExceptionHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpExceptionHandler.java deleted file mode 100644 index 678da796..00000000 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpExceptionHandler.java +++ /dev/null @@ -1,20 +0,0 @@ -package net.stzups.scribbleshare.server.http.handlers; - -import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.HttpResponseStatus; -import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.server.http.HttpUtils; - -import java.util.logging.Level; - -@ChannelHandler.Sharable -public class HttpExceptionHandler extends ChannelDuplexHandler { - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) { - Scribbleshare.getLogger(ctx).log(Level.WARNING, "Uncaught exception", throwable); - HttpUtils.send(ctx, null, HttpResponseStatus.INTERNAL_SERVER_ERROR); - //todo ctx.close(); - } -} diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/HttpHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/HttpHandler.java similarity index 78% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/HttpHandler.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/HttpHandler.java index 7c96cd38..0c896652 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/HttpHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/HttpHandler.java @@ -1,4 +1,4 @@ -package net.stzups.scribbleshare.backend.server.http.handler; +package net.stzups.scribbleshare.server.http.httphandler; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; @@ -16,7 +16,7 @@ public String getRoute() { } /** - * true if the request was handled + * true if the request was handled, or false if it should be passed down */ public abstract boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException; } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/FormHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/httphandlers/FormHandler.java similarity index 85% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/FormHandler.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/httphandlers/FormHandler.java index 1ee1a07e..698a1c6d 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/FormHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/httphandlers/FormHandler.java @@ -1,9 +1,10 @@ -package net.stzups.scribbleshare.backend.server.http.handler; +package net.stzups.scribbleshare.server.http.httphandler.httphandlers; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import net.stzups.scribbleshare.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.httphandler.HttpHandler; import net.stzups.scribbleshare.server.http.objects.Form; public abstract class FormHandler extends HttpHandler { diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/RequestHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/httphandlers/RequestHandler.java similarity index 83% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/RequestHandler.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/httphandlers/RequestHandler.java index fb8018dc..d2d86c14 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/RequestHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/httphandlers/RequestHandler.java @@ -1,8 +1,9 @@ -package net.stzups.scribbleshare.backend.server.http.handler; +package net.stzups.scribbleshare.server.http.httphandler.httphandlers; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; import net.stzups.scribbleshare.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.httphandler.HttpHandler; import net.stzups.scribbleshare.server.http.objects.Route; public abstract class RequestHandler extends HttpHandler { From b5ddb55f3d7ecccda86e0e99d848abfbcd59cffb Mon Sep 17 00:00:00 2001 From: stzups Date: Thu, 27 May 2021 15:00:39 -0400 Subject: [PATCH 103/144] change HttpAuthenticator to the right thing --- .../server/BackendHttpServerInitializer.java | 12 +++-- .../handlers/DocumentRequestHandler.java | 4 +- .../handler/handlers/FileRequestHandler.java | 2 +- .../handler/handlers/LoginFormHandler.java | 2 +- .../handler/handlers/LogoutFormHandler.java | 2 +- .../handler/handlers/RegisterFormHandler.java | 7 +-- .../data/database/ScribbleshareDatabase.java | 2 +- .../server/http/HttpServerHandler.java | 39 +++++++------- .../server/http/HttpServerInitializer.java | 23 +++++++-- .../httphandlers => handler}/FormHandler.java | 3 +- .../{httphandler => handler}/HttpHandler.java | 2 +- .../RequestHandler.java | 3 +- .../handlers/HealthcheckRequestHandler.java | 33 ++++++++++++ .../handlers/HttpAuthenticator.java | 30 +++-------- .../http/handlers/DebugOpenCloseLog.java | 21 -------- .../server/http/handlers/HttpHandler.java | 51 ------------------- .../server/RoomHttpServerInitializer.java | 13 +++-- .../websocket/state/states/InitialState.java | 2 +- 18 files changed, 104 insertions(+), 147 deletions(-) rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/{httphandler/httphandlers => handler}/FormHandler.java (85%) rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/{httphandler => handler}/HttpHandler.java (90%) rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/{httphandler/httphandlers => handler}/RequestHandler.java (83%) create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HealthcheckRequestHandler.java rename scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/{ => handler}/handlers/HttpAuthenticator.java (88%) delete mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/DebugOpenCloseLog.java delete mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpHandler.java diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java index a84c2195..47869c6e 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java @@ -13,6 +13,7 @@ import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.server.http.HttpServerHandler; import net.stzups.scribbleshare.server.http.HttpServerInitializer; +import net.stzups.scribbleshare.server.http.handler.handlers.HealthcheckRequestHandler; import javax.net.ssl.SSLException; @@ -23,11 +24,12 @@ public class BackendHttpServerInitializer extends HttpServerInitializer { public BackendHttpServerInitializer(ScribbleshareBackendConfig config, ScribbleshareDatabase database) throws SSLException { super(config); httpServerHandler = new HttpServerHandler() - .addHandler(new DocumentRequestHandler(database)) - .addHandler(new LoginFormHandler(config, database)) - .addHandler(new LogoutFormHandler(config, database)) - .addHandler(new RegisterFormHandler(config, database)) - .addHandler(new FileRequestHandler(config)); + .addLast(new HealthcheckRequestHandler()) + .addLast(new DocumentRequestHandler(database)) + .addLast(new LoginFormHandler(config, database)) + .addLast(new LogoutFormHandler(config, database)) + .addLast(new RegisterFormHandler(database)) + .addLast(new FileRequestHandler(config)); } @Override diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java index 45a3591d..f8b05b39 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java @@ -21,8 +21,8 @@ import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; import net.stzups.scribbleshare.server.http.exception.exceptions.UnauthorizedException; -import net.stzups.scribbleshare.server.http.handlers.HttpAuthenticator; -import net.stzups.scribbleshare.server.http.httphandler.httphandlers.RequestHandler; +import net.stzups.scribbleshare.server.http.handler.RequestHandler; +import net.stzups.scribbleshare.server.http.handler.handlers.HttpAuthenticator; import net.stzups.scribbleshare.server.http.objects.Route; import static net.stzups.scribbleshare.server.http.HttpUtils.send; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java index 5efdc59a..c6d9758e 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java @@ -14,7 +14,7 @@ import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; -import net.stzups.scribbleshare.server.http.httphandler.httphandlers.RequestHandler; +import net.stzups.scribbleshare.server.http.handler.RequestHandler; import net.stzups.scribbleshare.server.http.objects.Route; import net.stzups.scribbleshare.server.http.objects.Uri; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LoginFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LoginFormHandler.java index 6313dab0..30ec94ad 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LoginFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LoginFormHandler.java @@ -14,7 +14,7 @@ import net.stzups.scribbleshare.data.objects.authentication.login.Login; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; -import net.stzups.scribbleshare.server.http.httphandler.httphandlers.FormHandler; +import net.stzups.scribbleshare.server.http.handler.FormHandler; import net.stzups.scribbleshare.server.http.objects.Form; import java.nio.charset.StandardCharsets; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LogoutFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LogoutFormHandler.java index e8f0f237..d70c2f1e 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LogoutFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LogoutFormHandler.java @@ -6,7 +6,7 @@ import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; -import net.stzups.scribbleshare.server.http.httphandler.httphandlers.FormHandler; +import net.stzups.scribbleshare.server.http.handler.FormHandler; import net.stzups.scribbleshare.server.http.objects.Form; public class LogoutFormHandler extends FormHandler { diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/RegisterFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/RegisterFormHandler.java index 37e93ece..7f30a5df 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/RegisterFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/RegisterFormHandler.java @@ -6,14 +6,13 @@ import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.User; -import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.login.Login; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; -import net.stzups.scribbleshare.server.http.httphandler.httphandlers.FormHandler; +import net.stzups.scribbleshare.server.http.handler.FormHandler; import net.stzups.scribbleshare.server.http.objects.Form; import java.nio.charset.StandardCharsets; @@ -25,12 +24,10 @@ public class RegisterFormHandler extends FormHandler { private static final String REGISTER_PATH = "/register"; // where register requests should go private static final String REGISTER_SUCCESS = LoginFormHandler.LOGIN_PAGE; // redirect for a good register, should be the login page - private final HttpConfig config; private final ScribbleshareDatabase database; - public RegisterFormHandler(HttpConfig config, ScribbleshareDatabase database) { + public RegisterFormHandler(ScribbleshareDatabase database) { super(REGISTER_PATH); - this.config = config; this.database = database; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java index 43a380ab..309ba306 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/ScribbleshareDatabase.java @@ -7,7 +7,7 @@ import net.stzups.scribbleshare.data.database.databases.PersistentHttpSessionDatabase; import net.stzups.scribbleshare.data.database.databases.ResourceDatabase; import net.stzups.scribbleshare.data.database.databases.UserDatabase; -import net.stzups.scribbleshare.server.http.handlers.HttpAuthenticator; +import net.stzups.scribbleshare.server.http.handler.handlers.HttpAuthenticator; public interface ScribbleshareDatabase extends PersistentHttpSessionDatabase, ResourceDatabase, HttpSessionDatabase, UserDatabase, DocumentDatabase, InviteCodeDatabase, LoginDatabase, HttpAuthenticator.Database { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java index 32d2eeb6..917c49a4 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java @@ -2,48 +2,47 @@ import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.MessageToMessageDecoder; import io.netty.handler.codec.http.FullHttpRequest; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.server.http.exception.HttpException; -import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; -import net.stzups.scribbleshare.server.http.httphandler.HttpHandler; +import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.server.http.handler.HttpHandler; import java.util.ArrayDeque; +import java.util.List; import java.util.Queue; import java.util.logging.Level; import static net.stzups.scribbleshare.server.http.HttpUtils.send; @ChannelHandler.Sharable -public class HttpServerHandler extends SimpleChannelInboundHandler { +public class HttpServerHandler extends MessageToMessageDecoder { private final Queue handlers = new ArrayDeque<>(); - public HttpServerHandler() { - - } - - public HttpServerHandler addHandler(HttpHandler handler) { + public HttpServerHandler addLast(HttpHandler handler) { handlers.add(handler); return this; } @Override - public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) { + protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List out) { try { - handle(ctx, request); + Scribbleshare.getLogger(ctx).info(request.method() + " " + request.uri()); + + if (request.decoderResult().isFailure()) + throw new BadRequestException("Decoding request resulted in " + request.decoderResult()); + + for (HttpHandler handler : handlers) { + if (request.uri().startsWith(handler.getRoute()) && handler.handle(ctx, request)) { + return; + } + } + + out.add(request.retain()); } catch (HttpException e) { Scribbleshare.getLogger(ctx).log(Level.WARNING, "Exception while handling HTTP request", e); send(ctx, request, e.responseStatus()); } } - - private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { - for (HttpHandler handler : handlers) { - if (request.uri().startsWith(handler.getRoute()) && handler.handle(ctx, request)) { - return; - } - } - throw new NotFoundException("No " + HttpHandler.class + " for request"); - } } \ No newline at end of file diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java index 8fabd430..c1a995d6 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java @@ -1,6 +1,8 @@ package net.stzups.scribbleshare.server.http; +import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.http.HttpObjectAggregator; @@ -10,8 +12,6 @@ import io.netty.handler.traffic.GlobalTrafficShapingHandler; import io.netty.handler.traffic.TrafficCounter; import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.server.http.handlers.DebugOpenCloseLog; -import net.stzups.scribbleshare.server.http.handlers.HttpHandler; import javax.net.ssl.SSLException; import java.io.File; @@ -29,7 +29,6 @@ public interface Config { private final SslContext sslContext; private final DebugOpenCloseLog debugOpenCloseLog = new DebugOpenCloseLog(); - private final HttpHandler httpHandler = new HttpHandler(); protected HttpServerInitializer(Config config) throws SSLException { this.config = config; @@ -58,7 +57,21 @@ protected void doAccounting(TrafficCounter counter) { if (sslContext != null) channel.pipeline().addLast(sslContext.newHandler(channel.alloc())); channel.pipeline() .addLast(new HttpServerCodec()) - .addLast(new HttpObjectAggregator(Integer.MAX_VALUE)) //2gb todo decrease - .addLast(httpHandler); + .addLast(new HttpObjectAggregator(Integer.MAX_VALUE)); //2gb todo decrease + } +} + +@ChannelHandler.Sharable +class DebugOpenCloseLog extends ChannelDuplexHandler { + @Override + public void channelActive(ChannelHandlerContext ctx) { + Scribbleshare.getLogger(ctx).info("Connection opened"); + ctx.fireChannelActive(); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) { + Scribbleshare.getLogger(ctx).info("Connection closed"); + ctx.fireChannelInactive(); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/httphandlers/FormHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/FormHandler.java similarity index 85% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/httphandlers/FormHandler.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/FormHandler.java index 698a1c6d..50a85f6d 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/httphandlers/FormHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/FormHandler.java @@ -1,10 +1,9 @@ -package net.stzups.scribbleshare.server.http.httphandler.httphandlers; +package net.stzups.scribbleshare.server.http.handler; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import net.stzups.scribbleshare.server.http.exception.HttpException; -import net.stzups.scribbleshare.server.http.httphandler.HttpHandler; import net.stzups.scribbleshare.server.http.objects.Form; public abstract class FormHandler extends HttpHandler { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/HttpHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/HttpHandler.java similarity index 90% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/HttpHandler.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/HttpHandler.java index 0c896652..8c36cf7b 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/HttpHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/HttpHandler.java @@ -1,4 +1,4 @@ -package net.stzups.scribbleshare.server.http.httphandler; +package net.stzups.scribbleshare.server.http.handler; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/httphandlers/RequestHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java similarity index 83% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/httphandlers/RequestHandler.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java index d2d86c14..242fd3de 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/httphandler/httphandlers/RequestHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java @@ -1,9 +1,8 @@ -package net.stzups.scribbleshare.server.http.httphandler.httphandlers; +package net.stzups.scribbleshare.server.http.handler; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; import net.stzups.scribbleshare.server.http.exception.HttpException; -import net.stzups.scribbleshare.server.http.httphandler.HttpHandler; import net.stzups.scribbleshare.server.http.objects.Route; public abstract class RequestHandler extends HttpHandler { diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HealthcheckRequestHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HealthcheckRequestHandler.java new file mode 100644 index 00000000..57c46e24 --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HealthcheckRequestHandler.java @@ -0,0 +1,33 @@ +package net.stzups.scribbleshare.server.http.handler.handlers; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpResponseStatus; +import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; +import net.stzups.scribbleshare.server.http.handler.RequestHandler; +import net.stzups.scribbleshare.server.http.objects.Route; + +import java.net.InetSocketAddress; + +import static net.stzups.scribbleshare.server.http.HttpUtils.send; + +public class HealthcheckRequestHandler extends RequestHandler { + public HealthcheckRequestHandler() { + super("/healthcheck"); + } + + @Override + public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException { + if (request.uri().equals("/healthcheck")) { + if (!((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().isLoopbackAddress()) { + throw new NotFoundException("Healthcheck request from address which is not a loopback address"); + } else { + send(ctx, request, HttpResponseStatus.OK); + Scribbleshare.getLogger(ctx).info("Good healthcheck response"); + return; + } + } + } +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HttpAuthenticator.java similarity index 88% rename from scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HttpAuthenticator.java index 68cef11c..febe60b0 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpAuthenticator.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HttpAuthenticator.java @@ -1,12 +1,10 @@ -package net.stzups.scribbleshare.server.http.handlers; +package net.stzups.scribbleshare.server.http.handler.handlers; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageDecoder; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaders; import io.netty.util.AttributeKey; -import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.data.database.databases.HttpSessionDatabase; import net.stzups.scribbleshare.data.database.databases.PersistentHttpSessionDatabase; import net.stzups.scribbleshare.data.database.databases.UserDatabase; @@ -24,14 +22,10 @@ import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; import net.stzups.scribbleshare.server.http.exception.exceptions.UnauthorizedException; - -import java.util.List; -import java.util.logging.Level; - -import static net.stzups.scribbleshare.server.http.HttpUtils.send; +import net.stzups.scribbleshare.server.http.handler.HttpHandler; @ChannelHandler.Sharable -public class HttpAuthenticator extends MessageToMessageDecoder { +public class HttpAuthenticator extends HttpHandler { private static final AttributeKey USER = AttributeKey.valueOf(HttpAuthenticator.class, "USER"); public static AuthenticatedUserSession getUser(ChannelHandlerContext ctx) { return ctx.channel().attr(USER).get(); @@ -49,33 +43,23 @@ public HttpAuthenticator(Database database) { } public HttpAuthenticator(Database database, String uri) { + super("/"); this.database = database; this.uri = uri; } - @Override - protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List out) { - try { - handle(ctx, request); - } catch (HttpException e) { - Scribbleshare.getLogger(ctx).log(Level.WARNING, "Exception while handling HTTP request", e); - send(ctx, request, e.responseStatus()); - return; - } - out.add(request.retain()); - } - - private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { + public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { if (uri != null && !request.uri().equals(uri)) { throw new NotFoundException("Bad uri"); } AuthenticatedUserSession user = ctx.channel().attr(USER).get(); if (user != null) { - return; + return false; } ctx.channel().attr(USER).set(authenticateHttpUserSession(request, database)); + return false; } /** authenticates, or null if no authentication */ diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/DebugOpenCloseLog.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/DebugOpenCloseLog.java deleted file mode 100644 index a5352109..00000000 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/DebugOpenCloseLog.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.stzups.scribbleshare.server.http.handlers; - -import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import net.stzups.scribbleshare.Scribbleshare; - -@ChannelHandler.Sharable -public class DebugOpenCloseLog extends ChannelDuplexHandler { - @Override - public void channelActive(ChannelHandlerContext ctx) { - Scribbleshare.getLogger(ctx).info("Connection opened"); - ctx.fireChannelActive(); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) { - Scribbleshare.getLogger(ctx).info("Connection closed"); - ctx.fireChannelInactive(); - } -} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpHandler.java deleted file mode 100644 index 46fc3956..00000000 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handlers/HttpHandler.java +++ /dev/null @@ -1,51 +0,0 @@ -package net.stzups.scribbleshare.server.http.handlers; - -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageDecoder; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.HttpResponseStatus; -import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.server.http.exception.HttpException; -import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; -import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; - -import java.net.InetSocketAddress; -import java.util.List; -import java.util.logging.Level; - -import static net.stzups.scribbleshare.server.http.HttpUtils.send; - -@ChannelHandler.Sharable -public class HttpHandler extends MessageToMessageDecoder { - @Override - protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List out) { - try { - if (!handle(ctx, request)) { - out.add(request.retain()); - } - } catch (HttpException e) { - Scribbleshare.getLogger(ctx).log(Level.WARNING, "Exception while handling HTTP request", e); - send(ctx, request, e.responseStatus()); - } - } - - private boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { - Scribbleshare.getLogger(ctx).info(request.method() + " " + request.uri()); - - if (request.decoderResult().isFailure()) - throw new BadRequestException("Bad request"); - - if (request.uri().equals("/healthcheck")) { - if (!((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().isLoopbackAddress()) { - throw new NotFoundException("Healthcheck request from address which is not a loopback address"); - } else { - send(ctx, request, HttpResponseStatus.OK); - Scribbleshare.getLogger(ctx).info("Good healthcheck response"); - return true; - } - } - - return false; - } -} diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java index aed00252..8ecd1068 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java @@ -10,8 +10,10 @@ import net.stzups.scribbleshare.room.server.websocket.ClientMessageHandler; import net.stzups.scribbleshare.room.server.websocket.protocol.ClientMessageDecoder; import net.stzups.scribbleshare.room.server.websocket.protocol.ServerMessageEncoder; +import net.stzups.scribbleshare.server.http.HttpServerHandler; import net.stzups.scribbleshare.server.http.HttpServerInitializer; -import net.stzups.scribbleshare.server.http.handlers.HttpAuthenticator; +import net.stzups.scribbleshare.server.http.handler.handlers.HealthcheckRequestHandler; +import net.stzups.scribbleshare.server.http.handler.handlers.HttpAuthenticator; import javax.net.ssl.SSLException; @@ -32,7 +34,7 @@ public static ScribbleshareDatabase getDatabase(ChannelHandlerContext ctx) { private final ServerMessageEncoder serverMessageEncoder = new ServerMessageEncoder(); private final ClientMessageDecoder clientMessageDecoder = new ClientMessageDecoder(); private final ClientMessageHandler clientMessageHandler; - private final HttpAuthenticator httpAuthenticator; + private final HttpServerHandler httpServerHandler; public RoomHttpServerInitializer(Config config, ScribbleshareDatabase database) throws SSLException { @@ -40,7 +42,9 @@ public RoomHttpServerInitializer(Config config, ScribbleshareDatabase database) this.config = config; this.database = database; clientMessageHandler = new ClientMessageHandler(); - httpAuthenticator = new HttpAuthenticator(database); + httpServerHandler = new HttpServerHandler() + .addLast(new HealthcheckRequestHandler()) + .addLast(new HttpAuthenticator(database)); } @Override @@ -50,8 +54,7 @@ protected void initChannel(SocketChannel channel) { channel.attr(DATABASE).set(database); channel.pipeline() - .addLast(httpAuthenticator) - .addLast(httpExceptionHandler()) + .addLast(httpServerHandler) .addLast(new WebSocketServerCompressionHandler()) .addLast(new WebSocketServerProtocolHandler(config.getWebsocketPath(), null, true)) .addLast(serverMessageEncoder) diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java index 423f5cd6..f9286a9a 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/websocket/state/states/InitialState.java @@ -4,7 +4,7 @@ import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.room.server.websocket.state.State; -import net.stzups.scribbleshare.server.http.handlers.HttpAuthenticator; +import net.stzups.scribbleshare.server.http.handler.handlers.HttpAuthenticator; import net.stzups.scribbleshare.util.DebugString; public class InitialState extends State { From 1a2e19b94eed8d20eb83464192b4d48733bd00ba Mon Sep 17 00:00:00 2001 From: stzups Date: Thu, 27 May 2021 15:06:59 -0400 Subject: [PATCH 104/144] add explicit boolean returns to prevent no response --- .../handler/handlers/DocumentRequestHandler.java | 5 ++++- .../http/handler/handlers/FileRequestHandler.java | 13 +++++++------ .../http/handler/handlers/LoginFormHandler.java | 6 ++++-- .../http/handler/handlers/LogoutFormHandler.java | 7 +++++-- .../http/handler/handlers/RegisterFormHandler.java | 8 ++++---- .../server/http/handler/FormHandler.java | 9 ++++----- .../server/http/handler/RequestHandler.java | 5 ++--- .../handler/handlers/HealthcheckRequestHandler.java | 6 ++++-- 8 files changed, 34 insertions(+), 25 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java index f8b05b39..5a372d87 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java @@ -39,7 +39,7 @@ public DocumentRequestHandler(ScribbleshareDatabase database) { } @Override - public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException { + public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException { AuthenticatedUserSession session = HttpAuthenticator.authenticateHttpUserSession(request, database); if (session == null) { @@ -86,11 +86,13 @@ public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Route rou try { send(ctx, request, Unpooled.copyLong(database.addResource(document.getId(), new Resource(request.content())))); + return true; } catch (DatabaseException e) { throw new InternalServerException(e); } } else { send(ctx, request, HttpResponseStatus.METHOD_NOT_ALLOWED); + return true; } } else { // route.length == 4, get resource from document // does the document have this resource? @@ -128,6 +130,7 @@ public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Route rou } else { send(ctx, request, HttpResponseStatus.METHOD_NOT_ALLOWED); } + return true; } } } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java index c6d9758e..6d5c6fe5 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java @@ -73,24 +73,24 @@ public FileRequestHandler(Config config) { } @Override - public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException { + public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException { // otherwise try to serve a regular HTTP file resource if (!HttpMethod.GET.equals(request.method())) { send(ctx, request, HttpResponseStatus.METHOD_NOT_ALLOWED); - return; + return true; } // redirects if (route.path().endsWith(DEFAULT_FILE)) { // /index.html -> / sendRedirect(ctx, request, route.path().substring(0, route.path().length() - DEFAULT_FILE.length()) + route.rawQuery()); - return; + return true; } else if ((route.path() + DEFAULT_FILE_EXTENSION).endsWith(DEFAULT_FILE)) { // /index -> / sendRedirect(ctx, request, route.path().substring(0, route.path().length() - (DEFAULT_FILE.length() - DEFAULT_FILE_EXTENSION.length())) + route.rawQuery()); - return; + return true; } else if (route.path().endsWith(DEFAULT_FILE_EXTENSION)) { // /page.html -> /page sendRedirect(ctx, request, route.path().substring(0, route.path().length() - DEFAULT_FILE_EXTENSION.length()) + route.rawQuery()); - return; + return true; } // get filesystem filePath from provided filePath @@ -116,7 +116,7 @@ public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Route rou } else { throw new NotFoundException("File at path " + filePath + " not found"); } - return; + return true; } HttpHeaders headers = new DefaultHttpHeaders(); @@ -130,6 +130,7 @@ public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Route rou headers.set(HttpHeaderNames.CACHE_CONTROL, "public,max-age=" + httpCacheSeconds);//cache but revalidate if stale todo set to private cache for resources behind authentication try { sendFile(ctx, request, headers, file, mimeTypes.getMimeType(file)); + return true; } catch (IOException e) { throw new InternalServerException("Exception while sending file", e); } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LoginFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LoginFormHandler.java index 30ec94ad..f4ef1d77 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LoginFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LoginFormHandler.java @@ -36,7 +36,7 @@ public LoginFormHandler(HttpConfig config, ScribbleshareDatabase database) { } @Override - public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form) throws BadRequestException, InternalServerException { + public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form) throws BadRequestException, InternalServerException { String username = form.getText("username"); String password = form.getText("password"); boolean remember = form.getCheckbox("remember"); @@ -56,7 +56,7 @@ public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form } sendRedirect(ctx, request, LOGIN_PAGE); - return; + return true; } assert login != null : "Verified logins should never be null"; @@ -86,6 +86,8 @@ public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form throw new InternalServerException(e); } } + sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); + return true; } } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LogoutFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LogoutFormHandler.java index d70c2f1e..75237f2e 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LogoutFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LogoutFormHandler.java @@ -2,8 +2,10 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpResponseStatus; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; +import net.stzups.scribbleshare.server.http.HttpUtils; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; import net.stzups.scribbleshare.server.http.handler.FormHandler; @@ -24,7 +26,7 @@ public LogoutFormHandler(HttpConfig config, ScribbleshareDatabase database) { } @Override - public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form) throws BadRequestException, InternalServerException { + public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form) throws BadRequestException, InternalServerException { /* Form form = new Form(request);//todo necessary? @@ -72,6 +74,7 @@ public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form } sendRedirect(ctx, request, headers, LOGOUT_SUCCESS); return true;*/ - return; + HttpUtils.send(ctx, request, HttpResponseStatus.NOT_FOUND); + return true; } } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/RegisterFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/RegisterFormHandler.java index 7f30a5df..475712a9 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/RegisterFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/RegisterFormHandler.java @@ -32,7 +32,7 @@ public RegisterFormHandler(ScribbleshareDatabase database) { } @Override - public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form) throws BadRequestException, InternalServerException { + public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form) throws BadRequestException, InternalServerException { // validate @@ -44,7 +44,7 @@ public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form //todo rate limit and generic error handling sendRedirect(ctx, request, REGISTER_PAGE); - return; + return true; } User user; @@ -107,12 +107,12 @@ public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form if (!loginAdded) { Scribbleshare.getLogger(ctx).info("Tried to register with duplicate username " + username); sendRedirect(ctx, request, REGISTER_PAGE); - return; + return true; } Scribbleshare.getLogger(ctx).info("Registered with username " + username); sendRedirect(ctx, request, REGISTER_SUCCESS); - return; + return true; } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/FormHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/FormHandler.java index 50a85f6d..8cd5a632 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/FormHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/FormHandler.java @@ -14,12 +14,11 @@ protected FormHandler(String route) { @Override public final boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { if (request.method().equals(HttpMethod.POST)) { - handle(ctx, request, new Form(request)); - return true; - } else { - return false; + return handle(ctx, request, new Form(request)); } + + return false; } - public abstract void handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form) throws HttpException; + public abstract boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form) throws HttpException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java index 242fd3de..502c74c0 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java @@ -12,9 +12,8 @@ protected RequestHandler(String route) { @Override public final boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { - handle(ctx, request, new Route(request.uri())); - return true; + return handle(ctx, request, new Route(request.uri())); } - public abstract void handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException; + public abstract boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HealthcheckRequestHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HealthcheckRequestHandler.java index 57c46e24..048cade5 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HealthcheckRequestHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HealthcheckRequestHandler.java @@ -19,15 +19,17 @@ public HealthcheckRequestHandler() { } @Override - public void handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException { + public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException { if (request.uri().equals("/healthcheck")) { if (!((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().isLoopbackAddress()) { throw new NotFoundException("Healthcheck request from address which is not a loopback address"); } else { send(ctx, request, HttpResponseStatus.OK); Scribbleshare.getLogger(ctx).info("Good healthcheck response"); - return; + return true; } } + + return false; } } From 3e285c642708971d7d349397f3936b088054c5db Mon Sep 17 00:00:00 2001 From: stzups Date: Thu, 27 May 2021 15:16:46 -0400 Subject: [PATCH 105/144] clean up HttpUtils --- .../scribbleshare/server/http/HttpUtils.java | 121 ++++++++++-------- 1 file changed, 71 insertions(+), 50 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java index 8af47767..10d50f7f 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java @@ -42,39 +42,9 @@ public class HttpUtils { private static final String HTTP_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz"; private static final String HTTP_DATE_GMT_TIMEZONE = "GMT"; - public static void send(ChannelHandlerContext ctx, FullHttpRequest request, ByteBuf responseContent) { - FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/octet-stream"); - response.content().writeBytes(responseContent); - - send(ctx, request, response); - } - - public static boolean isModifiedSince(FullHttpRequest request, Timestamp lastModified) throws BadRequestException { - String ifModifiedSince = request.headers().get(HttpHeaderNames.IF_MODIFIED_SINCE); - if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) { - SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);//todo - - //round lastModified to nearest second and compare - try { - return Instant.ofEpochSecond(lastModified.getTime() / 1000).isAfter(dateFormatter.parse(ifModifiedSince).toInstant()); - } catch (ParseException e) { - throw new BadRequestException("Exception while parsing date " + ifModifiedSince, e); - } - } - - return true; - } - public static void setDateAndLastModified(HttpHeaders headers, Timestamp lastModified) {//todo - SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US); - dateFormatter.setTimeZone(TimeZone.getTimeZone(HTTP_DATE_GMT_TIMEZONE)); - Calendar time = new GregorianCalendar(); - headers.set(HttpHeaderNames.DATE, dateFormatter.format(time.getTime())); - headers.set(HttpHeaderNames.LAST_MODIFIED, dateFormatter.format(lastModified)); - } /** sets keep alive headers and returns whether the connection is keep alive */ public static boolean setKeepAlive(FullHttpRequest request, HttpResponse response) { @@ -87,8 +57,21 @@ public static boolean setKeepAlive(FullHttpRequest request, HttpResponse respons return keepAlive; } + /** + * Send {@link ByteBuf} + */ + public static void send(ChannelHandlerContext ctx, FullHttpRequest request, ByteBuf responseContent) { + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); + response.headers().set(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_OCTET_STREAM); + response.content().writeBytes(responseContent); + + send(ctx, request, response); + } + /** + * Send {@link FullHttpResponse} + */ public static void send(ChannelHandlerContext ctx, FullHttpRequest request, FullHttpResponse response) { response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes()); if (request == null) { // assume no keep alive @@ -106,6 +89,9 @@ public static void send(ChannelHandlerContext ctx, FullHttpRequest request, Full } } + /** + * Send {@link HttpResponse} followed by {@link HttpChunkedInput} + */ public static void send(ChannelHandlerContext ctx, FullHttpRequest request, HttpResponse response, HttpChunkedInput httpChunkedInput) { response.headers().set(HttpHeaderNames.CONTENT_LENGTH, httpChunkedInput.length()); @@ -123,6 +109,18 @@ public static void send(ChannelHandlerContext ctx, FullHttpRequest request, Http } } + /** + * Send {@link HttpResponseStatus} + */ + public static void send(ChannelHandlerContext ctx, FullHttpRequest request, HttpResponseStatus status) { + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, Unpooled.EMPTY_BUFFER); + + send(ctx, request, response); + } + + /** + * Send redirect to a new URI + */ public static void sendRedirect(ChannelHandlerContext ctx, FullHttpRequest request, HttpHeaders headers, String newUri) { FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.MOVED_PERMANENTLY, Unpooled.EMPTY_BUFFER); response.headers().set(headers); @@ -131,17 +129,52 @@ public static void sendRedirect(ChannelHandlerContext ctx, FullHttpRequest reque send(ctx, request, response); } + /** + * Send redirect to a new URI + */ public static void sendRedirect(ChannelHandlerContext ctx, FullHttpRequest request, String newUri) { sendRedirect(ctx, request, EmptyHttpHeaders.INSTANCE, newUri); } - public static void send(ChannelHandlerContext ctx, FullHttpRequest request, HttpResponseStatus status) { - FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, Unpooled.EMPTY_BUFFER); + /** + * Send {@link ChunkedInput} with {@link HttpHeaders} + */ + public static void sendChunkedResource(ChannelHandlerContext ctx, FullHttpRequest request, HttpHeaders headers, ChunkedInput chunkedInput) { + HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); + response.headers().set(headers); - send(ctx, request, response); + send(ctx, request, response, new HttpChunkedInput(chunkedInput)); + } + + public static void setDateAndLastModified(HttpHeaders headers, Timestamp lastModified) {//todo + SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US); + dateFormatter.setTimeZone(TimeZone.getTimeZone(HTTP_DATE_GMT_TIMEZONE)); + + Calendar time = new GregorianCalendar(); + headers.set(HttpHeaderNames.DATE, dateFormatter.format(time.getTime())); + + headers.set(HttpHeaderNames.LAST_MODIFIED, dateFormatter.format(lastModified)); + } + + public static boolean isModifiedSince(FullHttpRequest request, Timestamp lastModified) throws BadRequestException { + String ifModifiedSince = request.headers().get(HttpHeaderNames.IF_MODIFIED_SINCE); + if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) { + SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);//todo + + //round lastModified to nearest second and compare + try { + return Instant.ofEpochSecond(lastModified.getTime() / 1000).isAfter(dateFormatter.parse(ifModifiedSince).toInstant()); + } catch (ParseException e) { + throw new BadRequestException("Exception while parsing date " + ifModifiedSince, e); + } + } + + return true; } - /** sends if stale, otherwise sends not modified */ + /** + * Send {@link ChunkedInput} if stale, or {@link HttpResponseStatus#NOT_MODIFIED} if fresh + */ public static void sendChunkedResource(ChannelHandlerContext ctx, FullHttpRequest request, HttpHeaders headers, ChunkedInput chunkedInput, Timestamp lastModified) throws BadRequestException { setDateAndLastModified(headers, lastModified); if (isModifiedSince(request, lastModified)) { @@ -156,15 +189,9 @@ public static void sendChunkedResource(ChannelHandlerContext ctx, FullHttpReques } } - /** sends resource with headers */ - public static void sendChunkedResource(ChannelHandlerContext ctx, FullHttpRequest request, HttpHeaders headers, ChunkedInput chunkedInput) { - HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); - response.headers().set(headers); - - send(ctx, request, response, new HttpChunkedInput(chunkedInput)); - } - - /** make sure the file being sent is valid */ + /** + * Send {@link File} with respect to caching + */ public static void sendFile(ChannelHandlerContext ctx, FullHttpRequest request, HttpHeaders headers, File file, String mimeType) throws IOException, BadRequestException { try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r")) { long fileLength = randomAccessFile.length(); @@ -181,14 +208,8 @@ public static void sendFile(ChannelHandlerContext ctx, FullHttpRequest request, } } + //todo unused? public static void setCookie(HttpHeaders headers, Cookie cookie) { headers.add(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.STRICT.encode(cookie)); } - - - - - - - } From b62fa2d3175563ae21092a616864f4ad44686c30 Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 28 May 2021 09:47:16 -0400 Subject: [PATCH 106/144] move package --- .../backend/ScribbleshareBackendConfig.java | 2 +- .../backend/server/BackendHttpServerInitializer.java | 10 +++++----- .../handler => }/handlers/DocumentRequestHandler.java | 2 +- .../handler => }/handlers/FileRequestHandler.java | 2 +- .../{http/handler => }/handlers/LoginFormHandler.java | 2 +- .../{http/handler => }/handlers/LogoutFormHandler.java | 2 +- .../handler => }/handlers/RegisterFormHandler.java | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) rename scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/{http/handler => }/handlers/DocumentRequestHandler.java (98%) rename scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/{http/handler => }/handlers/FileRequestHandler.java (99%) rename scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/{http/handler => }/handlers/LoginFormHandler.java (98%) rename scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/{http/handler => }/handlers/LogoutFormHandler.java (98%) rename scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/{http/handler => }/handlers/RegisterFormHandler.java (98%) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfig.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfig.java index aee199cb..f92a7941 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfig.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfig.java @@ -1,7 +1,7 @@ package net.stzups.scribbleshare.backend; import net.stzups.scribbleshare.ScribbleshareConfig; -import net.stzups.scribbleshare.backend.server.http.handler.handlers.FileRequestHandler; +import net.stzups.scribbleshare.backend.server.handlers.FileRequestHandler; public interface ScribbleshareBackendConfig extends ScribbleshareConfig, FileRequestHandler.Config { diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java index 47869c6e..b65b4b0a 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java @@ -5,11 +5,11 @@ import io.netty.handler.codec.http.HttpContentCompressor; import io.netty.handler.stream.ChunkedWriteHandler; import net.stzups.scribbleshare.backend.ScribbleshareBackendConfig; -import net.stzups.scribbleshare.backend.server.http.handler.handlers.DocumentRequestHandler; -import net.stzups.scribbleshare.backend.server.http.handler.handlers.FileRequestHandler; -import net.stzups.scribbleshare.backend.server.http.handler.handlers.LoginFormHandler; -import net.stzups.scribbleshare.backend.server.http.handler.handlers.LogoutFormHandler; -import net.stzups.scribbleshare.backend.server.http.handler.handlers.RegisterFormHandler; +import net.stzups.scribbleshare.backend.server.handlers.DocumentRequestHandler; +import net.stzups.scribbleshare.backend.server.handlers.FileRequestHandler; +import net.stzups.scribbleshare.backend.server.handlers.LoginFormHandler; +import net.stzups.scribbleshare.backend.server.handlers.LogoutFormHandler; +import net.stzups.scribbleshare.backend.server.handlers.RegisterFormHandler; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.server.http.HttpServerHandler; import net.stzups.scribbleshare.server.http.HttpServerInitializer; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/DocumentRequestHandler.java similarity index 98% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java rename to scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/DocumentRequestHandler.java index 5a372d87..28e55491 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/DocumentRequestHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/DocumentRequestHandler.java @@ -1,4 +1,4 @@ -package net.stzups.scribbleshare.backend.server.http.handler.handlers; +package net.stzups.scribbleshare.backend.server.handlers; import io.netty.buffer.ByteBufInputStream; import io.netty.buffer.Unpooled; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/FileRequestHandler.java similarity index 99% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java rename to scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/FileRequestHandler.java index 6d5c6fe5..221df91f 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/FileRequestHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/FileRequestHandler.java @@ -1,4 +1,4 @@ -package net.stzups.scribbleshare.backend.server.http.handler.handlers; +package net.stzups.scribbleshare.backend.server.handlers; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.DefaultHttpHeaders; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LoginFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginFormHandler.java similarity index 98% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LoginFormHandler.java rename to scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginFormHandler.java index f4ef1d77..73a2ad7e 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LoginFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginFormHandler.java @@ -1,4 +1,4 @@ -package net.stzups.scribbleshare.backend.server.http.handler.handlers; +package net.stzups.scribbleshare.backend.server.handlers; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.DefaultHttpHeaders; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LogoutFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LogoutFormHandler.java similarity index 98% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LogoutFormHandler.java rename to scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LogoutFormHandler.java index 75237f2e..81087e2f 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/LogoutFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LogoutFormHandler.java @@ -1,4 +1,4 @@ -package net.stzups.scribbleshare.backend.server.http.handler.handlers; +package net.stzups.scribbleshare.backend.server.handlers; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/RegisterFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/RegisterFormHandler.java similarity index 98% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/RegisterFormHandler.java rename to scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/RegisterFormHandler.java index 475712a9..8bfdb524 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/http/handler/handlers/RegisterFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/RegisterFormHandler.java @@ -1,4 +1,4 @@ -package net.stzups.scribbleshare.backend.server.http.handler.handlers; +package net.stzups.scribbleshare.backend.server.handlers; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; From a826a5967560569e16131229651c025a63557c02 Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 28 May 2021 09:49:03 -0400 Subject: [PATCH 107/144] move FileRequestHandler --- .../scribbleshare/backend/ScribbleshareBackendConfig.java | 2 +- .../backend/server/BackendHttpServerInitializer.java | 2 +- .../server/http/handler}/handlers/FileRequestHandler.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename {scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server => scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler}/handlers/FileRequestHandler.java (99%) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfig.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfig.java index f92a7941..bcb02d7e 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfig.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/ScribbleshareBackendConfig.java @@ -1,7 +1,7 @@ package net.stzups.scribbleshare.backend; import net.stzups.scribbleshare.ScribbleshareConfig; -import net.stzups.scribbleshare.backend.server.handlers.FileRequestHandler; +import net.stzups.scribbleshare.server.http.handler.handlers.FileRequestHandler; public interface ScribbleshareBackendConfig extends ScribbleshareConfig, FileRequestHandler.Config { diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java index b65b4b0a..90a753e5 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java @@ -6,13 +6,13 @@ import io.netty.handler.stream.ChunkedWriteHandler; import net.stzups.scribbleshare.backend.ScribbleshareBackendConfig; import net.stzups.scribbleshare.backend.server.handlers.DocumentRequestHandler; -import net.stzups.scribbleshare.backend.server.handlers.FileRequestHandler; import net.stzups.scribbleshare.backend.server.handlers.LoginFormHandler; import net.stzups.scribbleshare.backend.server.handlers.LogoutFormHandler; import net.stzups.scribbleshare.backend.server.handlers.RegisterFormHandler; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.server.http.HttpServerHandler; import net.stzups.scribbleshare.server.http.HttpServerInitializer; +import net.stzups.scribbleshare.server.http.handler.handlers.FileRequestHandler; import net.stzups.scribbleshare.server.http.handler.handlers.HealthcheckRequestHandler; import javax.net.ssl.SSLException; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/FileRequestHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/FileRequestHandler.java similarity index 99% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/FileRequestHandler.java rename to scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/FileRequestHandler.java index 221df91f..ddb0d32a 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/FileRequestHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/FileRequestHandler.java @@ -1,4 +1,4 @@ -package net.stzups.scribbleshare.backend.server.handlers; +package net.stzups.scribbleshare.server.http.handler.handlers; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.DefaultHttpHeaders; From 4f8c54045b75b70fa6935ea68c8c2f086530d011 Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 28 May 2021 09:55:13 -0400 Subject: [PATCH 108/144] tiny change --- .../server/http/handler/handlers/FileRequestHandler.java | 2 +- .../java/net/stzups/scribbleshare/server/http/objects/Uri.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/FileRequestHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/FileRequestHandler.java index ddb0d32a..63969529 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/FileRequestHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/FileRequestHandler.java @@ -152,7 +152,7 @@ private static String getFilePath(String path) throws BadRequestException { || !ALLOWED_PATH.matcher(path).matches()) throw new BadRequestException("File path contains illegal characters"); - if (path.endsWith(File.separator)) { // / -> index.html + if (path.endsWith(File.separator)) { // / -> /index.html path = path + DEFAULT_FILE; } else if (path.lastIndexOf(File.separator) > path.lastIndexOf(".")) { // /page -> /page.html path = path + DEFAULT_FILE_EXTENSION; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Uri.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Uri.java index 3dd173cd..09941145 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Uri.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/Uri.java @@ -7,7 +7,7 @@ public class Uri { // abc-ABC_123.file - public static final String FILE_NAME_REGEX = "a-zA-Z0-9-_"; + public static final String FILE_NAME_REGEX = "a-zA-Z0-9-"; private static final Pattern ALLOWED_CHARACTERS = Pattern.compile("^[/." + Query.QUERY_REGEX + FILE_NAME_REGEX + "]+$"); final String uri; From d9185659b66430f7569da9b2d66d506c2c2e0388 Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 28 May 2021 09:57:43 -0400 Subject: [PATCH 109/144] simplified exception --- .../scribbleshare/server/http/objects/RenderPage.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/RenderPage.java diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/RenderPage.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/RenderPage.java new file mode 100644 index 00000000..784955df --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/RenderPage.java @@ -0,0 +1,11 @@ +package net.stzups.scribbleshare.server.http.objects; + +import java.io.File; + +public class RenderPage { + private File file; + + public RenderPage(File file) { + + } +} From f36af40a1b6633d2ad2045696470cd86880c43e0 Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 28 May 2021 09:57:51 -0400 Subject: [PATCH 110/144] oops --- .../net/stzups/scribbleshare/server/http/HttpUtils.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java index 10d50f7f..dbec7215 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpUtils.java @@ -22,8 +22,8 @@ import io.netty.handler.codec.http.cookie.ServerCookieEncoder; import io.netty.handler.stream.ChunkedFile; import io.netty.handler.stream.ChunkedInput; -import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; import java.io.File; import java.io.FileNotFoundException; @@ -192,13 +192,11 @@ public static void sendChunkedResource(ChannelHandlerContext ctx, FullHttpReques /** * Send {@link File} with respect to caching */ - public static void sendFile(ChannelHandlerContext ctx, FullHttpRequest request, HttpHeaders headers, File file, String mimeType) throws IOException, BadRequestException { + public static void sendFile(ChannelHandlerContext ctx, FullHttpRequest request, HttpHeaders headers, File file, String mimeType) throws IOException, BadRequestException, NotFoundException { try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r")) { long fileLength = randomAccessFile.length(); if (mimeType == null) { - Scribbleshare.getLogger(ctx).warning("Unknown MIME type for file " + file.getName()); - send(ctx, request, HttpResponseStatus.NOT_FOUND); - return; + throw new NotFoundException("Unknown MIME type for file " + file.getName()); } headers.set(HttpHeaderNames.CONTENT_TYPE, mimeType); From 0eee55ab6cd5399d5beb3b112f732d56df80f89f Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 28 May 2021 12:54:20 -0400 Subject: [PATCH 111/144] fix npe --- .../scribbleshare/server/http/objects/RenderPage.java | 11 ----------- .../net/stzups/scribbleshare/util/DebugString.java | 4 ++-- 2 files changed, 2 insertions(+), 13 deletions(-) delete mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/RenderPage.java diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/RenderPage.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/RenderPage.java deleted file mode 100644 index 784955df..00000000 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/objects/RenderPage.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.stzups.scribbleshare.server.http.objects; - -import java.io.File; - -public class RenderPage { - private File file; - - public RenderPage(File file) { - - } -} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java index b1fef663..bc1d6cdc 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/DebugString.java @@ -43,10 +43,10 @@ private Property(String name, Object value) { @Override public String toString() { String value; - if (this.value.getClass().isArray()) { + if (this.value != null && this.value.getClass().isArray()) { value = Arrays.toString((Object[]) this.value); } else { - value = this.value.toString(); + value = "" + this.value; } if (name == null) { From 13c716edfa6e9e3f09389b3bb2fdf7563b93aca0 Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 28 May 2021 13:02:58 -0400 Subject: [PATCH 112/144] fix logs instead of throws --- .../database/implementations/PostgresDatabase.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index 73923c7c..da4ce02f 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -31,7 +31,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Random; -import java.util.logging.Level; public class PostgresDatabase implements AutoCloseable, ScribbleshareDatabase { @Override @@ -46,8 +45,7 @@ public Login getLogin(String username) throws DatabaseException { } } } catch (SQLException e) { - Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting login for username " + username, e); - return null; + throw new DatabaseException("Exception while getting login for username " + username, e); } } @@ -138,8 +136,7 @@ public void addUser(User user) throws DatabaseException { resultSet.getString("username")); } } catch (SQLException e) { - Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + User.class.getSimpleName() + " with id " + id, e); - return null; + throw new DatabaseException("Exception while getting " + User.class.getSimpleName() + " with id " + id, e); } } @@ -249,8 +246,7 @@ public InviteCode getInviteCode(String code) throws DatabaseException {//gets a } } } catch (SQLException e) { - Scribbleshare.getLogger().log(Level.WARNING, "Exception while getting " + InviteCode.class.getSimpleName() + " code for " + document, e); - return null; + throw new DatabaseException("Exception while getting " + InviteCode.class.getSimpleName() + " code for " + document, e); } //invite code does not already exist, so a new one must be made InviteCode inviteCode = new InviteCode(document); From e5bbc4cdd1e8e8762f4b4cacaa9ded8f0063fa0b Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 28 May 2021 13:05:26 -0400 Subject: [PATCH 113/144] start to add login api --- .../server/BackendHttpServerInitializer.java | 4 +- ...mHandler.java => LoginRequestHandler.java} | 55 ++++++++++++------- .../server/handlers/LogoutFormHandler.java | 3 +- .../server/handlers/RegisterFormHandler.java | 10 ++-- .../scribbleshare-frontend/src/login.html | 2 +- .../src/scripts/Environment.ts | 2 +- .../src/scripts/Login.ts | 11 ++++ .../src/scripts/api/Api.ts | 36 ++++++++++++ .../api/protocol/request/ApiRequest.ts | 6 ++ .../protocol/request/requests/LoginRequest.ts | 25 +++++++++ .../api/protocol/response/ApiResponse.ts | 3 + .../protocol/response/error/ResponseError.ts | 7 +++ .../response/responses/LoginResponse.ts | 8 +++ .../src/scripts/main.ts | 3 +- .../src/scripts/protocol/ByteBuffer.ts | 8 +++ 15 files changed, 152 insertions(+), 31 deletions(-) rename scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/{LoginFormHandler.java => LoginRequestHandler.java} (64%) create mode 100644 scribbleshare-app/scribbleshare-frontend/src/scripts/Login.ts create mode 100644 scribbleshare-app/scribbleshare-frontend/src/scripts/api/Api.ts create mode 100644 scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/request/ApiRequest.ts create mode 100644 scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/request/requests/LoginRequest.ts create mode 100644 scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/response/ApiResponse.ts create mode 100644 scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/response/error/ResponseError.ts create mode 100644 scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/response/responses/LoginResponse.ts diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java index 90a753e5..b5c2f503 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java @@ -6,7 +6,7 @@ import io.netty.handler.stream.ChunkedWriteHandler; import net.stzups.scribbleshare.backend.ScribbleshareBackendConfig; import net.stzups.scribbleshare.backend.server.handlers.DocumentRequestHandler; -import net.stzups.scribbleshare.backend.server.handlers.LoginFormHandler; +import net.stzups.scribbleshare.backend.server.handlers.LoginRequestHandler; import net.stzups.scribbleshare.backend.server.handlers.LogoutFormHandler; import net.stzups.scribbleshare.backend.server.handlers.RegisterFormHandler; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; @@ -26,7 +26,7 @@ public BackendHttpServerInitializer(ScribbleshareBackendConfig config, Scribbles httpServerHandler = new HttpServerHandler() .addLast(new HealthcheckRequestHandler()) .addLast(new DocumentRequestHandler(database)) - .addLast(new LoginFormHandler(config, database)) + .addLast(new LoginRequestHandler(config, database)) .addLast(new LogoutFormHandler(config, database)) .addLast(new RegisterFormHandler(database)) .addLast(new FileRequestHandler(config)); diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginRequestHandler.java similarity index 64% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginFormHandler.java rename to scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginRequestHandler.java index 73a2ad7e..2f31d074 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginRequestHandler.java @@ -1,9 +1,11 @@ package net.stzups.scribbleshare.backend.server.handlers; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.DefaultHttpHeaders; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpResponseStatus; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.database.exception.DatabaseException; @@ -12,50 +14,59 @@ import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; import net.stzups.scribbleshare.data.objects.authentication.http.PersistentHttpUserSession; import net.stzups.scribbleshare.data.objects.authentication.login.Login; -import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.server.http.exception.HttpException; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; -import net.stzups.scribbleshare.server.http.handler.FormHandler; -import net.stzups.scribbleshare.server.http.objects.Form; +import net.stzups.scribbleshare.server.http.handler.RequestHandler; +import net.stzups.scribbleshare.server.http.objects.Route; import java.nio.charset.StandardCharsets; -import static net.stzups.scribbleshare.server.http.HttpUtils.sendRedirect; +import static net.stzups.scribbleshare.server.http.HttpUtils.send; -public class LoginFormHandler extends FormHandler { - static final String LOGIN_PAGE = "/login"; // the login page, where login requests should come from +public class LoginRequestHandler extends RequestHandler { + private static class LoginRequest { + private final String username; + private final String password; + private final boolean remember; + + LoginRequest(ByteBuf byteBuf) { + username = readString(byteBuf); + password = readString(byteBuf); + remember = byteBuf.readBoolean(); + } + } + + static final String LOGIN_PAGE = "/"; // the login page, where login requests should come from private static final String LOGIN_PATH = PersistentHttpUserSession.LOGIN_PATH; // where login requests should go - private static final String LOGIN_SUCCESS = "/"; // redirect for a good login, should be the main page private final HttpConfig config; private final ScribbleshareDatabase database; - public LoginFormHandler(HttpConfig config, ScribbleshareDatabase database) { + public LoginRequestHandler(HttpConfig config, ScribbleshareDatabase database) { super(LOGIN_PATH); this.database = database; this.config = config; } @Override - public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form) throws BadRequestException, InternalServerException { - String username = form.getText("username"); - String password = form.getText("password"); - boolean remember = form.getCheckbox("remember"); + public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException { + LoginRequest loginRequest = new LoginRequest(request.content()); Login login; try { - login = database.getLogin(username); + login = database.getLogin(loginRequest.username); } catch (DatabaseException e) { throw new InternalServerException(e); } - if (!Login.verify(login, password.getBytes(StandardCharsets.UTF_8))) { + if (!Login.verify(login, loginRequest.password.getBytes(StandardCharsets.UTF_8))) { //todo rate limit and generic error handling if (login == null) { - Scribbleshare.getLogger(ctx).info("Failed login attempt with bad username " + username); + Scribbleshare.getLogger(ctx).info("Failed login attempt with bad username " + loginRequest.username); } else { - Scribbleshare.getLogger(ctx).info("Failed login attempt with bad password for username " + username); + Scribbleshare.getLogger(ctx).info("Failed login attempt with bad password for username " + loginRequest.username); } - sendRedirect(ctx, request, LOGIN_PAGE); + send(ctx, request, HttpResponseStatus.UNAUTHORIZED); return true; } @@ -78,7 +89,7 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Form f } catch (DatabaseException e) { throw new InternalServerException(e); } - if (remember) { + if (loginRequest.remember) { PersistentHttpUserSession persistentHttpUserSession = new PersistentHttpUserSession(config, userSession, httpHeaders); try { database.addPersistentHttpUserSession(persistentHttpUserSession); @@ -87,7 +98,11 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Form f } } - sendRedirect(ctx, request, httpHeaders, LOGIN_SUCCESS); + send(ctx, request, HttpResponseStatus.OK); return true; } -} + + private static String readString(ByteBuf byteBuf) { + return byteBuf.readCharSequence(byteBuf.readUnsignedByte(), StandardCharsets.UTF_8).toString(); + } +} \ No newline at end of file diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LogoutFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LogoutFormHandler.java index 81087e2f..748a3bc1 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LogoutFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LogoutFormHandler.java @@ -12,9 +12,8 @@ import net.stzups.scribbleshare.server.http.objects.Form; public class LogoutFormHandler extends FormHandler { - private static final String LOGOUT_PAGE = "/logout"; // the logout page, where logout requests should come from + private static final String LOGOUT_PAGE = "/"; // the logout page, where logout requests should come from private static final String LOGOUT_PATH = "/logout"; // where logout requests should go - private static final String LOGOUT_SUCCESS = LoginFormHandler.LOGIN_PAGE; // redirect for a good logout, should be the login page private final HttpConfig config; private final ScribbleshareDatabase database; diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/RegisterFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/RegisterFormHandler.java index 8bfdb524..a82079a8 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/RegisterFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/RegisterFormHandler.java @@ -2,6 +2,7 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpResponseStatus; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.database.exception.DatabaseException; @@ -17,12 +18,13 @@ import java.nio.charset.StandardCharsets; +import static net.stzups.scribbleshare.server.http.HttpUtils.send; import static net.stzups.scribbleshare.server.http.HttpUtils.sendRedirect; public class RegisterFormHandler extends FormHandler { - private static final String REGISTER_PAGE = "/register"; // the register page, where register requests should come from + private static final String REGISTER_PAGE = "/"; // the register page, where register requests should come from private static final String REGISTER_PATH = "/register"; // where register requests should go - private static final String REGISTER_SUCCESS = LoginFormHandler.LOGIN_PAGE; // redirect for a good register, should be the login page + private static final String REGISTER_SUCCESS = LoginRequestHandler.LOGIN_PAGE; // redirect for a good register, should be the login page private final ScribbleshareDatabase database; @@ -106,13 +108,13 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Form f } if (!loginAdded) { Scribbleshare.getLogger(ctx).info("Tried to register with duplicate username " + username); - sendRedirect(ctx, request, REGISTER_PAGE); + send(ctx, request, HttpResponseStatus.CONFLICT); return true; } Scribbleshare.getLogger(ctx).info("Registered with username " + username); - sendRedirect(ctx, request, REGISTER_SUCCESS); + send(ctx, request, HttpResponseStatus.OK); return true; } } diff --git a/scribbleshare-app/scribbleshare-frontend/src/login.html b/scribbleshare-app/scribbleshare-frontend/src/login.html index 68b840b1..8b77fd99 100644 --- a/scribbleshare-app/scribbleshare-frontend/src/login.html +++ b/scribbleshare-app/scribbleshare-frontend/src/login.html @@ -1,7 +1,7 @@ - Login + LoginRequest
diff --git a/scribbleshare-app/scribbleshare-frontend/src/scripts/Environment.ts b/scribbleshare-app/scribbleshare-frontend/src/scripts/Environment.ts index 906150dd..2079c9ea 100644 --- a/scribbleshare-app/scribbleshare-frontend/src/scripts/Environment.ts +++ b/scribbleshare-app/scribbleshare-frontend/src/scripts/Environment.ts @@ -5,7 +5,7 @@ interface Environment { class DevEnvironment implements Environment { getApiHost(): string { - return 'http://localhost'; + return 'http://localhost:3456'; } getWebsocketHost(): string { diff --git a/scribbleshare-app/scribbleshare-frontend/src/scripts/Login.ts b/scribbleshare-app/scribbleshare-frontend/src/scripts/Login.ts new file mode 100644 index 00000000..d71bf79a --- /dev/null +++ b/scribbleshare-app/scribbleshare-frontend/src/scripts/Login.ts @@ -0,0 +1,11 @@ +import api from "./api/Api.js" +import LoginRequest from "./api/protocol/request/requests/LoginRequest.js"; +import ResponseError from "./api/protocol/response/error/ResponseError.js"; + +api.login(new LoginRequest("test", "test", true)) + .catch((requestError: ResponseError) => { + console.log(requestError); + }) + .finally(() => { + console.log(this); + }); \ No newline at end of file diff --git a/scribbleshare-app/scribbleshare-frontend/src/scripts/api/Api.ts b/scribbleshare-app/scribbleshare-frontend/src/scripts/api/Api.ts new file mode 100644 index 00000000..2e2978cc --- /dev/null +++ b/scribbleshare-app/scribbleshare-frontend/src/scripts/api/Api.ts @@ -0,0 +1,36 @@ +import ByteBuffer from "../protocol/ByteBuffer.js"; +import LoginRequest from "./protocol/request/requests/LoginRequest.js"; +import ResponseError from "./protocol/response/error/ResponseError.js" +import LoginResponse from "./protocol/response/responses/LoginResponse.js"; +import Environment from "../Environment.js" + +class Api { + uri: string; + + constructor(uri: string) { + this.uri = uri; + } + + async login(loginRequest: LoginRequest): Promise { + return new Promise((resolve, reject) => { + let request = new XMLHttpRequest(); + request.responseType = 'arraybuffer'; + request.open('POST', this.uri + loginRequest.getRoute()); + + request.addEventListener('load', (event) => { + if (request.status == 200) { + resolve(new LoginResponse(new ByteBuffer(request.response))); + } else { + reject(new ResponseError(request.status)) + } + }); + + let byteBuffer = new ByteBuffer(); + loginRequest.serialize(byteBuffer); + request.send(byteBuffer.getBuffer()); + }) + } +} + +export default new Api(Environment.getApiHost()); + diff --git a/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/request/ApiRequest.ts b/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/request/ApiRequest.ts new file mode 100644 index 00000000..3abc3274 --- /dev/null +++ b/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/request/ApiRequest.ts @@ -0,0 +1,6 @@ +import ByteBuffer from "../../../protocol/ByteBuffer.js"; + +export default abstract class ApiRequest { + abstract getRoute(): string; + abstract serialize(byteBuffer: ByteBuffer): void; +} \ No newline at end of file diff --git a/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/request/requests/LoginRequest.ts b/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/request/requests/LoginRequest.ts new file mode 100644 index 00000000..f978ddc6 --- /dev/null +++ b/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/request/requests/LoginRequest.ts @@ -0,0 +1,25 @@ +import ByteBuffer from "../../../../protocol/ByteBuffer.js"; +import ApiRequest from "../ApiRequest.js" + +export default class LoginRequest extends ApiRequest { + username: string; + password: string; + remember: boolean; + + constructor(username: string, password: string, remember: boolean) { + super(); + this.username = username; + this.password = password; + this.remember = remember; + } + + getRoute(): string { + return "/login"; + } + + serialize(byteBuffer: ByteBuffer): void { + byteBuffer.writeString8(this.username); + byteBuffer.writeString8(this.password); + byteBuffer.writeBoolean(this.remember); + } +} \ No newline at end of file diff --git a/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/response/ApiResponse.ts b/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/response/ApiResponse.ts new file mode 100644 index 00000000..be86ad60 --- /dev/null +++ b/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/response/ApiResponse.ts @@ -0,0 +1,3 @@ +export default class ApiResponse { + +} \ No newline at end of file diff --git a/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/response/error/ResponseError.ts b/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/response/error/ResponseError.ts new file mode 100644 index 00000000..9534d4ea --- /dev/null +++ b/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/response/error/ResponseError.ts @@ -0,0 +1,7 @@ +export default class HttpError { + responseCode: number; + + constructor(responseCode: number) { + this.responseCode = responseCode; + } +} \ No newline at end of file diff --git a/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/response/responses/LoginResponse.ts b/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/response/responses/LoginResponse.ts new file mode 100644 index 00000000..c444f7c9 --- /dev/null +++ b/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/response/responses/LoginResponse.ts @@ -0,0 +1,8 @@ +import ApiResponse from "../ApiResponse.js"; +import ByteBuffer from "../../../../protocol/ByteBuffer.js"; + +export default class LoginResponse extends ApiResponse { + constructor(byteBuffer: ByteBuffer) { + super(); + } +} \ No newline at end of file diff --git a/scribbleshare-app/scribbleshare-frontend/src/scripts/main.ts b/scribbleshare-app/scribbleshare-frontend/src/scripts/main.ts index f3f18412..fc050736 100644 --- a/scribbleshare-app/scribbleshare-frontend/src/scripts/main.ts +++ b/scribbleshare-app/scribbleshare-frontend/src/scripts/main.ts @@ -1,2 +1,3 @@ import './Document.js'; -import './FileUpload.js' \ No newline at end of file +import './FileUpload.js' +import './Login.js' \ No newline at end of file diff --git a/scribbleshare-app/scribbleshare-frontend/src/scripts/protocol/ByteBuffer.ts b/scribbleshare-app/scribbleshare-frontend/src/scripts/protocol/ByteBuffer.ts index fc463220..7ee1ea20 100644 --- a/scribbleshare-app/scribbleshare-frontend/src/scripts/protocol/ByteBuffer.ts +++ b/scribbleshare-app/scribbleshare-frontend/src/scripts/protocol/ByteBuffer.ts @@ -73,6 +73,10 @@ export default class ByteBuffer { return btoa(this.readString8()); } + readBoolean() { + return this.readUint8() == 1; + } + readInt8() { let value = this.view.getInt8(this.position); this.position += 1; @@ -171,6 +175,10 @@ export default class ByteBuffer { this.writeString32(atob(value)); } + writeBoolean(value: boolean) { + this.writeUint8(value ? 1 : 0); + } + writeInt8(value: number) { this.checkResize(1); this.view.setInt8(this.position, value); From 3dfd4c9fd07b658a25552f6966b9f76c2c4896bd Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 28 May 2021 14:23:13 -0400 Subject: [PATCH 114/144] add register api --- .../server/BackendHttpServerInitializer.java | 4 +- .../server/handlers/LoginRequestHandler.java | 2 +- ...ndler.java => RegisterRequestHandler.java} | 43 +++++++++++-------- .../src/scripts/Login.ts | 27 +++++++++--- .../src/scripts/api/Api.ts | 24 ++++++++++- .../request/requests/RegisterRequest.ts | 22 ++++++++++ .../response/responses/RegisterResponse.ts | 8 ++++ 7 files changed, 104 insertions(+), 26 deletions(-) rename scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/{RegisterFormHandler.java => RegisterRequestHandler.java} (76%) create mode 100644 scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/request/requests/RegisterRequest.ts create mode 100644 scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/response/responses/RegisterResponse.ts diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java index b5c2f503..cba9706a 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java @@ -8,7 +8,7 @@ import net.stzups.scribbleshare.backend.server.handlers.DocumentRequestHandler; import net.stzups.scribbleshare.backend.server.handlers.LoginRequestHandler; import net.stzups.scribbleshare.backend.server.handlers.LogoutFormHandler; -import net.stzups.scribbleshare.backend.server.handlers.RegisterFormHandler; +import net.stzups.scribbleshare.backend.server.handlers.RegisterRequestHandler; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.server.http.HttpServerHandler; import net.stzups.scribbleshare.server.http.HttpServerInitializer; @@ -28,7 +28,7 @@ public BackendHttpServerInitializer(ScribbleshareBackendConfig config, Scribbles .addLast(new DocumentRequestHandler(database)) .addLast(new LoginRequestHandler(config, database)) .addLast(new LogoutFormHandler(config, database)) - .addLast(new RegisterFormHandler(database)) + .addLast(new RegisterRequestHandler(database)) .addLast(new FileRequestHandler(config)); } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginRequestHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginRequestHandler.java index 2f31d074..40c6da74 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginRequestHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginRequestHandler.java @@ -102,7 +102,7 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route return true; } - private static String readString(ByteBuf byteBuf) { + static String readString(ByteBuf byteBuf) { return byteBuf.readCharSequence(byteBuf.readUnsignedByte(), StandardCharsets.UTF_8).toString(); } } \ No newline at end of file diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/RegisterFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/RegisterRequestHandler.java similarity index 76% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/RegisterFormHandler.java rename to scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/RegisterRequestHandler.java index a82079a8..3a36365a 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/RegisterFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/RegisterRequestHandler.java @@ -1,5 +1,6 @@ package net.stzups.scribbleshare.backend.server.handlers; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; @@ -11,35 +12,43 @@ import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.login.Login; -import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; +import net.stzups.scribbleshare.server.http.exception.HttpException; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; -import net.stzups.scribbleshare.server.http.handler.FormHandler; -import net.stzups.scribbleshare.server.http.objects.Form; - -import java.nio.charset.StandardCharsets; +import net.stzups.scribbleshare.server.http.handler.RequestHandler; +import net.stzups.scribbleshare.server.http.objects.Route; +import static net.stzups.scribbleshare.backend.server.handlers.LoginRequestHandler.readString; import static net.stzups.scribbleshare.server.http.HttpUtils.send; import static net.stzups.scribbleshare.server.http.HttpUtils.sendRedirect; -public class RegisterFormHandler extends FormHandler { +public class RegisterRequestHandler extends RequestHandler { + private static class RegisterRequest { + private final String username; + private final byte[] password; + + RegisterRequest(ByteBuf byteBuf) { + username = readString(byteBuf); + password = new byte[byteBuf.readUnsignedByte()]; + byteBuf.readBytes(password); + } + } + private static final String REGISTER_PAGE = "/"; // the register page, where register requests should come from private static final String REGISTER_PATH = "/register"; // where register requests should go private static final String REGISTER_SUCCESS = LoginRequestHandler.LOGIN_PAGE; // redirect for a good register, should be the login page private final ScribbleshareDatabase database; - public RegisterFormHandler(ScribbleshareDatabase database) { + public RegisterRequestHandler(ScribbleshareDatabase database) { super(REGISTER_PATH); this.database = database; } @Override - public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form) throws BadRequestException, InternalServerException { + public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException { // validate - - String username = form.getText("username"); - String password = form.getText("password"); + RegisterRequest registerRequest = new RegisterRequest(request.content()); //todo validate if (false) { @@ -70,7 +79,7 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Form f } if (u.isRegistered()) { Scribbleshare.getLogger(ctx).info("Registered user is creating a new account"); - user = new User(username); + user = new User(registerRequest.username); try { database.addUser(user); } catch (DatabaseException e) { @@ -81,7 +90,7 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Form f user = u; } } else { - user = new User(username); + user = new User(registerRequest.username); try { database.addUser(user); } catch (DatabaseException e) { @@ -89,7 +98,7 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Form f } } } else { - user = new User(username); + user = new User(registerRequest.username); try { database.addUser(user); } catch (DatabaseException e) { @@ -99,7 +108,7 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Form f assert !user.isRegistered(); - Login login = new Login(user, password.getBytes(StandardCharsets.UTF_8)); + Login login = new Login(user, registerRequest.password); boolean loginAdded; try { loginAdded = database.addLogin(login); @@ -107,12 +116,12 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Form f throw new InternalServerException(e); } if (!loginAdded) { - Scribbleshare.getLogger(ctx).info("Tried to register with duplicate username " + username); + Scribbleshare.getLogger(ctx).info("Tried to register with duplicate username " + registerRequest.username); send(ctx, request, HttpResponseStatus.CONFLICT); return true; } - Scribbleshare.getLogger(ctx).info("Registered with username " + username); + Scribbleshare.getLogger(ctx).info("Registered with username " + registerRequest.username); send(ctx, request, HttpResponseStatus.OK); return true; diff --git a/scribbleshare-app/scribbleshare-frontend/src/scripts/Login.ts b/scribbleshare-app/scribbleshare-frontend/src/scripts/Login.ts index d71bf79a..fcdcb3b2 100644 --- a/scribbleshare-app/scribbleshare-frontend/src/scripts/Login.ts +++ b/scribbleshare-app/scribbleshare-frontend/src/scripts/Login.ts @@ -1,11 +1,28 @@ import api from "./api/Api.js" import LoginRequest from "./api/protocol/request/requests/LoginRequest.js"; import ResponseError from "./api/protocol/response/error/ResponseError.js"; +import LoginResponse from "./api/protocol/response/responses/LoginResponse.js"; +import RegisterRequest from "./api/protocol/request/requests/RegisterRequest.js"; +import RegisterResponse from "./api/protocol/response/responses/RegisterResponse.js"; api.login(new LoginRequest("test", "test", true)) - .catch((requestError: ResponseError) => { - console.log(requestError); + .then((loginResponse : LoginResponse | void) => { + console.log(loginResponse, 'login success'); }) - .finally(() => { - console.log(this); - }); \ No newline at end of file + .catch((responseError: ResponseError) => { + console.log(responseError); + }); + +api.register(new RegisterRequest("asd", "asd")) + .then((registerResponse: RegisterResponse | void) => { + console.log(registerResponse); + }) + .catch((responseError: ResponseError) => { + switch (responseError.responseCode) { + case 409: + console.log('Username already taken') + break; + default: + console.log(responseError) + } + }); diff --git a/scribbleshare-app/scribbleshare-frontend/src/scripts/api/Api.ts b/scribbleshare-app/scribbleshare-frontend/src/scripts/api/Api.ts index 2e2978cc..4f3024a6 100644 --- a/scribbleshare-app/scribbleshare-frontend/src/scripts/api/Api.ts +++ b/scribbleshare-app/scribbleshare-frontend/src/scripts/api/Api.ts @@ -3,6 +3,8 @@ import LoginRequest from "./protocol/request/requests/LoginRequest.js"; import ResponseError from "./protocol/response/error/ResponseError.js" import LoginResponse from "./protocol/response/responses/LoginResponse.js"; import Environment from "../Environment.js" +import RegisterRequest from "./protocol/request/requests/RegisterRequest.js"; +import RegisterResponse from "./protocol/response/responses/RegisterResponse.js"; class Api { uri: string; @@ -11,7 +13,7 @@ class Api { this.uri = uri; } - async login(loginRequest: LoginRequest): Promise { + login(loginRequest: LoginRequest): Promise { return new Promise((resolve, reject) => { let request = new XMLHttpRequest(); request.responseType = 'arraybuffer'; @@ -30,6 +32,26 @@ class Api { request.send(byteBuffer.getBuffer()); }) } + + register(registerRequest: RegisterRequest): Promise { + return new Promise((resolve, reject) => { + let request = new XMLHttpRequest(); + request.responseType = 'arraybuffer'; + request.open('POST', this.uri + registerRequest.getRoute()); + + request.addEventListener('load', (event) => { + if (request.status == 200) { + resolve(new RegisterResponse(new ByteBuffer(request.response))); + } else { + reject(new ResponseError(request.status)) + } + }); + + let byteBuffer = new ByteBuffer(); + registerRequest.serialize(byteBuffer); + request.send(byteBuffer.getBuffer()); + }) + } } export default new Api(Environment.getApiHost()); diff --git a/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/request/requests/RegisterRequest.ts b/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/request/requests/RegisterRequest.ts new file mode 100644 index 00000000..65298c27 --- /dev/null +++ b/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/request/requests/RegisterRequest.ts @@ -0,0 +1,22 @@ +import ApiRequest from "../ApiRequest.js"; +import ByteBuffer from "../../../../protocol/ByteBuffer.js"; + +export default class RegisterRequest extends ApiRequest { + username: string; + password: string; + + constructor(username: string, password: string) { + super(); + this.username = username; + this.password = password; + } + + getRoute(): string { + return "/register"; + } + + serialize(byteBuffer: ByteBuffer) { + byteBuffer.writeString8(this.username); + byteBuffer.writeString8(this.password); + } +} \ No newline at end of file diff --git a/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/response/responses/RegisterResponse.ts b/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/response/responses/RegisterResponse.ts new file mode 100644 index 00000000..aa39ffb3 --- /dev/null +++ b/scribbleshare-app/scribbleshare-frontend/src/scripts/api/protocol/response/responses/RegisterResponse.ts @@ -0,0 +1,8 @@ +import ApiResponse from "../ApiResponse.js"; +import ByteBuffer from "../../../../protocol/ByteBuffer.js"; + +export default class RegisterResponse extends ApiResponse { + constructor(byteBuffer: ByteBuffer) { + super(); + } +} \ No newline at end of file From c405997a61d57497dab7575524f966a0c67dd37e Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 28 May 2021 14:50:00 -0400 Subject: [PATCH 115/144] fix authenticator allowing unauthenticated requests --- .../http/handler/handlers/HttpAuthenticator.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HttpAuthenticator.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HttpAuthenticator.java index febe60b0..5dc5c1dd 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HttpAuthenticator.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HttpAuthenticator.java @@ -55,11 +55,16 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws AuthenticatedUserSession user = ctx.channel().attr(USER).get(); if (user != null) { - return false; + return true; } - ctx.channel().attr(USER).set(authenticateHttpUserSession(request, database)); - return false; + AuthenticatedUserSession session = authenticateHttpUserSession(request, database); + if (session == null) { + throw new UnauthorizedException("No authentication"); + } + + ctx.channel().attr(USER).set(session); + return true; } /** authenticates, or null if no authentication */ From 49ac5adefb95ec29a3acc3bcdcb83dcac6cd5a97 Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 28 May 2021 14:58:04 -0400 Subject: [PATCH 116/144] improve log, headers are actually sent --- .../backend/server/handlers/LoginRequestHandler.java | 7 ++++++- .../server/http/handler/handlers/HttpAuthenticator.java | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginRequestHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginRequestHandler.java index 40c6da74..4f4fd308 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginRequestHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginRequestHandler.java @@ -1,11 +1,14 @@ package net.stzups.scribbleshare.backend.server.handlers; import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.DefaultHttpHeaders; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpVersion; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.database.exception.DatabaseException; @@ -98,7 +101,9 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route } } - send(ctx, request, HttpResponseStatus.OK); + DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.EMPTY_BUFFER); + response.headers().set(httpHeaders); + send(ctx, request, response); return true; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HttpAuthenticator.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HttpAuthenticator.java index 5dc5c1dd..de71adb4 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HttpAuthenticator.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HttpAuthenticator.java @@ -5,6 +5,7 @@ import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaders; import io.netty.util.AttributeKey; +import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.data.database.databases.HttpSessionDatabase; import net.stzups.scribbleshare.data.database.databases.PersistentHttpSessionDatabase; import net.stzups.scribbleshare.data.database.databases.UserDatabase; @@ -63,6 +64,7 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws throw new UnauthorizedException("No authentication"); } + Scribbleshare.getLogger(ctx).info("" + session); ctx.channel().attr(USER).set(session); return true; } From 8c03ad472888a7eef7ddc598b636872514c6d636 Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 28 May 2021 17:25:48 -0400 Subject: [PATCH 117/144] add some csrf protection i think --- .../server/BackendHttpServerInitializer.java | 8 +++---- .../handlers/DocumentRequestHandler.java | 14 ++++++----- .../server/handlers/LoginRequestHandler.java | 9 ++++--- ...Handler.java => LogoutRequestHandler.java} | 21 +++++++++------- .../handlers/RegisterRequestHandler.java | 14 +++++------ .../authentication/http/HttpConfig.java | 1 + .../server/http/handler/FormHandler.java | 24 ------------------- .../server/http/handler/RequestHandler.java | 23 ++++++++++++++---- .../handler/handlers/FileRequestHandler.java | 8 +++---- .../handlers/HealthcheckRequestHandler.java | 7 +++--- 10 files changed, 61 insertions(+), 68 deletions(-) rename scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/{LogoutFormHandler.java => LogoutRequestHandler.java} (84%) delete mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/FormHandler.java diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java index cba9706a..154e2b88 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java @@ -7,7 +7,7 @@ import net.stzups.scribbleshare.backend.ScribbleshareBackendConfig; import net.stzups.scribbleshare.backend.server.handlers.DocumentRequestHandler; import net.stzups.scribbleshare.backend.server.handlers.LoginRequestHandler; -import net.stzups.scribbleshare.backend.server.handlers.LogoutFormHandler; +import net.stzups.scribbleshare.backend.server.handlers.LogoutRequestHandler; import net.stzups.scribbleshare.backend.server.handlers.RegisterRequestHandler; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.server.http.HttpServerHandler; @@ -25,10 +25,10 @@ public BackendHttpServerInitializer(ScribbleshareBackendConfig config, Scribbles super(config); httpServerHandler = new HttpServerHandler() .addLast(new HealthcheckRequestHandler()) - .addLast(new DocumentRequestHandler(database)) + .addLast(new DocumentRequestHandler(config, database)) .addLast(new LoginRequestHandler(config, database)) - .addLast(new LogoutFormHandler(config, database)) - .addLast(new RegisterRequestHandler(database)) + .addLast(new LogoutRequestHandler(config, database)) + .addLast(new RegisterRequestHandler(config, database)) .addLast(new FileRequestHandler(config)); } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/DocumentRequestHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/DocumentRequestHandler.java index 28e55491..c0ee980c 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/DocumentRequestHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/DocumentRequestHandler.java @@ -16,6 +16,7 @@ import net.stzups.scribbleshare.data.objects.Resource; import net.stzups.scribbleshare.data.objects.User; import net.stzups.scribbleshare.data.objects.authentication.AuthenticatedUserSession; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.server.http.exception.HttpException; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; @@ -33,13 +34,14 @@ public class DocumentRequestHandler extends RequestHandler { private final ScribbleshareDatabase database; - public DocumentRequestHandler(ScribbleshareDatabase database) { - super("/document"); + public DocumentRequestHandler(HttpConfig config, ScribbleshareDatabase database) { + super(config, "/", "/document"); this.database = database; } @Override - public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException { + public void handleRequest(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { + Route route = new Route(request.uri()); AuthenticatedUserSession session = HttpAuthenticator.authenticateHttpUserSession(request, database); if (session == null) { @@ -86,13 +88,13 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route try { send(ctx, request, Unpooled.copyLong(database.addResource(document.getId(), new Resource(request.content())))); - return true; + return; } catch (DatabaseException e) { throw new InternalServerException(e); } } else { send(ctx, request, HttpResponseStatus.METHOD_NOT_ALLOWED); - return true; + return; } } else { // route.length == 4, get resource from document // does the document have this resource? @@ -130,7 +132,7 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route } else { send(ctx, request, HttpResponseStatus.METHOD_NOT_ALLOWED); } - return true; + return; } } } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginRequestHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginRequestHandler.java index 4f4fd308..b37dcd53 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginRequestHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LoginRequestHandler.java @@ -20,7 +20,6 @@ import net.stzups.scribbleshare.server.http.exception.HttpException; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; import net.stzups.scribbleshare.server.http.handler.RequestHandler; -import net.stzups.scribbleshare.server.http.objects.Route; import java.nio.charset.StandardCharsets; @@ -46,13 +45,13 @@ private static class LoginRequest { private final ScribbleshareDatabase database; public LoginRequestHandler(HttpConfig config, ScribbleshareDatabase database) { - super(LOGIN_PATH); + super(config, LOGIN_PAGE, LOGIN_PATH); this.database = database; this.config = config; } @Override - public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException { + public void handleRequest(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { LoginRequest loginRequest = new LoginRequest(request.content()); Login login; @@ -70,7 +69,7 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route } send(ctx, request, HttpResponseStatus.UNAUTHORIZED); - return true; + return; } assert login != null : "Verified logins should never be null"; @@ -104,7 +103,7 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.EMPTY_BUFFER); response.headers().set(httpHeaders); send(ctx, request, response); - return true; + return; } static String readString(ByteBuf byteBuf) { diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LogoutFormHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LogoutRequestHandler.java similarity index 84% rename from scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LogoutFormHandler.java rename to scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LogoutRequestHandler.java index 748a3bc1..80f32755 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LogoutFormHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/LogoutRequestHandler.java @@ -6,27 +6,25 @@ import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.server.http.HttpUtils; -import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; -import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; -import net.stzups.scribbleshare.server.http.handler.FormHandler; -import net.stzups.scribbleshare.server.http.objects.Form; +import net.stzups.scribbleshare.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.handler.RequestHandler; -public class LogoutFormHandler extends FormHandler { +public class LogoutRequestHandler extends RequestHandler { private static final String LOGOUT_PAGE = "/"; // the logout page, where logout requests should come from private static final String LOGOUT_PATH = "/logout"; // where logout requests should go private final HttpConfig config; private final ScribbleshareDatabase database; - public LogoutFormHandler(HttpConfig config, ScribbleshareDatabase database) { - super(LOGOUT_PATH); + public LogoutRequestHandler(HttpConfig config, ScribbleshareDatabase database) { + super(config, LOGOUT_PAGE, LOGOUT_PATH); this.config = config; this.database = database; } @Override - public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form) throws BadRequestException, InternalServerException { -/* Form form = new Form(request);//todo necessary? + public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { + /* Form form = new Form(request);//todo necessary? HttpHeaders headers = new DefaultHttpHeaders(); @@ -76,4 +74,9 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Form f HttpUtils.send(ctx, request, HttpResponseStatus.NOT_FOUND); return true; } + + @Override + protected void handleRequest(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { + + } } diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/RegisterRequestHandler.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/RegisterRequestHandler.java index 3a36365a..adc5c366 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/RegisterRequestHandler.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/handlers/RegisterRequestHandler.java @@ -8,6 +8,7 @@ import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; import net.stzups.scribbleshare.data.database.exception.DatabaseException; import net.stzups.scribbleshare.data.objects.User; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.data.objects.authentication.http.HttpSessionCookie; import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSession; import net.stzups.scribbleshare.data.objects.authentication.http.HttpUserSessionCookie; @@ -15,7 +16,6 @@ import net.stzups.scribbleshare.server.http.exception.HttpException; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; import net.stzups.scribbleshare.server.http.handler.RequestHandler; -import net.stzups.scribbleshare.server.http.objects.Route; import static net.stzups.scribbleshare.backend.server.handlers.LoginRequestHandler.readString; import static net.stzups.scribbleshare.server.http.HttpUtils.send; @@ -39,13 +39,13 @@ private static class RegisterRequest { private final ScribbleshareDatabase database; - public RegisterRequestHandler(ScribbleshareDatabase database) { - super(REGISTER_PATH); + public RegisterRequestHandler(HttpConfig config, ScribbleshareDatabase database) { + super(config, REGISTER_PAGE, REGISTER_PATH); this.database = database; } @Override - public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException { + public void handleRequest(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { // validate RegisterRequest registerRequest = new RegisterRequest(request.content()); @@ -55,7 +55,7 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route //todo rate limit and generic error handling sendRedirect(ctx, request, REGISTER_PAGE); - return true; + return; } User user; @@ -118,12 +118,12 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route if (!loginAdded) { Scribbleshare.getLogger(ctx).info("Tried to register with duplicate username " + registerRequest.username); send(ctx, request, HttpResponseStatus.CONFLICT); - return true; + return; } Scribbleshare.getLogger(ctx).info("Registered with username " + registerRequest.username); send(ctx, request, HttpResponseStatus.OK); - return true; + return; } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpConfig.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpConfig.java index 5fc62464..b314a116 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpConfig.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpConfig.java @@ -3,4 +3,5 @@ public interface HttpConfig { String getDomain(); boolean getSSL(); + int getPort(); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/FormHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/FormHandler.java deleted file mode 100644 index 8cd5a632..00000000 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/FormHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -package net.stzups.scribbleshare.server.http.handler; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.HttpMethod; -import net.stzups.scribbleshare.server.http.exception.HttpException; -import net.stzups.scribbleshare.server.http.objects.Form; - -public abstract class FormHandler extends HttpHandler { - protected FormHandler(String route) { - super(route); - } - - @Override - public final boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { - if (request.method().equals(HttpMethod.POST)) { - return handle(ctx, request, new Form(request)); - } - - return false; - } - - public abstract boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Form form) throws HttpException; -} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java index 502c74c0..f14c7825 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java @@ -2,18 +2,31 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaderNames; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.server.http.exception.HttpException; -import net.stzups.scribbleshare.server.http.objects.Route; +import net.stzups.scribbleshare.server.http.exception.exceptions.UnauthorizedException; public abstract class RequestHandler extends HttpHandler { - protected RequestHandler(String route) { + private final HttpConfig config; + private final String referer; + + protected RequestHandler(HttpConfig config, String referer, String route) { super(route); + this.config = config; + this.referer = referer; } @Override - public final boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { - return handle(ctx, request, new Route(request.uri())); + public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { + String referer = request.headers().get(HttpHeaderNames.REFERER); + String string = (config.getSSL() ? "https://" : "http://") + config.getDomain(); + if (referer != null && !referer.equals(string + this.referer) && !referer.equals(string + ":" + config.getPort() + this.referer)) { // https://example.com/referer or https://example.com:1234/referer + throw new UnauthorizedException("Bad referer for " + getRoute() + ", got " + HttpHeaderNames.REFERER + ": " + referer + ", should have been referred from " + this.referer); + } + handleRequest(ctx, request); + return true; } - public abstract boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException; + protected abstract void handleRequest(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/FileRequestHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/FileRequestHandler.java index 63969529..f3964746 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/FileRequestHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/FileRequestHandler.java @@ -14,7 +14,7 @@ import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import net.stzups.scribbleshare.server.http.exception.exceptions.InternalServerException; import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; -import net.stzups.scribbleshare.server.http.handler.RequestHandler; +import net.stzups.scribbleshare.server.http.handler.HttpHandler; import net.stzups.scribbleshare.server.http.objects.Route; import net.stzups.scribbleshare.server.http.objects.Uri; @@ -28,7 +28,7 @@ import static net.stzups.scribbleshare.server.http.HttpUtils.sendFile; import static net.stzups.scribbleshare.server.http.HttpUtils.sendRedirect; -public class FileRequestHandler extends RequestHandler { +public class FileRequestHandler extends HttpHandler { public interface Config extends HttpConfig { String getHttpRoot(); int getHttpCacheSeconds(); @@ -73,8 +73,8 @@ public FileRequestHandler(Config config) { } @Override - public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException { - // otherwise try to serve a regular HTTP file resource + public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { + Route route = new Route(request.uri()); if (!HttpMethod.GET.equals(request.method())) { send(ctx, request, HttpResponseStatus.METHOD_NOT_ALLOWED); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HealthcheckRequestHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HealthcheckRequestHandler.java index 048cade5..d0df63e6 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HealthcheckRequestHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HealthcheckRequestHandler.java @@ -6,20 +6,19 @@ import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.server.http.exception.HttpException; import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; -import net.stzups.scribbleshare.server.http.handler.RequestHandler; -import net.stzups.scribbleshare.server.http.objects.Route; +import net.stzups.scribbleshare.server.http.handler.HttpHandler; import java.net.InetSocketAddress; import static net.stzups.scribbleshare.server.http.HttpUtils.send; -public class HealthcheckRequestHandler extends RequestHandler { +public class HealthcheckRequestHandler extends HttpHandler { public HealthcheckRequestHandler() { super("/healthcheck"); } @Override - public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request, Route route) throws HttpException { + public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { if (request.uri().equals("/healthcheck")) { if (!((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().isLoopbackAddress()) { throw new NotFoundException("Healthcheck request from address which is not a loopback address"); From 2f09f2f8080a0507bf126297ee20bdbed2a2ddce Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 28 May 2021 18:04:41 -0400 Subject: [PATCH 118/144] add origin check --- .../server/BackendHttpServerInitializer.java | 2 +- .../server/http/HttpServerHandler.java | 15 +++++++++++++++ .../room/server/RoomHttpServerInitializer.java | 5 +++-- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java index 154e2b88..9f8bfcae 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java @@ -23,7 +23,7 @@ public class BackendHttpServerInitializer extends HttpServerInitializer { public BackendHttpServerInitializer(ScribbleshareBackendConfig config, ScribbleshareDatabase database) throws SSLException { super(config); - httpServerHandler = new HttpServerHandler() + httpServerHandler = new HttpServerHandler(config) .addLast(new HealthcheckRequestHandler()) .addLast(new DocumentRequestHandler(config, database)) .addLast(new LoginRequestHandler(config, database)) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java index 917c49a4..2bc625f1 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java @@ -4,7 +4,9 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToMessageDecoder; import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaderNames; import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.server.http.exception.HttpException; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import net.stzups.scribbleshare.server.http.handler.HttpHandler; @@ -18,8 +20,13 @@ @ChannelHandler.Sharable public class HttpServerHandler extends MessageToMessageDecoder { + private final HttpConfig config; private final Queue handlers = new ArrayDeque<>(); + public HttpServerHandler(HttpConfig config) { + this.config = config; + } + public HttpServerHandler addLast(HttpHandler handler) { handlers.add(handler); return this; @@ -30,6 +37,14 @@ protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List Date: Fri, 28 May 2021 18:05:54 -0400 Subject: [PATCH 119/144] microoptimization --- .../scribbleshare/server/http/handler/RequestHandler.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java index f14c7825..d73df1e3 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java @@ -20,9 +20,11 @@ protected RequestHandler(HttpConfig config, String referer, String route) { @Override public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { String referer = request.headers().get(HttpHeaderNames.REFERER); - String string = (config.getSSL() ? "https://" : "http://") + config.getDomain(); - if (referer != null && !referer.equals(string + this.referer) && !referer.equals(string + ":" + config.getPort() + this.referer)) { // https://example.com/referer or https://example.com:1234/referer - throw new UnauthorizedException("Bad referer for " + getRoute() + ", got " + HttpHeaderNames.REFERER + ": " + referer + ", should have been referred from " + this.referer); + if (referer != null) { + String string = (config.getSSL() ? "https://" : "http://") + config.getDomain(); + if (!referer.equals(string + this.referer) && !referer.equals(string + ":" + config.getPort() + this.referer)) { // https://example.com/referer or https://example.com:1234/referer + throw new UnauthorizedException("Bad referer for " + getRoute() + ", got " + HttpHeaderNames.REFERER + ": " + referer + ", should have been referred from " + this.referer); + } } handleRequest(ctx, request); return true; From 9f3c443b62a1b77a1f4dfa09cd717bda233e24c6 Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 28 May 2021 18:17:22 -0400 Subject: [PATCH 120/144] quieted down logging a bit --- .../server/http/HttpServerInitializer.java | 33 ++++++++----------- .../handlers/HealthcheckRequestHandler.java | 2 -- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java index c1a995d6..ac67832a 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerInitializer.java @@ -1,8 +1,6 @@ package net.stzups.scribbleshare.server.http; -import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.http.HttpObjectAggregator; @@ -28,8 +26,6 @@ public interface Config { private final Config config; private final SslContext sslContext; - private final DebugOpenCloseLog debugOpenCloseLog = new DebugOpenCloseLog(); - protected HttpServerInitializer(Config config) throws SSLException { this.config = config; @@ -47,7 +43,19 @@ protected HttpServerInitializer(Config config) throws SSLException { protected void initChannel(SocketChannel channel) { Scribbleshare.setLogger(channel); - channel.pipeline().addLast(debugOpenCloseLog); +/* channel.pipeline().addLast(new ChannelDuplexHandler() { + @Override + public void channelActive(ChannelHandlerContext ctx) { + Scribbleshare.getLogger(ctx).info("Connection opened"); + ctx.fireChannelActive(); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) { + Scribbleshare.getLogger(ctx).info("Connection closed"); + ctx.fireChannelInactive(); + } + });*/ if (config.getDebugLogTraffic()) channel.pipeline().addLast(new GlobalTrafficShapingHandler(channel.eventLoop(), 0, 0, 1000) { @Override protected void doAccounting(TrafficCounter counter) { @@ -60,18 +68,3 @@ protected void doAccounting(TrafficCounter counter) { .addLast(new HttpObjectAggregator(Integer.MAX_VALUE)); //2gb todo decrease } } - -@ChannelHandler.Sharable -class DebugOpenCloseLog extends ChannelDuplexHandler { - @Override - public void channelActive(ChannelHandlerContext ctx) { - Scribbleshare.getLogger(ctx).info("Connection opened"); - ctx.fireChannelActive(); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) { - Scribbleshare.getLogger(ctx).info("Connection closed"); - ctx.fireChannelInactive(); - } -} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HealthcheckRequestHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HealthcheckRequestHandler.java index d0df63e6..434748f2 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HealthcheckRequestHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/HealthcheckRequestHandler.java @@ -3,7 +3,6 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; -import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.server.http.exception.HttpException; import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; import net.stzups.scribbleshare.server.http.handler.HttpHandler; @@ -24,7 +23,6 @@ public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws throw new NotFoundException("Healthcheck request from address which is not a loopback address"); } else { send(ctx, request, HttpResponseStatus.OK); - Scribbleshare.getLogger(ctx).info("Good healthcheck response"); return true; } } From 58d7c14dd7a386fe59f0464c97f3d0053bf51c74 Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 28 May 2021 18:44:57 -0400 Subject: [PATCH 121/144] add uri check to pipeline --- .../room/server/RoomHttpServerInitializer.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java index 22ef3a49..a75cd590 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java @@ -3,6 +3,7 @@ import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler; import io.netty.util.AttributeKey; @@ -13,6 +14,8 @@ import net.stzups.scribbleshare.room.server.websocket.protocol.ServerMessageEncoder; import net.stzups.scribbleshare.server.http.HttpServerHandler; import net.stzups.scribbleshare.server.http.HttpServerInitializer; +import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; +import net.stzups.scribbleshare.server.http.handler.HttpHandler; import net.stzups.scribbleshare.server.http.handler.handlers.HealthcheckRequestHandler; import net.stzups.scribbleshare.server.http.handler.handlers.HttpAuthenticator; @@ -45,6 +48,16 @@ public RoomHttpServerInitializer(Config config, ScribbleshareDatabase database) clientMessageHandler = new ClientMessageHandler(); httpServerHandler = new HttpServerHandler(config) .addLast(new HealthcheckRequestHandler()) + .addLast(new HttpHandler("/") { + @Override + public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws NotFoundException { + if (!request.uri().equals(config.getWebsocketPath())) { + throw new NotFoundException("Bad uri " + request.uri()); + } + + return false; + } + }) .addLast(new HttpAuthenticator(database)); } From b2f92ebf1d42e9701e4857484b40b05afeb60198 Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 28 May 2021 23:01:21 -0400 Subject: [PATCH 122/144] probably rework bad origin checking --- .../server/BackendHttpServerInitializer.java | 4 +- .../server/http/HttpServerHandler.java | 15 ------- .../http/handler/handlers/OriginHandler.java | 45 +++++++++++++++++++ scribbleshare-room/scribbleshare.properties | 3 +- ...ScribbleshareRoomConfigImplementation.java | 6 ++- .../server/RoomHttpServerInitializer.java | 5 ++- 6 files changed, 59 insertions(+), 19 deletions(-) create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/OriginHandler.java diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java index 9f8bfcae..908bf280 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java @@ -14,6 +14,7 @@ import net.stzups.scribbleshare.server.http.HttpServerInitializer; import net.stzups.scribbleshare.server.http.handler.handlers.FileRequestHandler; import net.stzups.scribbleshare.server.http.handler.handlers.HealthcheckRequestHandler; +import net.stzups.scribbleshare.server.http.handler.handlers.OriginHandler; import javax.net.ssl.SSLException; @@ -23,7 +24,8 @@ public class BackendHttpServerInitializer extends HttpServerInitializer { public BackendHttpServerInitializer(ScribbleshareBackendConfig config, ScribbleshareDatabase database) throws SSLException { super(config); - httpServerHandler = new HttpServerHandler(config) + httpServerHandler = new HttpServerHandler() + .addLast(new OriginHandler(config)) .addLast(new HealthcheckRequestHandler()) .addLast(new DocumentRequestHandler(config, database)) .addLast(new LoginRequestHandler(config, database)) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java index 2bc625f1..917c49a4 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java @@ -4,9 +4,7 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToMessageDecoder; import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.HttpHeaderNames; import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.server.http.exception.HttpException; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; import net.stzups.scribbleshare.server.http.handler.HttpHandler; @@ -20,13 +18,8 @@ @ChannelHandler.Sharable public class HttpServerHandler extends MessageToMessageDecoder { - private final HttpConfig config; private final Queue handlers = new ArrayDeque<>(); - public HttpServerHandler(HttpConfig config) { - this.config = config; - } - public HttpServerHandler addLast(HttpHandler handler) { handlers.add(handler); return this; @@ -37,14 +30,6 @@ protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List WEBSOCKET_PATH = new OptionalConfigKey<>("websocket.path", "/scribblesocket"); + private static final ConfigKey ORIGIN = new OptionalConfigKey<>("origin", ""); public String getWebsocketPath() { return getString(WEBSOCKET_PATH); } + public String getOrigin() { + return getString(ORIGIN); + } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java index a75cd590..ef646af6 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java @@ -18,6 +18,7 @@ import net.stzups.scribbleshare.server.http.handler.HttpHandler; import net.stzups.scribbleshare.server.http.handler.handlers.HealthcheckRequestHandler; import net.stzups.scribbleshare.server.http.handler.handlers.HttpAuthenticator; +import net.stzups.scribbleshare.server.http.handler.handlers.OriginHandler; import javax.net.ssl.SSLException; @@ -25,6 +26,7 @@ public class RoomHttpServerInitializer extends HttpServerInitializer { public interface Config extends HttpServerInitializer.Config, HttpConfig { String getWebsocketPath(); + String getOrigin(); } private static final AttributeKey DATABASE = AttributeKey.valueOf(RoomHttpServerInitializer.class, "DATABASE"); @@ -46,8 +48,9 @@ public RoomHttpServerInitializer(Config config, ScribbleshareDatabase database) this.config = config; this.database = database; clientMessageHandler = new ClientMessageHandler(); - httpServerHandler = new HttpServerHandler(config) + httpServerHandler = new HttpServerHandler() .addLast(new HealthcheckRequestHandler()) + .addLast(new OriginHandler(config, config.getOrigin())) .addLast(new HttpHandler("/") { @Override public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws NotFoundException { From 903cff3daf6cef0f3094a8bb580eb3238d260e14 Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 28 May 2021 23:17:38 -0400 Subject: [PATCH 123/144] fix the build command not actually being run :/ --- scribbleshare-app/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scribbleshare-app/Dockerfile b/scribbleshare-app/Dockerfile index ab629164..8127b4e5 100644 --- a/scribbleshare-app/Dockerfile +++ b/scribbleshare-app/Dockerfile @@ -8,8 +8,8 @@ WORKDIR /usr/src/app COPY scribbleshare-frontend . RUN npm install -RUN chmod +x build.sh \ -build.sh +RUN chmod +x build.sh +RUN ./build.sh # From c07f7b10f671894705fdf29cc0c153fd8ce81837 Mon Sep 17 00:00:00 2001 From: stzups Date: Fri, 28 May 2021 23:17:56 -0400 Subject: [PATCH 124/144] fix production port --- .../scribbleshare-frontend/src/scripts/Environment.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scribbleshare-app/scribbleshare-frontend/src/scripts/Environment.ts b/scribbleshare-app/scribbleshare-frontend/src/scripts/Environment.ts index 2079c9ea..0f8afa57 100644 --- a/scribbleshare-app/scribbleshare-frontend/src/scripts/Environment.ts +++ b/scribbleshare-app/scribbleshare-frontend/src/scripts/Environment.ts @@ -19,7 +19,7 @@ class ProductionEnvironment implements Environment { } getWebsocketHost(): string { - return 'ws://scribbleshare.com:18080/scribblesocket'; + return 'ws://scribbleshare.com:8080/scribblesocket'; } } From f09de927134fcafe4d6b82c0cab12572d98944a2 Mon Sep 17 00:00:00 2001 From: stzups Date: Sat, 29 May 2021 00:07:38 -0400 Subject: [PATCH 125/144] simplify logging --- .../server/BackendHttpServerInitializer.java | 2 ++ .../server/http/HttpServerHandler.java | 6 ++++-- .../handlers/HealthcheckRequestHandler.java | 7 +++++++ .../http/handler/handlers/LogHandler.java | 19 +++++++++++++++++++ .../server/RoomHttpServerInitializer.java | 2 ++ .../room/server/websocket/state/State.java | 6 +++++- 6 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/LogHandler.java diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java index 908bf280..54fd479e 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java @@ -14,6 +14,7 @@ import net.stzups.scribbleshare.server.http.HttpServerInitializer; import net.stzups.scribbleshare.server.http.handler.handlers.FileRequestHandler; import net.stzups.scribbleshare.server.http.handler.handlers.HealthcheckRequestHandler; +import net.stzups.scribbleshare.server.http.handler.handlers.LogHandler; import net.stzups.scribbleshare.server.http.handler.handlers.OriginHandler; import javax.net.ssl.SSLException; @@ -27,6 +28,7 @@ public BackendHttpServerInitializer(ScribbleshareBackendConfig config, Scribbles httpServerHandler = new HttpServerHandler() .addLast(new OriginHandler(config)) .addLast(new HealthcheckRequestHandler()) + .addLast(new LogHandler()) .addLast(new DocumentRequestHandler(config, database)) .addLast(new LoginRequestHandler(config, database)) .addLast(new LogoutRequestHandler(config, database)) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java index 917c49a4..66d74731 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java @@ -4,6 +4,7 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToMessageDecoder; import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpResponseStatus; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.server.http.exception.HttpException; import net.stzups.scribbleshare.server.http.exception.exceptions.BadRequestException; @@ -28,8 +29,6 @@ public HttpServerHandler addLast(HttpHandler handler) { @Override protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List out) { try { - Scribbleshare.getLogger(ctx).info(request.method() + " " + request.uri()); - if (request.decoderResult().isFailure()) throw new BadRequestException("Decoding request resulted in " + request.decoderResult()); @@ -40,6 +39,9 @@ protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List Date: Sat, 29 May 2021 15:02:52 -0400 Subject: [PATCH 126/144] rework handlers --- .../server/BackendHttpServerInitializer.java | 9 +--- scribbleshare-app/scribbleshare.properties | 3 +- .../scribbleshare/ScribbleshareConfig.java | 1 + .../ScribbleshareConfigImplementation.java | 7 +++ .../authentication/http/HttpConfig.java | 1 + .../server/http/DefaultHttpServerHandler.java | 14 ++++++ .../http/handler/handlers/RefererHandler.java | 45 +++++++++++++++++++ ...ScribbleshareRoomConfigImplementation.java | 4 -- .../server/RoomHttpServerInitializer.java | 9 +--- 9 files changed, 74 insertions(+), 19 deletions(-) create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/DefaultHttpServerHandler.java create mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/RefererHandler.java diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java index 54fd479e..cfb3b0f7 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java @@ -10,12 +10,10 @@ import net.stzups.scribbleshare.backend.server.handlers.LogoutRequestHandler; import net.stzups.scribbleshare.backend.server.handlers.RegisterRequestHandler; import net.stzups.scribbleshare.data.database.ScribbleshareDatabase; +import net.stzups.scribbleshare.server.http.DefaultHttpServerHandler; import net.stzups.scribbleshare.server.http.HttpServerHandler; import net.stzups.scribbleshare.server.http.HttpServerInitializer; import net.stzups.scribbleshare.server.http.handler.handlers.FileRequestHandler; -import net.stzups.scribbleshare.server.http.handler.handlers.HealthcheckRequestHandler; -import net.stzups.scribbleshare.server.http.handler.handlers.LogHandler; -import net.stzups.scribbleshare.server.http.handler.handlers.OriginHandler; import javax.net.ssl.SSLException; @@ -25,10 +23,7 @@ public class BackendHttpServerInitializer extends HttpServerInitializer { public BackendHttpServerInitializer(ScribbleshareBackendConfig config, ScribbleshareDatabase database) throws SSLException { super(config); - httpServerHandler = new HttpServerHandler() - .addLast(new OriginHandler(config)) - .addLast(new HealthcheckRequestHandler()) - .addLast(new LogHandler()) + httpServerHandler = new DefaultHttpServerHandler(config) .addLast(new DocumentRequestHandler(config, database)) .addLast(new LoginRequestHandler(config, database)) .addLast(new LogoutRequestHandler(config, database)) diff --git a/scribbleshare-app/scribbleshare.properties b/scribbleshare-app/scribbleshare.properties index b2255263..e5f3f7dd 100644 --- a/scribbleshare-app/scribbleshare.properties +++ b/scribbleshare-app/scribbleshare.properties @@ -5,4 +5,5 @@ postgres.password=changeme html.root=scribbleshare-frontend/src domain=localhost port=3456 -debug.js.root=scribbleshare-frontend/build \ No newline at end of file +debug.js.root=scribbleshare-frontend/build +origin=http://localhost:3456 \ No newline at end of file diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/ScribbleshareConfig.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/ScribbleshareConfig.java index 87ea1212..d6cdb678 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/ScribbleshareConfig.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/ScribbleshareConfig.java @@ -10,4 +10,5 @@ public interface ScribbleshareConfig extends PostgresDatabase.Config, HttpServer int getPort(); String getDomain(); String getName(); + String getOrigin(); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/ScribbleshareConfigImplementation.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/ScribbleshareConfigImplementation.java index 63eb3720..954e165a 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/ScribbleshareConfigImplementation.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/ScribbleshareConfigImplementation.java @@ -25,6 +25,13 @@ public class ScribbleshareConfigImplementation extends Config implements Scribbl public static final ConfigKey DEBUG_LOG_TRAFFIC = new OptionalConfigKey<>("debug.log.traffic", false); + private static final ConfigKey ORIGIN = new OptionalConfigKey<>("origin", ""); + + @Override + public String getOrigin() { + return getString(ORIGIN); + } + @Override public String getEnvironmentVariablePrefix() { return getString(ENVIRONMENT_VARIABLE_PREFIX); diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpConfig.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpConfig.java index b314a116..d15d8df0 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpConfig.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/objects/authentication/http/HttpConfig.java @@ -4,4 +4,5 @@ public interface HttpConfig { String getDomain(); boolean getSSL(); int getPort(); + String getOrigin(); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/DefaultHttpServerHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/DefaultHttpServerHandler.java new file mode 100644 index 00000000..5e2b0522 --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/DefaultHttpServerHandler.java @@ -0,0 +1,14 @@ +package net.stzups.scribbleshare.server.http; + +import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; +import net.stzups.scribbleshare.server.http.handler.handlers.HealthcheckRequestHandler; +import net.stzups.scribbleshare.server.http.handler.handlers.LogHandler; +import net.stzups.scribbleshare.server.http.handler.handlers.OriginHandler; + +public class DefaultHttpServerHandler extends HttpServerHandler { + public DefaultHttpServerHandler(HttpConfig config) { + addLast(new HealthcheckRequestHandler()) + .addLast(new LogHandler()) + .addLast(new OriginHandler(config, config.getOrigin())); + } +} diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/RefererHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/RefererHandler.java new file mode 100644 index 00000000..ccdfa296 --- /dev/null +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/RefererHandler.java @@ -0,0 +1,45 @@ +package net.stzups.scribbleshare.server.http.handler.handlers; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpResponseStatus; +import net.stzups.scribbleshare.Scribbleshare; +import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; +import net.stzups.scribbleshare.server.http.HttpUtils; +import net.stzups.scribbleshare.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.handler.HttpHandler; + +public class RefererHandler extends HttpHandler { + private final HttpConfig config; + private final String origin; + + public RefererHandler(HttpConfig config) { + this(config, null); + } + + public RefererHandler(HttpConfig config, String origin) { + super("/"); + this.config = config; + this.origin = origin; + } + + @Override + public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { + String referer = request.headers().get(HttpHeaderNames.REFERER); + if (referer != null) { + String string = (config.getSSL() ? "https://" : "http://") + config.getDomain(); + if (!(this.origin != null && referer.startsWith(this.origin)) && !referer.startsWith(string) && !referer.startsWith(string + ":" + config.getPort())) { + if (this.origin != null) { // null for a warning + Scribbleshare.getLogger(ctx).warning("Unknown referer " + referer + ", serving 404"); + HttpUtils.send(ctx, request, HttpResponseStatus.NOT_FOUND); + return true; + } else { + Scribbleshare.getLogger(ctx).warning("Unknown referer " + referer + ", request will still be handled normally"); + } + } + } + + return false; + } +} diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/ScribbleshareRoomConfigImplementation.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/ScribbleshareRoomConfigImplementation.java index c928d672..dec99a04 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/ScribbleshareRoomConfigImplementation.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/ScribbleshareRoomConfigImplementation.java @@ -6,12 +6,8 @@ public class ScribbleshareRoomConfigImplementation extends ScribbleshareConfigImplementation implements ScribbleshareRoomConfig { private static final ConfigKey WEBSOCKET_PATH = new OptionalConfigKey<>("websocket.path", "/scribblesocket"); - private static final ConfigKey ORIGIN = new OptionalConfigKey<>("origin", ""); public String getWebsocketPath() { return getString(WEBSOCKET_PATH); } - public String getOrigin() { - return getString(ORIGIN); - } } diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java index f0a3b5b9..b306fb31 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java @@ -12,14 +12,12 @@ import net.stzups.scribbleshare.room.server.websocket.ClientMessageHandler; import net.stzups.scribbleshare.room.server.websocket.protocol.ClientMessageDecoder; import net.stzups.scribbleshare.room.server.websocket.protocol.ServerMessageEncoder; +import net.stzups.scribbleshare.server.http.DefaultHttpServerHandler; import net.stzups.scribbleshare.server.http.HttpServerHandler; import net.stzups.scribbleshare.server.http.HttpServerInitializer; import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; import net.stzups.scribbleshare.server.http.handler.HttpHandler; -import net.stzups.scribbleshare.server.http.handler.handlers.HealthcheckRequestHandler; import net.stzups.scribbleshare.server.http.handler.handlers.HttpAuthenticator; -import net.stzups.scribbleshare.server.http.handler.handlers.LogHandler; -import net.stzups.scribbleshare.server.http.handler.handlers.OriginHandler; import javax.net.ssl.SSLException; @@ -49,10 +47,7 @@ public RoomHttpServerInitializer(Config config, ScribbleshareDatabase database) this.config = config; this.database = database; clientMessageHandler = new ClientMessageHandler(); - httpServerHandler = new HttpServerHandler() - .addLast(new HealthcheckRequestHandler()) - .addLast(new LogHandler()) - .addLast(new OriginHandler(config, config.getOrigin())) + httpServerHandler = new DefaultHttpServerHandler(config) .addLast(new HttpHandler("/") { @Override public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws NotFoundException { From b1693d9d2a4f73c552df1edb2b1a06496e2c056a Mon Sep 17 00:00:00 2001 From: stzups Date: Sat, 29 May 2021 16:12:02 -0400 Subject: [PATCH 127/144] improve cors or something --- docker-compose.yml | 4 +- .../server/BackendHttpServerInitializer.java | 4 +- .../server/http/DefaultHttpServerHandler.java | 7 +-- .../server/http/handler/RequestHandler.java | 12 ++--- .../http/handler/handlers/OriginHandler.java | 25 ++--------- .../http/handler/handlers/RefererHandler.java | 45 ------------------- .../server/RoomHttpServerInitializer.java | 4 +- 7 files changed, 19 insertions(+), 82 deletions(-) delete mode 100644 scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/RefererHandler.java diff --git a/docker-compose.yml b/docker-compose.yml index 554514b9..7263a408 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,7 +16,8 @@ services: scribbleshare.postgres.url: "jdbc:postgresql://scribbleshare-postgres:5432/scribbleshare" scribbleshare.postgres.user: "scribbleshare_room" scribbleshare.postgres.password: "changeme" - scribbleshare.domain: "scribbleshare.com" + scribbleshare.domain: "scribbleshare.com:8080" + scribbleshare.origin: "http://scribbleshare.com" # scribbleshare.redis.url: "redis://default:changeme@scribbleshare-keydb:6379" # App backend scribbleshare-app: @@ -36,6 +37,7 @@ services: scribbleshare.postgres.user: "scribbleshare_backend" scribbleshare.postgres.password: "changeme" scribbleshare.domain: "scribbleshare.com" + scribbleshare.origin: "http://scribbleshare.com" # scribbleshare.redis.url: "redis://default:changeme@scribbleshare-keydb:6379" # Reverse proxy # scribbleshare-nginx: diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java index cfb3b0f7..cf7d5185 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java @@ -14,6 +14,7 @@ import net.stzups.scribbleshare.server.http.HttpServerHandler; import net.stzups.scribbleshare.server.http.HttpServerInitializer; import net.stzups.scribbleshare.server.http.handler.handlers.FileRequestHandler; +import net.stzups.scribbleshare.server.http.handler.handlers.OriginHandler; import javax.net.ssl.SSLException; @@ -23,7 +24,8 @@ public class BackendHttpServerInitializer extends HttpServerInitializer { public BackendHttpServerInitializer(ScribbleshareBackendConfig config, ScribbleshareDatabase database) throws SSLException { super(config); - httpServerHandler = new DefaultHttpServerHandler(config) + httpServerHandler = new DefaultHttpServerHandler() + .addLast(new OriginHandler(config)) .addLast(new DocumentRequestHandler(config, database)) .addLast(new LoginRequestHandler(config, database)) .addLast(new LogoutRequestHandler(config, database)) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/DefaultHttpServerHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/DefaultHttpServerHandler.java index 5e2b0522..d1a8eb8b 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/DefaultHttpServerHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/DefaultHttpServerHandler.java @@ -1,14 +1,11 @@ package net.stzups.scribbleshare.server.http; -import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.server.http.handler.handlers.HealthcheckRequestHandler; import net.stzups.scribbleshare.server.http.handler.handlers.LogHandler; -import net.stzups.scribbleshare.server.http.handler.handlers.OriginHandler; public class DefaultHttpServerHandler extends HttpServerHandler { - public DefaultHttpServerHandler(HttpConfig config) { + public DefaultHttpServerHandler() { addLast(new HealthcheckRequestHandler()) - .addLast(new LogHandler()) - .addLast(new OriginHandler(config, config.getOrigin())); + .addLast(new LogHandler()); } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java index d73df1e3..86768e83 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/RequestHandler.java @@ -8,24 +8,20 @@ import net.stzups.scribbleshare.server.http.exception.exceptions.UnauthorizedException; public abstract class RequestHandler extends HttpHandler { - private final HttpConfig config; private final String referer; protected RequestHandler(HttpConfig config, String referer, String route) { super(route); - this.config = config; - this.referer = referer; + this.referer = config.getOrigin() + referer; } @Override public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { String referer = request.headers().get(HttpHeaderNames.REFERER); - if (referer != null) { - String string = (config.getSSL() ? "https://" : "http://") + config.getDomain(); - if (!referer.equals(string + this.referer) && !referer.equals(string + ":" + config.getPort() + this.referer)) { // https://example.com/referer or https://example.com:1234/referer - throw new UnauthorizedException("Bad referer for " + getRoute() + ", got " + HttpHeaderNames.REFERER + ": " + referer + ", should have been referred from " + this.referer); - } + if (referer != null && !referer.equals(this.referer)) { + throw new UnauthorizedException("Bad referer for " + getRoute() + ", got " + HttpHeaderNames.REFERER + ": " + referer + ", should have been referred from " + this.referer); } + handleRequest(ctx, request); return true; } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/OriginHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/OriginHandler.java index f8acb428..bb9ce534 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/OriginHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/OriginHandler.java @@ -3,41 +3,24 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpResponseStatus; -import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; -import net.stzups.scribbleshare.server.http.HttpUtils; import net.stzups.scribbleshare.server.http.exception.HttpException; +import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; import net.stzups.scribbleshare.server.http.handler.HttpHandler; public class OriginHandler extends HttpHandler { - private final HttpConfig config; private final String origin; public OriginHandler(HttpConfig config) { - this(config, null); - } - - public OriginHandler(HttpConfig config, String origin) { super("/"); - this.config = config; - this.origin = origin; + this.origin = config.getOrigin(); } @Override public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { String origin = request.headers().get(HttpHeaderNames.ORIGIN); - if (origin != null) { - String string = (config.getSSL() ? "https://" : "http://") + config.getDomain(); - if (!origin.equals(this.origin) && !origin.equals(string) && !origin.equals(string + ":" + config.getPort())) { - if (this.origin != null) { // null for a warning - Scribbleshare.getLogger(ctx).warning("Unknown origin " + origin + ", serving 404"); - HttpUtils.send(ctx, request, HttpResponseStatus.NOT_FOUND); - return true; - } else { - Scribbleshare.getLogger(ctx).warning("Unknown origin " + origin + ", request will still be handled normally"); - } - } + if (origin != null && !origin.equals(this.origin)) { + throw new NotFoundException("Unknown origin " + origin + ", should have been " + this.origin); } return false; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/RefererHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/RefererHandler.java deleted file mode 100644 index ccdfa296..00000000 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/RefererHandler.java +++ /dev/null @@ -1,45 +0,0 @@ -package net.stzups.scribbleshare.server.http.handler.handlers; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpResponseStatus; -import net.stzups.scribbleshare.Scribbleshare; -import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; -import net.stzups.scribbleshare.server.http.HttpUtils; -import net.stzups.scribbleshare.server.http.exception.HttpException; -import net.stzups.scribbleshare.server.http.handler.HttpHandler; - -public class RefererHandler extends HttpHandler { - private final HttpConfig config; - private final String origin; - - public RefererHandler(HttpConfig config) { - this(config, null); - } - - public RefererHandler(HttpConfig config, String origin) { - super("/"); - this.config = config; - this.origin = origin; - } - - @Override - public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { - String referer = request.headers().get(HttpHeaderNames.REFERER); - if (referer != null) { - String string = (config.getSSL() ? "https://" : "http://") + config.getDomain(); - if (!(this.origin != null && referer.startsWith(this.origin)) && !referer.startsWith(string) && !referer.startsWith(string + ":" + config.getPort())) { - if (this.origin != null) { // null for a warning - Scribbleshare.getLogger(ctx).warning("Unknown referer " + referer + ", serving 404"); - HttpUtils.send(ctx, request, HttpResponseStatus.NOT_FOUND); - return true; - } else { - Scribbleshare.getLogger(ctx).warning("Unknown referer " + referer + ", request will still be handled normally"); - } - } - } - - return false; - } -} diff --git a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java index b306fb31..ff8094f5 100644 --- a/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java +++ b/scribbleshare-room/src/main/java/net/stzups/scribbleshare/room/server/RoomHttpServerInitializer.java @@ -18,6 +18,7 @@ import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; import net.stzups.scribbleshare.server.http.handler.HttpHandler; import net.stzups.scribbleshare.server.http.handler.handlers.HttpAuthenticator; +import net.stzups.scribbleshare.server.http.handler.handlers.OriginHandler; import javax.net.ssl.SSLException; @@ -47,7 +48,8 @@ public RoomHttpServerInitializer(Config config, ScribbleshareDatabase database) this.config = config; this.database = database; clientMessageHandler = new ClientMessageHandler(); - httpServerHandler = new DefaultHttpServerHandler(config) + httpServerHandler = new DefaultHttpServerHandler() + .addLast(new OriginHandler(config)) .addLast(new HttpHandler("/") { @Override public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws NotFoundException { From a11c53d3fd52f9ca8034c294becf22acd6e66d6b Mon Sep 17 00:00:00 2001 From: stzups Date: Sat, 29 May 2021 16:29:19 -0400 Subject: [PATCH 128/144] logging --- .../http/handler/handlers/LogHandler.java | 19 ++++++++++++++++++- .../http/handler/handlers/OriginHandler.java | 4 ++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/LogHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/LogHandler.java index b76e31fb..418e5164 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/LogHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/LogHandler.java @@ -2,6 +2,7 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaderNames; import net.stzups.scribbleshare.Scribbleshare; import net.stzups.scribbleshare.server.http.exception.HttpException; import net.stzups.scribbleshare.server.http.handler.HttpHandler; @@ -13,7 +14,23 @@ public LogHandler() { @Override public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { - Scribbleshare.getLogger(ctx).info(request.method() + " " + request.uri()); + Scribbleshare.getLogger(ctx).info(log("user-agent", request.headers().get(HttpHeaderNames.USER_AGENT), 40) + log("origin", request.headers().get(HttpHeaderNames.ORIGIN)) + log("referer", request.headers().get(HttpHeaderNames.REFERER)) + request.method() + " " + request.uri() + " " + request.protocolVersion()); return false; } + + private static String log(String key, String value) { + return log(key, value, -1); + } + + private static String log(String key, String value, int limit) { + if (value == null) { + return ""; + } else { + if (limit > 0) { + return key + ": " + value.substring(0, Math.min(value.length(), limit)) + ", "; + } else { + return key + ": " + value + ", "; + } + } + } } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/OriginHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/OriginHandler.java index bb9ce534..74c43c26 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/OriginHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/OriginHandler.java @@ -5,7 +5,7 @@ import io.netty.handler.codec.http.HttpHeaderNames; import net.stzups.scribbleshare.data.objects.authentication.http.HttpConfig; import net.stzups.scribbleshare.server.http.exception.HttpException; -import net.stzups.scribbleshare.server.http.exception.exceptions.NotFoundException; +import net.stzups.scribbleshare.server.http.exception.exceptions.UnauthorizedException; import net.stzups.scribbleshare.server.http.handler.HttpHandler; public class OriginHandler extends HttpHandler { @@ -20,7 +20,7 @@ public OriginHandler(HttpConfig config) { public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { String origin = request.headers().get(HttpHeaderNames.ORIGIN); if (origin != null && !origin.equals(this.origin)) { - throw new NotFoundException("Unknown origin " + origin + ", should have been " + this.origin); + throw new UnauthorizedException("Unknown origin " + origin + ", should have been " + this.origin); } return false; From 9a3c877a8e54410d907301ab0caa449e4c4e7a74 Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 30 May 2021 10:24:07 -0400 Subject: [PATCH 129/144] finally add slf4j impl --- scribbleshare-commons/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/scribbleshare-commons/build.gradle b/scribbleshare-commons/build.gradle index 8bc06697..ad037b37 100644 --- a/scribbleshare-commons/build.gradle +++ b/scribbleshare-commons/build.gradle @@ -7,6 +7,7 @@ apply from: rootProject.file('gradle/jmh.gradle') dependencies { api 'io.netty:netty-all:4.1.55.Final' + compile 'org.slf4j:slf4j-simple:1.7.30' implementation 'org.postgresql:postgresql:42.2.13' implementation 'redis.clients:jedis:3.5.2' implementation 'at.favre.lib:bcrypt:0.9.0' From 18290ab0cc1fe78b9bc238896ffe10e2147993fb Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 30 May 2021 11:35:37 -0400 Subject: [PATCH 130/144] rework origin and logging --- .../backend/server/BackendHttpServerInitializer.java | 2 -- .../stzups/scribbleshare/server/http/HttpServerHandler.java | 6 +++++- .../server/http/handler/handlers/LogHandler.java | 4 ++-- .../server/http/handler/handlers/OriginHandler.java | 2 +- .../main/java/net/stzups/scribbleshare/util/LogFactory.java | 3 +-- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java index cf7d5185..382666ca 100644 --- a/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java +++ b/scribbleshare-app/scribbleshare-backend/src/main/java/net/stzups/scribbleshare/backend/server/BackendHttpServerInitializer.java @@ -14,7 +14,6 @@ import net.stzups.scribbleshare.server.http.HttpServerHandler; import net.stzups.scribbleshare.server.http.HttpServerInitializer; import net.stzups.scribbleshare.server.http.handler.handlers.FileRequestHandler; -import net.stzups.scribbleshare.server.http.handler.handlers.OriginHandler; import javax.net.ssl.SSLException; @@ -25,7 +24,6 @@ public class BackendHttpServerInitializer extends HttpServerInitializer { public BackendHttpServerInitializer(ScribbleshareBackendConfig config, ScribbleshareDatabase database) throws SSLException { super(config); httpServerHandler = new DefaultHttpServerHandler() - .addLast(new OriginHandler(config)) .addLast(new DocumentRequestHandler(config, database)) .addLast(new LoginRequestHandler(config, database)) .addLast(new LogoutRequestHandler(config, database)) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java index 66d74731..bbb27bf5 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/HttpServerHandler.java @@ -43,7 +43,11 @@ protected void decode(ChannelHandlerContext ctx, FullHttpRequest request, List 0) { + if (limit >= 0) { return key + ": " + value.substring(0, Math.min(value.length(), limit)) + ", "; } else { return key + ": " + value + ", "; diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/OriginHandler.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/OriginHandler.java index 74c43c26..3f409027 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/OriginHandler.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/server/http/handler/handlers/OriginHandler.java @@ -19,7 +19,7 @@ public OriginHandler(HttpConfig config) { @Override public boolean handle(ChannelHandlerContext ctx, FullHttpRequest request) throws HttpException { String origin = request.headers().get(HttpHeaderNames.ORIGIN); - if (origin != null && !origin.equals(this.origin)) { + if (origin == null || !origin.equals(this.origin)) { throw new UnauthorizedException("Unknown origin " + origin + ", should have been " + this.origin); } diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/LogFactory.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/LogFactory.java index 8b778e64..2180ea2f 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/LogFactory.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/util/LogFactory.java @@ -48,10 +48,9 @@ public static void setLogger(Logger logger, String name) { handler.setFormatter(new Formatter() { @Override public String format(LogRecord record) { - String level = (record.getLevel() == Level.INFO) ? "" : "[" + record.getLevel() + "] "; // include Logger Level if it is not Level.INFO return FORMAT.format(Date.from(Instant.now())) + + ((record.getLevel() == Level.INFO) ? "" : "[" + record.getLevel() + "] ") // include Logger Level if it is not Level.INFO + "[" + name + "] " - + level + record.getMessage() + System.lineSeparator() + ((record.getThrown() == null) ? "" : getStackTrace(record.getThrown())); From 8384cacb68409dff25fb20709ac56fbe232c0c35 Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 30 May 2021 11:46:02 -0400 Subject: [PATCH 131/144] fix login causing postgres warnings --- .../data/database/implementations/PostgresDatabase.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java index da4ce02f..e2b0475a 100644 --- a/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java +++ b/scribbleshare-commons/src/main/java/net/stzups/scribbleshare/data/database/implementations/PostgresDatabase.java @@ -51,17 +51,20 @@ public Login getLogin(String username) throws DatabaseException { @Override public boolean addLogin(Login login) throws DatabaseException { + if (getLogin(login.getUsername()) != null) { + return false; + } try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO logins(username, user_id, hashed_password) VALUES(?, ?, ?)")) { preparedStatement.setString(1, login.getUsername()); preparedStatement.setLong(2, login.getId()); preparedStatement.setBinaryStream(3, new ByteArrayInputStream(login.getHashedPassword())); preparedStatement.execute(); } catch (SQLException e) { - if (e.getSQLState().equals("23505")) { // PostgreSQL error code unique_violation + /*if (e.getSQLState().equals("23505")) { // PostgreSQL error code unique_violation return false; } else { - throw new DatabaseException(e); - } + }*/ + throw new DatabaseException(e); } return true; From 30a94376af029405e5fa95c6de9efe98aa896d63 Mon Sep 17 00:00:00 2001 From: stzups Date: Sun, 30 May 2021 15:05:09 -0400 Subject: [PATCH 132/144] rework js for multi stuff --- .../scribbleshare-frontend/rollup.config.js | 42 ++++++++++++------- .../scribbleshare-frontend/src/index.css | 6 +++ .../scribbleshare-frontend/src/index.html | 2 +- .../scribbleshare-frontend/src/login.html | 2 +- .../scribbleshare-frontend/src/logout.html | 3 +- .../src/scripts/{ => common}/Client.ts | 0 .../src/scripts/{ => common}/Color.ts | 0 .../src/scripts/{ => common}/ColorSelector.ts | 0 .../src/scripts/{ => common}/Document.ts | 0 .../src/scripts/{ => common}/Environment.ts | 0 .../src/scripts/{ => common}/FileUpload.ts | 0 .../src/scripts/{ => common}/Invite.ts | 0 .../src/scripts/{ => common}/Login.ts | 29 +++++++------ .../src/scripts/{ => common}/Modal.ts | 0 .../src/scripts/{ => common}/Mouse.ts | 0 .../src/scripts/{ => common}/MouseMove.ts | 0 .../src/scripts/{ => common}/ShapeSelector.ts | 0 .../src/scripts/{ => common}/Sidebar.ts | 0 .../src/scripts/{ => common}/ToolSelector.ts | 0 .../src/scripts/{ => common}/User.ts | 2 +- .../src/scripts/{ => common}/api/Api.ts | 0 .../api/protocol/request/ApiRequest.ts | 0 .../protocol/request/requests/LoginRequest.ts | 0 .../request/requests/RegisterRequest.ts | 0 .../api/protocol/response/ApiResponse.ts | 0 .../protocol/response/error/ResponseError.ts | 0 .../response/responses/LoginResponse.ts | 0 .../response/responses/RegisterResponse.ts | 0 .../src/scripts/{ => common}/canvas/Canvas.ts | 0 .../canvas/canvasObject/CanvasObject.ts | 0 .../canvas/canvasObject/CanvasObjectType.ts | 0 .../canvas/canvasObject/EntityCanvasObject.ts | 0 .../canvasObject/canvasObjects/CanvasImage.ts | 0 .../canvasObject/canvasObjects/CanvasMouse.ts | 2 +- .../canvas/canvasObject/canvasObjects/Line.ts | 0 .../canvasObject/canvasObjects/Shape.ts | 0 .../canvas/canvasUpdate/CanvasUpdate.ts | 0 .../canvas/canvasUpdate/CanvasUpdateType.ts | 0 .../canvas/canvasUpdate/CanvasUpdates.ts | 0 .../canvasUpdates/CanvasUpdateDelete.ts | 0 .../canvasUpdates/CanvasUpdateInsert.ts | 0 .../canvasUpdates/CanvasUpdateMove.ts | 0 .../{ => common}/protocol/ByteBuffer.ts | 0 .../{ => common}/protocol/SocketEventType.ts | 0 .../{ => common}/protocol/WebSocketHandler.ts | 0 .../protocol/client/ClientMessage.ts | 0 .../protocol/client/ClientMessageType.ts | 0 .../messages/ClientMessageCanvasUpdate.ts | 2 +- .../messages/ClientMessageCreateDocument.ts | 0 .../messages/ClientMessageDeleteDocument.ts | 0 .../client/messages/ClientMessageGetInvite.ts | 0 .../client/messages/ClientMessageHandshake.ts | 0 .../client/messages/ClientMessageMouseMove.ts | 0 .../messages/ClientMessageOpenDocument.ts | 0 .../messages/ClientMessageUpdateDocument.ts | 0 .../protocol/server/ServerMessage.ts | 0 .../protocol/server/ServerMessageType.ts | 0 .../server/messages/ServerMessageAddClient.ts | 0 .../server/messages/ServerMessageAddUser.ts | 0 .../messages/ServerMessageCanvasUpdate.ts | 0 .../messages/ServerMessageDeleteDocument.ts | 0 .../server/messages/ServerMessageGetInvite.ts | 0 .../server/messages/ServerMessageHandshake.ts | 0 .../server/messages/ServerMessageMouseMove.ts | 0 .../messages/ServerMessageOpenDocument.ts | 0 .../messages/ServerMessageRemoveClient.ts | 0 .../messages/ServerMessageUpdateDocument.ts | 0 .../src/scripts/index.ts | 2 + .../src/scripts/logout.ts | 6 +++ .../src/scripts/main.ts | 3 -- 70 files changed, 62 insertions(+), 39 deletions(-) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/Client.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/Color.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/ColorSelector.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/Document.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/Environment.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/FileUpload.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/Invite.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/Login.ts (55%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/Modal.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/Mouse.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/MouseMove.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/ShapeSelector.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/Sidebar.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/ToolSelector.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/User.ts (97%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/api/Api.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/api/protocol/request/ApiRequest.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/api/protocol/request/requests/LoginRequest.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/api/protocol/request/requests/RegisterRequest.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/api/protocol/response/ApiResponse.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/api/protocol/response/error/ResponseError.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/api/protocol/response/responses/LoginResponse.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/api/protocol/response/responses/RegisterResponse.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/canvas/Canvas.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/canvas/canvasObject/CanvasObject.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/canvas/canvasObject/CanvasObjectType.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/canvas/canvasObject/EntityCanvasObject.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/canvas/canvasObject/canvasObjects/CanvasImage.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/canvas/canvasObject/canvasObjects/CanvasMouse.ts (92%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/canvas/canvasObject/canvasObjects/Line.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/canvas/canvasObject/canvasObjects/Shape.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/canvas/canvasUpdate/CanvasUpdate.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/canvas/canvasUpdate/CanvasUpdateType.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/canvas/canvasUpdate/CanvasUpdates.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/canvas/canvasUpdate/canvasUpdates/CanvasUpdateDelete.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/canvas/canvasUpdate/canvasUpdates/CanvasUpdateInsert.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/canvas/canvasUpdate/canvasUpdates/CanvasUpdateMove.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/ByteBuffer.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/SocketEventType.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/WebSocketHandler.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/client/ClientMessage.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/client/ClientMessageType.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/client/messages/ClientMessageCanvasUpdate.ts (98%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/client/messages/ClientMessageCreateDocument.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/client/messages/ClientMessageDeleteDocument.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/client/messages/ClientMessageGetInvite.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/client/messages/ClientMessageHandshake.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/client/messages/ClientMessageMouseMove.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/client/messages/ClientMessageOpenDocument.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/client/messages/ClientMessageUpdateDocument.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/server/ServerMessage.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/server/ServerMessageType.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/server/messages/ServerMessageAddClient.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/server/messages/ServerMessageAddUser.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/server/messages/ServerMessageCanvasUpdate.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/server/messages/ServerMessageDeleteDocument.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/server/messages/ServerMessageGetInvite.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/server/messages/ServerMessageHandshake.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/server/messages/ServerMessageMouseMove.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/server/messages/ServerMessageOpenDocument.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/server/messages/ServerMessageRemoveClient.ts (100%) rename scribbleshare-app/scribbleshare-frontend/src/scripts/{ => common}/protocol/server/messages/ServerMessageUpdateDocument.ts (100%) create mode 100644 scribbleshare-app/scribbleshare-frontend/src/scripts/index.ts create mode 100644 scribbleshare-app/scribbleshare-frontend/src/scripts/logout.ts delete mode 100644 scribbleshare-app/scribbleshare-frontend/src/scripts/main.ts diff --git a/scribbleshare-app/scribbleshare-frontend/rollup.config.js b/scribbleshare-app/scribbleshare-frontend/rollup.config.js index aa2d9857..3b9c2ec5 100644 --- a/scribbleshare-app/scribbleshare-frontend/rollup.config.js +++ b/scribbleshare-app/scribbleshare-frontend/rollup.config.js @@ -2,19 +2,31 @@ import {nodeResolve} from '@rollup/plugin-node-resolve'; import typescript from '@rollup/plugin-typescript'; import {terser} from "rollup-plugin-terser"; -export default { - input: 'src/scripts/main.ts', - output: { - file: 'build/scripts/main.js', - format: 'iife', +const plugins = [ + nodeResolve(), + terser({ + mangle: { + properties:true, + }, + }), + typescript(), +] + +export default [ + { + input: 'src/scripts/index.ts', + output: { + file: 'build/scripts/index.js', + format: 'iife', + }, + plugins: plugins }, - plugins: [ - nodeResolve(), - terser({ - mangle: { - properties:true, - }, - }), - typescript(), - ] -}; + { + input: 'src/scripts/logout.ts', + output: { + file: 'build/scripts/logout.js', + format: 'iife', + }, + plugins: plugins + } +]; diff --git a/scribbleshare-app/scribbleshare-frontend/src/index.css b/scribbleshare-app/scribbleshare-frontend/src/index.css index 6364c2f0..6a70a219 100644 --- a/scribbleshare-app/scribbleshare-frontend/src/index.css +++ b/scribbleshare-app/scribbleshare-frontend/src/index.css @@ -110,4 +110,10 @@ aside button:active { input[type="radio"] { visibility: hidden; +} + +#loginModal { + display: flex; + flex-direction: column; + justify-content: flex-end; } \ No newline at end of file diff --git a/scribbleshare-app/scribbleshare-frontend/src/index.html b/scribbleshare-app/scribbleshare-frontend/src/index.html index c5ad8efa..2a3ec6df 100644 --- a/scribbleshare-app/scribbleshare-frontend/src/index.html +++ b/scribbleshare-app/scribbleshare-frontend/src/index.html @@ -6,7 +6,7 @@ - +