diff --git a/.travis.yml b/.travis.yml index f5c99a7..f464142 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1 +1,28 @@ -language: java \ No newline at end of file +language: java +jdk: oraclejdk9 +spring: + datasource: + url: ${JDBC_DATABASE_URL} + username: ${JDBC_DATABASE_USERNAME} + password: ${JDBC_DATABASE_PASSWORD} + +addons: + postgresql: "9.6" + +services: + - postgresql + +before_install: + - psql -c "create user vitalya with password '1324qwer';" -U postgres + - psql -c "create database brodb;" -U postgres + - psql -c "grant all on database brodb to vitalya;" -U postgres + +#deploy: +# provider: heroku +# api_key: +# secure: $HEROKU_API_KEY +# app: BroForce-02-2018 +# on: +# repo: BatrSens/BroForce-02-2018 +# branch: master +# skip_cleanup: true \ No newline at end of file diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..8549ebd --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: java -jar ./target/BroForce-02-2018-1.0-SNAPSHOT.jar diff --git a/README.md b/README.md index 54fd6db..231278e 100644 --- a/README.md +++ b/README.md @@ -4,16 +4,4 @@ - Масягин Михаил АПО-22 - Мельников Владислав АПО-22 - Полещук Виталий АПО-22 -- Саркисян Артур АПО-21 - - -| | url | Тело запроса | -| ------ | ------ | ------ | -| Зарегистрироваться | /api/signup | ```{"login":"vitalya", "password":"1324qwer", "email":"vitalya@mail.ru"}``` -| Авторизоваться | /api/signin | ```{"login":"vitalya", "password":"1324qwer"}``` -| Запросить пользователя текущей сессии | /api/loginfo | - -| Изменить пароль | /api/newpassword | ```{"password":"1324qwer", "change":"1234"}``` -| Изменить логин | /api/newlogin | ```{"password":"1324qwer", "change":"vitalik"}``` -| Изменить email | /api/newemail | ```{"password":"1324qwer", "change":"vitalya@yandex.ru"}``` -| Изменить аватар | /api/newavatar | ```{"password":"1324qwer", "change":"_NEW_AVATAR_"}``` -| Разлогиниться | /api/logout | - +- Саркисян Артур АПО-21 \ No newline at end of file diff --git a/inspection_profile.xml b/inspection_profile.xml new file mode 100644 index 0000000..e68535b --- /dev/null +++ b/inspection_profile.xml @@ -0,0 +1,730 @@ + + + \ No newline at end of file diff --git a/park_checks.xml b/park_checks.xml index ce90222..47cfe4b 100644 --- a/park_checks.xml +++ b/park_checks.xml @@ -1,24 +1,17 @@ + "-//Puppy Crawl//DTD Check Configuration 1.3//EN" + "http://www.puppycrawl.com/dtds/configuration_1_3.dtd"> @@ -29,12 +22,11 @@ - - - + + + - @@ -58,7 +50,9 @@ - + + + @@ -70,9 +64,9 @@ - + value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/> + @@ -95,49 +89,49 @@ + value="Package name ''{0}'' must match pattern ''{1}''."/> + value="Type name ''{0}'' must match pattern ''{1}''."/> + value="Member name ''{0}'' must match pattern ''{1}''."/> + value="Parameter name ''{0}'' must match pattern ''{1}''."/> + value="Local variable name ''{0}'' must match pattern ''{1}''."/> + value="Class type name ''{0}'' must match pattern ''{1}''."/> + value="Method type name ''{0}'' must match pattern ''{1}''."/> - - - + value="GenericWhitespace ''{0}'' is followed by whitespace."/> + + + @@ -167,7 +161,7 @@ + value="Method name ''{0}'' must match pattern ''{1}''."/> @@ -227,6 +221,7 @@ + @@ -235,6 +230,7 @@ + @@ -243,7 +239,7 @@ - + @@ -252,4 +248,4 @@ - + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 5318e48..15da787 100644 --- a/pom.xml +++ b/pom.xml @@ -5,20 +5,16 @@ 4.0.0 BroForce - BroForce + BroForce-02-2018 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 2.0.0.RELEASE - - - UTF-8 - UTF-8 - 1.8 + 1.9 @@ -35,13 +31,13 @@ org.springframework.boot - spring-boot-starter-test - test + spring-boot-starter-jetty - org.springframework.boot - spring-boot-starter-jetty + org.jetbrains + annotations + 13.0 @@ -60,9 +56,9 @@ - org.jetbrains - annotations - 13.0 + org.springframework.boot + spring-boot-starter-test + test @@ -82,13 +78,6 @@ org.apache.maven.plugins maven-checkstyle-plugin 2.17 - - - com.puppycrawl.tools - checkstyle - 8.8 - - park_checks.xml true @@ -106,28 +95,14 @@ org.springframework.boot spring-boot-maven-plugin + + + org.flywaydb + flyway-maven-plugin + 4.1.2 + + - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - diff --git a/src/main/java/application/Application.java b/src/main/java/application/Application.java index 55dbb35..29143ae 100644 --- a/src/main/java/application/Application.java +++ b/src/main/java/application/Application.java @@ -1,7 +1,8 @@ package application; -import application.database.DAOi; -import application.database.DbDAO; +import application.db.UserDao; +import application.db.UserDaoImpl; + import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; @@ -10,17 +11,19 @@ @SpringBootApplication public class Application { + public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean - public DAOi database() { - return new DbDAO(); + public UserDao database() { + return new UserDaoImpl(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } + } diff --git a/src/main/java/application/controllers/SessionController.java b/src/main/java/application/controllers/SessionController.java index 8f93fb8..8907942 100644 --- a/src/main/java/application/controllers/SessionController.java +++ b/src/main/java/application/controllers/SessionController.java @@ -1,259 +1,174 @@ package application.controllers; -import application.controllers.requests.ChangeRequest; -import application.controllers.requests.SigninRequest; -import application.controllers.requests.SignupRequest; -import application.controllers.responses.ErrorResponse; -import application.controllers.responses.MessageResponse; +import application.models.User; +import application.services.AccountService; +import application.utils.Validator; +import application.utils.requests.SettingsRequest; +import application.utils.requests.SigninRequest; +import application.utils.requests.SignupRequest; +import application.utils.responses.MessageResponse; +import application.utils.responses.UserResponseWP; +import application.utils.Messages; +import application.utils.responses.ValidatorResponse; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import application.models.UserService; -import application.models.User; +import org.springframework.web.bind.annotation.PostMapping; import javax.servlet.http.HttpSession; - -import static application.controllers.messages.Message.*; - +import java.util.ArrayList; @RestController +@CrossOrigin(origins = "*", allowCredentials = "true") public class SessionController { - private final UserService service; + private AccountService service; public static final String JSON = MediaType.APPLICATION_JSON_UTF8_VALUE; + public static final String USER_ID = "userId"; + public static final Integer DEFAULT_TOP_SIZE = 10; - public SessionController(UserService service) { + public SessionController(AccountService service) { this.service = service; } - @GetMapping("/api/loginfo") - public ResponseEntity getLoggedUser(HttpSession session) { - final Long id = (Long) session.getAttribute("userId"); - if (id == null) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new ErrorResponse(NOT_AUTHORIZED)); - } - - final User user = service.getUser(id); - if (user == null) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new ErrorResponse(WRONG_ID)); - } - - return ResponseEntity.ok(user); - } - - @PostMapping(path = "/api/signup", consumes = JSON, produces = JSON) - public ResponseEntity signUp(@RequestBody(required = false) SignupRequest profile, HttpSession session) { - if (session.getAttribute("userId") != null) { - return ResponseEntity.badRequest().body(new ErrorResponse(ALREADY_AUTHORIZED)); + @PostMapping(path = "/signup", consumes = JSON, produces = JSON) + public ResponseEntity signup(@RequestBody SignupRequest body, HttpSession httpSession) { + final ArrayList error = Validator.checkSignup(body); + if (!error.isEmpty()) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ValidatorResponse(error)); } - - if (profile == null) { - return ResponseEntity.badRequest().body(new ErrorResponse(NO_LOGIN_OR_PASSWORD)); + if (httpSession.getAttribute(USER_ID) != null) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new MessageResponse(Messages.AUTHORIZED)); } - - if (profile.getLogin().isEmpty() || profile.getPassword().isEmpty()) { - return ResponseEntity.badRequest().body(new ErrorResponse(EMPTY_LOGIN_OR_PASSWORD)); - } - - if (!service.checkLogin(profile.getLogin())) { - return ResponseEntity.status(HttpStatus.CONFLICT).body(new ErrorResponse(LOGIN_IS_ALREADY_TAKEN)); - } - - if (!service.checkEmail(profile.getEmail())) { - return ResponseEntity.status(HttpStatus.CONFLICT).body(new ErrorResponse(EMAIL_IS_ALREADY_TAKEN)); + if (!service.checkSignup(body.getLogin(), body.getEmail())) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(new MessageResponse(Messages.EXISTS)); } - - final long id = service.createUser(profile.getLogin(), profile.getPassword(), profile.getEmail()); - session.setAttribute("userId", id); - - return ResponseEntity.ok().body(new MessageResponse(SIGNED_UP)); + final Long id = service.addUser(body); + httpSession.setAttribute(USER_ID, id); + return ResponseEntity.ok(new UserResponseWP(id, body)); } - @PostMapping(path = "/api/signin", consumes = JSON, produces = JSON) - public ResponseEntity signIn(@RequestBody(required = false) SigninRequest profile, HttpSession session) { - if (session.getAttribute("userId") != null) { - return ResponseEntity.badRequest().body(new ErrorResponse(ALREADY_AUTHORIZED)); + @PostMapping(path = "/signin", consumes = JSON, produces = JSON) + public ResponseEntity signin(@RequestBody SigninRequest body, HttpSession httpSession) { + if (httpSession.getAttribute(USER_ID) != null) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new MessageResponse(Messages.AUTHORIZED)); } - - if (profile == null) { - return ResponseEntity.badRequest().body(new ErrorResponse(NO_LOGIN_OR_PASSWORD)); - } - - if (profile.getLogin().isEmpty() || profile.getPassword().isEmpty()) { - return ResponseEntity.badRequest().body(new ErrorResponse(EMPTY_LOGIN_OR_PASSWORD)); - } - - final User user = service.getUser(profile.getLogin()); + final User user = service.getUser(body.getLogin()); if (user == null) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ErrorResponse(WRONG_LOGIN)); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new MessageResponse(Messages.WRONG_LOGIN_PASSWORD)); } - final long userId = user.getId(); - if (!service.checkSignin(userId, profile.getPassword())) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ErrorResponse(WRONG_PASSWORD)); + if (!service.checkSignin(userId, body.getPassword())) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new MessageResponse(Messages.WRONG_LOGIN_PASSWORD)); } - - session.setAttribute("userId", userId); - return ResponseEntity.ok(new MessageResponse(AUTHORIZED)); + httpSession.setAttribute(USER_ID, userId); + return ResponseEntity.ok(new UserResponseWP(user)); } - @PostMapping(path = "/api/newpassword", consumes = JSON, produces = JSON) - public ResponseEntity setPassword(@RequestBody(required = false) ChangeRequest body, HttpSession session) { - final Long id = (Long) session.getAttribute("userId"); - if (id == null) { - return ResponseEntity.badRequest().body(new ErrorResponse(NOT_AUTHORIZED)); + @PostMapping(path = "/newpassword", consumes = JSON, produces = JSON) + public ResponseEntity setPassword(@RequestBody SettingsRequest body, HttpSession httpSession) { + if (httpSession.getAttribute(USER_ID) == null) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new MessageResponse(Messages.NOT_AUTHORIZE)); } - - if (body == null) { - return ResponseEntity.badRequest().body(new ErrorResponse(EMPTY_DATA)); - } - - if (body.getModifiedString().isEmpty() || body.getPassword().isEmpty()) { - return ResponseEntity.badRequest().body(new ErrorResponse(EMPTY_DATA)); - } - + final Long id = (Long) httpSession.getAttribute(USER_ID); final User user = service.getUser(id); if (user == null) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new ErrorResponse(WRONG_ID)); + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new MessageResponse(Messages.BAD_COOKIE)); } - if (!service.checkSignin(id, body.getPassword())) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ErrorResponse(WRONG_PASSWORD)); - } - - service.changePassword(user, body.getModifiedString()); - return ResponseEntity.ok(new MessageResponse(USER_PROFILE_UPDATED)); - } - - @PostMapping(path = "/api/newlogin", consumes = JSON, produces = JSON) - public ResponseEntity setLogin(@RequestBody(required = false) ChangeRequest body, HttpSession session) { - final Long id = (Long) session.getAttribute("userId"); - if (id == null) { - return ResponseEntity.badRequest().body(new ErrorResponse(NOT_AUTHORIZED)); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new MessageResponse(Messages.WRONG_PASSWORD)); } - - if (body == null) { - return ResponseEntity.badRequest().body(new ErrorResponse(EMPTY_DATA)); + final ArrayList error = Validator.checkPassword(body.getPassword()); + if (!error.isEmpty()) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ValidatorResponse(error)); } + service.changePassword(user, body.getFieldToChange()); + return ResponseEntity.ok(new UserResponseWP(user)); + } - if (body.getModifiedString().isEmpty() || body.getPassword().isEmpty()) { - return ResponseEntity.badRequest().body(new ErrorResponse(EMPTY_DATA)); + @PostMapping(path = "/newlogin", consumes = JSON, produces = JSON) + public ResponseEntity setLogin(@RequestBody SettingsRequest body, HttpSession httpSession) { + if (httpSession.getAttribute(USER_ID) == null) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new MessageResponse(Messages.NOT_AUTHORIZE)); } - + final Long id = (Long) httpSession.getAttribute(USER_ID); final User user = service.getUser(id); if (user == null) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new ErrorResponse(WRONG_ID)); + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new MessageResponse(Messages.BAD_COOKIE)); } - if (!service.checkSignin(id, body.getPassword())) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ErrorResponse(WRONG_PASSWORD)); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new MessageResponse(Messages.WRONG_PASSWORD)); } - - if (!service.checkLogin(body.getModifiedString())) { - return ResponseEntity.status(HttpStatus.CONFLICT).body(new ErrorResponse(LOGIN_IS_ALREADY_TAKEN)); + if (!service.checkLogin(body.getFieldToChange())) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(new MessageResponse(Messages.LOGIN_EXISTS)); } - - service.changeLogin(user, body.getModifiedString()); - return ResponseEntity.ok(new MessageResponse(USER_PROFILE_UPDATED)); + service.changeLogin(user, body.getFieldToChange()); + return ResponseEntity.ok(new UserResponseWP(user)); } - @PostMapping(path = "/api/newemail", consumes = JSON, produces = JSON) - public ResponseEntity setEmail(@RequestBody(required = false) ChangeRequest body, HttpSession session) { - final Long id = (Long) session.getAttribute("userId"); - if (id == null) { - return ResponseEntity.badRequest().body(new ErrorResponse(NOT_AUTHORIZED)); - } - - if (body == null) { - return ResponseEntity.badRequest().body(new ErrorResponse(EMPTY_DATA)); + @PostMapping(path = "/newemail", consumes = JSON, produces = JSON) + public ResponseEntity setEmail(@RequestBody SettingsRequest body, HttpSession httpSession) { + if (httpSession.getAttribute(USER_ID) == null) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new MessageResponse(Messages.NOT_AUTHORIZE)); } - - if (body.getModifiedString().isEmpty() || body.getPassword().isEmpty()) { - return ResponseEntity.badRequest().body(new ErrorResponse(EMPTY_DATA)); - } - + final Long id = (Long) httpSession.getAttribute(USER_ID); final User user = service.getUser(id); if (user == null) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new ErrorResponse(WRONG_ID)); + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new MessageResponse(Messages.BAD_COOKIE)); } - if (!service.checkSignin(id, body.getPassword())) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ErrorResponse(WRONG_PASSWORD)); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new MessageResponse(Messages.WRONG_PASSWORD)); } - - if (!service.checkEmail(body.getModifiedString())) { - return ResponseEntity.status(HttpStatus.CONFLICT).body(new ErrorResponse(EMAIL_IS_ALREADY_TAKEN)); + if (!service.checkEmail(body.getFieldToChange())) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(new MessageResponse(Messages.EMAIL_EXISTS)); } - - service.changeEmail(user, body.getModifiedString()); - return ResponseEntity.ok(new MessageResponse(USER_PROFILE_UPDATED)); + service.changeEmail(user, body.getFieldToChange()); + return ResponseEntity.ok(new UserResponseWP(user)); } - @PostMapping(path = "/api/newavatar", consumes = JSON, produces = JSON) - public ResponseEntity setAvatar(@RequestBody(required = false) ChangeRequest body, HttpSession session) { - final Long id = (Long) session.getAttribute("userId"); - if (id == null) { - return ResponseEntity.badRequest().body(new ErrorResponse(NOT_AUTHORIZED)); - } - - if (body == null) { - return ResponseEntity.badRequest().body(new ErrorResponse(EMPTY_DATA)); + @PostMapping(path = "/logout", produces = JSON) + public ResponseEntity logout(HttpSession httpSession) { + if (httpSession.getAttribute(USER_ID) == null) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new MessageResponse(Messages.NOT_AUTHORIZE)); } + httpSession.removeAttribute(USER_ID); + return ResponseEntity.status(HttpStatus.OK).body(new MessageResponse(Messages.SUCCESS)); + } - if (body.getModifiedString().isEmpty() || body.getPassword().isEmpty()) { - return ResponseEntity.badRequest().body(new ErrorResponse(EMPTY_DATA)); + @GetMapping(path = "/user", produces = JSON) + public ResponseEntity user(HttpSession httpSession) { + if (httpSession.getAttribute(USER_ID) == null) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new MessageResponse(Messages.NOT_AUTHORIZE)); } - + final Long id = (Long) httpSession.getAttribute(USER_ID); final User user = service.getUser(id); if (user == null) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new ErrorResponse(WRONG_ID)); + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new MessageResponse(Messages.BAD_COOKIE)); } - - if (!service.checkSignin(id, body.getPassword())) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ErrorResponse(WRONG_PASSWORD)); - } - - service.changeAvatar(user, body.getModifiedString()); - return ResponseEntity.ok(new MessageResponse(USER_PROFILE_UPDATED)); + return ResponseEntity.ok(new UserResponseWP(user)); } - @DeleteMapping(path = "/api/logout", produces = JSON) - public ResponseEntity logout(HttpSession session) { - if (session.getAttribute("userId") == null) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new ErrorResponse(NOT_AUTHORIZED)); + @GetMapping(path = "stop", produces = JSON) + public ResponseEntity getSTopp(@RequestParam(value = "limit", required = false) Integer limit, + @RequestParam(value = "since", required = false) Integer since) { + if (limit == null) { + limit = DEFAULT_TOP_SIZE; } - - session.removeAttribute("userId"); - return ResponseEntity.status(HttpStatus.OK).body(new MessageResponse(LOGGED_OUT)); - } - - @DeleteMapping("/api/clear") - public ResponseEntity clear(HttpSession session) { - - final Long id = (Long) session.getAttribute("userId"); - if (id != null) { - - final User user = service.getUser(id); - if (user != null && user.getLogin().equals("root")) { - service.clear(); - session.removeAttribute("userId"); - return ResponseEntity.status(HttpStatus.OK).body("CLEARED"); - } - + if (since == null) { + since = 0; } - - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ErrorResponse(WRONG_LOGIN)); + return ResponseEntity.status(HttpStatus.OK).body(service.getSTop(limit, since)); } - @GetMapping(path = "/api/top", produces = JSON) - public ResponseEntity getSTopp(@RequestParam(value = "limit", required = false) Integer limit, + @GetMapping(path = "mtop", produces = JSON) + public ResponseEntity getMTopp(@RequestParam(value = "limit", required = false) Integer limit, @RequestParam(value = "since", required = false) Integer since) { if (limit == null) { - limit = 10; + limit = DEFAULT_TOP_SIZE; } if (since == null) { since = 0; } - return ResponseEntity.status(HttpStatus.OK).body(service.getTop(limit, since)); + return ResponseEntity.status(HttpStatus.OK).body(service.getMTop(limit, since)); } -} \ No newline at end of file +} diff --git a/src/main/java/application/controllers/messages/Message.java b/src/main/java/application/controllers/messages/Message.java deleted file mode 100644 index d940543..0000000 --- a/src/main/java/application/controllers/messages/Message.java +++ /dev/null @@ -1,30 +0,0 @@ -package application.controllers.messages; - - -public enum Message { - SIGNED_UP("User signed up"), - NO_LOGIN_OR_PASSWORD("No login or password"), - EMPTY_LOGIN_OR_PASSWORD("Empty login or password"), - WRONG_LOGIN("Wrong login"), - WRONG_PASSWORD("Wrong password"), - WRONG_ID("Incorrect session data"), - EMPTY_DATA("Empty data"), - LOGIN_IS_ALREADY_TAKEN("Login is already taken"), - EMAIL_IS_ALREADY_TAKEN("Email is already taken"), - AUTHORIZED("User authorized"), - LOGGED_OUT("User logged out"), - NOT_AUTHORIZED("User not authorized"), - ALREADY_AUTHORIZED("User is already authorized"), - USER_PROFILE_UPDATED("User profile data updated"); - - private final String message; - - Message(String message) { - this.message = message; - } - - @SuppressWarnings("unused") - public String getMessage() { - return message; - } -} diff --git a/src/main/java/application/controllers/responses/ErrorResponse.java b/src/main/java/application/controllers/responses/ErrorResponse.java deleted file mode 100644 index 9e249ba..0000000 --- a/src/main/java/application/controllers/responses/ErrorResponse.java +++ /dev/null @@ -1,19 +0,0 @@ -package application.controllers.responses; - -import application.controllers.messages.Message; -import com.fasterxml.jackson.annotation.JsonProperty; - -import javax.validation.constraints.NotNull; - -public class ErrorResponse { - private final String error; - - public ErrorResponse(@NotNull Message message) { - this.error = message.getMessage(); - } - - @JsonProperty("error") - public String getMessage() { - return error; - } -} diff --git a/src/main/java/application/database/DAOi.java b/src/main/java/application/db/UserDao.java similarity index 64% rename from src/main/java/application/database/DAOi.java rename to src/main/java/application/db/UserDao.java index 5d6d30e..1f7874b 100644 --- a/src/main/java/application/database/DAOi.java +++ b/src/main/java/application/db/UserDao.java @@ -1,4 +1,4 @@ -package application.database; +package application.db; import application.models.User; @@ -8,7 +8,8 @@ import java.util.List; -public interface DAOi { +public interface UserDao { + int DEFAULT_SCORE = 1000; @NotNull Long addUser(@NotNull String login, @NotNull String password, @NotNull String email); @@ -29,10 +30,14 @@ public interface DAOi { boolean checkSignup(@NotNull String login, @NotNull String email); @NotNull - Integer updateScore(long userId, boolean result); + Integer updateSScore(long userId, boolean result); - List getTop(@NotNull Integer limit, @NotNull Integer since); + @NotNull + Integer updateMScore(long userId, boolean result); + + List getSTop(@NotNull Integer limit, @NotNull Integer since); + + List getMTop(@NotNull Integer limit, @NotNull Integer since); void clear(); } - diff --git a/src/main/java/application/database/DbDAO.java b/src/main/java/application/db/UserDaoImpl.java similarity index 76% rename from src/main/java/application/database/DbDAO.java rename to src/main/java/application/db/UserDaoImpl.java index d76bce5..771757b 100644 --- a/src/main/java/application/database/DbDAO.java +++ b/src/main/java/application/db/UserDaoImpl.java @@ -1,4 +1,4 @@ -package application.database; +package application.db; import application.models.User; import org.jetbrains.annotations.NotNull; @@ -15,11 +15,11 @@ import java.util.List; @Transactional -public class DbDAO implements DAOi { +public class UserDaoImpl implements UserDao { @Autowired private JdbcTemplate template; @NotNull - private static final Logger LOGGER = LoggerFactory.getLogger(DbDAO.class); + private static final Logger LOGGER = LoggerFactory.getLogger(UserDaoImpl.class); private static final Integer SCORE_CHANGE = 25; @Override @@ -47,7 +47,9 @@ public void changeUserData(@NotNull User user) { new User(res.getLong("id"), res.getString("login"), res.getString("password"), - res.getString("email") + res.getString("email"), + res.getInt("sscore"), + res.getInt("mscore") ); @Override @@ -85,14 +87,27 @@ public boolean checkSignup(@NotNull String login, @NotNull String email) { @Override @NotNull - public Integer updateScore(long userId, boolean result) { - String query = "UPDATE users SET score = score "; + public Integer updateSScore(long userId, boolean result) { + String query = "UPDATE users SET sscore = sscore "; if (result) { query += "+ " + SCORE_CHANGE + ' '; } else { query += "- " + SCORE_CHANGE + ' '; } - query += "WHERE id = ? RETURNING score"; + query += "WHERE id = ? RETURNING sscore"; + return template.queryForObject(query, Integer.class, userId); + } + + @Override + @NotNull + public Integer updateMScore(long userId, boolean result) { + String query = "UPDATE users SET mscore = mscore "; + if (result) { + query += "+ " + SCORE_CHANGE + ' '; + } else { + query += "- " + SCORE_CHANGE + ' '; + } + query += "WHERE id = ? RETURNING mscore"; return template.queryForObject(query, Integer.class, userId); } @@ -120,8 +135,15 @@ public Long getIdByEmail(@NotNull String email) { @Override @NotNull - public List getTop(@NotNull Integer limit, @NotNull Integer since) { - final String query = "SELECT * FROM users ORDER BY score DESC LIMIT ? OFFSET ?"; + public List getSTop(@NotNull Integer limit, @NotNull Integer since) { + final String query = "SELECT * FROM users ORDER BY sscore DESC LIMIT ? OFFSET ?"; + return template.query(query, USER_MAPPER, limit, since); + } + + @Override + @NotNull + public List getMTop(@NotNull Integer limit, @NotNull Integer since) { + final String query = "SELECT * FROM users ORDER BY mscore DESC LIMIT ? OFFSET ?"; return template.query(query, USER_MAPPER, limit, since); } diff --git a/src/main/java/application/mechanics/Game.java b/src/main/java/application/mechanics/Game.java new file mode 100644 index 0000000..d277075 --- /dev/null +++ b/src/main/java/application/mechanics/Game.java @@ -0,0 +1,73 @@ +package application.mechanics; + +import application.mechanics.entity.Direction; +import application.mechanics.entity.Enemy; +import application.mechanics.entity.Player; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; + +public class Game { + + private static final int NUMBER_OF_BOTS = 50; + + private Player player1; + private Player player2; + private ArrayList bots; + private int winner; + + public Game() { + player1 = new Player(1 / 3, 1 / 3); + player2 = new Player(2 / 3, 2 / 3); + bots = new ArrayList<>(); + for (int i = 0; i < NUMBER_OF_BOTS; i++) { + bots.add(new Enemy()); + } + winner = 0; + } + + public void move() { + player1.move(); + player2.move(); + for (Enemy b : bots) { + b.move(); + if (!player1.eat(b)) { + player2.eat(b); + } + } + if (player1.isEaten(player2)) { + winner = 1; + } else if (player2.isEaten(player1)) { + winner = 2; + } + } + + public void buttonClick(Direction dir, int player) { + switch (player) { + case 1: + player1.buttonClick(dir); + break; + case 2: + player2.buttonClick(dir); + break; + default: + break; + } + } + + @JsonProperty("Player1") + public Player getPlayer1() { + return player1; + } + + @JsonProperty("Player2") + public Player getPlayer2() { + return player2; + } + + @JsonProperty("bots") + public ArrayList getBots() { + return bots; + } + +} diff --git a/src/main/java/application/mechanics/entity/Direction.java b/src/main/java/application/mechanics/entity/Direction.java new file mode 100644 index 0000000..8b2fced --- /dev/null +++ b/src/main/java/application/mechanics/entity/Direction.java @@ -0,0 +1,8 @@ +package application.mechanics.entity; + +public enum Direction { + UPPP, + DOWN, + LEFT, + RIGHT +} diff --git a/src/main/java/application/mechanics/entity/Enemy.java b/src/main/java/application/mechanics/entity/Enemy.java new file mode 100644 index 0000000..713151b --- /dev/null +++ b/src/main/java/application/mechanics/entity/Enemy.java @@ -0,0 +1,68 @@ +package application.mechanics.entity; + +public class Enemy extends Entity { + + private static final double MAX_SIZE = 0.01; + private static final double MIN_SIZE = 0.005; + + private static final double D_DIST = 1.35; + + + public Enemy() { + xx = Math.random(); + yy = Math.random(); + size = Math.random() * (MAX_SIZE - MIN_SIZE) + MIN_SIZE; + direction = Math.random() * Math.PI * 2; + speed = size / 10; + } + + + public void move(Player p1, Player p2) { + + if (dist(this, p1) / p1.size < D_DIST + && dist(this, p2) / p2.size < D_DIST) { + + double p1Angle = Math.acos((xx - p1.xx) / dist(this, p1)); + if (Math.asin((xx - p1.xx) / dist(this, p1)) < 0) { + p1Angle += 2 * Math.PI; + } + double p2Angle = Math.acos((xx - p2.xx) / dist(this, p2)); + if (Math.asin((xx - p2.xx) / dist(this, p2)) < 0) { + p2Angle += 2 * Math.PI; + } + direction = (p1Angle + p2Angle) / 2; + + } else { + + if (dist(this, p1) / p1.size < D_DIST) { + double p1Angle = Math.acos((xx - p1.xx) / dist(this, p1)); + if (Math.asin((xx - p1.xx) / dist(this, p1)) < 0) { + p1Angle += 2 * Math.PI; + } + direction = p1Angle; + } + + if (dist(this, p2) / p2.size < D_DIST) { + double p2Angle = Math.acos((xx - p2.xx) / dist(this, p2)); + if (Math.asin((xx - p2.xx) / dist(this, p2)) < 0) { + p2Angle += 2 * Math.PI; + } + direction = p2Angle; + } + + } + + super.move(); + + } + + + public void reincarnation() { + xx = Math.random(); + yy = Math.random(); + size = Math.random() * (MAX_SIZE - MIN_SIZE) + MIN_SIZE; + direction = Math.random() * Math.PI * 2; + speed = size / 10; + } + +} diff --git a/src/main/java/application/mechanics/entity/Entity.java b/src/main/java/application/mechanics/entity/Entity.java new file mode 100644 index 0000000..493d698 --- /dev/null +++ b/src/main/java/application/mechanics/entity/Entity.java @@ -0,0 +1,60 @@ +package application.mechanics.entity; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Entity { + + protected double xx; + protected double yy; + protected double size; + protected double direction; + protected double speed; + + + public void move() { + xx += Math.cos(direction) * speed; + yy += Math.sin(direction) * speed; + if (xx > 1) { + xx = 1; + direction = Math.PI - direction; + } else if (xx < 0) { + xx = 0; + direction = Math.PI - direction; + } + if (yy > 1) { + yy = 1; + direction = 2 * Math.PI - direction; + } else if (yy < 0) { + yy = 0; + direction = 2 * Math.PI - direction; + } + if (direction < 0) { + direction += 2 * Math.PI; + } + } + + + @JsonProperty("xx") + public double getxx() { + return xx; + } + + + @JsonProperty("yy") + public double getyy() { + return yy; + } + + + @JsonProperty("size") + public double getSize() { + return size; + } + + + static double dist(Entity e1, Entity e2) { + return (Math.sqrt(Math.pow(e1.xx - e2.xx, 2) + + Math.pow(e1.yy - e2.yy, 2))); + } + +} diff --git a/src/main/java/application/mechanics/entity/Player.java b/src/main/java/application/mechanics/entity/Player.java new file mode 100644 index 0000000..0f582e4 --- /dev/null +++ b/src/main/java/application/mechanics/entity/Player.java @@ -0,0 +1,96 @@ +package application.mechanics.entity; + +import org.jetbrains.annotations.NotNull; + +public class Player extends Entity { + + private static final double MIN_SIZE = 0.02; + private static final double MAX_SPEED = 0.013; + private static final double SPEED_DIF = MAX_SPEED / 20; + private static final double WIN_DIF = 1.2; + private static final double ANGLE_STEP = Math.PI / 20; + + private double curDirection; + + + public Player(double xxx, double yyy) { + xx = xxx; + yy = yyy; + size = MIN_SIZE; + direction = 0; + curDirection = 0; + speed = 0; + } + + + public boolean eat(Enemy enemy) { + if (isTouched(enemy)) { + size += enemy.size; + enemy.reincarnation(); + return true; + } + return false; + } + + + public boolean isEaten(Player enemy) { + return isTouched(enemy) && size / enemy.size > WIN_DIF; + } + + + @Override + public void move() { + super.move(); + speed -= SPEED_DIF; + if (speed < 0) { + speed = 0; + } + if (curDirection != direction) { + final double dif = curDirection - direction; + final int sign1 = dif > 0 ? 1 : -1; + final int sign2 = Math.abs(dif) > Math.PI ? -1 : 1; + direction += ANGLE_STEP * sign1 * sign2; + if (direction > Math.PI * 2) { + direction -= Math.PI * 2; + } + if (direction < 0) { + direction += Math.PI * 2; + } + if (Math.abs(curDirection - direction) < ANGLE_STEP) { + direction = curDirection; + } + } + } + + + public void buttonClick(Direction dir) { + switch (dir) { + case UPPP: + curDirection = Math.PI / 2; + break; + case DOWN: + curDirection = Math.PI * 3 / 2; + break; + case LEFT: + curDirection = Math.PI; + break; + case RIGHT: + curDirection = 0; + break; + default: + break; + } + speed += SPEED_DIF * 2; + if (speed > MAX_SPEED) { + speed = MAX_SPEED; + } + } + + + private boolean isTouched(@NotNull Entity enemy) { + return (Math.pow(xx - enemy.xx, 2) + + Math.pow(yy - enemy.yy, 2)) + < Math.pow(size + enemy.size, 2); + } + +} diff --git a/src/main/java/application/models/User.java b/src/main/java/application/models/User.java index 9f57a96..ba9b6c5 100644 --- a/src/main/java/application/models/User.java +++ b/src/main/java/application/models/User.java @@ -1,43 +1,50 @@ package application.models; +import javax.validation.constraints.NotNull; public class User { private final Long id; private String login; private String password; private String email; - private String avatar; - private int score; + private int sscore; + private int mscore; public User(Long id, String login, String password, String email) { this.id = id; + this.password = password; this.login = login; + this.email = email; + } + + public User(Long id, String login, String password, String email, int sscore, int mscore) { + this.id = id; this.password = password; + this.login = login; this.email = email; - this.avatar = ""; - score = 0; + this.sscore = sscore; + this.mscore = mscore; } - public Long getId() { + public long getId() { return id; } + @NotNull public String getLogin() { return login; } + @NotNull public String getPassword() { return password; } + @NotNull public String getEmail() { return email; } - public String getAvatar() { - return avatar; - } - public void setLogin(String login) { this.login = login; } @@ -50,7 +57,19 @@ public void setEmail(String email) { this.email = email; } - public void setAvatar(String avatar) { - this.avatar = avatar; + public int getSscore() { + return sscore; + } + + public void setSscore(int sscore) { + this.sscore = sscore; + } + + public int getMscore() { + return mscore; + } + + public void setMscore(int mscore) { + this.mscore = mscore; } -} \ No newline at end of file +} diff --git a/src/main/java/application/models/UserService.java b/src/main/java/application/services/AccountService.java similarity index 64% rename from src/main/java/application/models/UserService.java rename to src/main/java/application/services/AccountService.java index e3a3242..783e776 100644 --- a/src/main/java/application/models/UserService.java +++ b/src/main/java/application/services/AccountService.java @@ -1,6 +1,8 @@ -package application.models; +package application.services; -import application.database.DAOi; +import application.db.UserDao; +import application.models.User; +import application.utils.requests.SignupRequest; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.springframework.security.crypto.password.PasswordEncoder; @@ -9,21 +11,21 @@ import java.util.List; @Service -public class UserService { +public class AccountService { @NotNull - private final DAOi db; + private final UserDao db; @NotNull private final PasswordEncoder encoder; - public UserService(@NotNull DAOi db, @NotNull PasswordEncoder encoder) { + public AccountService(@NotNull UserDao db, @NotNull PasswordEncoder encoder) { this.db = db; this.encoder = encoder; } @NotNull - public Long createUser(String login, String password, String email) { - final String encodedPassword = encoder.encode(password); - return db.addUser(login, encodedPassword, email); + public Long addUser(@NotNull SignupRequest user) { + final String encodedPassword = encoder.encode(user.getPassword()); + return db.addUser(user.getLogin(), encodedPassword, user.getEmail()); } public void changePassword(@NotNull User user, @NotNull String password) { @@ -42,11 +44,6 @@ public void changeEmail(@NotNull User user, @NotNull String email) { db.changeUserData(user); } - public void changeAvatar(@NotNull User user, @NotNull String avatar) { - user.setAvatar(avatar); - db.changeUserData(user); - } - @Nullable public User getUser(long id) { return db.getUser(id); @@ -72,14 +69,23 @@ public boolean checkSignup(@NotNull String login, @NotNull String email) { public boolean checkSignin(long id, @NotNull String password) { final User user = db.getUser(id); return user != null && encoder.matches(password, user.getPassword()); + + } + + public Integer updateSScore(long id, boolean result) { + return db.updateSScore(id, result); + } + + public Integer updateMScore(long id, boolean result) { + return db.updateMScore(id, result); } - public Integer updateScore(long id, boolean result) { - return db.updateScore(id, result); + public List getSTop(Integer limit, Integer since) { + return db.getSTop(limit, since); } - public List getTop(Integer limit, Integer since) { - return db.getTop(limit, since); + public List getMTop(Integer limit, Integer since) { + return db.getMTop(limit, since); } public void clear() { diff --git a/src/main/java/application/utils/Messages.java b/src/main/java/application/utils/Messages.java new file mode 100644 index 0000000..845c505 --- /dev/null +++ b/src/main/java/application/utils/Messages.java @@ -0,0 +1,13 @@ +package application.utils; + +public class Messages { + public static final String NOT_AUTHORIZE = "You're not authorized"; + public static final String AUTHORIZED = "You're authorized"; + public static final String EXISTS = "Login or email already exists"; + public static final String WRONG_LOGIN_PASSWORD = "Wrong login or password"; + public static final String WRONG_PASSWORD = "Wrong password"; + public static final String LOGIN_EXISTS = "Login already exists"; + public static final String EMAIL_EXISTS = "Email already exists"; + public static final String SUCCESS = "Success"; + public static final String BAD_COOKIE = "Bad cookie"; +} diff --git a/src/main/java/application/utils/Validator.java b/src/main/java/application/utils/Validator.java new file mode 100644 index 0000000..1c02386 --- /dev/null +++ b/src/main/java/application/utils/Validator.java @@ -0,0 +1,85 @@ +package application.utils; + +import application.utils.requests.SignupRequest; +import org.springframework.util.StringUtils; + +import javax.validation.constraints.NotNull; +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +public class Validator { + public static final String LOGIN_ERROR = "Invalid login"; + public static final String EMAIL_ERROR = "Invalid email"; + public static final String EMPTY_LOGIN = "Empty login"; + public static final String SHORT_LOGIN = "Short login(min 3 symbols)"; + public static final String LONG_LOGIN = "Long login(max 15 symbols)"; + public static final String EMPTY_EMAIL = "Empty email"; + public static final String EMPTY_PASSWORD = "Empty password"; + public static final String SHORT_PASSWORD = "Short password(min 8 symbols)"; + public static final String LONG_PASSWORD = "Long password(max 24 symbols)"; + private static final int LOGIN_MIN_LENGTH = 3; + private static final int LOGIN_MAX_LENGTH = 15; + private static final int PASSWORD_MIN_LENGTH = 8; + private static final int PASSWORD_MAX_LENGTH = 24; + private static final Pattern LOGIN_PATTERN = Pattern.compile("^[A-Za-z0-9_-]+$"); + private static final Pattern EMAIL_PATTERN = Pattern.compile("^[-\\w.]+@([A-z0-9][-A-z0-9]+\\.)+[A-z]{2,4}$"); + + public static ArrayList checkLogin(@NotNull String login) { + final ArrayList error = new ArrayList<>(); + if (StringUtils.isEmpty(login)) { + error.add(EMPTY_LOGIN); + } else { + final int length = login.length(); + if (length < LOGIN_MIN_LENGTH) { + error.add(SHORT_LOGIN); + } else if (length > LOGIN_MAX_LENGTH) { + error.add(LONG_LOGIN); + } + + final Matcher m = LOGIN_PATTERN.matcher(login); + if (!m.matches()) { + error.add(LOGIN_ERROR); + } + } + return error; + } + + public static ArrayList checkEmail(@NotNull String email) { + final ArrayList error = new ArrayList<>(); + if (StringUtils.isEmpty(email)) { + error.add(EMPTY_EMAIL); + } else { + final Matcher m = EMAIL_PATTERN.matcher(email); + if (!m.matches()) { + error.add(EMAIL_ERROR); + } + } + return error; + } + + public static ArrayList checkPassword(@NotNull String password) { + final ArrayList error = new ArrayList<>(); + if (StringUtils.isEmpty(password)) { + error.add(EMPTY_PASSWORD); + } else { + final int length = password.length(); + if (length < PASSWORD_MIN_LENGTH) { + error.add(SHORT_PASSWORD); + } else if (length > PASSWORD_MAX_LENGTH) { + error.add(LONG_PASSWORD); + } + } + return error; + } + + public static ArrayList checkSignup(@NotNull SignupRequest user) { + final ArrayList error = new ArrayList<>(); + error.addAll(checkLogin(user.getLogin())); + error.addAll(checkPassword(user.getPassword())); + error.addAll(checkEmail(user.getEmail())); + return error; + } + +} diff --git a/src/main/java/application/controllers/requests/ChangeRequest.java b/src/main/java/application/utils/requests/SettingsRequest.java similarity index 59% rename from src/main/java/application/controllers/requests/ChangeRequest.java rename to src/main/java/application/utils/requests/SettingsRequest.java index 6649a97..eb081bd 100644 --- a/src/main/java/application/controllers/requests/ChangeRequest.java +++ b/src/main/java/application/utils/requests/SettingsRequest.java @@ -1,21 +1,21 @@ -package application.controllers.requests; +package application.utils.requests; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import org.jetbrains.annotations.NotNull; -public class ChangeRequest { +import org.jetbrains.annotations.NotNull; - @NotNull - private final String modifiedString; +public class SettingsRequest { @NotNull private final String password; + @NotNull + private final String fieldToChange; @JsonCreator - public ChangeRequest(@JsonProperty("password") @NotNull String password, + public SettingsRequest(@JsonProperty("password") @NotNull String password, @JsonProperty("change") @NotNull String fieldToChange) { this.password = password; - this.modifiedString = fieldToChange; + this.fieldToChange = fieldToChange; } @NotNull @@ -24,7 +24,8 @@ public String getPassword() { } @NotNull - public String getModifiedString() { - return modifiedString; + public String getFieldToChange() { + return fieldToChange; } } + diff --git a/src/main/java/application/controllers/requests/SigninRequest.java b/src/main/java/application/utils/requests/SigninRequest.java similarity index 94% rename from src/main/java/application/controllers/requests/SigninRequest.java rename to src/main/java/application/utils/requests/SigninRequest.java index eff0567..5dcfdb9 100644 --- a/src/main/java/application/controllers/requests/SigninRequest.java +++ b/src/main/java/application/utils/requests/SigninRequest.java @@ -1,9 +1,9 @@ -package application.controllers.requests; +package application.utils.requests; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.NotNull; public class SigninRequest { @@ -28,4 +28,5 @@ public String getLogin() { public String getPassword() { return password; } + } diff --git a/src/main/java/application/controllers/requests/SignupRequest.java b/src/main/java/application/utils/requests/SignupRequest.java similarity index 95% rename from src/main/java/application/controllers/requests/SignupRequest.java rename to src/main/java/application/utils/requests/SignupRequest.java index e7ea906..5b51a3b 100644 --- a/src/main/java/application/controllers/requests/SignupRequest.java +++ b/src/main/java/application/utils/requests/SignupRequest.java @@ -1,10 +1,9 @@ -package application.controllers.requests; +package application.utils.requests; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import org.jetbrains.annotations.NotNull; - public class SignupRequest { @NotNull diff --git a/src/main/java/application/controllers/responses/MessageResponse.java b/src/main/java/application/utils/responses/MessageResponse.java similarity index 51% rename from src/main/java/application/controllers/responses/MessageResponse.java rename to src/main/java/application/utils/responses/MessageResponse.java index c4c03bd..36f5983 100644 --- a/src/main/java/application/controllers/responses/MessageResponse.java +++ b/src/main/java/application/utils/responses/MessageResponse.java @@ -1,20 +1,19 @@ -package application.controllers.responses; +package application.utils.responses; -import application.controllers.messages.Message; import com.fasterxml.jackson.annotation.JsonProperty; import javax.validation.constraints.NotNull; public class MessageResponse { + @NotNull private final String message; - public MessageResponse(@NotNull Message message) { - this.message = message.getMessage(); + public MessageResponse(@JsonProperty("message") @NotNull String message) { + this.message = message; } - @JsonProperty("message") + @NotNull public String getMessage() { return message; } } - diff --git a/src/main/java/application/utils/responses/UserResponseWP.java b/src/main/java/application/utils/responses/UserResponseWP.java new file mode 100644 index 0000000..d18baab --- /dev/null +++ b/src/main/java/application/utils/responses/UserResponseWP.java @@ -0,0 +1,53 @@ +package application.utils.responses; + +import application.db.UserDao; +import application.models.User; +import application.utils.requests.SignupRequest; + +import javax.validation.constraints.NotNull; + +public class UserResponseWP { + private final long id; + @NotNull + private final String login; + @NotNull + private final String email; + private final int sscore; + private final int mscore; + + public UserResponseWP(@NotNull User user) { + this.id = user.getId(); + this.login = user.getLogin(); + this.email = user.getEmail(); + this.sscore = user.getSscore(); + this.mscore = user.getMscore(); + } + + public UserResponseWP(Long id, SignupRequest user) { + this.id = id; + this.login = user.getLogin(); + this.email = user.getEmail(); + this.sscore = UserDao.DEFAULT_SCORE; + this.mscore = UserDao.DEFAULT_SCORE; + } + + public String getLogin() { + return login; + } + + public String getEmail() { + return email; + } + + public Long getId() { + return id; + } + + public int getSscore() { + return sscore; + } + + public int getMscore() { + return mscore; + } +} diff --git a/src/main/java/application/utils/responses/ValidatorResponse.java b/src/main/java/application/utils/responses/ValidatorResponse.java new file mode 100644 index 0000000..3089358 --- /dev/null +++ b/src/main/java/application/utils/responses/ValidatorResponse.java @@ -0,0 +1,19 @@ +package application.utils.responses; + +import javax.validation.constraints.NotNull; +import java.util.ArrayList; + +public class ValidatorResponse { + @NotNull + private final ArrayList messageList; + + public ValidatorResponse(@NotNull ArrayList messageList) { + this.messageList = messageList; + } + + @NotNull + public ArrayList getMessage() { + return messageList; + } +} + diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index cfd74e7..011b186 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,6 +1,11 @@ -#spring.datasource.url=${JDBC_DATABASE_URL} -#server.port=${PORT} -spring.datasource.url=jdbc:postgresql://localhost:5432/brodb -spring.datasource.username=vitalya -spring.datasource.password=1324qwer -server.port=8080 +spring.datasource.url=${JDBC_DATABASE_URL} +server.port=${PORT} +#postgres://ziqxmgohkremcs:e34f9b875ea7f71a1c84fc5aa77a0078dc5e831b5143353d90802ff20215fa28@ec2-54-75-244-248.eu-west-1.compute.amazonaws.com:5432/d13q0vpi92neot +#spring.datasource.url=jdbc:postgresql://localhost:5432/brodb +#spring.datasource.username=vitalya +#spring.datasource.password=1324qwer +#server.port=8080 +#spring.datasource.url=jdbc:postgresql://ec2-54-75-244-248.eu-west-1.compute.amazonaws.com:5432/d13q0vpi92neot +#spring.datasource.username=ziqxmgohkremcs +#spring.datasource.password=e34f9b875ea7f71a1c84fc5aa77a0078dc5e831b5143353d90802ff20215fa28 +#server.port=8080 diff --git a/src/main/resources/db/migration/V1__init.sql b/src/main/resources/db/migration/V1__init.sql index 85a81b6..2062e90 100644 --- a/src/main/resources/db/migration/V1__init.sql +++ b/src/main/resources/db/migration/V1__init.sql @@ -1,8 +1,9 @@ -CREATE TABLE IF NOT EXISTS users ( - id SERIAL NOT NULL PRIMARY KEY, - login VARCHAR(50) NOT NULL UNIQUE, - email VARCHAR(50) NOT NULL UNIQUE, - password VARCHAR(200) NOT NULL, - score INTEGER DEFAULT 0 -); - +CREATE TABLE IF NOT EXISTS users ( + id SERIAL NOT NULL PRIMARY KEY, + login VARCHAR(50) NOT NULL UNIQUE, + email VARCHAR(50) NOT NULL UNIQUE, + password VARCHAR(200) NOT NULL, + sscore INTEGER DEFAULT 1000, + mscore INTEGER DEFAULT 1000 +); + diff --git a/src/test/java/application/controller/ControllerTest.java b/src/test/java/application/controller/ControllerTest.java new file mode 100644 index 0000000..019613d --- /dev/null +++ b/src/test/java/application/controller/ControllerTest.java @@ -0,0 +1,354 @@ +package application.controller; + +import application.services.AccountService; +import application.utils.Messages; +import application.utils.Validator; +import application.utils.requests.SignupRequest; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrint; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@Transactional +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK) +@AutoConfigureMockMvc(print = MockMvcPrint.NONE) +public class ControllerTest { + private static final String LOGIN = "vitalya"; + private static final String PASSWORD = "qwerty123"; + private static final String EMAIL = "vitalya@mail.ru"; + private static final long BADID = 34348L; + private long userId; + + @Autowired + AccountService service; + + @Autowired + MockMvc mock; + + @Before + public void before() { + userId = service.addUser(new SignupRequest(LOGIN, PASSWORD, EMAIL)); + } + + @After + public void after() { + service.clear(); + } + + @Test + public void signup() throws Exception { + mock.perform(post("/signup") + .contentType(MediaType.APPLICATION_JSON) + .content("{\"login\":\"vitalya123\", \"password\":\"qwerty123\", \"email\":\"vitalya123@mail.ru\"}")) + .andExpect(status().isOk()) + .andExpect(jsonPath("id").value(String.valueOf(userId + 1))) + .andExpect(jsonPath("login").value("vitalya123")) + .andExpect(jsonPath("email").value("vitalya123@mail.ru")); + } + + @Test + public void authorizedSignup() throws Exception { + mock.perform(post("/signup") + .sessionAttr("userId", userId) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"login\":\"vitalya123\", \"password\":\"qwerty123\", \"email\":\"vitalya123@mail.ru\"}")) + .andExpect(status().isForbidden()) + .andExpect(jsonPath("message").value(Messages.AUTHORIZED)); + } + + @Test + public void conflictSignup() throws Exception { + mock.perform(post("/signup") + .contentType(MediaType.APPLICATION_JSON) + .content("{\"login\":\"vitalya\", \"password\":\"qwerty123\", \"email\":\"vitalya123@mail.ru\"}")) + .andExpect(status().isConflict()) + .andExpect(jsonPath("message").value(Messages.EXISTS)); + + mock.perform(post("/signup") + .contentType(MediaType.APPLICATION_JSON) + .content("{\"login\":\"vitalya123\", \"password\":\"qwerty123\", \"email\":\"vitalya@mail.ru\"}")) + .andExpect(status().isConflict()) + .andExpect(jsonPath("message").value(Messages.EXISTS)); + + mock.perform(post("/signup") + .contentType(MediaType.APPLICATION_JSON) + .content("{\"login\":\"vitalya\", \"password\":\"qwerty123\", \"email\":\"vitalya@mail.ru\"}")) + .andExpect(status().isConflict()) + .andExpect(jsonPath("message").value(Messages.EXISTS)); + } + + @Test + public void invalidSignup() throws Exception { + final ArrayList error = new ArrayList<>(); + error.add(Validator.SHORT_LOGIN); + error.add(Validator.SHORT_PASSWORD); + error.add(Validator.EMPTY_EMAIL); + mock.perform(post("/signup") + .contentType(MediaType.APPLICATION_JSON) + .content("{\"login\":\"il\", \"password\":\"qwe\", \"email\":\"\"}")) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("message").value(error)); + + error.clear(); + error.add(Validator.LONG_LOGIN); + error.add(Validator.LONG_PASSWORD); + error.add(Validator.EMAIL_ERROR); + mock.perform(post("/signup") + .contentType(MediaType.APPLICATION_JSON) + .content("{\"login\":\"vitalya12jvnhjgnvvhgnvhghvnhg3\", \"password\":\"ufhgnvbchftfgdbcvfgcvfvfvv\", \"email\":\"vitalya123mail.ru\"}")) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("message").value(error)); + + error.clear(); + error.add(Validator.LOGIN_ERROR); + error.add(Validator.EMPTY_PASSWORD); + error.add(Validator.EMAIL_ERROR); + mock.perform(post("/signup") + .contentType(MediaType.APPLICATION_JSON) + .content("{\"login\":\"вввсакмкмк\", \"password\":\"\", \"email\":\"vitalya123mail.ru\"}")) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("message").value(error)); + } + + @Test + public void signin() throws Exception { + mock.perform(post("/signin") + .contentType(MediaType.APPLICATION_JSON) + .content("{\"login\":\"vitalya\", \"password\":\"qwerty123\"}")) + .andExpect(status().isOk()) + .andExpect(jsonPath("id").value(String.valueOf(userId))) + .andExpect(jsonPath("login").value("vitalya")) + .andExpect(jsonPath("email").value("vitalya@mail.ru")); + } + + @Test + public void authorizedSignin() throws Exception { + mock.perform(post("/signin") + .sessionAttr("userId", userId) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"login\":\"vitalya\", \"password\":\"qwerty123\"}")) + .andExpect(status().isForbidden()) + .andExpect(jsonPath("message").value(Messages.AUTHORIZED)); + } + + @Test + public void wrongSignin() throws Exception { + mock.perform(post("/signin") + .contentType(MediaType.APPLICATION_JSON) + .content("{\"login\":\"jrhvbghjrv\", \"password\":\"qwerty123\"}")) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("message").value(Messages.WRONG_LOGIN_PASSWORD)); + + mock.perform(post("/signin") + .contentType(MediaType.APPLICATION_JSON) + .content("{\"login\":\"vitalya\", \"password\":\"qwefvty123\"}")) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("message").value(Messages.WRONG_LOGIN_PASSWORD)); + + mock.perform(post("/signin") + .contentType(MediaType.APPLICATION_JSON) + .content("{\"login\":\"idfvdfa12\", \"password\":\"qwertdfvdy123\"}")) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("message").value(Messages.WRONG_LOGIN_PASSWORD)); + } + + @Test + public void unauthorizedChangePassword() throws Exception { + mock.perform(post("/newpassword") + .contentType(MediaType.APPLICATION_JSON) + .content("{\"password\":\"qwerty123\", \"change\":\"qwerty1234\"}")) + .andExpect(status().isUnauthorized()) + .andExpect(jsonPath("message").value(Messages.NOT_AUTHORIZE)); + } + + @Test + public void unauthorizedChangeEmail() throws Exception { + mock.perform(post("/newemail") + .contentType(MediaType.APPLICATION_JSON) + .content("{\"password\":\"qwerty123\", \"change\":\"qwerty@mail.ru\"}")) + .andExpect(status().isUnauthorized()) + .andExpect(jsonPath("message").value(Messages.NOT_AUTHORIZE)); + } + + @Test + public void unauthorizedChangeLogin() throws Exception { + mock.perform(post("/newlogin") + .contentType(MediaType.APPLICATION_JSON) + .content("{\"password\":\"qwerty123\", \"change\":\"qwerty\"}")) + .andExpect(status().isUnauthorized()) + .andExpect(jsonPath("message").value(Messages.NOT_AUTHORIZE)); + } + + @Test + public void changePassword() throws Exception { + mock.perform(post("/newpassword") + .sessionAttr("userId", userId) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"password\":\"qwerty123\", \"change\":\"qwerty1234\"}")) + .andExpect(status().isOk()) + .andExpect(jsonPath("id").value(String.valueOf(userId))) + .andExpect(jsonPath("login").value("vitalya")) + .andExpect(jsonPath("email").value("vitalya@mail.ru")); + } + + @Test + public void changeEmail() throws Exception { + mock.perform(post("/newemail") + .sessionAttr("userId", userId) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"password\":\"qwerty123\", \"change\":\"qwerty@mail.ru\"}")) + .andExpect(status().isOk()) + .andExpect(jsonPath("id").value(String.valueOf(userId))) + .andExpect(jsonPath("login").value("vitalya")) + .andExpect(jsonPath("email").value("qwerty@mail.ru")); + } + + @Test + public void changeLogin() throws Exception { + mock.perform(post("/newlogin") + .sessionAttr("userId", userId) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"password\":\"qwerty123\", \"change\":\"qwerty\"}")) + .andExpect(status().isOk()) + .andExpect(jsonPath("id").value(String.valueOf(userId))) + .andExpect(jsonPath("login").value("qwerty")) + .andExpect(jsonPath("email").value("vitalya@mail.ru")); + } + + @Test + public void changePasswordBadCookie() throws Exception { + mock.perform(post("/newpassword") + .sessionAttr("userId", BADID) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"password\":\"qwerty123\", \"change\":\"qwerty1234\"}")) + .andExpect(status().isForbidden()) + .andExpect(jsonPath("message").value(Messages.BAD_COOKIE)); + } + + @Test + public void changeEmailBadCookie() throws Exception { + mock.perform(post("/newemail") + .sessionAttr("userId", BADID) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"password\":\"qwerty123\", \"change\":\"qwerty@mail.ru\"}")) + .andExpect(status().isForbidden()) + .andExpect(jsonPath("message").value(Messages.BAD_COOKIE)); + } + + @Test + public void changeLoginBadCookie() throws Exception { + mock.perform(post("/newlogin") + .sessionAttr("userId", BADID) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"password\":\"qwerty123\", \"change\":\"qwerty\"}")) + .andExpect(status().isForbidden()) + .andExpect(jsonPath("message").value(Messages.BAD_COOKIE)); + } + + @Test + public void changeLoginWrongPassword() throws Exception { + mock.perform(post("/newlogin") + .sessionAttr("userId", userId) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"password\":\"qwer1ty123\", \"change\":\"qwerty\"}")) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("message").value(Messages.WRONG_PASSWORD)); + } + + @Test + public void changePasswordWrongPassword() throws Exception { + mock.perform(post("/newpassword") + .sessionAttr("userId", userId) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"password\":\"qwe1rty123\", \"change\":\"qwerty1234\"}")) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("message").value(Messages.WRONG_PASSWORD)); + } + + @Test + public void changeEmailWrongPassword() throws Exception { + mock.perform(post("/newemail") + .sessionAttr("userId", userId) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"password\":\"qwert1y123\", \"change\":\"qwerty@mail.ru\"}")) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("message").value(Messages.WRONG_PASSWORD)); + } + + @Test + public void changeLoginConflict() throws Exception { + mock.perform(post("/newlogin") + .sessionAttr("userId", userId) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"password\":\"qwerty123\", \"change\":\"vitalya\"}")) + .andExpect(status().isConflict()) + .andExpect(jsonPath("message").value(Messages.LOGIN_EXISTS)); + } + + @Test + public void changeEmailConflict() throws Exception { + mock.perform(post("/newemail") + .sessionAttr("userId", userId) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"password\":\"qwerty123\", \"change\":\"vitalya@mail.ru\"}")) + .andExpect(status().isConflict()) + .andExpect(jsonPath("message").value(Messages.EMAIL_EXISTS)); + } + + @Test + public void unauthorizedLogout() throws Exception { + mock.perform(post("/logout")) + .andExpect(status().isUnauthorized()) + .andExpect(jsonPath("message").value(Messages.NOT_AUTHORIZE)); + } + + @Test + public void logout() throws Exception { + mock.perform(post("/logout") + .sessionAttr("userId", userId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("message").value(Messages.SUCCESS)); + } + + @Test + public void getUser() throws Exception { + mock.perform(get("/user") + .sessionAttr("userId", userId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("id").value(String.valueOf(userId))) + .andExpect(jsonPath("login").value(LOGIN)) + .andExpect(jsonPath("email").value(EMAIL)); + } + + @Test + public void unauthorizedGetUser() throws Exception { + mock.perform(get("/user")) + .andExpect(status().isUnauthorized()) + .andExpect(jsonPath("message").value(Messages.NOT_AUTHORIZE)); + } + + @Test + public void getUserWithBadCookies() throws Exception { + mock.perform(get("/user") + .sessionAttr("userId", BADID)) + .andExpect(status().isForbidden()) + .andExpect(jsonPath("message").value(Messages.BAD_COOKIE)); + } + +} diff --git a/src/test/java/application/service/AccountServiceTest.java b/src/test/java/application/service/AccountServiceTest.java new file mode 100644 index 0000000..b6ade5f --- /dev/null +++ b/src/test/java/application/service/AccountServiceTest.java @@ -0,0 +1,96 @@ +package application.service; + +import application.models.User; +import application.services.AccountService; +import application.utils.requests.SignupRequest; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; + +import static org.junit.Assert.*; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) +@Transactional +public class AccountServiceTest { + static final String LOGIN = "login"; + static final String EMAIL = "email@mail.ru"; + static final String PASSWORD = "qwerty123"; + + @Autowired + private AccountService service; + @Autowired + private PasswordEncoder encoder; + + private long testUserId; + + @Before + public void before() { + final SignupRequest user = new SignupRequest(LOGIN, PASSWORD, EMAIL); + testUserId = service.addUser(user); + } + + @Test + public void testAddUser() { + final SignupRequest user = new SignupRequest("qghnghn", "qfnhfn565756fgh", "qfghf@mail.ru"); + final long id = service.addUser(user); + assertTrue(id > 0); + } + + @Test + public void testGetUserById() { + final User user = service.getUser(testUserId); + assertEquals(user.getId(), testUserId); + assertEquals(user.getEmail(), EMAIL); + assertEquals(user.getLogin(), LOGIN); + assertTrue(encoder.matches(PASSWORD, user.getPassword())); + } + + @Test + public void testGetUserByLogin() { + final User user = service.getUser(LOGIN); + assertEquals(user.getId(), testUserId); + assertEquals(user.getEmail(), EMAIL); + assertEquals(user.getLogin(), LOGIN); + } + + @Test + public void testCheckLogin() { + assertFalse(service.checkLogin(LOGIN)); + assertTrue(service.checkLogin("dfghjjfnjdfnvj")); + } + + @Test + public void testCheckEmail() { + assertFalse(service.checkEmail(EMAIL)); + assertTrue(service.checkEmail("dfghjjfnjdfnvj@mail.dh")); + } + + @Test + public void testCheckSignup() { + assertFalse(service.checkSignup(LOGIN, EMAIL)); + assertFalse(service.checkSignup(LOGIN, "fvejfnve@jf.v")); + assertFalse(service.checkSignup("sfjnjsfv", EMAIL)); + assertTrue(service.checkSignup("login123", "dfghjjfnjdfnvj@mail.dh")); + } + + @Test + public void testCheckSignin() { + assertFalse(service.checkSignin(testUserId + 1, "fbhfbh7438473b")); + assertFalse(service.checkSignin(testUserId, "2313hdbch")); + assertFalse(service.checkSignin(testUserId + 1, PASSWORD)); + assertTrue(service.checkSignin(testUserId, PASSWORD)); + } + + @After + public void clear() { + service.clear(); + } + +} diff --git a/src/test/java/application/utils/ValidatorTest.java b/src/test/java/application/utils/ValidatorTest.java new file mode 100644 index 0000000..3fbfb5f --- /dev/null +++ b/src/test/java/application/utils/ValidatorTest.java @@ -0,0 +1,27 @@ +package application.utils; + +import org.junit.Assert; +import org.junit.Test; + +public class ValidatorTest { + @Test + public void testWrongLogin() { + Assert.assertTrue(Validator.checkLogin("").contains(Validator.EMPTY_LOGIN)); + Assert.assertTrue(Validator.checkLogin("123456789012345678901234567890123456789012345678901234567").contains(Validator.LONG_LOGIN)); + Assert.assertTrue(Validator.checkLogin("12").contains(Validator.SHORT_LOGIN)); + Assert.assertTrue(Validator.checkLogin("AYE@#$%").contains(Validator.LOGIN_ERROR)); + } + + @Test + public void testWrongEmail() { + Assert.assertTrue(Validator.checkEmail("").contains(Validator.EMPTY_EMAIL)); + Assert.assertTrue(Validator.checkEmail("misha").contains(Validator.EMAIL_ERROR)); + } + + @Test + public void testWrongPassword() { + Assert.assertTrue(Validator.checkPassword("").contains(Validator.EMPTY_PASSWORD)); + Assert.assertTrue(Validator.checkPassword("12").contains(Validator.SHORT_PASSWORD)); + Assert.assertTrue(Validator.checkPassword("1234567111111111111111111111111111111111").contains(Validator.LONG_PASSWORD)); + } +} diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 0000000..bf4d099 --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,4 @@ +spring.datasource.url=jdbc:postgresql://localhost:5432/brodb +spring.datasource.username=vitalya +spring.datasource.password=1324qwer +spring.datasource.name=brodb \ No newline at end of file diff --git a/system.properties b/system.properties new file mode 100644 index 0000000..e1303ea --- /dev/null +++ b/system.properties @@ -0,0 +1 @@ +java.runtime.version=9 \ No newline at end of file