From 0a22f55e4ef5c7b0d4d58211af6b1bfd6beea515 Mon Sep 17 00:00:00 2001 From: jeffcheasey88 <66554203+jeffcheasey88@users.noreply.github.com> Date: Sun, 9 Apr 2023 21:31:42 +0200 Subject: [PATCH] Group Join & Quit --- src/be/jeffcheasey88/peeratcode/Main.java | 16 ++-- .../peeratcode/framework/Client.java | 27 +++--- .../peeratcode/framework/HttpUtil.java | 94 +++++++++---------- .../peeratcode/framework/HttpWriter.java | 12 +-- .../peeratcode/framework/RequestType.java | 7 ++ .../peeratcode/framework/Route.java | 4 +- .../peeratcode/framework/Router.java | 35 ++++--- .../peeratcode/framework/User.java | 6 +- .../peeratcode/repository/DatabaseQuery.java | 11 ++- .../repository/DatabaseRepository.java | 48 +++++++++- .../peeratcode/routes/BadgeDetails.java | 1 - .../peeratcode/routes/ChapterElement.java | 1 - .../peeratcode/routes/ChapterList.java | 1 - .../peeratcode/routes/Leaderboard.java | 1 - .../peeratcode/routes/Login.java | 5 +- .../peeratcode/routes/PlayerDetails.java | 1 - .../peeratcode/routes/PuzzleElement.java | 1 - .../peeratcode/routes/PuzzleResponse.java | 5 +- .../peeratcode/routes/Register.java | 5 +- .../peeratcode/routes/Result.java | 1 - .../peeratcode/routes/groups/CreateGroup.java | 7 +- .../peeratcode/routes/groups/GroupJoin.java | 37 ++++++++ .../peeratcode/routes/groups/GroupList.java | 4 +- .../peeratcode/routes/groups/GroupQuit.java | 37 ++++++++ 24 files changed, 238 insertions(+), 129 deletions(-) create mode 100644 src/be/jeffcheasey88/peeratcode/framework/RequestType.java create mode 100644 src/be/jeffcheasey88/peeratcode/routes/groups/GroupJoin.java create mode 100644 src/be/jeffcheasey88/peeratcode/routes/groups/GroupQuit.java diff --git a/src/be/jeffcheasey88/peeratcode/Main.java b/src/be/jeffcheasey88/peeratcode/Main.java index dd5ed3a..587b1de 100644 --- a/src/be/jeffcheasey88/peeratcode/Main.java +++ b/src/be/jeffcheasey88/peeratcode/Main.java @@ -1,5 +1,7 @@ package be.jeffcheasey88.peeratcode; +import static be.jeffcheasey88.peeratcode.framework.RequestType.OPTIONS; + import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; @@ -8,9 +10,6 @@ import java.util.regex.Matcher; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; -import org.jose4j.jwk.RsaJsonWebKey; -import org.jose4j.jwk.RsaJwkGenerator; - import be.jeffcheasey88.peeratcode.framework.Client; import be.jeffcheasey88.peeratcode.framework.HttpReader; import be.jeffcheasey88.peeratcode.framework.HttpUtil; @@ -31,7 +30,9 @@ import be.jeffcheasey88.peeratcode.routes.PuzzleResponse; import be.jeffcheasey88.peeratcode.routes.Register; import be.jeffcheasey88.peeratcode.routes.Result; import be.jeffcheasey88.peeratcode.routes.groups.CreateGroup; +import be.jeffcheasey88.peeratcode.routes.groups.GroupJoin; import be.jeffcheasey88.peeratcode.routes.groups.GroupList; +import be.jeffcheasey88.peeratcode.routes.groups.GroupQuit; public class Main { public static void main(String[] args) throws Exception { @@ -54,7 +55,7 @@ public class Main { }); router.register(new Response() { - @Route(path = "^(.*)$", type = "OPTIONS") + @Route(path = "^(.*)$", type = OPTIONS) @Override public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { HttpUtil.responseHeaders(writer, 200, "Access-Control-Allow-Origin: *", @@ -81,6 +82,8 @@ public class Main { router.register(new GroupList(router.getDataBase())); router.register(new CreateGroup(router.getDataBase())); + router.register(new GroupJoin(router.getDataBase())); + router.register(new GroupQuit(router.getDataBase())); } private static void startWebServer(Configuration config, Router router) throws IOException { @@ -95,7 +98,7 @@ public class Main { while (!server.isClosed()) { Socket socket = server.accept(); - Client client = new Client(socket, router, RsaJwkGenerator.generateJwk(2048)); + Client client = new Client(socket, router); client.start(); } } catch (Exception e) { @@ -109,8 +112,7 @@ public class Main { try (ServerSocket server = new ServerSocket(config.getTcpPort())) { while (!server.isClosed()) { Socket socket = server.accept(); - RsaJsonWebKey rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048); - Client client = new Client(socket, router, rsaJsonWebKey); + Client client = new Client(socket, router); client.start(); } } catch (Exception e) { diff --git a/src/be/jeffcheasey88/peeratcode/framework/Client.java b/src/be/jeffcheasey88/peeratcode/framework/Client.java index 7d1b9b6..15268d4 100644 --- a/src/be/jeffcheasey88/peeratcode/framework/Client.java +++ b/src/be/jeffcheasey88/peeratcode/framework/Client.java @@ -10,47 +10,46 @@ import org.jose4j.jwt.JwtClaims; import org.jose4j.jwt.consumer.JwtConsumer; import org.jose4j.jwt.consumer.JwtConsumerBuilder; -public class Client extends Thread { +public class Client extends Thread{ private HttpReader reader; private HttpWriter writer; private Router router; - private RsaJsonWebKey key; // Really needed ? - public Client(Socket socket, Router router, RsaJsonWebKey key) throws Exception { + public Client(Socket socket, Router router) throws Exception{ this.reader = new HttpReader(socket); this.writer = new HttpWriter(socket); this.router = router; - this.key = key; } @Override - public void run() { + public void run(){ try { String[] headers = reader.readLine().split("\\s"); System.out.println(Arrays.toString(headers)); - router.exec(headers[0], headers[1], isLogin(reader), reader, writer); + router.exec(RequestType.valueOf(headers[0]), headers[1], isLogin(reader), reader, writer); writer.flush(); writer.close(); - } catch (Exception e) { + }catch(Exception e){ e.printStackTrace(); } } - private User isLogin(HttpReader reader) throws Exception { + private User isLogin(HttpReader reader) throws Exception{ String auth = HttpUtil.readAuthorization(reader); - if (auth == null) - return null; - try { - JwtConsumer jwtConsumer = new JwtConsumerBuilder().setRequireExpirationTime() - .setAllowedClockSkewInSeconds(30).setExpectedIssuer(this.router.getTokenIssuer()) + if(auth == null) return null; + try{ + JwtConsumer jwtConsumer = new JwtConsumerBuilder() + .setRequireExpirationTime() + .setAllowedClockSkewInSeconds(30) + .setExpectedIssuer(this.router.getTokenIssuer()) .setVerificationKey(this.router.getWebKey().getKey()) .setJwsAlgorithmConstraints(ConstraintType.PERMIT, AlgorithmIdentifiers.RSA_USING_SHA256).build(); JwtClaims jwtClaims = jwtConsumer.processToClaims(auth); return new User(jwtClaims); - } catch (Exception e) { + }catch(Exception e){ HttpUtil.responseHeaders(writer, 401, "Access-Control-Allow-Origin: *"); writer.flush(); writer.close(); diff --git a/src/be/jeffcheasey88/peeratcode/framework/HttpUtil.java b/src/be/jeffcheasey88/peeratcode/framework/HttpUtil.java index 3740bf3..f93eee0 100644 --- a/src/be/jeffcheasey88/peeratcode/framework/HttpUtil.java +++ b/src/be/jeffcheasey88/peeratcode/framework/HttpUtil.java @@ -8,37 +8,34 @@ import java.util.regex.Pattern; import org.json.simple.parser.JSONParser; -public class HttpUtil { +public class HttpUtil{ - private HttpUtil() { - } + private HttpUtil(){} - public static void responseHeaders(HttpWriter writer, int code, String... headers) throws Exception { + public static void responseHeaders(HttpWriter writer, int code, String... headers) throws Exception{ writer.write("HTTP/1.1 " + code + " " + codeMessage(code) + "\n"); - for (String header : headers) - writer.write(header + "\n"); + for(String header : headers) writer.write(header + "\n"); writer.write("\n"); writer.flush(); } - public static void skipHeaders(HttpReader reader) throws Exception { + public static void skipHeaders(HttpReader reader) throws Exception{ String line; - while (((line = reader.readLine()) != null) && (line.length() > 0)) - ; + while(((line = reader.readLine()) != null) && (line.length() > 0)); } - public static List readMultiPartData(HttpReader reader) throws Exception { + public static List readMultiPartData(HttpReader reader) throws Exception{ List list = new ArrayList<>(); reader.readLine(); - while (reader.ready()) { + while(reader.ready()){ String line; - while (((line = reader.readLine()) != null) && (line.length() > 0)) { + while (((line = reader.readLine()) != null) && (line.length() > 0)){ } String buffer = ""; - while (((line = reader.readLine()) != null) && (!line.startsWith("------WebKitFormBoundary"))) { + while (((line = reader.readLine()) != null) && (!line.startsWith("------WebKitFormBoundary"))){ buffer += line; } list.add(buffer); @@ -47,44 +44,40 @@ public class HttpUtil { return list; } - public static void switchToWebSocket(HttpReader reader, HttpWriter writer) throws Exception { + public static void switchToWebSocket(HttpReader reader, HttpWriter writer) throws Exception{ String key = readWebSocketKey(reader); - if (key == null) - throw new IllegalArgumentException(); + if (key == null) throw new IllegalArgumentException(); writer.write("HTTP/1.1 101 Switching Protocols\n"); writer.write("Connection: Upgrade\n"); writer.write("Upgrade: websocket\n"); writer.write("Sec-WebSocket-Accept: " + printBase64Binary(MessageDigest.getInstance("SHA-1") - .digest((key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes("UTF-8"))) + "\n"); + .digest((key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes("UTF-8"))) + "\n"); writer.write("\n"); writer.flush(); } private static Pattern WEBSOCKET_KEY = Pattern.compile("Sec-WebSocket-Key: (.*)"); - public static String readWebSocketKey(HttpReader reader) throws Exception { + public static String readWebSocketKey(HttpReader reader) throws Exception{ String line; String key = null; - while (((line = reader.readLine()) != null) && (line.length() > 0)) { - if (key != null) { - continue; - } + while(((line = reader.readLine()) != null) && (line.length() > 0)){ + if(key != null) continue; Matcher matcher = WEBSOCKET_KEY.matcher(line); - if (matcher.matches()) - key = matcher.group(1); + if(matcher.matches()) key = matcher.group(1); } return key; } private static Pattern AUTORIZATION = Pattern.compile("Authorization: Bearer (.*)"); - public static String readAuthorization(HttpReader reader) throws Exception { + public static String readAuthorization(HttpReader reader) throws Exception{ String line; String key = null; - while (((line = reader.readLine()) != null) && (line.length() > 0)) { + while (((line = reader.readLine()) != null) && (line.length() > 0)){ Matcher matcher = AUTORIZATION.matcher(line); - if (matcher.matches()) { + if(matcher.matches()){ key = matcher.group(1); break; } @@ -92,34 +85,33 @@ public class HttpUtil { return key; } - public static Object readJson(HttpReader reader) throws Exception { + public static Object readJson(HttpReader reader) throws Exception{ String line = ""; - while (reader.ready()) { + while (reader.ready()){ char[] c = new char[1]; reader.read(c); line += c[0]; - if (c[0] == '}') { + if (c[0] == '}'){ Object parse; try { parse = new JSONParser().parse(line); if (parse != null) return parse; - } catch (Exception e) { - } + }catch(Exception e){} } } return null; } // I found this code on StackOverFlow !!!!! (and the write too) - public static String readWebSocket(HttpReader reader) throws Exception { + public static String readWebSocket(HttpReader reader) throws Exception{ int buffLenth = 1024; int len = 0; byte[] b = new byte[buffLenth]; // rawIn is a Socket.getInputStream(); - while (true) { + while (true){ len = reader.read(b); - if (len != -1) { + if (len != -1){ byte rLength = 0; int rMaskIndex = 2; int rDataStart = 0; @@ -137,7 +129,7 @@ public class HttpUtil { int j = 0; int i = 0; - for (i = rMaskIndex; i < (rMaskIndex + 4); i++) { + for (i = rMaskIndex; i < (rMaskIndex + 4); i++){ masks[j] = b[i]; j++; } @@ -148,7 +140,7 @@ public class HttpUtil { byte[] message = new byte[messLen]; - for (i = rDataStart, j = 0; i < len; i++, j++) { + for (i = rDataStart, j = 0; i < len; i++, j++){ message[j] = (byte) (b[i] ^ masks[j % 4]); } @@ -160,7 +152,7 @@ public class HttpUtil { return null; } - public static void sendWebSocket(HttpWriter writer, String message) throws Exception { + public static void sendWebSocket(HttpWriter writer, String message) throws Exception{ byte[] rawData = message.getBytes(); int frameCount = 0; @@ -168,10 +160,10 @@ public class HttpUtil { frame[0] = (byte) 129; - if (rawData.length <= 125) { + if (rawData.length <= 125){ frame[1] = (byte) rawData.length; frameCount = 2; - } else if (rawData.length >= 126 && rawData.length <= 65535) { + } else if (rawData.length >= 126 && rawData.length <= 65535){ frame[1] = (byte) 126; int len = rawData.length; frame[2] = (byte) ((len >> 8) & (byte) 255); @@ -196,11 +188,11 @@ public class HttpUtil { byte[] reply = new byte[bLength]; int bLim = 0; - for (int i = 0; i < frameCount; i++) { + for (int i = 0; i < frameCount; i++){ reply[bLim] = frame[i]; bLim++; } - for (int i = 0; i < rawData.length; i++) { + for (int i = 0; i < rawData.length; i++){ reply[bLim] = rawData[i]; bLim++; } @@ -209,8 +201,8 @@ public class HttpUtil { writer.flush(); } - private static String codeMessage(int paramInt) { - switch (paramInt) { + private static String codeMessage(int paramInt){ + switch (paramInt){ case 200: return " OK"; case 100: @@ -288,7 +280,7 @@ public class HttpUtil { } // From javax.xml.bind.DatatypeConverter - private static String printBase64Binary(byte[] array) { + private static String printBase64Binary(byte[] array){ char[] arrayOfChar = new char[(array.length + 2) / 3 * 4]; int i = _printBase64Binary(array, 0, array.length, arrayOfChar, 0); assert i == arrayOfChar.length; @@ -296,10 +288,10 @@ public class HttpUtil { } private static int _printBase64Binary(byte[] paramArrayOfbyte, int paramInt1, int paramInt2, - char[] paramArrayOfchar, int paramInt3) { + char[] paramArrayOfchar, int paramInt3){ int i = paramInt2; int j; - for (j = paramInt1; i >= 3; j += 3) { + for (j = paramInt1; i >= 3; j += 3){ paramArrayOfchar[paramInt3++] = encode(paramArrayOfbyte[j] >> 2); paramArrayOfchar[paramInt3++] = encode( (paramArrayOfbyte[j] & 0x3) << 4 | paramArrayOfbyte[j + 1] >> 4 & 0xF); @@ -308,13 +300,13 @@ public class HttpUtil { paramArrayOfchar[paramInt3++] = encode(paramArrayOfbyte[j + 2] & 0x3F); i -= 3; } - if (i == 1) { + if (i == 1){ paramArrayOfchar[paramInt3++] = encode(paramArrayOfbyte[j] >> 2); paramArrayOfchar[paramInt3++] = encode((paramArrayOfbyte[j] & 0x3) << 4); paramArrayOfchar[paramInt3++] = '='; paramArrayOfchar[paramInt3++] = '='; } - if (i == 2) { + if (i == 2){ paramArrayOfchar[paramInt3++] = encode(paramArrayOfbyte[j] >> 2); paramArrayOfchar[paramInt3++] = encode( (paramArrayOfbyte[j] & 0x3) << 4 | paramArrayOfbyte[j + 1] >> 4 & 0xF); @@ -324,13 +316,13 @@ public class HttpUtil { return paramInt3; } - private static char encode(int paramInt) { + private static char encode(int paramInt){ return encodeMap[paramInt & 0x3F]; } private static final char[] encodeMap = initEncodeMap(); - private static char[] initEncodeMap() { + private static char[] initEncodeMap(){ char[] arrayOfChar = new char[64]; byte b; for (b = 0; b < 26; b++) diff --git a/src/be/jeffcheasey88/peeratcode/framework/HttpWriter.java b/src/be/jeffcheasey88/peeratcode/framework/HttpWriter.java index 614f8fb..52bdd11 100644 --- a/src/be/jeffcheasey88/peeratcode/framework/HttpWriter.java +++ b/src/be/jeffcheasey88/peeratcode/framework/HttpWriter.java @@ -7,30 +7,30 @@ import java.io.OutputStreamWriter; import java.net.Socket; import java.nio.charset.StandardCharsets; -public class HttpWriter { +public class HttpWriter{ private OutputStream out; private BufferedWriter writer; - public HttpWriter(Socket socket) throws Exception { + public HttpWriter(Socket socket) throws Exception{ this.out = socket.getOutputStream(); this.writer = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8)); } - public void write(byte[] buffer) throws IOException { + public void write(byte[] buffer) throws IOException{ this.out.write(buffer); this.out.flush(); } - public void write(String message) throws IOException { + public void write(String message) throws IOException{ this.writer.write(message); } - public void flush() throws IOException { + public void flush() throws IOException{ this.writer.flush(); } - public void close() throws IOException { + public void close() throws IOException{ this.writer.close(); } } \ No newline at end of file diff --git a/src/be/jeffcheasey88/peeratcode/framework/RequestType.java b/src/be/jeffcheasey88/peeratcode/framework/RequestType.java new file mode 100644 index 0000000..8262f9c --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/framework/RequestType.java @@ -0,0 +1,7 @@ +package be.jeffcheasey88.peeratcode.framework; + +public enum RequestType { + + GET, POST, OPTIONS; + +} diff --git a/src/be/jeffcheasey88/peeratcode/framework/Route.java b/src/be/jeffcheasey88/peeratcode/framework/Route.java index 487eaaf..cec122b 100644 --- a/src/be/jeffcheasey88/peeratcode/framework/Route.java +++ b/src/be/jeffcheasey88/peeratcode/framework/Route.java @@ -7,11 +7,11 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) -public @interface Route { +public @interface Route{ String path() default "^.*$"; - String type() default "GET"; + RequestType type() default RequestType.GET; boolean needLogin() default false; diff --git a/src/be/jeffcheasey88/peeratcode/framework/Router.java b/src/be/jeffcheasey88/peeratcode/framework/Router.java index c1295bd..669c57e 100644 --- a/src/be/jeffcheasey88/peeratcode/framework/Router.java +++ b/src/be/jeffcheasey88/peeratcode/framework/Router.java @@ -16,7 +16,7 @@ import org.jose4j.lang.JoseException; import be.jeffcheasey88.peeratcode.repository.DatabaseRepository; -public class Router { +public class Router{ private Map responses; private Map patterns; @@ -26,7 +26,7 @@ public class Router { private String token_issuer; private int token_expiration; - public Router(DatabaseRepository repo, String token_issuer, int token_expiration) throws Exception { + public Router(DatabaseRepository repo, String token_issuer, int token_expiration) throws Exception{ this.repo = repo; this.token_issuer = token_issuer; this.token_expiration = token_expiration; @@ -35,52 +35,51 @@ public class Router { this.rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048); } - public DatabaseRepository getDataBase() { + public DatabaseRepository getDataBase(){ return this.repo; } - public void register(Response response) { - try { + public void register(Response response){ + try{ Method method = response.getClass().getDeclaredMethod("exec", Response.class.getDeclaredMethods()[0].getParameterTypes()); Route route = method.getAnnotation(Route.class); this.responses.put(response, route); this.patterns.put(response, Pattern.compile(route.path())); - } catch (Exception e) { + }catch(Exception e){ throw new IllegalArgumentException(e); } } - public void setDefault(Response response) { + public void setDefault(Response response){ this.noFileFound = response; } - public void exec(String type, String path, User user, HttpReader reader, HttpWriter writer) throws Exception { - for (Entry routes : this.responses.entrySet()) { - if (routes.getValue().type().equals(type)) { + public void exec(RequestType type, String path, User user, HttpReader reader, HttpWriter writer) throws Exception{ + if(type == null) return; + for(Entry routes : this.responses.entrySet()){ + if(routes.getValue().type().equals(type)){ Matcher matcher = this.patterns.get(routes.getKey()).matcher(path); - if (matcher.matches()) { - if (user == null && routes.getValue().needLogin()) - return; + if(matcher.matches()){ + if(user == null && routes.getValue().needLogin()) return; routes.getKey().exec(matcher, user, reader, writer); return; } } } - if (noFileFound != null) - noFileFound.exec(null, user, reader, writer); + if(noFileFound != null) noFileFound.exec(null, user, reader, writer); } - public RsaJsonWebKey getWebKey() { + public RsaJsonWebKey getWebKey(){ return this.rsaJsonWebKey; } - public String getTokenIssuer() { + public String getTokenIssuer(){ return this.token_issuer; } - public String createAuthUser(int id) throws JoseException { + public String createAuthUser(int id) throws JoseException{ JwtClaims claims = new JwtClaims(); claims.setIssuer(token_issuer); // who creates the token and signs it claims.setExpirationTimeMinutesInTheFuture(token_expiration); diff --git a/src/be/jeffcheasey88/peeratcode/framework/User.java b/src/be/jeffcheasey88/peeratcode/framework/User.java index e8073ff..0f9247c 100644 --- a/src/be/jeffcheasey88/peeratcode/framework/User.java +++ b/src/be/jeffcheasey88/peeratcode/framework/User.java @@ -2,15 +2,15 @@ package be.jeffcheasey88.peeratcode.framework; import org.jose4j.jwt.JwtClaims; -public class User { +public class User{ private int id; - public User(JwtClaims jwtClaims) { + public User(JwtClaims jwtClaims){ this.id = ((Long) jwtClaims.getClaimValue("id")).intValue(); } - public int getId() { + public int getId(){ return this.id; } } \ No newline at end of file diff --git a/src/be/jeffcheasey88/peeratcode/repository/DatabaseQuery.java b/src/be/jeffcheasey88/peeratcode/repository/DatabaseQuery.java index fe876a5..f21d2e0 100644 --- a/src/be/jeffcheasey88/peeratcode/repository/DatabaseQuery.java +++ b/src/be/jeffcheasey88/peeratcode/repository/DatabaseQuery.java @@ -16,10 +16,13 @@ public enum DatabaseQuery { ALL_CHAPTERS_QUERY("SELECT * FROM chapters WHERE id_chapter > 0"), // GROUPS - ALL_GROUPS("SELCT * FROM groups"), INSERT_GROUP("INSERT INTO groups (name, fk_chapter, fk_puzzle) VALUES (?,?,?)"), - UPDATE_COMPLETION( - "UPDATE completions SET tries = ?, filename = ?, score = ? WHERE fk_puzzle = ? AND fk_player = ?"), - + ALL_GROUPS("SELECT * FROM groups"), + GET_GROUP_ID_BY_DATA("SELECT id_group FROM groups WHERE name = ? AND fk_chapter = ? AND fk_puzzle = ?"), + INSERT_GROUP("INSERT INTO groups (name, fk_chapter, fk_puzzle) VALUES (?,?,?)"), + INSERT_PLAYER_IN_GROUP("INSERT INTO containsGroups (fk_player, fk_group) VALUES (?,?)"), + UPDATE_COMPLETION("UPDATE completions SET tries = ?, filename = ?, score = ? WHERE fk_puzzle = ? AND fk_player = ?"), + LEAVE_GROUP("DELETE FROM containsGroups WHERE fk_player = ? AND fk_group = ?"), + // LEADERBOARD ALL_PLAYERS_FOR_LEADERBOARD( "select p.*, scores.*, g.* from players p ,(SELECT fk_player, SUM(c.score) AS score, COUNT(c.id_completion) AS completions, SUM(c.tries) AS tries, rank() over(ORDER BY score DESC) AS rank FROM completions c GROUP BY c.fk_player) AS scores LEFT JOIN containsGroups cg ON scores.fk_player = cg.fk_player LEFT JOIN groups g ON cg.fk_group = g.id_group WHERE p.id_player = scores.fk_player ORDER BY g.fk_chapter, g.fk_puzzle"), diff --git a/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java b/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java index 45b840e..2ef3f97 100644 --- a/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java +++ b/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java @@ -16,6 +16,7 @@ import com.password4j.Hash; import com.password4j.Password; import be.jeffcheasey88.peeratcode.Configuration; +import be.jeffcheasey88.peeratcode.framework.User; import be.jeffcheasey88.peeratcode.model.Badge; import be.jeffcheasey88.peeratcode.model.Chapter; import be.jeffcheasey88.peeratcode.model.Completion; @@ -485,19 +486,56 @@ public class DatabaseRepository { statement.executeUpdate(); } - public boolean insertGroup(Group group) { + public boolean insertGroup(Group group, User creator){ try { ensureConnection(); PreparedStatement statement = DatabaseQuery.INSERT_GROUP.prepare(this.con); statement.setString(1, group.getName()); statement.setInt(2, group.getLinkToChapter()); statement.setInt(3, group.getLinkToPuzzle()); - return statement.executeUpdate() >= 0; - } catch (Exception e) { - } + if(statement.executeUpdate() >= 0) return insertUserInGroup(group, creator); + } catch (Exception e){} return false; } - + + private int getGroupId(Group group) throws Exception{ + ensureConnection(); + PreparedStatement stmt = DatabaseQuery.GET_GROUP_ID_BY_DATA.prepare(this.con); + stmt.setString(1, group.getName()); + stmt.setInt(2, group.getLinkToChapter()); + stmt.setInt(3, group.getLinkToPuzzle()); + + ResultSet result = stmt.executeQuery(); + if(result.next()) return result.getInt("id_group"); + throw new NullPointerException(); + } + + public boolean insertUserInGroup(Group group, User user){ + try { + int id = getGroupId(group); + PreparedStatement stmt = DatabaseQuery.INSERT_PLAYER_IN_GROUP.prepare(this.con); + + stmt.setInt(1, user.getId()); + stmt.setInt(2, id); + + return stmt.executeUpdate() >= 0; + }catch(Exception e){} + return false; + } + + public boolean leaveGroup(Group group, User user){ + try { + int id = getGroupId(group); + PreparedStatement stmt = DatabaseQuery.LEAVE_GROUP.prepare(this.con); + + stmt.setInt(1, user.getId()); + stmt.setInt(2, id); + + return stmt.executeUpdate() >= 0; + }catch(Exception e){} + return false; + } + private void updateCompletion(Completion completionToUpdate) throws SQLException { // Update completions PreparedStatement statement = DatabaseQuery.UPDATE_COMPLETION.prepare(this.con); diff --git a/src/be/jeffcheasey88/peeratcode/routes/BadgeDetails.java b/src/be/jeffcheasey88/peeratcode/routes/BadgeDetails.java index bd55db4..0055f76 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/BadgeDetails.java +++ b/src/be/jeffcheasey88/peeratcode/routes/BadgeDetails.java @@ -23,7 +23,6 @@ public class BadgeDetails implements Response { } @Route(path = "^\\/badge\\/([0-9]+)$", needLogin = true) - @Override public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { if (matcher.groupCount() > 0) { int badgeId = Integer.parseInt(matcher.group(1)); diff --git a/src/be/jeffcheasey88/peeratcode/routes/ChapterElement.java b/src/be/jeffcheasey88/peeratcode/routes/ChapterElement.java index 803ecad..aa6f9c2 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/ChapterElement.java +++ b/src/be/jeffcheasey88/peeratcode/routes/ChapterElement.java @@ -24,7 +24,6 @@ public class ChapterElement implements Response { } @Route(path = "^\\/chapter\\/([0-9]+)$", needLogin = true) - @Override public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { Chapter chapter = databaseRepo.getChapter(extractId(matcher)); if (chapter != null) { diff --git a/src/be/jeffcheasey88/peeratcode/routes/ChapterList.java b/src/be/jeffcheasey88/peeratcode/routes/ChapterList.java index 6982242..af7228b 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/ChapterList.java +++ b/src/be/jeffcheasey88/peeratcode/routes/ChapterList.java @@ -24,7 +24,6 @@ public class ChapterList implements Response { } @Route(path = "^\\/chapters$", needLogin = true) - @Override public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { List allChapters = databaseRepo.getAllChapters(); if (allChapters != null) { diff --git a/src/be/jeffcheasey88/peeratcode/routes/Leaderboard.java b/src/be/jeffcheasey88/peeratcode/routes/Leaderboard.java index 4bd0958..0c34854 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/Leaderboard.java +++ b/src/be/jeffcheasey88/peeratcode/routes/Leaderboard.java @@ -28,7 +28,6 @@ public class Leaderboard implements Response { } @Route(path = "^\\/leaderboard\\/?(\\d+)?$") - @Override public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { HttpUtil.responseHeaders(writer, 200, "Access-Control-Allow-Origin: *"); if (matcher.group(1) != null) { diff --git a/src/be/jeffcheasey88/peeratcode/routes/Login.java b/src/be/jeffcheasey88/peeratcode/routes/Login.java index cae3a74..1b0755b 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/Login.java +++ b/src/be/jeffcheasey88/peeratcode/routes/Login.java @@ -1,5 +1,7 @@ package be.jeffcheasey88.peeratcode.routes; +import static be.jeffcheasey88.peeratcode.framework.RequestType.POST; + import java.util.regex.Matcher; import org.json.simple.JSONObject; @@ -23,8 +25,7 @@ public class Login implements Response { this.router = router; } - @Route(path = "^\\/login$", type = "POST") - @Override + @Route(path = "^\\/login$", type = POST) public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { if (user != null) { HttpUtil.responseHeaders(writer, 403, "Access-Control-Allow-Origin: *"); diff --git a/src/be/jeffcheasey88/peeratcode/routes/PlayerDetails.java b/src/be/jeffcheasey88/peeratcode/routes/PlayerDetails.java index 48663a0..1ae1916 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/PlayerDetails.java +++ b/src/be/jeffcheasey88/peeratcode/routes/PlayerDetails.java @@ -23,7 +23,6 @@ public class PlayerDetails implements Response { } @Route(path = "^\\/player\\/?(.+)?$", needLogin = true) - @Override public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { Player player; if (matcher.group(1) != null) { diff --git a/src/be/jeffcheasey88/peeratcode/routes/PuzzleElement.java b/src/be/jeffcheasey88/peeratcode/routes/PuzzleElement.java index f26e2a7..bcb359a 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/PuzzleElement.java +++ b/src/be/jeffcheasey88/peeratcode/routes/PuzzleElement.java @@ -22,7 +22,6 @@ public class PuzzleElement implements Response { } @Route(path = "^\\/puzzle\\/([0-9]+)$", needLogin = true) - @Override public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { Puzzle puzzle = databaseRepo.getPuzzle(extractId(matcher)); if (puzzle != null) { diff --git a/src/be/jeffcheasey88/peeratcode/routes/PuzzleResponse.java b/src/be/jeffcheasey88/peeratcode/routes/PuzzleResponse.java index f1e9eb7..2ecbfc6 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/PuzzleResponse.java +++ b/src/be/jeffcheasey88/peeratcode/routes/PuzzleResponse.java @@ -1,5 +1,7 @@ package be.jeffcheasey88.peeratcode.routes; +import static be.jeffcheasey88.peeratcode.framework.RequestType.POST; + import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -29,8 +31,7 @@ public class PuzzleResponse implements Response { usersFilesPath = initUsersFilesPath; } - @Route(path = "^\\/puzzleResponse\\/([0-9]+)$", type = "POST", needLogin = true) - @Override + @Route(path = "^\\/puzzleResponse\\/([0-9]+)$", type = POST, needLogin = true) public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { ReceivedResponse received = new ReceivedResponse(matcher, reader); saveSourceCode(received, databaseRepo.getPlayer(user.getId())); diff --git a/src/be/jeffcheasey88/peeratcode/routes/Register.java b/src/be/jeffcheasey88/peeratcode/routes/Register.java index 7eb20a4..d80c0a0 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/Register.java +++ b/src/be/jeffcheasey88/peeratcode/routes/Register.java @@ -1,5 +1,7 @@ package be.jeffcheasey88.peeratcode.routes; +import static be.jeffcheasey88.peeratcode.framework.RequestType.POST; + import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; @@ -28,8 +30,7 @@ public class Register implements Response { usersFilesPath = initUsersFilesPath; } - @Route(path = "^\\/register$", type = "POST") - @Override + @Route(path = "^\\/register$", type = POST) public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { if (user != null) { HttpUtil.responseHeaders(writer, 403, "Access-Control-Allow-Origin: *"); diff --git a/src/be/jeffcheasey88/peeratcode/routes/Result.java b/src/be/jeffcheasey88/peeratcode/routes/Result.java index 5dd8cc4..dc19947 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/Result.java +++ b/src/be/jeffcheasey88/peeratcode/routes/Result.java @@ -19,7 +19,6 @@ public class Result implements Response { } @Route(path = "^\\/result\\/(\\d+)$", needLogin = true) - @Override public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { int puzzle = Integer.parseInt(matcher.group(1)); diff --git a/src/be/jeffcheasey88/peeratcode/routes/groups/CreateGroup.java b/src/be/jeffcheasey88/peeratcode/routes/groups/CreateGroup.java index c630cbb..c0f891c 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/groups/CreateGroup.java +++ b/src/be/jeffcheasey88/peeratcode/routes/groups/CreateGroup.java @@ -1,5 +1,7 @@ package be.jeffcheasey88.peeratcode.routes.groups; +import static be.jeffcheasey88.peeratcode.framework.RequestType.POST; + import java.util.regex.Matcher; import org.json.simple.JSONObject; @@ -21,12 +23,11 @@ public class CreateGroup implements Response { this.repo = repo; } - @Route(path = "^\\/groupCreate$", type = "POST", needLogin = true) - @Override + @Route(path = "^\\/groupCreate$", type = POST, needLogin = true) public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { HttpUtil.skipHeaders(reader); - if (this.repo.insertGroup(new Group((JSONObject) HttpUtil.readJson(reader)))) { + if (this.repo.insertGroup(new Group((JSONObject) HttpUtil.readJson(reader)), user)) { HttpUtil.responseHeaders(writer, 200, "Access-Control-Allow-Origin: *"); } else { HttpUtil.responseHeaders(writer, 403, "Access-Control-Allow-Origin: *"); diff --git a/src/be/jeffcheasey88/peeratcode/routes/groups/GroupJoin.java b/src/be/jeffcheasey88/peeratcode/routes/groups/GroupJoin.java new file mode 100644 index 0000000..0cbb670 --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/routes/groups/GroupJoin.java @@ -0,0 +1,37 @@ +package be.jeffcheasey88.peeratcode.routes.groups; + +import static be.jeffcheasey88.peeratcode.framework.RequestType.POST; + +import java.util.regex.Matcher; + +import org.json.simple.JSONObject; + +import be.jeffcheasey88.peeratcode.framework.HttpReader; +import be.jeffcheasey88.peeratcode.framework.HttpUtil; +import be.jeffcheasey88.peeratcode.framework.HttpWriter; +import be.jeffcheasey88.peeratcode.framework.Response; +import be.jeffcheasey88.peeratcode.framework.Route; +import be.jeffcheasey88.peeratcode.framework.User; +import be.jeffcheasey88.peeratcode.model.Group; +import be.jeffcheasey88.peeratcode.repository.DatabaseRepository; + +public class GroupJoin implements Response{ + + private DatabaseRepository repo; + + public GroupJoin(DatabaseRepository repo){ + this.repo = repo; + } + + @Route(path = "^\\/groupJoin$", type = POST, needLogin = true) + public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { + HttpUtil.responseHeaders(writer, 200, "Access-Control-Allow-Origin: *"); + + if (this.repo.insertUserInGroup(new Group((JSONObject) HttpUtil.readJson(reader)), user)) { + HttpUtil.responseHeaders(writer, 200, "Access-Control-Allow-Origin: *"); + } else { + HttpUtil.responseHeaders(writer, 403, "Access-Control-Allow-Origin: *"); + } + } + +} diff --git a/src/be/jeffcheasey88/peeratcode/routes/groups/GroupList.java b/src/be/jeffcheasey88/peeratcode/routes/groups/GroupList.java index 5bf64f8..d21ab8b 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/groups/GroupList.java +++ b/src/be/jeffcheasey88/peeratcode/routes/groups/GroupList.java @@ -22,12 +22,10 @@ public class GroupList implements Response { } @Route(path = "^\\/groups$", needLogin = true) - @Override public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { HttpUtil.responseHeaders(writer, 200, "Access-Control-Allow-Origin: *"); JSONArray result = new JSONArray(); - for (Group group : this.repo.getAllGroups()) - result.add(group.toJson()); + for(Group group : this.repo.getAllGroups()) result.add(group.toJson()); writer.write(result.toJSONString()); } diff --git a/src/be/jeffcheasey88/peeratcode/routes/groups/GroupQuit.java b/src/be/jeffcheasey88/peeratcode/routes/groups/GroupQuit.java new file mode 100644 index 0000000..5dd7fcf --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/routes/groups/GroupQuit.java @@ -0,0 +1,37 @@ +package be.jeffcheasey88.peeratcode.routes.groups; + +import static be.jeffcheasey88.peeratcode.framework.RequestType.POST; + +import java.util.regex.Matcher; + +import org.json.simple.JSONObject; + +import be.jeffcheasey88.peeratcode.framework.HttpReader; +import be.jeffcheasey88.peeratcode.framework.HttpUtil; +import be.jeffcheasey88.peeratcode.framework.HttpWriter; +import be.jeffcheasey88.peeratcode.framework.Response; +import be.jeffcheasey88.peeratcode.framework.Route; +import be.jeffcheasey88.peeratcode.framework.User; +import be.jeffcheasey88.peeratcode.model.Group; +import be.jeffcheasey88.peeratcode.repository.DatabaseRepository; + +public class GroupQuit implements Response{ + + private DatabaseRepository repo; + + public GroupQuit(DatabaseRepository repo){ + this.repo = repo; + } + + @Route(path = "^\\/groupQuit$", type = POST, needLogin = true) + public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { + HttpUtil.responseHeaders(writer, 200, "Access-Control-Allow-Origin: *"); + + if (this.repo.leaveGroup(new Group((JSONObject) HttpUtil.readJson(reader)), user)) { + HttpUtil.responseHeaders(writer, 200, "Access-Control-Allow-Origin: *"); + } else { + HttpUtil.responseHeaders(writer, 403, "Access-Control-Allow-Origin: *"); + } + } + +}