diff --git a/.gitignore b/.gitignore index 38fb1c2..e567647 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ bin/ .project config.txt +config-test.txt dist/ testApi/ .apt_generated/* diff --git a/PeerAtCodeFramework.jar b/PeerAtCodeFramework.jar index 781d052..ef73b46 100644 Binary files a/PeerAtCodeFramework.jar and b/PeerAtCodeFramework.jar differ diff --git a/database-schem.sql b/database-schem.sql new file mode 100644 index 0000000..504140e --- /dev/null +++ b/database-schem.sql @@ -0,0 +1,126 @@ +DROP TABLE IF EXISTS `containsTags`; +DROP TABLE IF EXISTS `tags`; +DROP TABLE IF EXISTS `containsBadges`; +DROP TABLE IF EXISTS `badges`; +DROP TABLE IF EXISTS `containsGroups`; +DROP TABLE IF EXISTS `nextPart`; +DROP TABLE IF EXISTS `groups`; +DROP TABLE IF EXISTS `completions`; +DROP TABLE IF EXISTS `players`; +DROP TABLE IF EXISTS `puzzles`; +DROP TABLE IF EXISTS `chapters`; + +CREATE TABLE `players` ( + `id_player` int(11) NOT NULL AUTO_INCREMENT, + `pseudo` varchar(100) NOT NULL, + `email` varchar(100) NOT NULL, + `passwd` varchar(150) NOT NULL, + `firstname` varchar(100) NOT NULL, + `lastname` varchar(100) NOT NULL, + `description` varchar(200) DEFAULT NULL, + `avatar` blob DEFAULT NULL, + PRIMARY KEY (`id_player`) +) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +CREATE TABLE badges ( + id_badge int(11) NOT NULL AUTO_INCREMENT, + name varchar(50) NOT NULL, + logo mediumblob DEFAULT NULL, + level int(11) DEFAULT 1, + PRIMARY KEY (id_badge) +); + +CREATE TABLE `chapters` ( + `id_chapter` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(150) NOT NULL, + `start_date` datetime DEFAULT NULL, + `end_date` datetime DEFAULT NULL, + PRIMARY KEY (`id_chapter`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +CREATE TABLE `puzzles` ( + `id_puzzle` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(150) NOT NULL, + `content` text NOT NULL, + `soluce` blob NOT NULL, + `verify` text DEFAULT NULL, + `score_max` int(11) NOT NULL, + `fk_chapter` int(11) NOT NULL, + PRIMARY KEY (`id_puzzle`), + KEY `fk_chapter` (`fk_chapter`), + CONSTRAINT `puzzles_ibfk_1` FOREIGN KEY (`fk_chapter`) REFERENCES `chapters` (`id_chapter`) +) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + + +CREATE TABLE `groups` ( + `id_group` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(150) DEFAULT NULL, + `fk_chapter` int(11) DEFAULT NULL, + `fk_puzzle` int(11) DEFAULT NULL, + PRIMARY KEY (`id_group`), + KEY `fk_chapter` (`fk_chapter`), + KEY `fk_puzzle` (`fk_puzzle`), + CONSTRAINT `groups_ibfk_1` FOREIGN KEY (`fk_chapter`) REFERENCES `chapters` (`id_chapter`), + CONSTRAINT `groups_ibfk_2` FOREIGN KEY (`fk_puzzle`) REFERENCES `puzzles` (`id_puzzle`) +) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + + +CREATE TABLE `nextPart` ( + `origin` int(11) NOT NULL, + `next` int(11) NOT NULL, + PRIMARY KEY (`origin`,`next`), + KEY `next` (`next`), + CONSTRAINT `nextPart_ibfk_1` FOREIGN KEY (`origin`) REFERENCES `puzzles` (`id_puzzle`), + CONSTRAINT `nextPart_ibfk_2` FOREIGN KEY (`next`) REFERENCES `puzzles` (`id_puzzle`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + + +CREATE TABLE `completions` ( + `id_completion` int(11) NOT NULL AUTO_INCREMENT, + `fk_puzzle` int(11) NOT NULL, + `fk_player` int(11) NOT NULL, + `tries` int(11) DEFAULT 0, + `code` blob DEFAULT NULL, + `score` int(11) DEFAULT 0, + `fileName` varchar(100) DEFAULT NULL, + PRIMARY KEY (`id_completion`), + KEY `fk_puzzle` (`fk_puzzle`), + KEY `fk_player` (`fk_player`), + CONSTRAINT `completions_ibfk_1` FOREIGN KEY (`fk_puzzle`) REFERENCES `puzzles` (`id_puzzle`), + CONSTRAINT `completions_ibfk_2` FOREIGN KEY (`fk_player`) REFERENCES `players` (`id_player`) +) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +CREATE TABLE `tags` ( + `id_tag` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + PRIMARY KEY (`id_tag`) +) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +CREATE TABLE `containsBadges` ( + `fk_player` int(11) NOT NULL, + `fk_badge` int(11) NOT NULL, + PRIMARY KEY (`fk_player`,`fk_badge`), + KEY `fk_badge` (`fk_badge`), + CONSTRAINT `containsBadges_ibfk_1` FOREIGN KEY (`fk_player`) REFERENCES `players` (`id_player`), + CONSTRAINT `containsBadges_ibfk_2` FOREIGN KEY (`fk_badge`) REFERENCES `badges` (`id_badge`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +CREATE TABLE `containsGroups` ( + `fk_player` int(11) NOT NULL, + `fk_group` int(11) NOT NULL, + PRIMARY KEY (`fk_player`,`fk_group`), + KEY `fk_group` (`fk_group`), + CONSTRAINT `containsGroups_ibfk_1` FOREIGN KEY (`fk_player`) REFERENCES `players` (`id_player`), + CONSTRAINT `containsGroups_ibfk_2` FOREIGN KEY (`fk_group`) REFERENCES `groups` (`id_group`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +CREATE TABLE `containsTags` ( + `fk_tag` int(11) NOT NULL, + `fk_puzzle` int(11) NOT NULL, + PRIMARY KEY (`fk_tag`,`fk_puzzle`), + KEY `fk_puzzle` (`fk_puzzle`), + CONSTRAINT `containsTags_ibfk_1` FOREIGN KEY (`fk_tag`) REFERENCES `tags` (`id_tag`), + CONSTRAINT `containsTags_ibfk_2` FOREIGN KEY (`fk_puzzle`) REFERENCES `puzzles` (`id_puzzle`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + + diff --git a/src/dev/peerat/backend/Configuration.java b/src/dev/peerat/backend/Configuration.java index 8e05047..5eea2f7 100644 --- a/src/dev/peerat/backend/Configuration.java +++ b/src/dev/peerat/backend/Configuration.java @@ -35,20 +35,22 @@ public class Configuration { private String mailUsername; private String mailPassword; private String mailSmtpHost; - private int mailSmptPort; + private int mailSmtpPort; private String mailFromAddress; + + private String git_token; - private File file; + private File _file; public Configuration(String path) { - this.file = new File(path); - System.out.println("Config on " + file.getAbsolutePath()); + this._file = new File(path); + System.out.println("Config on " + _file.getAbsolutePath()); } public void load() throws Exception { - if (!this.file.exists()) + if (!this._file.exists()) return; - BufferedReader reader = new BufferedReader(new FileReader(this.file)); + BufferedReader reader = new BufferedReader(new FileReader(this._file)); String line; while ((line = reader.readLine()) != null) { String[] split = line.split("="); @@ -101,14 +103,13 @@ public class Configuration { } public void save() throws Exception { - if (!file.exists()) { - File parent = file.getParentFile(); - if (!parent.exists()) - parent.mkdirs(); - file.createNewFile(); + if (!_file.exists()) { + File parent = _file.getParentFile(); + if(!parent.exists()) parent.mkdirs(); + _file.createNewFile(); } Field[] fields = getClass().getDeclaredFields(); - BufferedWriter writer = new BufferedWriter(new FileWriter(file)); + BufferedWriter writer = new BufferedWriter(new FileWriter(_file)); for (Field field : fields) { field.setAccessible(true); if (field.getName().startsWith("_")) @@ -187,7 +188,11 @@ public class Configuration { this.mailUsername, this.mailPassword, this.mailSmtpHost, - this.mailSmptPort, + this.mailSmtpPort, this.mailFromAddress); } + + public String getGitToken(){ + return this.git_token; + } } \ No newline at end of file diff --git a/src/dev/peerat/backend/Main.java b/src/dev/peerat/backend/Main.java index 41d87bd..f19b519 100644 --- a/src/dev/peerat/backend/Main.java +++ b/src/dev/peerat/backend/Main.java @@ -16,18 +16,21 @@ import dev.peerat.backend.routes.ChapterElement; import dev.peerat.backend.routes.ChapterList; import dev.peerat.backend.routes.DynamicLeaderboard; import dev.peerat.backend.routes.Leaderboard; -import dev.peerat.backend.routes.Login; -import dev.peerat.backend.routes.MailConfirmation; import dev.peerat.backend.routes.PlayerDetails; import dev.peerat.backend.routes.PuzzleElement; import dev.peerat.backend.routes.PuzzleResponse; -import dev.peerat.backend.routes.Register; import dev.peerat.backend.routes.Result; +import dev.peerat.backend.routes.admins.DynamicLogs; import dev.peerat.backend.routes.groups.GroupCreate; import dev.peerat.backend.routes.groups.GroupJoin; import dev.peerat.backend.routes.groups.GroupList; import dev.peerat.backend.routes.groups.GroupQuit; -import dev.peerat.backend.utils.Mail; +import dev.peerat.backend.routes.users.ChangePassword; +import dev.peerat.backend.routes.users.ForgotPassword; +import dev.peerat.backend.routes.users.Login; +import dev.peerat.backend.routes.users.MailConfirmation; +import dev.peerat.backend.routes.users.ProfileSettings; +import dev.peerat.backend.routes.users.Register; import dev.peerat.framework.Context; import dev.peerat.framework.HttpReader; import dev.peerat.framework.HttpWriter; @@ -47,15 +50,19 @@ public class Main{ DatabaseRepository repo = new DatabaseRepository(config); Router router = new Router() .configureJwt( - (builder) -> builder.setExpectedIssuer(config.getTokenIssuer()), - (claims) -> { - claims.setIssuer(config.getTokenIssuer()); // who creates the token and signs it - claims.setExpirationTimeMinutesInTheFuture(config.getTokenExpiration()); - }, - (claims) -> new PeerAtUser(claims)); - - router.addDefaultHeaders(RequestType.GET, "Access-Control-Allow-Origin: *"); - router.addDefaultHeaders(RequestType.POST, "Access-Control-Allow-Origin: *"); + (builder) -> builder.setExpectedIssuer(config.getTokenIssuer()), + (claims) -> { + claims.setIssuer(config.getTokenIssuer()); // who creates the token and signs it + claims.setExpirationTimeMinutesInTheFuture(config.getTokenExpiration()); + }, + (claims) -> new PeerAtUser(claims)) + .activeReOrdering(). + addDefaultHeaders(RequestType.GET, "Access-Control-Allow-Origin: *"). + addDefaultHeaders(RequestType.POST, "Access-Control-Allow-Origin: *"). + addDefaultHeaders(RequestType.OPTIONS, + "Access-Control-Allow-Origin: *", + "Access-Control-Allow-Methods: *", + "Access-Control-Allow-Headers: *"); router.setDefault((matcher, context, reader, writer) -> { context.response(404); @@ -65,10 +72,7 @@ public class Main{ router.register(new Response(){ @Route(path = "^(.*)$", type = OPTIONS) public void exec(Matcher matcher, Context context, HttpReader reader, HttpWriter writer) throws Exception { - context.response(200, - "Access-Control-Allow-Origin: *", - "Access-Control-Allow-Methods: *", - "Access-Control-Allow-Headers: *"); + context.response(200); } }); @@ -84,26 +88,30 @@ public class Main{ private static void initRoutes(Router router, DatabaseRepository repo, Configuration config){ Map playersWaiting = new HashMap<>(); + router.register(new Register(repo, playersWaiting)); + router.register(new MailConfirmation(repo, router, config.getUsersFiles(), config.getGitToken(), playersWaiting)); + router.register(new Login(repo, router)); + router.register(new ProfileSettings(repo)); + router.register(new ChangePassword(repo)); + router.register(new ForgotPassword()); + + router.register(new DynamicLogs(repo, router.getLogger())); + router.register(new ChapterElement(repo)); router.register(new ChapterList(repo)); router.register(new PuzzleElement(repo)); - router.register(new Register(repo, router, config.getUsersFiles(), playersWaiting)); - router.register(new MailConfirmation(repo, router, config.getUsersFiles(), playersWaiting)); - router.register(new Login(repo, router)); router.register(new Result(repo)); router.register(new Leaderboard(repo)); router.register(new PlayerDetails(repo)); router.register(new BadgeDetails(repo)); Locker groupLock = new Locker<>(); - router.register(new GroupCreate(repo, groupLock, config.getGroupJoinMinutes())); - - DynamicLeaderboard dlb = new DynamicLeaderboard(repo); - router.register(dlb); - - Locker leaderboard = dlb.getLocker(); + Locker leaderboard = new Locker<>(); + router.register(new DynamicLeaderboard(repo, leaderboard)); router.register(new PuzzleResponse(repo, config.getUsersFiles(), leaderboard)); + + router.register(new GroupCreate(repo, groupLock, config.getGroupJoinMinutes())); router.register(new GroupList(repo)); router.register(new GroupJoin(repo, config.getGroupJoinMinutes(), config.getGroupQuitMinutes(), leaderboard)); router.register(new GroupQuit(repo, config.getGroupJoinMinutes(), leaderboard)); diff --git a/src/dev/peerat/backend/model/Chapter.java b/src/dev/peerat/backend/model/Chapter.java index 0167932..dc35c49 100644 --- a/src/dev/peerat/backend/model/Chapter.java +++ b/src/dev/peerat/backend/model/Chapter.java @@ -1,6 +1,7 @@ package dev.peerat.backend.model; import java.sql.Timestamp; +import java.time.LocalDateTime; import java.util.List; public class Chapter { @@ -33,6 +34,14 @@ public class Chapter { public void setPuzzles(List puzzles) { this.puzzles = puzzles; } + + public boolean isInCurrentTime(){ + LocalDateTime now = LocalDateTime.now(); + boolean show = true; + if(startDate != null) show &= now.isAfter(startDate.toLocalDateTime()); + if(endDate != null) show &= now.isBefore(endDate.toLocalDateTime()); + return show; + } public Timestamp getStartDate() { return startDate; diff --git a/src/dev/peerat/backend/model/Player.java b/src/dev/peerat/backend/model/Player.java index 53d5575..a532052 100644 --- a/src/dev/peerat/backend/model/Player.java +++ b/src/dev/peerat/backend/model/Player.java @@ -41,6 +41,10 @@ public class Player implements Comparable { // For player find in Map during register process this.email = email; } + + public void setPseudo(String pseudo){ + this.pseudo = pseudo; + } public String getPseudo() { return this.pseudo; @@ -185,8 +189,8 @@ public class Player implements Comparable { } @Override - public int hashCode() { - return Objects.hash(email, pseudo); + public int hashCode(){ + return Objects.hash(email); } @Override @@ -198,6 +202,6 @@ public class Player implements Comparable { if (getClass() != obj.getClass()) return false; Player other = (Player) obj; - return Objects.equals(email, other.email) && Objects.equals(pseudo, other.pseudo); + return Objects.equals(email, other.email); } } diff --git a/src/dev/peerat/backend/repository/DatabaseQuery.java b/src/dev/peerat/backend/repository/DatabaseQuery.java index 8d4ce39..b0ba59f 100644 --- a/src/dev/peerat/backend/repository/DatabaseQuery.java +++ b/src/dev/peerat/backend/repository/DatabaseQuery.java @@ -69,6 +69,7 @@ public enum DatabaseQuery { // PLAYERS GET_PLAYER_SIMPLE("SELECT pseudo, email, firstname, lastname, description FROM players WHERE id_player = ?"), + GET_PLAYER_PSEUDO("SELECT * FROM players WHERE pseudo = ?"), GET_PLAYER_DETAILS("SELECT p.*, g.*\r\n" + "FROM players p\r\n" + "LEFT OUTER JOIN containsGroups cg ON p.id_player = cg.fk_player\r\n" @@ -79,6 +80,8 @@ public enum DatabaseQuery { GET_PLAYER_DETAILS_BY_PSEUDO(GET_PLAYER_DETAILS, "p.pseudo = ? GROUP BY g.name ORDER BY g.fk_chapter, g.fk_puzzle;"), GET_PLAYER_COMPLETIONS("select c.*, p.name from completions c left join puzzles p on c.fk_puzzle = p.id_puzzle where fk_player = ?;"), GET_PLAYER_RANK("SELECT * FROM (SELECT fk_player, RANK() OVER(ORDER BY SUM(score) DESC) rank FROM completions c LEFT JOIN players p ON p.id_player = c.fk_player GROUP BY fk_player ORDER BY rank) AS ranks WHERE ranks.fk_player = ?;"), + UPDATE_PLAYER_INFO("UPDATE players SET pseudo = ?, email = ?, first_name = ?, last_name = ? WHERE id_player = ?"), + UPDATE_PLAYER_PASSWORD("UPDATE players SET passwd = ? WHERE id_player = ?"), // BADGES GET_BADGE("SELECT * FROM badges WHERE id_badge = ?"), GET_BADGES_OF_PLAYER( diff --git a/src/dev/peerat/backend/repository/DatabaseRepository.java b/src/dev/peerat/backend/repository/DatabaseRepository.java index 259fa88..87bbe74 100644 --- a/src/dev/peerat/backend/repository/DatabaseRepository.java +++ b/src/dev/peerat/backend/repository/DatabaseRepository.java @@ -32,68 +32,6 @@ public class DatabaseRepository { public DatabaseRepository(Configuration config) { this.config = config; } -// testTrigger(); -// } -// -// private void testTrigger(){ -// try { -// ensureConnection(); -// }catch(Exception e){ -// e.printStackTrace(); -// } -// System.out.println("connection ensured"); -// -// try { -// PreparedStatement log = this.con.prepareStatement("DROP TABLE mycustomlog;"); -// log.execute(); -// }catch(Exception e){ -// e.printStackTrace(); -// } -// System.out.println("log dropped"); -// -// try { -// PreparedStatement log = this.con.prepareStatement("CREATE TABLE mycustomlog(\r\n" -// + " message VARCHAR(255),\r\n" -// + " primary key (message)\r\n" -// + ");"); -// log.execute(); -// }catch(Exception e){ -// e.printStackTrace(); -// } -// System.out.println("log created"); -// -// try { -// System.out.println(DatabaseQuery.FIRST_TRY.toString()); -// DatabaseQuery.FIRST_TRY.prepare(this.con).execute(); -// }catch(Exception e){ -// e.printStackTrace(); -// } -// -// System.out.println("trigger inserted"); -// -// try { -// insertCompletion(new Completion(1, 1, 1, null, 1)); -// } catch (SQLException e1) { -// e1.printStackTrace(); -// } -// -// try { -// showLog(); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// System.out.println("------------------------------"); -// } -// -// private void showLog() throws Exception{ -// ensureConnection(); -// -// PreparedStatement stmt = this.con.prepareStatement("SELECT * FROM mycustomlog"); -// ResultSet result = stmt.executeQuery(); -// while(result.next()){ -// System.out.println("[LOG] "+result.getString("message")); -// } -// } private void ensureConnection() throws SQLException { if (con == null || (!con.isValid(5))) { @@ -277,6 +215,50 @@ public class DatabaseRepository { } return null; } + + public boolean updatePseudo(int id, Player player, String pseudo){ + try{ + PreparedStatement statment = DatabaseQuery.GET_PLAYER_PSEUDO.prepare(this.con); + statment.setString(1, pseudo); + ResultSet result = statment.executeQuery(); + if(result.next()) return false; + statment = DatabaseQuery.UPDATE_PLAYER_INFO.prepare(this.con); + statment.setString(1, player.getPseudo()); + statment.setString(2, player.getEmail()); + statment.setString(3, player.getFirstname()); + statment.setString(4, player.getLastname()); + statment.setInt(5, id); + return statment.executeUpdate() > 0; + }catch(Exception e){ + e.printStackTrace(); + } + return false; + } + + public void updateProfile(int id, Player player, String lastname, String firstname){ + try{ + PreparedStatement statment = DatabaseQuery.UPDATE_PLAYER_INFO.prepare(this.con); + statment.setString(1, player.getPseudo()); + statment.setString(2, player.getEmail()); + statment.setString(3, firstname); + statment.setString(4, lastname); + statment.setInt(5, id); + statment.executeUpdate(); + }catch(Exception e){ + e.printStackTrace(); + } + } + + public void updatePassword(int id, String password){ + try{ + PreparedStatement statment = DatabaseQuery.UPDATE_PLAYER_PASSWORD.prepare(this.con); + statment.setString(1, Password.hash(password).withArgon2().getResult()); + statment.setInt(2, id); + statment.executeUpdate(); + }catch(Exception e){ + e.printStackTrace(); + } + } public Player getPlayerDetails(int idPlayer) { return getPlayerDetails(idPlayer, null); @@ -520,7 +502,6 @@ public class DatabaseRepository { */ 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(); con.setAutoCommit(false); @@ -528,7 +509,7 @@ public class DatabaseRepository { Statement.RETURN_GENERATED_KEYS)) { playerStatement.setString(1, pseudo); playerStatement.setString(2, email); - playerStatement.setString(3, hash.getResult()); + playerStatement.setString(3, Password.hash(password).withArgon2().getResult()); playerStatement.setString(4, firstname); playerStatement.setString(5, lastname); playerStatement.setString(6, description); diff --git a/src/dev/peerat/backend/routes/ChapterElement.java b/src/dev/peerat/backend/routes/ChapterElement.java index a54ee61..74e75b0 100644 --- a/src/dev/peerat/backend/routes/ChapterElement.java +++ b/src/dev/peerat/backend/routes/ChapterElement.java @@ -34,23 +34,23 @@ public class ChapterElement implements Response { JSONObject chapterJSON = new JSONObject(); chapterJSON.put("id", chapter.getId()); chapterJSON.put("name", chapter.getName()); - if (chapter.getStartDate() != null) - chapterJSON.put("startDate", chapter.getStartDate().toString()); - if (chapter.getEndDate() != null) - chapterJSON.put("endDate", chapter.getEndDate().toString()); - JSONArray puzzles = new JSONArray(); + boolean show = chapter.isInCurrentTime(); + chapterJSON.put("show", show); PeerAtUser user = context.getUser(); - for (Puzzle puzzle : chapter.getPuzzles()){ - JSONObject puzzleJSON = new JSONObject(); - puzzleJSON.put("id", puzzle.getId()); - puzzleJSON.put("name", puzzle.getName()); - puzzleJSON.put("scoreMax", puzzle.getScoreMax()); - if (puzzle.getTags() != null) puzzleJSON.put("tags", puzzle.getJsonTags()); - int score = this.databaseRepo.getScore(user.getId(), puzzle.getId()); - if(score >= 0) puzzleJSON.put("score", score); - puzzles.add(puzzleJSON); + if(show){ + JSONArray puzzles = new JSONArray(); + for (Puzzle puzzle : chapter.getPuzzles()){ + JSONObject puzzleJSON = new JSONObject(); + puzzleJSON.put("id", puzzle.getId()); + puzzleJSON.put("name", puzzle.getName()); + puzzleJSON.put("scoreMax", puzzle.getScoreMax()); + if (puzzle.getTags() != null) puzzleJSON.put("tags", puzzle.getJsonTags()); + int score = this.databaseRepo.getScore(user.getId(), puzzle.getId()); + if(score >= 0) puzzleJSON.put("score", score); + puzzles.add(puzzleJSON); + } + chapterJSON.put("puzzles", puzzles); } - chapterJSON.put("puzzles", puzzles); context.response(200); writer.write(chapterJSON.toJSONString()); } else { diff --git a/src/dev/peerat/backend/routes/ChapterList.java b/src/dev/peerat/backend/routes/ChapterList.java index c5ccedc..19b6a16 100644 --- a/src/dev/peerat/backend/routes/ChapterList.java +++ b/src/dev/peerat/backend/routes/ChapterList.java @@ -35,10 +35,7 @@ public class ChapterList implements Response { JSONObject chapterJSON = new JSONObject(); chapterJSON.put("id", chapter.getId()); chapterJSON.put("name", chapter.getName()); - if (chapter.getStartDate() != null) - chapterJSON.put("startDate", chapter.getStartDate().toString()); - if (chapter.getEndDate() != null) - chapterJSON.put("endDate", chapter.getEndDate().toString()); + chapterJSON.put("show", chapter.isInCurrentTime()); chaptersJSON.add(chapterJSON); } context.response(200); diff --git a/src/dev/peerat/backend/routes/DynamicLeaderboard.java b/src/dev/peerat/backend/routes/DynamicLeaderboard.java index 08ffea5..b2df758 100644 --- a/src/dev/peerat/backend/routes/DynamicLeaderboard.java +++ b/src/dev/peerat/backend/routes/DynamicLeaderboard.java @@ -16,9 +16,9 @@ public class DynamicLeaderboard extends Leaderboard{ private Locker locker; - public DynamicLeaderboard(DatabaseRepository databaseRepo){ + public DynamicLeaderboard(DatabaseRepository databaseRepo, Locker locker){ super(databaseRepo); - this.locker = new Locker<>(); + this.locker = locker; } public Locker getLocker(){ diff --git a/src/dev/peerat/backend/routes/MailConfirmation.java b/src/dev/peerat/backend/routes/MailConfirmation.java deleted file mode 100644 index 62ca4a3..0000000 --- a/src/dev/peerat/backend/routes/MailConfirmation.java +++ /dev/null @@ -1,96 +0,0 @@ -package dev.peerat.backend.routes; - -import static dev.peerat.framework.RequestType.POST; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Map; -import java.util.regex.Matcher; - -import org.json.simple.JSONObject; - -import dev.peerat.backend.bonus.extract.RouteDoc; -import dev.peerat.backend.model.PeerAtUser; -import dev.peerat.backend.model.Player; -import dev.peerat.backend.repository.DatabaseRepository; -import dev.peerat.framework.Context; -import dev.peerat.framework.HttpReader; -import dev.peerat.framework.HttpWriter; -import dev.peerat.framework.Response; -import dev.peerat.framework.Route; -import dev.peerat.framework.Router; - -public class MailConfirmation implements Response { - - private DatabaseRepository databaseRepo; - private Router router; - private String usersFilesPath; - private Map playersWaiting; - - public MailConfirmation(DatabaseRepository databaseRepo, Router router, String initUsersFilesPath, - Map playersWaiting) { - this.databaseRepo = databaseRepo; - this.router = router; - usersFilesPath = initUsersFilesPath; - } - - @RouteDoc(path = "/confirmation", responseCode = 200, responseDescription = "L'utilisateur est inscrit") - @RouteDoc(responseCode = 403, responseDescription = "L'utilisateur est connecté") - @RouteDoc(responseCode = 400, responseDescription = "Aucune données fournie / données invalide") - - @Route(path = "^\\/confirmation$", type = POST) - public void exec(Matcher matcher, Context context, HttpReader reader, HttpWriter writer) throws Exception { - if (context.getUser() != null) { - context.response(403); - return; - } - JSONObject informations = reader.readJson(); - if (informations != null) { - boolean allNecessaryFieldsFilled = informations.containsKey("email") && informations.containsKey("code") - && informations.containsKey("passwd"); - if (!allNecessaryFieldsFilled) { - context.response(400); - return; - } - String email = (String) informations.get("email"); - String password = (String) informations.get("passwd"); - int code = (int) informations.get("code"); - - Player newPlayer = getPlayerFromEmail(email); - if (newPlayer != null && code == playersWaiting.get(newPlayer)) { - String pseudo = newPlayer.getPseudo(); - int id; - if ((id = databaseRepo.register(pseudo, email, password, newPlayer.getFirstname(), newPlayer.getLastname(), "", "", "")) >= 0) { - context.response(200, "Access-Control-Expose-Headers: Authorization", - "Authorization: Bearer " + this.router.createAuthUser(new PeerAtUser(id))); - createFolderToSaveSourceCode(pseudo); - return; - } else { - context.response(400); - JSONObject error = new JSONObject(); - error.put("username_valid", pseudo); - error.put("email_valid", email); - writer.write(error.toJSONString()); - return; - } - } - } - context.response(400); - } - - private void createFolderToSaveSourceCode(String pseudo) throws IOException { - - Files.createDirectories(Paths.get(String.format("%s/%s", usersFilesPath, pseudo))); - } - - private Player getPlayerFromEmail(String email) { - Player toMatch = new Player(email); - for (Player p: playersWaiting.keySet()) { - if (p.equals(toMatch)) { - return p; - } - } - return null; - } -} diff --git a/src/dev/peerat/backend/routes/admins/DynamicLogs.java b/src/dev/peerat/backend/routes/admins/DynamicLogs.java new file mode 100644 index 0000000..ac74691 --- /dev/null +++ b/src/dev/peerat/backend/routes/admins/DynamicLogs.java @@ -0,0 +1,56 @@ +package dev.peerat.backend.routes.admins; + +import java.util.regex.Matcher; + +import org.json.simple.JSONObject; + +import dev.peerat.backend.model.PeerAtUser; +import dev.peerat.backend.repository.DatabaseRepository; +import dev.peerat.framework.Context; +import dev.peerat.framework.HttpReader; +import dev.peerat.framework.HttpWriter; +import dev.peerat.framework.Locker; +import dev.peerat.framework.Locker.Key; +import dev.peerat.framework.Response; +import dev.peerat.framework.Route; + +public class DynamicLogs implements Response{ + + private Locker locker; //Context + private DatabaseRepository repo; + + public DynamicLogs(DatabaseRepository repo, Locker locker){ + this.repo = repo; + this.locker = locker; + } + + @Route(path = "^/admin/logs$", needLogin = true, websocket = true) + public void exec(Matcher matcher, Context context, HttpReader reader, HttpWriter writer) throws Exception { + //check if admin + + Key key = new Key(); + + locker.init(key); + try { + while(!reader.isClosed()){ + Context instance = locker.getValue(key); + JSONObject json = new JSONObject(); + json.put("logged", instance.isLogged()); + if(instance.isLogged()) json.put("pseudo", repo.getPlayer(instance.getUser().getId()).getPseudo()); + json.put("path", instance.getPath()); + json.put("type", instance.getType()); + json.put("code", instance.getResponseCode()); + + writer.write(json.toJSONString()); + writer.flush(); + locker.lock(key); + } + }catch(Exception e){ + e.printStackTrace(); + } + locker.remove(key); + } + + + +} diff --git a/src/dev/peerat/backend/routes/users/ChangePassword.java b/src/dev/peerat/backend/routes/users/ChangePassword.java new file mode 100644 index 0000000..ab4bff6 --- /dev/null +++ b/src/dev/peerat/backend/routes/users/ChangePassword.java @@ -0,0 +1,36 @@ +package dev.peerat.backend.routes.users; + +import java.util.regex.Matcher; + +import org.jose4j.json.internal.json_simple.JSONObject; + +import dev.peerat.backend.bonus.extract.RouteDoc; +import dev.peerat.backend.model.PeerAtUser; +import dev.peerat.backend.repository.DatabaseRepository; +import dev.peerat.framework.Context; +import dev.peerat.framework.HttpReader; +import dev.peerat.framework.HttpWriter; +import dev.peerat.framework.RequestType; +import dev.peerat.framework.Response; +import dev.peerat.framework.Route; + +public class ChangePassword implements Response{ + + private DatabaseRepository repo; + + public ChangePassword(DatabaseRepository repo){ + this.repo = repo; + } + + @RouteDoc(path = "/user/cpw", responseCode = 200, responseDescription = "L'utilisateur a mis à jours sont mots de passe") + @RouteDoc(responseCode = 400, responseDescription = "L'utilisateur a envoyer un mots de passe invalide") + + @Route(path = "^/user/cpw$", type = RequestType.POST, needLogin = true) + public void exec(Matcher matcher, Context context, HttpReader reader, HttpWriter writer) throws Exception { + String password = (String) reader.readJson().get("password"); + + repo.updatePassword(context.getUser().getId(), password); + context.response(200); + } + +} diff --git a/src/dev/peerat/backend/routes/users/ForgotPassword.java b/src/dev/peerat/backend/routes/users/ForgotPassword.java new file mode 100644 index 0000000..fd25fcc --- /dev/null +++ b/src/dev/peerat/backend/routes/users/ForgotPassword.java @@ -0,0 +1,25 @@ +package dev.peerat.backend.routes.users; + +import java.util.regex.Matcher; + +import dev.peerat.framework.Context; +import dev.peerat.framework.HttpReader; +import dev.peerat.framework.HttpWriter; +import dev.peerat.framework.Response; +import dev.peerat.framework.Route; + +public class ForgotPassword implements Response{ + + @Route(path = "^/user/fpw$") + public void exec(Matcher matcher, Context context, HttpReader reader, HttpWriter writer) throws Exception { + if(context.isLogged()){ + context.response(403); + return; + } + + + } + + + +} diff --git a/src/dev/peerat/backend/routes/Login.java b/src/dev/peerat/backend/routes/users/Login.java similarity index 64% rename from src/dev/peerat/backend/routes/Login.java rename to src/dev/peerat/backend/routes/users/Login.java index 95dccfb..9cb11b8 100644 --- a/src/dev/peerat/backend/routes/Login.java +++ b/src/dev/peerat/backend/routes/users/Login.java @@ -1,4 +1,4 @@ -package dev.peerat.backend.routes; +package dev.peerat.backend.routes.users; import static dev.peerat.framework.RequestType.POST; @@ -9,19 +9,19 @@ import org.json.simple.JSONObject; import dev.peerat.backend.bonus.extract.RouteDoc; import dev.peerat.backend.model.PeerAtUser; import dev.peerat.backend.repository.DatabaseRepository; +import dev.peerat.backend.utils.FormResponse; import dev.peerat.framework.Context; import dev.peerat.framework.HttpReader; import dev.peerat.framework.HttpWriter; -import dev.peerat.framework.Response; import dev.peerat.framework.Route; import dev.peerat.framework.Router; -public class Login implements Response { +public class Login extends FormResponse{ private DatabaseRepository databaseRepo; private Router router; - public Login(DatabaseRepository databaseRepo, Router router) { + public Login(DatabaseRepository databaseRepo, Router router){ this.databaseRepo = databaseRepo; this.router = router; } @@ -32,23 +32,23 @@ public class Login implements Response { @Route(path = "^\\/login$", type = POST) public void exec(Matcher matcher, Context context, HttpReader reader, HttpWriter writer) throws Exception { - if (context.getUser() != null) { + if(context.isLogged()){ context.response(403); return; } - JSONObject informations = reader.readJson(); - if (informations != null) { - String pseudo = (String) informations.get("pseudo"); - String password = (String) informations.get("passwd"); - int id; - if ((id = databaseRepo.login(pseudo, password)) >= 0) { - context.response(200, - "Access-Control-Expose-Headers: Authorization", - "Authorization: Bearer " + this.router.createAuthUser(new PeerAtUser(id))); - return; - } + JSONObject json = json(reader); + if(!areValids("pseudo", "passwd")){ + context.response(400); + return; + } + int id; + if((id = databaseRepo.login((String)json.get("pseudo"), (String)json.get("passwd"))) >= 0){ + context.response(200, + "Access-Control-Expose-Headers: Authorization", + "Authorization: Bearer " + this.router.createAuthUser(new PeerAtUser(id))); + }else{ + context.response(400); } - context.response(400); } } diff --git a/src/dev/peerat/backend/routes/users/MailConfirmation.java b/src/dev/peerat/backend/routes/users/MailConfirmation.java new file mode 100644 index 0000000..d650495 --- /dev/null +++ b/src/dev/peerat/backend/routes/users/MailConfirmation.java @@ -0,0 +1,156 @@ +package dev.peerat.backend.routes.users; + +import static dev.peerat.framework.RequestType.POST; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import java.util.Map; +import java.util.Base64.Encoder; +import java.util.regex.Matcher; + +import javax.net.ssl.HttpsURLConnection; + +import org.json.simple.JSONAware; +import org.json.simple.JSONObject; + +import dev.peerat.backend.bonus.extract.RouteDoc; +import dev.peerat.backend.model.PeerAtUser; +import dev.peerat.backend.model.Player; +import dev.peerat.backend.repository.DatabaseRepository; +import dev.peerat.backend.utils.FormResponse; +import dev.peerat.framework.Context; +import dev.peerat.framework.HttpReader; +import dev.peerat.framework.HttpWriter; +import dev.peerat.framework.Route; +import dev.peerat.framework.Router; + +public class MailConfirmation extends FormResponse { + + private DatabaseRepository databaseRepo; + private Router router; + private String usersFilesPath; + private KeyPairGenerator generator; + private Encoder encoder; + private String gitToken; + private Map playersWaiting; + + public MailConfirmation( + DatabaseRepository databaseRepo, + Router router, + String initUsersFilesPath, + String gitToken, + Map playersWaiting){ + this.databaseRepo = databaseRepo; + this.router = router; + usersFilesPath = initUsersFilesPath; + this.gitToken = gitToken; + try { + generator = KeyPairGenerator.getInstance("RSA"); + generator.initialize(2048); //a changer ? + } catch (NoSuchAlgorithmException e){ + e.printStackTrace(); + } + encoder = Base64.getEncoder(); + } + + @RouteDoc(path = "/confirmation", responseCode = 200, responseDescription = "L'utilisateur est inscrit") + @RouteDoc(responseCode = 403, responseDescription = "L'utilisateur est connecté") + @RouteDoc(responseCode = 400, responseDescription = "Aucune données fournie / données invalide") + + @Route(path = "^\\/confirmation$", type = POST) + public void exec(Matcher matcher, Context context, HttpReader reader, HttpWriter writer) throws Exception { + if (context.isLogged()){ + context.response(403); + return; + } + JSONObject json = json(reader); + if(!areValids("email","code","passwd")){ + context.response(400); + return; + } + String email = (String) json.get("email"); + String password = (String) json.get("passwd"); + int code = (int) json.get("code"); + + Player newPlayer = getPlayerFromEmail(email); + if (newPlayer != null && code == playersWaiting.get(newPlayer)){ + playersWaiting.remove(newPlayer); + String pseudo = newPlayer.getPseudo(); + int id; + if ((id = databaseRepo.register(pseudo, email, password, newPlayer.getFirstname(), newPlayer.getLastname(), "", "", "")) >= 0) { + context.response(200, + "Access-Control-Expose-Headers: Authorization", + "Authorization: Bearer " + this.router.createAuthUser(new PeerAtUser(id))); + createFolderToSaveSourceCode(pseudo); + generateGitKey(email, pseudo, password); + return; + } else { + context.response(400); + JSONObject error = new JSONObject(); + error.put("username_valid", pseudo); + error.put("email_valid", email); + writer.write(error.toJSONString()); + return; + } + } + context.response(400); + } + + private void createFolderToSaveSourceCode(String pseudo) throws IOException { + + Files.createDirectories(Paths.get(String.format("%s/%s", usersFilesPath, pseudo))); + } + + private Player getPlayerFromEmail(String email) { + Player toMatch = new Player(email); + for (Player p: playersWaiting.keySet()) { + if (p.equals(toMatch)) { + return p; + } + } + return null; + } + + private String generateGitKey(String email, String pseudo, String password) throws Exception{ + KeyPair pair = generator.generateKeyPair(); //doit être unique ??? + + JSONObject createUser = new JSONObject(); + createUser.put("email", email); + createUser.put("username", pseudo); + createUser.put("password", password); + post("https://git-users.peerat.dev/api/v1/admin/users/", createUser); + + JSONObject sendKey = new JSONObject(); + sendKey.put("key", new String(encoder.encode(pair.getPrivate().getEncoded()))); //add ssh-rsa au début ? + sendKey.put("read_only", false); + sendKey.put("title", "peer_at_code_auto_push_key_"+pseudo); + post("https://git-users.peerat.dev/api/v1/admin/users/"+pseudo+"/keys", sendKey); + + return new String(encoder.encode(pair.getPrivate().getEncoded())); + } + + private void post(String url, JSONAware json) throws Exception{ + HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection(); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type","application/json"); + connection.setRequestProperty("Authorization","Bearer "+this.gitToken); + connection.setDoInput(true); + connection.setDoOutput(true); + + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream())); + writer.write(json.toJSONString()); + writer.flush(); + writer.close(); + + int response = connection.getResponseCode(); + if(response != 201) throw new Exception("Call to "+url+" failed with response code "+response); + } +} diff --git a/src/dev/peerat/backend/routes/users/ProfileSettings.java b/src/dev/peerat/backend/routes/users/ProfileSettings.java new file mode 100644 index 0000000..8293824 --- /dev/null +++ b/src/dev/peerat/backend/routes/users/ProfileSettings.java @@ -0,0 +1,58 @@ +package dev.peerat.backend.routes.users; + +import java.util.regex.Matcher; + +import org.json.simple.JSONObject; + +import dev.peerat.backend.bonus.extract.RouteDoc; +import dev.peerat.backend.model.PeerAtUser; +import dev.peerat.backend.model.Player; +import dev.peerat.backend.repository.DatabaseRepository; +import dev.peerat.framework.Context; +import dev.peerat.framework.HttpReader; +import dev.peerat.framework.HttpWriter; +import dev.peerat.framework.RequestType; +import dev.peerat.framework.Response; +import dev.peerat.framework.Route; + +public class ProfileSettings implements Response{ + + private DatabaseRepository repo; + + public ProfileSettings(DatabaseRepository repo){ + this.repo = repo; + } + + @RouteDoc(path = "/user/settings", responseCode = 200, responseDescription = "L'utilisateur a mis à jours sont profile") + @RouteDoc(responseCode = 400, responseDescription = "L'utilisateur a envoyer une donnée unique, déjà utilisée") + + @Route(path = "^/user/settings$", type = RequestType.POST, needLogin = true) + public void exec(Matcher matcher, Context context, HttpReader reader, HttpWriter writer) throws Exception { + JSONObject json = reader.readJson(); + + String pseudo = (String) json.get("pseudo"); + String email = (String) json.get("email"); + String firstname = (String) json.get("firstname"); + String lastname = (String) json.get("lastname"); + Player player = repo.getPlayer(context.getUser().getId()); + + if(!player.getPseudo().equals(pseudo)){ + if(!repo.updatePseudo(context.getUser().getId(), player, pseudo)){ + context.response(400); + return; + } + player.setPseudo(pseudo); + } + + if(!player.getEmail().equals(email)){ + + } + + if((!player.getFirstname().equals(firstname)) || (!player.getLastname().equals(lastname))){ + repo.updateProfile(context.getUser().getId(), player, lastname, firstname); + } + + context.response(200); + } + +} diff --git a/src/dev/peerat/backend/routes/users/Register.java b/src/dev/peerat/backend/routes/users/Register.java new file mode 100644 index 0000000..9aeef35 --- /dev/null +++ b/src/dev/peerat/backend/routes/users/Register.java @@ -0,0 +1,74 @@ +package dev.peerat.backend.routes.users; + +import static dev.peerat.framework.RequestType.POST; + +import java.util.Map; +import java.util.Random; +import java.util.regex.Matcher; + +import org.json.simple.JSONObject; + +import dev.peerat.backend.bonus.extract.RouteDoc; +import dev.peerat.backend.model.PeerAtUser; +import dev.peerat.backend.model.Player; +import dev.peerat.backend.repository.DatabaseRepository; +import dev.peerat.backend.utils.FormResponse; +import dev.peerat.framework.Context; +import dev.peerat.framework.HttpReader; +import dev.peerat.framework.HttpWriter; +import dev.peerat.framework.Route; + +public class Register extends FormResponse { + + private DatabaseRepository databaseRepo; + private Map playersWaiting; + + public Register(DatabaseRepository databaseRepo, Map playersWaiting){ + this.databaseRepo = databaseRepo; + this.playersWaiting = playersWaiting; + } + + @RouteDoc(path = "/register", responseCode = 200, responseDescription = "L'utilisateur est inscrit") + @RouteDoc(responseCode = 403, responseDescription = "L'utilisateur est connecté") + @RouteDoc(responseCode = 400, responseDescription = "Aucune données fournie / données invalide") + + @Route(path = "^\\/register$", type = POST) + public void exec(Matcher matcher, Context context, HttpReader reader, HttpWriter writer) throws Exception{ + if (context.isLogged()){ + context.response(403); + return; + } + JSONObject json = json(reader); + if(!areValids("pseudo","email","firstname","lastname")){ + context.response(400); + return; + } + + String pseudo = (String) json.get("pseudo"); + String email = (String) json.get("email"); + String firstname = (String) json.get("firstname"); + String lastname = (String) json.get("lastname"); + + boolean pseudoAvailable = databaseRepo.checkPseudoAvailability(pseudo); + boolean emailAvailable = databaseRepo.checkEmailAvailability(email); + if(pseudoAvailable && emailAvailable){ + Player player = new Player(pseudo, email, firstname, lastname); + playersWaiting.put(player, codeGenerator()); + context.response(200); + }else{ + context.response(400); + JSONObject error = new JSONObject(); + error.put("username_valid", pseudoAvailable); + error.put("email_valid", emailAvailable); + writer.write(error.toJSONString()); + } + } + + private int codeGenerator() { + int min = 1000; + int max = 9999; + return new Random().nextInt((max-min)) + min; + + } + +} diff --git a/src/dev/peerat/backend/utils/FormResponse.java b/src/dev/peerat/backend/utils/FormResponse.java new file mode 100644 index 0000000..e91c9ea --- /dev/null +++ b/src/dev/peerat/backend/utils/FormResponse.java @@ -0,0 +1,49 @@ +package dev.peerat.backend.utils; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; + +import org.json.simple.JSONAware; + +import dev.peerat.framework.HttpReader; +import dev.peerat.framework.Response; + +public abstract class FormResponse implements Response{ + + private JSONAware json; + private Map checker; + + public FormResponse(){ + this.checker = new HashMap<>(); + } + + public void validator(String key, Pattern regex){ + this.checker.put(key, regex); + } + + public T json(HttpReader reader) throws Exception{ + return (T) (this.json = reader.readJson()); + } + + public boolean hasFields(String... fields){ + Map map = (Map)json; + for(String field : fields){ + if(!map.containsKey(field)) return false; + } + return true; + } + + public boolean areValids(String... fields){ + Map map = (Map)json; + for(String field : fields){ + String value = (String) map.get(field); + if(value == null) return false; + if(value.isEmpty()) return false; + Pattern pattern = checker.get(field); + if(pattern == null) continue; + if(!pattern.matcher(value).matches()) return false; + } + return true; + } +} diff --git a/src/dev/peerat/backend/utils/Mail.java b/src/dev/peerat/backend/utils/Mail.java index b6e1137..b82f03a 100644 --- a/src/dev/peerat/backend/utils/Mail.java +++ b/src/dev/peerat/backend/utils/Mail.java @@ -42,8 +42,8 @@ public class Mail { msg.addHeader("format", "flowed"); msg.addHeader("Content-Transfer-Encoding", "8bit"); - msg.setFrom(new InternetAddress("ping@peerat.dev", "NoReply-JD")); - msg.setReplyTo(InternetAddress.parse("ping@peerat.dev", false)); + msg.setFrom(new InternetAddress(fromAddress, "NoReply-JD")); + msg.setReplyTo(InternetAddress.parse(fromAddress, false)); msg.setSubject(subject, "UTF-8"); msg.setText(text, "UTF-8"); msg.setSentDate(new Date()); diff --git a/test/dev/peerat/backend/TestDatabaseRepository.java b/test/dev/peerat/backend/TestDatabaseRepository.java new file mode 100644 index 0000000..4e00be3 --- /dev/null +++ b/test/dev/peerat/backend/TestDatabaseRepository.java @@ -0,0 +1,64 @@ +package dev.peerat.backend; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.sql.Connection; +import java.sql.SQLException; + +import dev.peerat.backend.repository.DatabaseRepository; + +public class TestDatabaseRepository extends DatabaseRepository{ + + private Connection con; + private String schem; + + public TestDatabaseRepository(Configuration config, File databaseSchem){ + super(config); + + try{ + schem = ""; + BufferedReader reader = new BufferedReader(new FileReader(databaseSchem)); + String line; + while((line = reader.readLine()) != null) schem+=line; + reader.close(); + }catch(Exception e){ + e.printStackTrace(); + } + } + + public void init(){ + try { + Method method = DatabaseRepository.class.getDeclaredMethod("ensureConnection"); + method.setAccessible(true); + method.invoke(this); + + Field field = DatabaseRepository.class.getDeclaredField("con"); + field.setAccessible(true); + this.con = (Connection) field.get(this); + }catch(Exception e){ + e.getCause().printStackTrace(); + } + } + + public void close(){ + try { + this.con.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public void reset(){ + try{ + String[] split = schem.split(";"); + for(String statment : split){ + this.con.prepareStatement(statment).execute(); + } + }catch(Exception e){ + e.printStackTrace(); + } + } +} diff --git a/test/dev/peerat/backend/webclient/WebClient.java b/test/dev/peerat/backend/WebClient.java similarity index 99% rename from test/dev/peerat/backend/webclient/WebClient.java rename to test/dev/peerat/backend/WebClient.java index 59f0872..392cfaa 100644 --- a/test/dev/peerat/backend/webclient/WebClient.java +++ b/test/dev/peerat/backend/WebClient.java @@ -1,4 +1,4 @@ -package dev.peerat.backend.webclient; +package dev.peerat.backend; import static org.junit.Assert.fail; diff --git a/test/dev/peerat/backend/routes/PlayerDetailsTests.java b/test/dev/peerat/backend/routes/PlayerDetailsTests.java index d8c8260..3dcc745 100644 --- a/test/dev/peerat/backend/routes/PlayerDetailsTests.java +++ b/test/dev/peerat/backend/routes/PlayerDetailsTests.java @@ -9,7 +9,7 @@ import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; import dev.peerat.backend.Main; -import dev.peerat.backend.webclient.WebClient; +import dev.peerat.backend.WebClient; @TestInstance(Lifecycle.PER_CLASS) class PlayerDetailsTests { diff --git a/test/dev/peerat/backend/routes/ScoreTests.java b/test/dev/peerat/backend/routes/ScoreTests.java index c81ddfc..cbffc0a 100644 --- a/test/dev/peerat/backend/routes/ScoreTests.java +++ b/test/dev/peerat/backend/routes/ScoreTests.java @@ -10,7 +10,7 @@ import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; import dev.peerat.backend.Main; -import dev.peerat.backend.webclient.WebClient; +import dev.peerat.backend.WebClient; @TestInstance(Lifecycle.PER_CLASS) public class ScoreTests { diff --git a/test/dev/peerat/backend/routes/TmpRoutesTests.java b/test/dev/peerat/backend/routes/TmpRoutesTests.java index b6079e3..b5617a0 100644 --- a/test/dev/peerat/backend/routes/TmpRoutesTests.java +++ b/test/dev/peerat/backend/routes/TmpRoutesTests.java @@ -10,7 +10,7 @@ import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; import dev.peerat.backend.Main; -import dev.peerat.backend.webclient.WebClient; +import dev.peerat.backend.WebClient; @TestInstance(Lifecycle.PER_CLASS) public class TmpRoutesTests { diff --git a/test/dev/peerat/backend/routes/TriggerTests.java b/test/dev/peerat/backend/routes/TriggerTests.java index a150c8c..8609c8d 100644 --- a/test/dev/peerat/backend/routes/TriggerTests.java +++ b/test/dev/peerat/backend/routes/TriggerTests.java @@ -9,7 +9,7 @@ import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; import dev.peerat.backend.Main; -import dev.peerat.backend.webclient.WebClient; +import dev.peerat.backend.WebClient; @TestInstance(Lifecycle.PER_CLASS) public class TriggerTests { diff --git a/test/dev/peerat/backend/userstories/BaseUserStoriesTest.java b/test/dev/peerat/backend/userstories/BaseUserStoriesTest.java new file mode 100644 index 0000000..10ced61 --- /dev/null +++ b/test/dev/peerat/backend/userstories/BaseUserStoriesTest.java @@ -0,0 +1,30 @@ +package dev.peerat.backend.userstories; + +import java.io.File; + +import dev.peerat.backend.Configuration; +import dev.peerat.backend.TestDatabaseRepository; + +public class BaseUserStoriesTest { + + private Configuration config; + private TestDatabaseRepository repo; + + public BaseUserStoriesTest(){} + + public void init() throws Exception{ + this.config = new Configuration("config-test.txt"); + this.repo = new TestDatabaseRepository(config, new File("database-schem.sql")); + + this.config.load(); + } + + public Configuration getConfig(){ + return this.config; + } + + public TestDatabaseRepository getRepository(){ + return this.repo; + } + +} diff --git a/test/dev/peerat/backend/userstories/LoginTests.java b/test/dev/peerat/backend/userstories/LoginTests.java new file mode 100644 index 0000000..105e636 --- /dev/null +++ b/test/dev/peerat/backend/userstories/LoginTests.java @@ -0,0 +1,79 @@ +package dev.peerat.backend.userstories; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; + +import dev.peerat.backend.Main; +import dev.peerat.backend.WebClient; + +@TestInstance(Lifecycle.PER_METHOD) +public class LoginTests extends BaseUserStoriesTest{ + + private Thread server; + private WebClient client; + + @BeforeEach + public void init() throws Exception{ + Class.forName("com.mysql.cj.jdbc.Driver"); + + super.init(); + getRepository().init(); + getRepository().reset(); + + server = new Thread(new Runnable(){ + @Override + public void run(){ + try { + Main.main(null); + } catch (Exception e){ + e.printStackTrace(); + }; + } + }); + server.start(); + client = new WebClient("localhost", 80); + + try { + client.register("user", "password", "mail@peerat.dev", "firstname", "lastname", "description"); + client.assertResponseCode(200); + client.disconnect(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @AfterEach + public void stop(){ + server.interrupt(); + } + + @Test + public void normalLogin() throws Exception{ + client.auth("user", "password"); + client.assertResponseCode(200); + + } + + @Test + public void wrongPassword() throws Exception{ + client.auth("user", "password1"); + client.assertResponseCode(400); + } + + @Test + public void wrongUsername() throws Exception{ + client.auth("user1", "password"); + client.assertResponseCode(400); + } + + @Test + public void alreadyLoggedin() throws Exception{ + client.auth("user", "password"); + client.assertResponseCode(200); + client.auth("user", "password"); + client.assertResponseCode(403); + } +} diff --git a/test/dev/peerat/backend/userstories/RegisterTests.java b/test/dev/peerat/backend/userstories/RegisterTests.java new file mode 100644 index 0000000..2e69e92 --- /dev/null +++ b/test/dev/peerat/backend/userstories/RegisterTests.java @@ -0,0 +1,90 @@ +package dev.peerat.backend.userstories; + +import org.json.simple.JSONObject; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; + +import dev.peerat.backend.Main; +import dev.peerat.backend.WebClient; + +@TestInstance(Lifecycle.PER_METHOD) +public class RegisterTests extends BaseUserStoriesTest{ + + private Thread server; + private WebClient client; + + @BeforeEach + public void init() throws Exception{ + Class.forName("com.mysql.cj.jdbc.Driver"); + + super.init(); + getRepository().init(); + getRepository().reset(); + + server = new Thread(new Runnable(){ + @Override + public void run(){ + try { + Main.main(null); + } catch (Exception e){ + e.printStackTrace(); + }; + } + }); + server.start(); + client = new WebClient("localhost", 80); + } + + @AfterEach + public void stop(){ + server.interrupt(); + getRepository().close(); + } + + @Test + public void normalRegister() throws Exception{ + client.register("test", "test", "test@peerat.dev", "te", "st", "my desc"); + client.assertResponseCode(200); + } + + @Test + public void pseudoAlreadyUse() throws Exception{ + client.register("test", "test", "test@peerat.dev", "te", "st", "my desc"); + client.assertResponseCode(200); + client.disconnect(); + client.register("test", "test", "test1@peerat.dev", "te", "st", "my desc"); + client.assertResponseCode(400); + } + + @Test + public void emailAlreadyUse() throws Exception{ + client.register("test", "test", "test@peerat.dev", "te", "st", "my desc"); + client.assertResponseCode(200); + client.disconnect(); + client.register("test1", "test", "test@peerat.dev", "te", "st", "my desc"); + client.assertResponseCode(400); + } + + @Test + public void emptyField() throws Exception{ + client.register("","","",",","",""); + client.assertResponseCode(400); + } + + @Test + public void lostField() throws Exception{ + client.route("/register", "POST", new JSONObject().toJSONString()); + client.assertResponseCode(400); + } + + @Test + public void alreadyLoggedin() throws Exception{ + client.register("test", "test", "test@peerat.dev", "te", "st", "my desc"); + client.assertResponseCode(200); + client.register("test1", "test", "test@peerat.dev", "te", "st", "my desc"); + client.assertResponseCode(403); + } +}