diff --git a/src/at/nanopenguin/mtcg/application/SessionHandler.java b/src/at/nanopenguin/mtcg/application/SessionHandler.java index 33c9309..a2c7218 100644 --- a/src/at/nanopenguin/mtcg/application/SessionHandler.java +++ b/src/at/nanopenguin/mtcg/application/SessionHandler.java @@ -6,7 +6,6 @@ import at.nanopenguin.mtcg.db.SqlCommand; import at.nanopenguin.mtcg.db.Table; import lombok.val; -import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; @@ -14,7 +13,7 @@ import java.util.UUID; public final class SessionHandler { private static SessionHandler INSTANCE; - private final Map Sessions = new HashMap<>(); + private final Map Sessions = new HashMap<>(); private SessionHandler() { @@ -34,19 +33,38 @@ public final class SessionHandler { .table(Table.USERS) .column("id") .column("password") + .column("admin") .condition("username", userCredentials.username()) .executeQuery(); if (result.isEmpty()) { // user not found return null; } - if (!result.get(0).get("password").equals(userCredentials.password())) { + + val row1 = result.get(0); + if (!row1.get("password").equals(userCredentials.password())) { // wrong password return null; } UUID uuid = UUID.randomUUID(); - this.Sessions.put(uuid, (Integer) result.get(0).get("id")); + this.Sessions.put(uuid, new UserInfo((int) row1.get("id"), userCredentials.username(), (boolean) row1.get("admin"))); return uuid; } + + public boolean verifyUUID(UUID uuid) { + return verifyUUID(uuid, false); + } + + public boolean verifyUUID(UUID uuid, boolean requireAdmin) { + return Sessions.containsKey(uuid) && (!requireAdmin || Sessions.get(uuid).admin()); + } + + public boolean verifyUUID(UUID uuid, String username) { + return verifyUUID(uuid, username, false); + } + + public boolean verifyUUID(UUID uuid, String username, boolean allowAdmin) { + return Sessions.containsKey(uuid) && (username.equals(Sessions.get(uuid).username()) || (allowAdmin && Sessions.get(uuid).admin())); + } } diff --git a/src/at/nanopenguin/mtcg/application/UserInfo.java b/src/at/nanopenguin/mtcg/application/UserInfo.java new file mode 100644 index 0000000..f547784 --- /dev/null +++ b/src/at/nanopenguin/mtcg/application/UserInfo.java @@ -0,0 +1,4 @@ +package at.nanopenguin.mtcg.application; + +public record UserInfo(int id, String username, boolean admin) { +} diff --git a/src/at/nanopenguin/mtcg/application/service/UserService.java b/src/at/nanopenguin/mtcg/application/service/UserService.java index 89df042..6e60458 100644 --- a/src/at/nanopenguin/mtcg/application/service/UserService.java +++ b/src/at/nanopenguin/mtcg/application/service/UserService.java @@ -3,12 +3,17 @@ package at.nanopenguin.mtcg.application.service; import at.nanopenguin.mtcg.application.SessionHandler; import at.nanopenguin.mtcg.application.User; import at.nanopenguin.mtcg.application.service.schemas.UserCredentials; +import at.nanopenguin.mtcg.application.service.schemas.UserData; +import at.nanopenguin.mtcg.db.DbQuery; +import at.nanopenguin.mtcg.db.SqlCommand; +import at.nanopenguin.mtcg.db.Table; import at.nanopenguin.mtcg.http.HttpMethod; import at.nanopenguin.mtcg.http.HttpRequest; import at.nanopenguin.mtcg.http.HttpStatus; import at.nanopenguin.mtcg.http.Response; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.val; import java.sql.SQLException; import java.util.UUID; @@ -28,12 +33,41 @@ public class UserService implements Service { if (request.getPath().split("/")[1].equals("users")) { return switch (request.getMethod()) { - case GET -> new Response(HttpStatus.NOT_IMPLEMENTED); + case GET -> { + String username = request.getPath().split("/")[2]; + if (request.getHttpHeader("Authorization") == null || !SessionHandler.getInstance().verifyUUID(UUID.fromString(request.getHttpHeader("Authorization").replaceFirst("^Bearer ", "")), username, true)) + yield new Response(HttpStatus.UNAUTHORIZED); + val result = DbQuery.builder() + .command(SqlCommand.SELECT) + .table(Table.USERS) + .condition("username", username) + .executeQuery(); + if (result.isEmpty()) yield new Response(HttpStatus.NOT_FOUND); + val row1 = result.get(0); + UserData userData = new UserData((String) row1.get("name"), (String) row1.get("bio"), (String) row1.get("image")); + yield new Response(HttpStatus.OK, "application/json", new ObjectMapper().writeValueAsString(userData)); + } case POST -> { // register new user int success = User.create(new ObjectMapper().readValue(request.getBody(), UserCredentials.class)); yield new Response(success > 0 ? HttpStatus.CREATED : HttpStatus.CONFLICT); } - case PUT -> new Response(HttpStatus.NOT_IMPLEMENTED); // new ObjectMapper().readValue(request.getBody(), UserData.class); + case PUT -> { + String username = request.getPath().split("/")[2]; + UserData userData = new ObjectMapper().readValue(request.getBody(), UserData.class); + if (request.getHttpHeader("Authorization") == null || !SessionHandler.getInstance().verifyUUID(UUID.fromString(request.getHttpHeader("Authorization").replaceFirst("^Bearer ", "")), username, true)) + yield new Response(HttpStatus.UNAUTHORIZED); + if (DbQuery.builder() + .command(SqlCommand.UPDATE) + .table(Table.USERS) + .parameter("name", userData.name()) + .parameter("bio", userData.bio()) + .parameter("image", userData.image()) + .condition("username", username) + .executeUpdate() == 1) { + yield new Response(HttpStatus.OK); + } + yield new Response(HttpStatus.NOT_FOUND); + } default -> new Response(HttpStatus.NOT_FOUND); }; } @@ -42,7 +76,8 @@ public class UserService implements Service { } catch (ArrayIndexOutOfBoundsException e) { return new Response(HttpStatus.BAD_REQUEST); - } catch (SQLException e) { + } + catch (SQLException e) { System.out.println(e.getMessage()); return new Response(HttpStatus.INTERNAL); } diff --git a/src/at/nanopenguin/mtcg/http/HttpRequest.java b/src/at/nanopenguin/mtcg/http/HttpRequest.java index 4a6aeb4..6fe4b62 100644 --- a/src/at/nanopenguin/mtcg/http/HttpRequest.java +++ b/src/at/nanopenguin/mtcg/http/HttpRequest.java @@ -32,11 +32,9 @@ public class HttpRequest { this.httpHeaders.put(headerEntry[0], headerEntry[1]); } - // this.body = this.httpHeaders.containsKey("Content-Length") ? new String(new char[Integer.parseInt(this.httpHeaders.get("Content-Length"))]) : null; - int contentLength = Integer.parseInt(this.httpHeaders.get("Content-Length")); + int contentLength = this.httpHeaders.containsKey("Content-Length") ? Integer.parseInt(this.httpHeaders.get("Content-Length")) : 0; char[] charBuffer = new char[contentLength]; this.body = br.read(charBuffer, 0, contentLength) > 0 ? new String(charBuffer) : null; - return; } diff --git a/src/at/nanopenguin/mtcg/http/RequestHandler.java b/src/at/nanopenguin/mtcg/http/RequestHandler.java index d45bbbe..ab13d28 100644 --- a/src/at/nanopenguin/mtcg/http/RequestHandler.java +++ b/src/at/nanopenguin/mtcg/http/RequestHandler.java @@ -26,6 +26,7 @@ public class RequestHandler implements Runnable { Response response; responseBuilder: { if (httpRequest.getMethod() == null) { + System.out.println("Thanks, postman"); return; }