From a9f44c29af214d40200468e6514d64172ae8a75e Mon Sep 17 00:00:00 2001 From: Gnarwhal Date: Fri, 19 Feb 2021 15:49:24 -0500 Subject: [PATCH] Final Product --- .gitignore | 3 +- .../main/java/achievements/apis/SteamAPI.java | 77 +- .../controllers/AchievementController.java | 41 +- .../controllers/AuthController.java | 15 +- .../controllers/ImportController.java | 47 + .../controllers/UserController.java | 12 +- .../main/java/achievements/data/Profile.java | 65 +- .../main/java/achievements/data/Session.java | 8 - .../src/main/java/achievements/data/User.java | 6 - .../data/importing/ImportPlatform.java | 37 + .../data/importing/ImportUser.java | 38 + .../data/importing/ImportUserPlatform.java | 28 + .../data/request/RateAchievement.java | 47 + .../data/response/search/Achievement.java | 65 + .../achievements/misc/SessionManager.java | 6 +- .../achievements/services/APIService.java | 2 +- .../services/AchievementService.java | 112 ++ .../services/AuthenticationService.java | 24 +- .../achievements/services/ImportService.java | 81 + .../achievements/services/UserService.java | 45 +- frontend/.gitignore | 3 + frontend/server.js | 29 +- frontend/webpage/achievement.html | 163 ++ frontend/webpage/import.html | 39 + frontend/webpage/search_achievements.html | 2 +- frontend/webpage/static/res/import-hover.svg | 1 + frontend/webpage/static/res/import.svg | 1 + frontend/webpage/static/scripts/about.js | 8 - .../webpage/static/scripts/achievement.js | 167 ++ frontend/webpage/static/scripts/common.js | 82 +- frontend/webpage/static/scripts/import.js | 105 ++ frontend/webpage/static/scripts/login.js | 4 +- .../static/scripts/search_achievements.js | 7 + .../webpage/static/scripts/search_games.js | 1 - frontend/webpage/static/scripts/user.js | 47 +- frontend/webpage/static/styles/about.css | 13 - .../webpage/static/styles/achievement.css | 459 ++++++ frontend/webpage/static/styles/common.css | 355 +++++ frontend/webpage/static/styles/import.css | 78 + frontend/webpage/static/styles/search.css | 346 ----- frontend/webpage/static/styles/user.css | 45 +- frontend/webpage/user.html | 140 +- sql/DataProcs.sql | 263 +++- sql/Indexes.sql | 21 + sql/Mondo.sql | 1339 +++++++++++++++++ sql/SearchProcs.sql | 6 +- sql/Tables.sql | 4 +- sql/Views.sql | 2 +- 48 files changed, 3908 insertions(+), 581 deletions(-) create mode 100644 backend/src/main/java/achievements/controllers/ImportController.java create mode 100644 backend/src/main/java/achievements/data/importing/ImportPlatform.java create mode 100644 backend/src/main/java/achievements/data/importing/ImportUser.java create mode 100644 backend/src/main/java/achievements/data/importing/ImportUserPlatform.java create mode 100644 backend/src/main/java/achievements/data/request/RateAchievement.java create mode 100644 backend/src/main/java/achievements/services/ImportService.java create mode 100644 frontend/webpage/achievement.html create mode 100644 frontend/webpage/import.html create mode 100644 frontend/webpage/static/res/import-hover.svg create mode 100644 frontend/webpage/static/res/import.svg delete mode 100644 frontend/webpage/static/scripts/about.js create mode 100644 frontend/webpage/static/scripts/achievement.js create mode 100644 frontend/webpage/static/scripts/import.js delete mode 100644 frontend/webpage/static/styles/about.css create mode 100644 frontend/webpage/static/styles/achievement.css create mode 100644 frontend/webpage/static/styles/import.css create mode 100644 sql/Indexes.sql create mode 100644 sql/Mondo.sql diff --git a/.gitignore b/.gitignore index e540f5b..5133e6d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -tmp/* \ No newline at end of file +tmp/* +sql/CreateBackendUser.sql diff --git a/backend/src/main/java/achievements/apis/SteamAPI.java b/backend/src/main/java/achievements/apis/SteamAPI.java index 1aec9bf..3bbe0d5 100644 --- a/backend/src/main/java/achievements/apis/SteamAPI.java +++ b/backend/src/main/java/achievements/apis/SteamAPI.java @@ -55,47 +55,56 @@ public class SteamAPI extends PlatformAPI { .queryParam("steamid", userId); var games = new ArrayList(); - var ownedResponse = rest.exchange(ownedGamesUrl, HttpMethod.GET, entity, GetOwnedGameBody.class).getBody(); - for (var game : ownedResponse.getResponse().getGames()) { - var newGame = new APIResponse.Game(); - newGame.setPlatformGameId(Integer.toString(game.getAppid())); - newGame.setName(game.getName()); - // Technically this is not the advertised logo url, but it's used be steamcommunity.com - // and steamdb.info and it gives better aspect ratios and it means I don't need the random - // logo_url field - newGame.setThumbnail("https://cdn.cloudflare.steamstatic.com/steam/apps/" + game.getAppid() + "/header.jpg"); - newGame.setPlayed(game.getPlaytime_forever() > 0); + try { + var ownedResponse = rest.exchange(ownedGamesUrl, HttpMethod.GET, entity, GetOwnedGameBody.class).getBody(); + for (var game : ownedResponse.getResponse().getGames()) { + var newGame = new APIResponse.Game(); + newGame.setPlatformGameId(Integer.toString(game.getAppid())); + newGame.setName(game.getName()); + // Technically this is not the advertised logo url, but it's used be steamcommunity.com + // and steamdb.info and it gives better aspect ratios and it means I don't need the random + // logo_url field + newGame.setThumbnail("https://cdn.cloudflare.steamstatic.com/steam/apps/" + game.getAppid() + "/header.jpg"); + newGame.setPlayed(game.getPlaytime_forever() > 0); - var achievements = new HashMap(); + var achievements = new HashMap(); - var gameSchemaUrl = gameSchemaBaseUrl.cloneBuilder() - .queryParam("appid", game.getAppid()) - .toUriString(); - var playerAchievementsUrl = playerAchievementsBaseUrl.cloneBuilder() - .queryParam("appid", game.getAppid()) - .toUriString(); + var gameSchemaUrl = gameSchemaBaseUrl.cloneBuilder() + .queryParam("appid", game.getAppid()) + .toUriString(); + var playerAchievementsUrl = playerAchievementsBaseUrl.cloneBuilder() + .queryParam("appid", game.getAppid()) + .toUriString(); - var schemaResponse = rest.exchange(gameSchemaUrl, HttpMethod.GET, entity, GetSchemaForGameBody.class).getBody().getGame().getAvailableGameStats(); - if (schemaResponse != null && schemaResponse.getAchievements() != null) { - for (var schema : schemaResponse.getAchievements()) { - var achievement = new APIResponse.Game.Achievement(); - achievement.setName(schema.getDisplayName()); - achievement.setDescription(schema.getDescription()); - achievement.setStages(1); - achievement.setThumbnail(schema.getIcon()); - achievements.put(schema.getName(), achievement); - } + try { + var schemaResponse = rest.exchange(gameSchemaUrl, HttpMethod.GET, entity, GetSchemaForGameBody.class).getBody().getGame().getAvailableGameStats(); + if (schemaResponse != null && schemaResponse.getAchievements() != null) { + for (var schema : schemaResponse.getAchievements()) { + var achievement = new APIResponse.Game.Achievement(); + achievement.setName(schema.getDisplayName()); + achievement.setDescription(schema.getDescription()); + achievement.setStages(1); + achievement.setThumbnail(schema.getIcon()); + achievements.put(schema.getName(), achievement); + } - var playerAchievementsResponse = rest.exchange(playerAchievementsUrl, HttpMethod.GET, entity, GetPlayerAchievementsBody.class).getBody().getPlayerstats().getAchievements(); - for (var achievement : playerAchievementsResponse) { - achievements.get(achievement.getApiname()).setProgress(achievement.getAchieved()); - } + var playerAchievementsResponse = rest.exchange(playerAchievementsUrl, HttpMethod.GET, entity, GetPlayerAchievementsBody.class).getBody().getPlayerstats().getAchievements(); + for (var achievement : playerAchievementsResponse) { + achievements.get(achievement.getApiname()).setProgress(achievement.getAchieved()); + } - newGame.setAchievements(new ArrayList<>(achievements.values())); - if (newGame.getAchievements().size() > 0) { - games.add(newGame); + newGame.setAchievements(new ArrayList<>(achievements.values())); + if (newGame.getAchievements().size() > 0) { + games.add(newGame); + } + } + } catch (Exception e) { + System.err.println("Forbidden APPID: " + game.getAppid()); + e.printStackTrace(); } } + } catch (Exception e) { + e.printStackTrace(); } var response = new APIResponse(); response.setGames(games); diff --git a/backend/src/main/java/achievements/controllers/AchievementController.java b/backend/src/main/java/achievements/controllers/AchievementController.java index 6e72521..c523d59 100644 --- a/backend/src/main/java/achievements/controllers/AchievementController.java +++ b/backend/src/main/java/achievements/controllers/AchievementController.java @@ -1,12 +1,13 @@ package achievements.controllers; +import achievements.data.APError; +import achievements.data.request.RateAchievement; import achievements.services.ImageService; import achievements.services.AchievementService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; @@ -19,9 +20,41 @@ public class AchievementController { @Autowired private ImageService imageService; + @GetMapping(value = "/{achievement}", produces = "application/json") + public ResponseEntity getAchievement(@PathVariable("achievement") int achievementId) { + var achievement = achievementService.getAchievement(achievementId); + if (achievement == null) { + return ResponseEntity.badRequest().body(new APError(1, "Failed to get achievement")); + } else { + return ResponseEntity.ok(achievement); + } + } + @GetMapping(value = "/{achievement}/image") public void getProfilePicture(@PathVariable("achievement") int achievement, HttpServletResponse response) { var icon = achievementService.getIcon(achievement); imageService.send(icon, "achievement", response); } + + @GetMapping(value = "/{achievement}/rating/{user}") + public ResponseEntity getRating(@PathVariable("achievement") int achievement, @PathVariable("user") int user) { + var rating = achievementService.getRating(achievement, user); + if (rating == null) { + return ResponseEntity.badRequest().body("{}"); + } else { + return ResponseEntity.ok(rating); + } + } + + @PostMapping(value = "/{achievement}/rating/{user}") + public ResponseEntity setRating(@PathVariable("achievement") int achievement, @PathVariable("user") int user, @RequestBody RateAchievement rating) { + var review = achievementService.setRating(achievement, user, rating); + if (review == null) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("{}"); + } else if (review.getSessionKey() == null) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(review); + } else { + return ResponseEntity.status(HttpStatus.CREATED).body("{}"); + } + } } diff --git a/backend/src/main/java/achievements/controllers/AuthController.java b/backend/src/main/java/achievements/controllers/AuthController.java index 6897ffa..988f6ef 100644 --- a/backend/src/main/java/achievements/controllers/AuthController.java +++ b/backend/src/main/java/achievements/controllers/AuthController.java @@ -65,11 +65,18 @@ public class AuthController { @PostMapping(value = "/refresh", consumes = "application/json", produces = "application/json") public ResponseEntity refresh(@RequestBody Session key) { - if (authService.refresh(key)) { - return ResponseEntity.ok("{}"); - } else { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("{}"); + if (key.getId() == -1) { + if (authService.openAuth()) { + if (authService.refresh(key)) { + return ResponseEntity.ok(key); + } else { + return ResponseEntity.ok(authService.session().generate(-1, 0, true)); + } + } + } else if (authService.refresh(key)) { + return ResponseEntity.ok(key); } + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("{}"); } @PostMapping(value = "/logout", consumes = "application/json") diff --git a/backend/src/main/java/achievements/controllers/ImportController.java b/backend/src/main/java/achievements/controllers/ImportController.java new file mode 100644 index 0000000..6e2b7d4 --- /dev/null +++ b/backend/src/main/java/achievements/controllers/ImportController.java @@ -0,0 +1,47 @@ +package achievements.controllers; + +import achievements.data.importing.ImportPlatform; +import achievements.data.importing.ImportUser; +import achievements.data.importing.ImportUserPlatform; +import achievements.services.ImportService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/import") +public class ImportController { + + @Autowired + private ImportService importService; + + @PostMapping(value = "/platform", consumes = "application/json", produces = "application/json") + public ResponseEntity createPlatform(@RequestBody ImportPlatform platform) { + var response = importService.importPlatform(platform); + if (response == 0) { + return ResponseEntity.ok("{}"); + } else { + return ResponseEntity.badRequest().body("{}"); + } + } + + @PostMapping(value = "/user", consumes = "application/json", produces = "application/json") + public ResponseEntity createUser(@RequestBody ImportUser user) { + var response = importService.importUser(user); + if (response == 0) { + return ResponseEntity.ok("{}"); + } else { + return ResponseEntity.badRequest().body("{}"); + } + } + + @PostMapping(value = "/user/platform", consumes = "application/json", produces = "application/json") + public ResponseEntity addUserToPlatform(@RequestBody ImportUserPlatform userPlatform) { + var response = importService.importUserPlatform(userPlatform); + if (response == 0) { + return ResponseEntity.ok("{}"); + } else { + return ResponseEntity.badRequest().body("{}"); + } + } +} diff --git a/backend/src/main/java/achievements/controllers/UserController.java b/backend/src/main/java/achievements/controllers/UserController.java index f3e30e6..84e060e 100644 --- a/backend/src/main/java/achievements/controllers/UserController.java +++ b/backend/src/main/java/achievements/controllers/UserController.java @@ -72,7 +72,7 @@ public class UserController { @PostMapping(value = "/{user}/platforms/add", consumes = "application/json", produces = "application/json") public ResponseEntity addPlatformForUser(@PathVariable("user") int userId, @RequestBody AddPlatform request) { - var result = userService.addPlatform(userId, request); + var result = userService.addPlatform(userId, request, true); if (result == 0) { return ResponseEntity.status(HttpStatus.CREATED).body("{}"); } else { @@ -89,4 +89,14 @@ public class UserController { return ResponseEntity.badRequest().body("{}"); } } + + @GetMapping(value = "/{user}/noteworthy", produces = "application/json") + public ResponseEntity getNoteworthy(@PathVariable("user") int userId) { + var result = userService.getNoteworthy(userId); + if (result != null) { + return ResponseEntity.ok(result); + } else { + return ResponseEntity.badRequest().body("{}"); + } + } } diff --git a/backend/src/main/java/achievements/data/Profile.java b/backend/src/main/java/achievements/data/Profile.java index 63e025f..2c02d38 100644 --- a/backend/src/main/java/achievements/data/Profile.java +++ b/backend/src/main/java/achievements/data/Profile.java @@ -40,6 +40,59 @@ public class Profile { } } + public static class Rating { + @JsonProperty("achievementId") + private int achievementId; + @JsonProperty("name") + private String name; + @JsonProperty("difficulty") + private Float difficulty; + @JsonProperty("quality") + private Float quality; + @JsonProperty("review") + private String review; + + public int getAchievementId() { + return achievementId; + } + + public void setAchievementId(int achievementId) { + this.achievementId = achievementId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Float getDifficulty() { + return difficulty; + } + + public void setDifficulty(Float difficulty) { + this.difficulty = difficulty; + } + + public Float getQuality() { + return quality; + } + + public void setQuality(Float quality) { + this.quality = quality; + } + + public String getReview() { + return review; + } + + public void setReview(String review) { + this.review = review; + } + } + @JsonProperty("username") private String username; @JsonProperty("completed") @@ -52,8 +105,8 @@ public class Profile { private List noteworthy; @JsonProperty("platforms") private List platforms; - /*@JsonProperty("ratings") - private List ratings;*/ + @JsonProperty("ratings") + private List ratings; public String getUsername() { return username; @@ -102,4 +155,12 @@ public class Profile { public void setPlatforms(List platforms) { this.platforms = platforms; } + + public List getRatings() { + return ratings; + } + + public void setRatings(List ratings) { + this.ratings = ratings; + } } diff --git a/backend/src/main/java/achievements/data/Session.java b/backend/src/main/java/achievements/data/Session.java index e88da56..a5c5e2f 100644 --- a/backend/src/main/java/achievements/data/Session.java +++ b/backend/src/main/java/achievements/data/Session.java @@ -16,14 +16,6 @@ public class Session { @JsonIgnore private boolean used; - public Session(String key, int id, int hue, boolean admin) { - this.key = key; - this.id = id; - this.hue = hue; - this.admin = admin; - this.used = false; - } - public String getKey() { return key; } diff --git a/backend/src/main/java/achievements/data/User.java b/backend/src/main/java/achievements/data/User.java index b0e086b..065de1d 100644 --- a/backend/src/main/java/achievements/data/User.java +++ b/backend/src/main/java/achievements/data/User.java @@ -11,12 +11,6 @@ public class User { @JsonProperty("password") public String password; - public User(String email, String username, String password) { - this.email = email; - this.username = username; - this.password = password; - } - public String getEmail() { return email; } diff --git a/backend/src/main/java/achievements/data/importing/ImportPlatform.java b/backend/src/main/java/achievements/data/importing/ImportPlatform.java new file mode 100644 index 0000000..fa24903 --- /dev/null +++ b/backend/src/main/java/achievements/data/importing/ImportPlatform.java @@ -0,0 +1,37 @@ +package achievements.data.importing; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ImportPlatform { + + @JsonProperty("userId") + private int userId; + @JsonProperty("sessionKey") + private String sessionKey; + @JsonProperty("name") + private String name; + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public String getSessionKey() { + return sessionKey; + } + + public void setSessionKey(String sessionKey) { + this.sessionKey = sessionKey; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/backend/src/main/java/achievements/data/importing/ImportUser.java b/backend/src/main/java/achievements/data/importing/ImportUser.java new file mode 100644 index 0000000..c46bedf --- /dev/null +++ b/backend/src/main/java/achievements/data/importing/ImportUser.java @@ -0,0 +1,38 @@ +package achievements.data.importing; + +import achievements.data.User; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ImportUser extends User { + + @JsonProperty("userId") + private int userId; + @JsonProperty("sessionKey") + private String sessionKey; + @JsonProperty("admin") + private boolean admin; + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public String getSessionKey() { + return sessionKey; + } + + public void setSessionKey(String sessionKey) { + this.sessionKey = sessionKey; + } + + public boolean isAdmin() { + return admin; + } + + public void setAdmin(boolean admin) { + this.admin = admin; + } +} diff --git a/backend/src/main/java/achievements/data/importing/ImportUserPlatform.java b/backend/src/main/java/achievements/data/importing/ImportUserPlatform.java new file mode 100644 index 0000000..b43519a --- /dev/null +++ b/backend/src/main/java/achievements/data/importing/ImportUserPlatform.java @@ -0,0 +1,28 @@ +package achievements.data.importing; + +import achievements.data.request.AddPlatform; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ImportUserPlatform extends AddPlatform { + + @JsonProperty("userId") + private int userId; + @JsonProperty("userEmail") + private String userEmail; + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public String getUserEmail() { + return userEmail; + } + + public void setUserEmail(String userEmail) { + this.userEmail = userEmail; + } +} diff --git a/backend/src/main/java/achievements/data/request/RateAchievement.java b/backend/src/main/java/achievements/data/request/RateAchievement.java new file mode 100644 index 0000000..d38cbf4 --- /dev/null +++ b/backend/src/main/java/achievements/data/request/RateAchievement.java @@ -0,0 +1,47 @@ +package achievements.data.request; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class RateAchievement { + + @JsonProperty("sessionKey") + private String sessionKey; + @JsonProperty("difficulty") + private Float difficulty; + @JsonProperty("quality") + private Float quality; + @JsonProperty("review") + private String review; + + public String getSessionKey() { + return sessionKey; + } + + public void setSessionKey(String sessionKey) { + this.sessionKey = sessionKey; + } + + public Float getDifficulty() { + return difficulty; + } + + public void setDifficulty(Float difficulty) { + this.difficulty = difficulty; + } + + public Float getQuality() { + return quality; + } + + public void setQuality(Float quality) { + this.quality = quality; + } + + public String getReview() { + return review; + } + + public void setReview(String review) { + this.review = review; + } +} diff --git a/backend/src/main/java/achievements/data/response/search/Achievement.java b/backend/src/main/java/achievements/data/response/search/Achievement.java index fd92c6d..fa8969e 100644 --- a/backend/src/main/java/achievements/data/response/search/Achievement.java +++ b/backend/src/main/java/achievements/data/response/search/Achievement.java @@ -2,8 +2,63 @@ package achievements.data.response.search; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + public class Achievement { + public static class Rating { + @JsonProperty("userId") + private int userId; + @JsonProperty("username") + private String username; + @JsonProperty("difficulty") + private Float difficulty; + @JsonProperty("quality") + private Float quality; + @JsonProperty("review") + private String review; + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public Float getDifficulty() { + return difficulty; + } + + public void setDifficulty(Float difficulty) { + this.difficulty = difficulty; + } + + public Float getQuality() { + return quality; + } + + public void setQuality(Float quality) { + this.quality = quality; + } + + public String getReview() { + return review; + } + + public void setReview(String review) { + this.review = review; + } + } + @JsonProperty("ID") private int ID; @JsonProperty("game") @@ -18,6 +73,8 @@ public class Achievement { private Float difficulty; @JsonProperty("quality") private Float quality; + @JsonProperty("ratings") + private List ratings; public int getID() { return ID; @@ -66,4 +123,12 @@ public class Achievement { public void setQuality(Float quality) { this.quality = quality; } + + public List getRatings() { + return ratings; + } + + public void setRatings(List ratings) { + this.ratings = ratings; + } } diff --git a/backend/src/main/java/achievements/misc/SessionManager.java b/backend/src/main/java/achievements/misc/SessionManager.java index 5237967..9f01c42 100644 --- a/backend/src/main/java/achievements/misc/SessionManager.java +++ b/backend/src/main/java/achievements/misc/SessionManager.java @@ -18,7 +18,11 @@ public class SessionManager { public Session generate(int user, int hue, boolean admin) { var key = HashManager.encode(HashManager.generateBytes(16)); - var session = new Session(key, user, hue, admin); + var session = new Session(); + session.setKey(key); + session.setId(user); + session.setHue(hue); + session.setAdmin(admin); sessions.put(key, session); return session; } diff --git a/backend/src/main/java/achievements/services/APIService.java b/backend/src/main/java/achievements/services/APIService.java index 1594ef3..14d1ed3 100644 --- a/backend/src/main/java/achievements/services/APIService.java +++ b/backend/src/main/java/achievements/services/APIService.java @@ -55,7 +55,7 @@ public class APIService { addGameToPlatform.setInt(1, gameId); addGameToPlatform.setInt(2, platformId); - addGameToPlatform.setString(3, platformUserId); + addGameToPlatform.setString(3, game.getPlatformGameId()); addGameToPlatform.execute(); var gameThumbnail = new File("storage/images/game/" + gameId + "." + getFileType(game.getThumbnail())); diff --git a/backend/src/main/java/achievements/services/AchievementService.java b/backend/src/main/java/achievements/services/AchievementService.java index 20f6d79..06cb554 100644 --- a/backend/src/main/java/achievements/services/AchievementService.java +++ b/backend/src/main/java/achievements/services/AchievementService.java @@ -1,11 +1,15 @@ package achievements.services; +import achievements.data.request.RateAchievement; +import achievements.data.response.search.Achievement; import achievements.misc.DbConnection; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import java.sql.Connection; +import java.sql.Types; +import java.util.ArrayList; @Service public class AchievementService { @@ -17,6 +21,9 @@ public class AchievementService { @Autowired private ImageService imageService; + @Autowired + private AuthenticationService authService; + @PostConstruct private void init() { db = dbs.getConnection(); @@ -31,4 +38,109 @@ public class AchievementService { } return null; } + + public Achievement getAchievement(int achievementId) { + try { + var stmt = db.prepareCall("{call GetAchievement(?)}"); + stmt.setInt(1, achievementId); + + var result = stmt.executeQuery(); + if (result.next()) { + var achievement = new Achievement(); + achievement.setID(result.getInt("ID")); + achievement.setName(result.getString("Name")); + achievement.setCompletion(result.getInt("Completion")); if (result.wasNull()) { achievement.setCompletion(null); } + achievement.setDescription(result.getString("Description")); + achievement.setDifficulty(result.getFloat("Difficulty")); if (result.wasNull()) { achievement.setDifficulty(null); } + achievement.setQuality(result.getFloat("Quality")); if (result.wasNull()) { achievement.setQuality(null); } + + stmt = db.prepareCall("{call GetRatingsForAchievement(?)}"); + stmt.setInt(1, achievementId); + + var ratings = new ArrayList(); + var results = stmt.executeQuery(); + while (results.next()) { + var rating = new Achievement.Rating(); + rating.setUserId(results.getInt("UserID")); + rating.setUsername(results.getString("Username")); + rating.setDifficulty(results.getFloat("Difficulty")); if (results.wasNull()) { rating.setDifficulty(null); } + rating.setQuality(results.getFloat("Quality")); if (results.wasNull()) { rating.setQuality(null); } + rating.setReview(results.getString("Description")); + ratings.add(rating); + } + achievement.setRatings(ratings); + return achievement; + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public RateAchievement getRating(int achievement, int user) { + try { + var stmt = db.prepareCall("{call HasProgress(?, ?, ?)}"); + stmt.setInt(1, user); + stmt.setInt(2, achievement); + stmt.registerOutParameter(3, Types.BOOLEAN); + + stmt.execute(); + if (stmt.getBoolean(3)) { + stmt = db.prepareCall("{call GetRating(?, ?)}"); + stmt.setInt(1, user); + stmt.setInt(2, achievement); + + var result = stmt.executeQuery(); + if (result.next()) { + var rating = new RateAchievement(); + rating.setDifficulty(result.getFloat("Difficulty")); if (result.wasNull()) { rating.setDifficulty(null); } + rating.setQuality(result.getFloat("Quality")); if (result.wasNull()) { rating.setQuality(null); } + rating.setReview(result.getString("Description")); + return rating; + } else { + return new RateAchievement(); + } + } else { + return null; + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public RateAchievement setRating(int achievementId, int userId, RateAchievement rateAchievement) { + if (authService.session().validate(userId, rateAchievement.getSessionKey())) { + try { + var stmt = db.prepareCall("{call SetRating(?, ?, ?, ?, ?)}"); + stmt.setInt(1, userId); + stmt.setInt(2, achievementId); + stmt.setFloat(3, rateAchievement.getDifficulty()); + stmt.setFloat(4, rateAchievement.getQuality()); + stmt.setString(5, rateAchievement.getReview()); + + stmt.execute(); + return rateAchievement; + } catch (Exception e) { + e.printStackTrace(); + } + } + try { + var stmt = db.prepareCall("{call GetRating(?, ?)}"); + stmt.setInt(1, userId); + stmt.setInt(2, achievementId); + + var result = stmt.executeQuery(); + if (result.next()) { + var rating = new RateAchievement(); + rating.setDifficulty(result.getFloat("Difficulty")); + rating.setQuality(result.getFloat("Quality")); + rating.setReview(result.getString("Review")); + return rating; + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } } diff --git a/backend/src/main/java/achievements/services/AuthenticationService.java b/backend/src/main/java/achievements/services/AuthenticationService.java index 4bfeeaa..e2387db 100644 --- a/backend/src/main/java/achievements/services/AuthenticationService.java +++ b/backend/src/main/java/achievements/services/AuthenticationService.java @@ -84,11 +84,14 @@ public class AuthenticationService { public LoginResponse login(User user) { var response = new LoginResponse(-1); try { - var statement = db.prepareCall("{call GetUserLogin(?)}"); - statement.setString(1, user.email); + var statement = db.prepareCall("{? = call GetUserLogin(?)}"); + statement.registerOutParameter(1, Types.INTEGER); + statement.setString(2, user.email); - var result = statement.executeQuery(); - if (result.next()) { + statement.execute(); + if (statement.getInt(1) == 0) { + var result = statement.executeQuery(); + result.next(); var salt = result.getString("Salt"); var hash = result.getString("Password"); if (Password.validate(salt, user.getPassword(), hash)) { @@ -115,6 +118,19 @@ public class AuthenticationService { public boolean refresh(Session key) { return session.refresh(key.getKey()); } + public boolean openAuth() { + try { + var stmt = db.prepareCall("{call HasUser(?)}"); + stmt.registerOutParameter(1, Types.BOOLEAN); + + stmt.execute(); + return !stmt.getBoolean(1); + } catch (SQLException e) { + e.printStackTrace(); + } + return false; + } + public void logout(Session key) { session.remove(key.getKey()); } diff --git a/backend/src/main/java/achievements/services/ImportService.java b/backend/src/main/java/achievements/services/ImportService.java new file mode 100644 index 0000000..f2bf8b7 --- /dev/null +++ b/backend/src/main/java/achievements/services/ImportService.java @@ -0,0 +1,81 @@ +package achievements.services; + +import achievements.data.importing.ImportPlatform; +import achievements.data.importing.ImportUser; +import achievements.data.importing.ImportUserPlatform; +import achievements.misc.DbConnection; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Types; + +@Service +public class ImportService { + + @Autowired + private DbConnection dbs; + private Connection db; + + @Autowired + private AuthenticationService authService; + @Autowired + private UserService userService; + + @PostConstruct + public void init() { + db = dbs.getConnection(); + } + + public int importPlatform(ImportPlatform platform) { + if (authService.session().validateAdmin(platform.getUserId(), platform.getSessionKey())) { + try { + var stmt = db.prepareCall("{call AddPlatform(?, ?)}"); + stmt.setString(1, platform.getName()); + stmt.registerOutParameter(2, Types.INTEGER); + + stmt.execute(); + return 0; + } catch (SQLException e) { + e.printStackTrace(); + } + } + return -1; + } + + public int importUser(ImportUser user) { + if (authService.session().validateAdmin(user.getUserId(), user.getSessionKey())) { + try { + var response = authService.createUser(user); + if (user.isAdmin()) { + var stmt = db.prepareCall("{call OpUser(?)}"); + stmt.setInt(1, response.session.getId()); + stmt.execute(); + } + + return 0; + } catch (SQLException e) { + e.printStackTrace(); + } + } + return -1; + } + + public int importUserPlatform(ImportUserPlatform userPlatform) { + if (authService.session().validateAdmin(userPlatform.getUserId(), userPlatform.getSessionKey())) { + try { + var stmt = db.prepareCall("{call GetIdFromEmail(?, ?)}"); + stmt.setString(1, userPlatform.getUserEmail()); + stmt.registerOutParameter(2, Types.INTEGER); + + stmt.execute(); + return userService.addPlatform(stmt.getInt(2), userPlatform, false); + } catch (Exception e) { + e.printStackTrace(); + } + } + return -1; + } +} diff --git a/backend/src/main/java/achievements/services/UserService.java b/backend/src/main/java/achievements/services/UserService.java index 3ceffd2..56aa863 100644 --- a/backend/src/main/java/achievements/services/UserService.java +++ b/backend/src/main/java/achievements/services/UserService.java @@ -4,6 +4,7 @@ import achievements.data.Profile; import achievements.data.request.AddPlatform; import achievements.data.request.RemovePlatform; import achievements.data.request.SetUsername; +import achievements.data.response.search.Achievement; import achievements.misc.DbConnection; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -17,6 +18,7 @@ import java.sql.Connection; import java.sql.SQLException; import java.sql.Types; import java.util.ArrayList; +import java.util.List; import static achievements.services.ImageService.MIME_TO_EXT; @@ -64,6 +66,8 @@ public class UserService { if (average != null) { profile.setAverage(Integer.parseInt(average)); } + } else { + return null; } } @@ -83,6 +87,24 @@ public class UserService { profile.setPlatforms(platforms); } + { + var stmt = db.prepareCall("{call GetRatingsByUser(?)}"); + stmt.setInt(1, userId); + + var results = stmt.executeQuery(); + var ratings = new ArrayList(); + while (results.next()) { + var rating = new Profile.Rating(); + rating.setAchievementId(results.getInt("AchievementID")); + rating.setName(results.getString("Name")); + rating.setDifficulty(results.getFloat("Difficulty")); if (results.wasNull()) { rating.setDifficulty(null); } + rating.setQuality(results.getFloat("Quality")); if (results.wasNull()) { rating.setQuality(null); } + rating.setReview(results.getString("Description")); + ratings.add(rating); + } + profile.setRatings(ratings); + } + return profile; } catch (SQLException e) { e.printStackTrace(); @@ -163,8 +185,8 @@ public class UserService { return "unknown"; } - public int addPlatform(int userId, AddPlatform request) { - if (auth.session().validate(userId, request.getSessionKey())) { + public int addPlatform(int userId, AddPlatform request, boolean validate) { + if (!validate || auth.session().validate(userId, request.getSessionKey())) { try { db.setAutoCommit(false); try { @@ -211,5 +233,24 @@ public class UserService { return -1; } + public List getNoteworthy(int userId) { + try { + var stmt = db.prepareCall("{call GetNoteworthyAchievementsForUser(?)}"); + stmt.setInt(1, userId); + var results = stmt.executeQuery(); + var achievements = new ArrayList(); + while (results.next()) { + var achievement = new Achievement(); + achievement.setID(results.getInt("ID")); + achievement.setName(results.getString("Name")); + achievement.setCompletion(results.getInt("Completion")); + achievements.add(achievement); + } + return achievements; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } } diff --git a/frontend/.gitignore b/frontend/.gitignore index 8967c66..a9e3966 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -1,3 +1,6 @@ # Node files node_modules/ package-lock.json + +# Import Data +import.json diff --git a/frontend/server.js b/frontend/server.js index 2cb035d..ac88714 100644 --- a/frontend/server.js +++ b/frontend/server.js @@ -22,27 +22,14 @@ passport.use(new SteamStrategy({ const app = express(); app.use("/", morgan("dev")); app.use("/static", express.static("webpage/static")); -app.get("/login", (req, res) => { - res.sendFile(path.join(__dirname + "/webpage/login.html")); -}); -app.get("/", (req, res) => { - res.sendFile(path.join(__dirname + "/webpage/search_achievements.html")); -}); -app.get("/achievements", (req, res) => { - res.sendFile(path.join(__dirname + "/webpage/search_achievements.html")); -}); -app.get("/users", (req, res) => { - res.sendFile(path.join(__dirname + "/webpage/search_users.html")); -}); -app.get("/games", (req, res) => { - res.sendFile(path.join(__dirname + "/webpage/search_games.html")); -}); -app.get("/achievement/:id", (req, res) => { - res.sendFile(path.join(__dirname + "/webpage/achievement.html")); -}); -app.get("/user/:id", (req, res) => { - res.sendFile(path.join(__dirname + "/webpage/user.html")); -}); +app.get("/login", (req, res) => res.sendFile(path.join(__dirname + "/webpage/login.html"))); +app.get("/", (req, res) => res.sendFile(path.join(__dirname + "/webpage/search_achievements.html"))); +app.get("/achievements", (req, res) => res.sendFile(path.join(__dirname + "/webpage/search_achievements.html"))); +app.get("/users", (req, res) => res.sendFile(path.join(__dirname + "/webpage/search_users.html"))); +app.get("/games", (req, res) => res.sendFile(path.join(__dirname + "/webpage/search_games.html"))); +app.get("/import", (req, res) => res.sendFile(path.join(__dirname + "/webpage/import.html"))); +app.get("/achievement/:id", (req, res) => res.sendFile(path.join(__dirname + "/webpage/achievement.html"))); +app.get("/user/:id", (req, res) => res.sendFile(path.join(__dirname + "/webpage/user.html"))); app.get("/auth/steam", passport.authenticate('steam'), (req, res) => {}); // --- API Forward --- // diff --git a/frontend/webpage/achievement.html b/frontend/webpage/achievement.html new file mode 100644 index 0000000..b33132a --- /dev/null +++ b/frontend/webpage/achievement.html @@ -0,0 +1,163 @@ + + + + + Achievements Project + + + + + + + +
+
+
+ +
+
+

Contemplating...

+ Loading Symbol +
+ +
+
+ + + + + \ No newline at end of file diff --git a/frontend/webpage/import.html b/frontend/webpage/import.html new file mode 100644 index 0000000..74e9cfb --- /dev/null +++ b/frontend/webpage/import.html @@ -0,0 +1,39 @@ + + + + + Achievements Project | Import + + + + + + +
+
+
+ +
+
+
+
+
+ Import Icon + Import Icon Hover +
+
+
+
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/frontend/webpage/search_achievements.html b/frontend/webpage/search_achievements.html index 1d60b81..cd93d68 100644 --- a/frontend/webpage/search_achievements.html +++ b/frontend/webpage/search_achievements.html @@ -119,7 +119,7 @@

Quality