diff --git a/src/be/jeffcheasey88/peeratcode/Main.java b/src/be/jeffcheasey88/peeratcode/Main.java index 84e808f..36cfb90 100644 --- a/src/be/jeffcheasey88/peeratcode/Main.java +++ b/src/be/jeffcheasey88/peeratcode/Main.java @@ -48,7 +48,7 @@ public class Main { Class.forName("com.mysql.cj.jdbc.Driver"); - Router router = new Router(); + Router router = new Router(new DatabaseRepository(config)); router.setDefault(new Response(){ @@ -66,19 +66,19 @@ public class Main { } }); - initRoutes(router, new DatabaseRepository(config)); + initRoutes(router); startWebServer(config, router); } - private static void initRoutes(Router router, DatabaseRepository repo) { - router.register(new ChapterElement(repo)); - router.register(new ChapterList(repo)); - router.register(new PuzzleElement(repo)); - router.register(new Register(repo)); - router.register(new Login(repo)); - router.register(new Result(repo)); - router.register(new PuzzleResponse(repo)); + private static void initRoutes(Router router) { + router.register(new ChapterElement(router.getDataBase())); + router.register(new ChapterList(router.getDataBase())); + router.register(new PuzzleElement(router.getDataBase())); + router.register(new Register(router.getDataBase(), router)); + router.register(new Login(router.getDataBase(), router)); + router.register(new Result(router.getDataBase())); + router.register(new PuzzleResponse(router.getDataBase())); } private static void startWebServer(Configuration config, Router router) throws IOException { diff --git a/src/be/jeffcheasey88/peeratcode/model/Player.java b/src/be/jeffcheasey88/peeratcode/model/Player.java new file mode 100644 index 0000000..f53e845 --- /dev/null +++ b/src/be/jeffcheasey88/peeratcode/model/Player.java @@ -0,0 +1,45 @@ +package be.jeffcheasey88.peeratcode.model; + +public class Player { + + private String pseudo; + private String email; + private String firstname; + private String lastname; + private String description; + private String sgroup; + + public Player(String pseudo, String email, String firstname, String lastname, String description, String sgroup){ + this.pseudo = pseudo; + this.email = email; + this.firstname = firstname; + this.lastname = lastname; + this.description = description; + this.sgroup = sgroup; + } + + public String getPseudo(){ + return this.pseudo; + } + + public String getEmail(){ + return this.email; + } + + public String getFirstname(){ + return this.firstname; + } + + public String getLastname(){ + return this.lastname; + } + + public String getDescription(){ + return this.description; + } + + public String getGroup(){ + return this.sgroup; + } + +} diff --git a/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java b/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java index b233f3d..9ad6e79 100644 --- a/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java +++ b/src/be/jeffcheasey88/peeratcode/repository/DatabaseRepository.java @@ -1,19 +1,21 @@ package be.jeffcheasey88.peeratcode.repository; -import be.jeffcheasey88.peeratcode.Configuration; -import be.jeffcheasey88.peeratcode.model.Chapter; -import be.jeffcheasey88.peeratcode.model.Puzzle; -import com.password4j.Hash; -import com.password4j.Password; - import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Statement; import java.util.ArrayList; import java.util.List; +import com.password4j.Hash; +import com.password4j.Password; + +import be.jeffcheasey88.peeratcode.Configuration; +import be.jeffcheasey88.peeratcode.model.Chapter; +import be.jeffcheasey88.peeratcode.model.Puzzle; + public class DatabaseRepository { private static final String SPECIFIC_PUZZLE_QUERY = "SELECT * FROM puzzles WHERE id_puzzle = ?"; private static final String SPECIFIC_CHAPTER_QUERY = "SELECT * FROM chapters WHERE id_chapter = ?"; @@ -22,7 +24,7 @@ public class DatabaseRepository { private static final String CHECK_PSEUDO_AVAILABLE_QUERY = "SELECT * FROM players WHERE pseudo = ?"; private static final String CHECK_EMAIL_AVAILABLE_QUERY = "SELECT * FROM players WHERE email = ?"; private static final String REGISTER_QUERY = "INSERT INTO players (pseudo, email, passwd, firstname, lastname, description, sgroup, avatar) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; - private static final String CHECK_PASSWORD = "SELECT passwd FROM players WHERE pseudo=?"; + private static final String CHECK_PASSWORD = "SELECT id_player, passwd FROM players WHERE pseudo=?"; private static final String SCORE = "SELECT score FROM completions WHERE fk_player = ? AND fk_puzzle = ?"; private static final String GET_PUZZLE_SOLUTION = "SELECT soluce FROM puzzles WHERE id_puzzle=?"; private static final String GET_PUZZLE_SCORE_MAX = "SELECT score_max FROM puzzles WHERE id_puzzle=?"; @@ -192,11 +194,11 @@ public class DatabaseRepository { * @param avatar The avatar of the user * @return True if the user was registered, false if an error occurred */ - public boolean register(String pseudo, String email, String password, String firstname, String lastname, String description, String sgroup, String avatar) { + public int register(String pseudo, String email, String password, String firstname, String lastname, String description, String sgroup, String avatar) { Hash hash = Password.hash(password).withArgon2(); try { ensureConnection(); - PreparedStatement statement = con.prepareStatement(REGISTER_QUERY); + PreparedStatement statement = con.prepareStatement(REGISTER_QUERY, Statement.RETURN_GENERATED_KEYS); statement.setString(1, pseudo); statement.setString(2, email); statement.setString(3, hash.getResult()); @@ -205,11 +207,14 @@ public class DatabaseRepository { statement.setString(6, description); statement.setString(7, sgroup); statement.setString(8, avatar); - return statement.executeUpdate() == 1; + if(statement.executeUpdate() == 1){ + ResultSet inserted = statement.getGeneratedKeys(); + if(inserted.next()) return inserted.getInt("id_player"); + } } catch (SQLException e) { e.printStackTrace(); } - return false; + return -1; } /** @@ -217,9 +222,9 @@ public class DatabaseRepository { * * @param username The username of the user * @param password The password of the user - * @return True if the user's information are correct, false otherwise (or if an error occurred) + * @return id the id of the user, -1 if not login successefuly */ - public boolean login(String username, String password) { + public int login(String username, String password) { try { ensureConnection(); PreparedStatement statement = con.prepareStatement(CHECK_PASSWORD); @@ -227,12 +232,11 @@ public class DatabaseRepository { ResultSet result = statement.executeQuery(); if (result.next()) { String hashedPassword = result.getString("passwd"); - return Password.check(password, hashedPassword).withArgon2(); + if(Password.check(password, hashedPassword).withArgon2()) return result.getInt("id_player"); } } catch (SQLException e) { - e.printStackTrace(); } - return false; + return -1; } public byte[] getPuzzleSolution(int puzzleId) { diff --git a/src/be/jeffcheasey88/peeratcode/routes/Login.java b/src/be/jeffcheasey88/peeratcode/routes/Login.java index e65ec49..0162637 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/Login.java +++ b/src/be/jeffcheasey88/peeratcode/routes/Login.java @@ -3,6 +3,10 @@ package be.jeffcheasey88.peeratcode.routes; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.jose4j.jwk.RsaJsonWebKey; +import org.jose4j.jws.AlgorithmIdentifiers; +import org.jose4j.jws.JsonWebSignature; +import org.jose4j.jwt.JwtClaims; import org.json.simple.JSONObject; import be.jeffcheasey88.peeratcode.repository.DatabaseRepository; @@ -10,14 +14,17 @@ import be.jeffcheasey88.peeratcode.webserver.HttpReader; import be.jeffcheasey88.peeratcode.webserver.HttpUtil; import be.jeffcheasey88.peeratcode.webserver.HttpWriter; import be.jeffcheasey88.peeratcode.webserver.Response; +import be.jeffcheasey88.peeratcode.webserver.Router; import be.jeffcheasey88.peeratcode.webserver.User; public class Login implements Response { - private final DatabaseRepository databaseRepo; + private DatabaseRepository databaseRepo; + private Router router; - public Login(DatabaseRepository databaseRepo) { + public Login(DatabaseRepository databaseRepo, Router router){ this.databaseRepo = databaseRepo; + this.router = router; } @Override @@ -27,8 +34,11 @@ public class Login implements Response { if (informations != null) { String pseudo = (String) informations.get("pseudo"); String password = (String) informations.get("passwd"); - if (databaseRepo.login(pseudo, password)) { - HttpUtil.responseHeaders(writer, 200, "Access-Control-Allow-Origin: *"); + int id; + if ((id = databaseRepo.login(pseudo, password)) >= 0){ + HttpUtil.responseHeaders(writer, 200, + "Access-Control-Allow-Origin: *", + "Authorization: Bearer "+this.router.createAuthUser(id)); return; } } diff --git a/src/be/jeffcheasey88/peeratcode/routes/PuzzleResponse.java b/src/be/jeffcheasey88/peeratcode/routes/PuzzleResponse.java index 81e7b64..75732ff 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/PuzzleResponse.java +++ b/src/be/jeffcheasey88/peeratcode/routes/PuzzleResponse.java @@ -22,8 +22,12 @@ public class PuzzleResponse implements Response { @Override public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { - HttpUtil.skipHeaders(reader); + if(user == null){ + HttpUtil.responseHeaders(writer, 403, "Access-Control-Allow-Origin: *"); + return; + } + HttpUtil.skipHeaders(reader); int puzzleId = Integer.parseInt(matcher.group(1)); byte[] response; byte[] fileName; diff --git a/src/be/jeffcheasey88/peeratcode/routes/Register.java b/src/be/jeffcheasey88/peeratcode/routes/Register.java index ed8005d..cc9b318 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/Register.java +++ b/src/be/jeffcheasey88/peeratcode/routes/Register.java @@ -10,14 +10,17 @@ import be.jeffcheasey88.peeratcode.webserver.HttpReader; import be.jeffcheasey88.peeratcode.webserver.HttpUtil; import be.jeffcheasey88.peeratcode.webserver.HttpWriter; import be.jeffcheasey88.peeratcode.webserver.Response; +import be.jeffcheasey88.peeratcode.webserver.Router; import be.jeffcheasey88.peeratcode.webserver.User; public class Register implements Response { - private final DatabaseRepository databaseRepo; + private DatabaseRepository databaseRepo; + private Router router; - public Register(DatabaseRepository databaseRepo) { + public Register(DatabaseRepository databaseRepo, Router router) { this.databaseRepo = databaseRepo; + this.router = router; } @Override @@ -45,8 +48,11 @@ public class Register implements Response { boolean pseudoAvailable = databaseRepo.checkPseudoAvailability(pseudo); boolean emailAvailable = databaseRepo.checkEmailAvailability(email); if (pseudoAvailable && emailAvailable) { - if (databaseRepo.register(pseudo, email, password, firstname, lastname, description, group, avatar)){ - HttpUtil.responseHeaders(writer, 200, "Access-Control-Allow-Origin: *"); + int id; + if ((id = databaseRepo.register(pseudo, email, password, firstname, lastname, description, group, avatar)) >= 0){ + HttpUtil.responseHeaders(writer, 200, + "Access-Control-Allow-Origin: *", + "Authorization: Bearer "+this.router.createAuthUser(id)); return; } } else { diff --git a/src/be/jeffcheasey88/peeratcode/routes/Result.java b/src/be/jeffcheasey88/peeratcode/routes/Result.java index de1cb0d..6163f98 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/Result.java +++ b/src/be/jeffcheasey88/peeratcode/routes/Result.java @@ -20,9 +20,14 @@ public class Result implements Response{ @Override public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception { + if(user == null){ + HttpUtil.responseHeaders(writer, 403, "Access-Control-Allow-Origin: *"); + return; + } + int puzzle = Integer.parseInt(matcher.group(1)); - int score = this.repo.getScore(0, puzzle); + int score = this.repo.getScore(user.getId(), puzzle); if(score < 0) { HttpUtil.responseHeaders(writer, 425, "Access-Control-Allow-Origin: *"); }else{ diff --git a/src/be/jeffcheasey88/peeratcode/webserver/Router.java b/src/be/jeffcheasey88/peeratcode/webserver/Router.java index 0159e28..0999d33 100644 --- a/src/be/jeffcheasey88/peeratcode/webserver/Router.java +++ b/src/be/jeffcheasey88/peeratcode/webserver/Router.java @@ -6,18 +6,30 @@ import java.util.regex.Matcher; import org.jose4j.jwk.RsaJsonWebKey; import org.jose4j.jwk.RsaJwkGenerator; +import org.jose4j.jws.AlgorithmIdentifiers; +import org.jose4j.jws.JsonWebSignature; +import org.jose4j.jwt.JwtClaims; +import org.jose4j.lang.JoseException; + +import be.jeffcheasey88.peeratcode.repository.DatabaseRepository; public class Router{ private List responses; private Response noFileFound; private RsaJsonWebKey rsaJsonWebKey; + private DatabaseRepository repo; - public Router() throws Exception{ + public Router(DatabaseRepository repo) throws Exception{ + this.repo = repo; this.responses = new ArrayList<>(); this.rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048); } + public DatabaseRepository getDataBase(){ + return this.repo; + } + public void register(Response response){ this.responses.add(response); } @@ -42,4 +54,23 @@ public class Router{ public RsaJsonWebKey getWebKey(){ return this.rsaJsonWebKey; } + + public String createAuthUser(int id) throws JoseException{ + JwtClaims claims = new JwtClaims(); + claims.setIssuer("Issuer"); // who creates the token and signs it + claims.setAudience("Audience"); // to whom the token is intended to be sent + claims.setExpirationTimeMinutesInTheFuture(10); // time when the token will expire (10 minutes from now) + claims.setGeneratedJwtId(); // a unique identifier for the token + claims.setIssuedAtToNow(); // when the token was issued/created (now) + claims.setNotBeforeMinutesInThePast(2); // time before which the token is not yet valid (2 minutes ago) + + claims.setClaim("id", id); + + JsonWebSignature jws = new JsonWebSignature(); + jws.setPayload(claims.toJson()); + jws.setKey(rsaJsonWebKey.getPrivateKey()); + jws.setKeyIdHeaderValue(rsaJsonWebKey.getKeyId()); + jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256); + return jws.getCompactSerialization(); + } } \ No newline at end of file diff --git a/src/be/jeffcheasey88/peeratcode/webserver/User.java b/src/be/jeffcheasey88/peeratcode/webserver/User.java index b4c91fc..05d2cda 100644 --- a/src/be/jeffcheasey88/peeratcode/webserver/User.java +++ b/src/be/jeffcheasey88/peeratcode/webserver/User.java @@ -4,18 +4,12 @@ import org.jose4j.jwt.JwtClaims; public class User { - private String username; private int id; public User(JwtClaims jwtClaims){ - this.username = (String) jwtClaims.getClaimValue("username"); this.id = (int) jwtClaims.getClaimValue("id"); } - public String getUsername(){ - return username; - } - public int getId(){ return this.id; }