diff --git a/db/ddl.sql b/db/ddl.sql index 62a5368..df636d3 100644 --- a/db/ddl.sql +++ b/db/ddl.sql @@ -1,17 +1,24 @@ CREATE TABLE IF NOT EXISTS auth.users ( id SERIAL PRIMARY KEY, username VARCHAR(255) UNIQUE NOT NULL, + nickname VARCHAR(255) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, - email VARCHAR(255) UNIQUE NOT NULL, - firstname VARCHAR(100) NULL, - surname VARCHAR(100) NULL, + dateofborn DATE NULL, + gender CHAR(1) NULL, + state CHAR(2) NOT NULL, + city VARCHAR(255) NOT NULL, + institutiontype CHAR(1) NULL, + institution VARCHAR(255) NULL, + securityquestion VARCHAR(255) NULL, + securityanswer VARCHAR(255) NULL, + termsofusage BOOLEAN NOT NULL, avatar VARCHAR(100) NULL, active INT NOT NULL ); CREATE TABLE IF NOT EXISTS auth.forgotpassword_keys ( id SERIAL PRIMARY KEY, - email VARCHAR(255) NOT NULL, + username VARCHAR(255) NOT NULL, key VARCHAR(4) NOT NULL, created_at TIMESTAMP DEFAULT NOW() ); @@ -43,13 +50,11 @@ CREATE TABLE IF NOT EXISTS auth.users_roles ( FOREIGN KEY (users_id) REFERENCES auth.users (id) ); -CREATE TABLE IF NOT EXISTS auth.users_rolesprovider_activationkey ( +CREATE TABLE IF NOT EXISTS auth.users_provider_activationkey ( id SERIAL PRIMARY KEY, users_id INT NOT NULL, - roles_id INT NOT NULL, - activationkey uuid NOT NULL, - FOREIGN KEY (users_id) REFERENCES auth.users (id), - FOREIGN KEY (roles_id) REFERENCES auth.roles (id) + activationkey uuid UNIQUE NOT NULL, + FOREIGN KEY (users_id) REFERENCES auth.users (id) ); CREATE TABLE IF NOT EXISTS auth.educemaden_organizations ( @@ -63,13 +68,15 @@ CREATE TABLE IF NOT EXISTS auth.educemaden_organizations ( website varchar(255) NULL, login varchar(50) NULL, address varchar(50) NULL, - responsible varchar(50) NULL + responsible varchar(50) NULL, + email VARCHAR(255) UNIQUE NOT NULL ); CREATE TABLE IF NOT EXISTS auth.users_educemaden_organizations ( id SERIAL PRIMARY KEY, users_id INT NOT NULL, educemaden_organizations_id INT NOT NULL, - activationkey uuid NOT NULL, + activationkey uuid UNIQUE NOT NULL, + active INT NOT NULL, FOREIGN KEY (users_id) REFERENCES auth.users (id) ); diff --git a/src/main/java/org/waterproofingdata/wpdauth/WpdauthApplication.java b/src/main/java/org/waterproofingdata/wpdauth/WpdauthApplication.java index 375439a..87d6f21 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/WpdauthApplication.java +++ b/src/main/java/org/waterproofingdata/wpdauth/WpdauthApplication.java @@ -33,8 +33,11 @@ public class WpdauthApplication implements CommandLineRunner { if (!userService.existsByUsername("admin")) { Users admin = new Users(); admin.setUsername("admin"); + admin.setNickname("admin"); admin.setPassword("admin"); - admin.setEmail("admin@wpd.com"); + admin.setState("SP"); + admin.setCity("São Paulo"); + admin.setTermsofusage(true); admin.setActive(1); admin.setRoles(new ArrayList(Arrays.asList(Roles.ROLE_ADMIN))); diff --git a/src/main/java/org/waterproofingdata/wpdauth/controller/ForgotPasswordsController.java b/src/main/java/org/waterproofingdata/wpdauth/controller/ForgotPasswordsController.java index 4b1b574..cf1aa9a 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/controller/ForgotPasswordsController.java +++ b/src/main/java/org/waterproofingdata/wpdauth/controller/ForgotPasswordsController.java @@ -36,31 +36,31 @@ public class ForgotPasswordsController { @ApiResponses(value = {// @ApiResponse(code = 400, message = "Something went wrong"), // @ApiResponse(code = 422, message = "Invalid email supplied")}) - public void sendkeybyemail(@ApiParam("Email") @RequestParam String email) { - forgotPasswordsService.sendKeyByEmail(email); + public void sendkeybyemail(@ApiParam("Email") @RequestParam String email, @ApiParam("Username") @RequestParam String username) { + forgotPasswordsService.sendKeyByEmail(email, username); } - @PostMapping("/loginbyemailandkey") - @ApiOperation(value = "${ForgotPasswordsController.loginbyemailandkey}") + @PostMapping("/loginbyusernameandkey") + @ApiOperation(value = "${ForgotPasswordsController.loginbyusernameandkey}") @ApiResponses(value = {// @ApiResponse(code = 400, message = "Something went wrong"), // @ApiResponse(code = 422, message = "Invalid username/password supplied")}) - public String loginbyemailandkey(// - @ApiParam("Email") @RequestParam String email, // + public String loginbyusernameandkey(// + @ApiParam("Username") @RequestParam String username, // @ApiParam("Key") @RequestParam String key) { - return forgotPasswordsService.loginByEmailAndKey(email, key); + return forgotPasswordsService.loginByUsernameAndKey(username, key); } - @PostMapping("/passwordupdatebyemail") + @PostMapping("/passwordupdatebyusername") @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_INSTITUTION') or hasRole('ROLE_CLIENT')") - @ApiOperation(value = "${ForgotPasswordsController.passwordupdatebyemail}", authorizations = { @Authorization(value="apiKey") }) + @ApiOperation(value = "${ForgotPasswordsController.passwordupdatebyusername}", authorizations = { @Authorization(value="apiKey") }) @ApiResponses(value = {// @ApiResponse(code = 400, message = "Something went wrong"), // @ApiResponse(code = 403, message = "Access denied"), // @ApiResponse(code = 404, message = "The user doesn't exist"), // @ApiResponse(code = 500, message = "Expired or invalid JWT token")}) - public void passwordupdatebyemail(@ApiParam("Email") @RequestParam String email, @ApiParam("NewPassword") @RequestParam String newPassword) { - forgotPasswordsService.passwordUpdateByEmail(email, newPassword); + public void passwordupdatebyusername(@ApiParam("Username") @RequestParam String username, @ApiParam("NewPassword") @RequestParam String newPassword) { + forgotPasswordsService.passwordUpdateByUsername(username, newPassword); } @GetMapping("/findallforgotpasswordquestions") @@ -83,15 +83,15 @@ public class ForgotPasswordsController { forgotPasswordsService.saveForgotPasswordQuestionsUsersAnswers(CustomMapper.map(answer, ForgotPasswordsQuestionsUsersAnswers.class)); } - @PostMapping("/loginbyemailandanswers") - @ApiOperation(value = "${ForgotPasswordsController.loginbyemailandanswers}") + @PostMapping("/loginbyusernameandanswers") + @ApiOperation(value = "${ForgotPasswordsController.loginbyusernameandanswers}") @ApiResponses(value = {// @ApiResponse(code = 400, message = "Something went wrong"), // @ApiResponse(code = 404, message = "The user or answer don't exist"), // @ApiResponse(code = 422, message = "Invalid answers supplied to login. Must have at least 2 correct ones.")}) - public String loginbyemailandanswers(// - @ApiParam("Email") @RequestParam String email, // + public String loginbyusernameandanswers(// + @ApiParam("Username") @RequestParam String username, // @ApiParam("Answers") @RequestBody List answers) { - return forgotPasswordsService.loginByEmailAndAnswers(email, CustomMapper.mapAll(answers, ForgotPasswordsQuestionsUsersAnswers.class)); + return forgotPasswordsService.loginByUsernameAndAnswers(username, CustomMapper.mapAll(answers, ForgotPasswordsQuestionsUsersAnswers.class)); } } diff --git a/src/main/java/org/waterproofingdata/wpdauth/controller/UsersController.java b/src/main/java/org/waterproofingdata/wpdauth/controller/UsersController.java index ac6ff0f..847e454 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/controller/UsersController.java +++ b/src/main/java/org/waterproofingdata/wpdauth/controller/UsersController.java @@ -31,6 +31,15 @@ public class UsersController { @Autowired private UsersService userService; +/* + @ApiParam( + name = "firstName", + type = "String", + value = "First Name of the user", + example = "Vatsal", + required = true) + @RequestParam String firstName) + */ @PostMapping("/login") @ApiOperation(value = "${UserController.login}") @ApiResponses(value = {// @@ -76,7 +85,7 @@ public class UsersController { public UsersResponseDTO search(@ApiParam("Username") @PathVariable String username) { UsersResponseDTO urDTO = CustomMapper.map(userService.search(username), UsersResponseDTO.class); urDTO.setEduCemadenOrganization(userService.findEduCemadenOrganizationById(urDTO.getId())); - urDTO.setRolesProviderActivationKeys(userService.findRolesproviderActivationKeysById(urDTO.getId())); + urDTO.setProviderActivationKey(userService.findProviderActivationKeyById(urDTO.getId())); return urDTO; } @@ -90,7 +99,7 @@ public class UsersController { public UsersResponseDTO whoami(HttpServletRequest req) { UsersResponseDTO urDTO = CustomMapper.map(userService.whoami(req), UsersResponseDTO.class); urDTO.setEduCemadenOrganization(userService.findEduCemadenOrganizationById(urDTO.getId())); - urDTO.setRolesProviderActivationKeys(userService.findRolesproviderActivationKeysById(urDTO.getId())); + urDTO.setProviderActivationKey(userService.findProviderActivationKeyById(urDTO.getId())); return urDTO; } diff --git a/src/main/java/org/waterproofingdata/wpdauth/dto/UsersRequestDTO.java b/src/main/java/org/waterproofingdata/wpdauth/dto/UsersRequestDTO.java index 696fd43..251f0d8 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/dto/UsersRequestDTO.java +++ b/src/main/java/org/waterproofingdata/wpdauth/dto/UsersRequestDTO.java @@ -1,5 +1,10 @@ package org.waterproofingdata.wpdauth.dto; +import java.sql.Date; +import java.util.List; + +import org.waterproofingdata.wpdauth.model.Roles; + import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; @@ -7,9 +12,135 @@ import lombok.Setter; @Getter @Setter public class UsersRequestDTO { - @ApiModelProperty(position = 0) + @ApiModelProperty( + position = 0, + name = "username", + dataType = "String", + value = "username of the user.", + example = "This is an unique field, and consumers should be aware of it. By convention, WP6 should send the user phone number (i.e. (99)99999-9999).", + required = true + ) private String username; + + @ApiModelProperty( + position = 1, + name = "nickname", + dataType = "String", + value = "nickname of the user.", + example = "i.e. beth2021. This is an unique field, and consumers should be aware of it.", + required = true + ) + private String nickname; - @ApiModelProperty(position = 1) + @ApiModelProperty( + position = 2, + name = "password", + dataType = "String", + value = "password of the user.", + example = "i.e. P@s5w0rD.", + required = true + ) private String password; + + @ApiModelProperty( + position = 3, + name = "dateofborn", + dataType = "String", + value = "Date of Born of the user.", + example = "i.e. 01/12/1978. Format should be dd/MM/yyyy.", + required = false + ) + private Date dateofborn; + + @ApiModelProperty( + position = 4, + name = "gender", + dataType = "String", + value = "Gender of the user.", + example = "i.e. M. 'M' stands for Male, 'F' Female, 'N' Not Informed", + allowableValues = "{@code M, F, N}", + required = false + ) + private String gender; + + @ApiModelProperty( + position = 5, + name = "state", + dataType = "String", + value = "state of the user.", + example = "i.e. SP. State should be 2 characteres (UF)", + required = true + ) + private String state; + + @ApiModelProperty( + position = 6, + name = "city", + dataType = "String", + value = "city of the user.", + example = "i.e. 'Governador Valadares'.", + required = true + ) + private String city; + + @ApiModelProperty( + position = 7, + name = "institutiontype", + dataType = "String", + value = "institution type of the user.", + example = "i.e. 'E'. E stands for 'School', D 'Civil Defense', N 'No governamental', O 'others'", + allowableValues = "{@code E, D, N, O}", + required = false + ) + private String institutiontype; + + @ApiModelProperty( + position = 8, + name = "institution", + dataType = "String", + value = "institution of the user.", + example = "i.e. 'Colegio Imaginario'.", + required = false + ) + private String institution; + + @ApiModelProperty( + position = 9, + name = "securityquestion", + dataType = "String", + value = "security question of the user.", + example = "i.e. 'What is my favorite color?'.", + required = false + ) + private String securityquestion; + + @ApiModelProperty( + position = 10, + name = "securityanswer", + dataType = "String", + value = "security answer of the user.", + example = "i.e. 'Blue'.", + required = false + ) + private String securityanswer; + + @ApiModelProperty( + position = 11, + name = "termsofusage", + dataType = "String", + value = "terms of usage of the user.", + example = "i.e. true.", + required = true + ) + private boolean termsofusage; + + @ApiModelProperty( + position = 12, + name = "roles", + dataType = "String", + value = "roles of the user.", + example = "i.e. ROLE_CLIENT.", + required = true + ) + private List roles; } diff --git a/src/main/java/org/waterproofingdata/wpdauth/dto/UsersResponseDTO.java b/src/main/java/org/waterproofingdata/wpdauth/dto/UsersResponseDTO.java index 453b840..3f020cd 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/dto/UsersResponseDTO.java +++ b/src/main/java/org/waterproofingdata/wpdauth/dto/UsersResponseDTO.java @@ -1,30 +1,177 @@ package org.waterproofingdata.wpdauth.dto; -import java.util.List; - import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; +import java.sql.Date; + import org.waterproofingdata.wpdauth.model.EduCemadenOrganizations; import org.waterproofingdata.wpdauth.model.Roles; -import org.waterproofingdata.wpdauth.model.UsersRolesproviderActivationKey; +import org.waterproofingdata.wpdauth.model.UsersProviderActivationKey; @Getter @Setter public class UsersResponseDTO { - @ApiModelProperty(position = 0) + @ApiModelProperty( + position = 0, + name = "id", + dataType = "Integer", + value = "id of the user.", + example = "This is a SERIAL and Primary Key field.", + required = true + ) private Integer id; - @ApiModelProperty(position = 1) + @ApiModelProperty( + position = 1, + name = "username", + dataType = "String", + value = "username of the user.", + example = "This is an unique field, and consumers should be aware of it. By convention, WP6 should send the user phone number (i.e. (99)99999-9999).", + required = true + ) private String username; - @ApiModelProperty(position = 2) - List roles; + @ApiModelProperty( + position = 2, + name = "nickname", + dataType = "String", + value = "nickname of the user.", + example = "i.e. beth2021. This is an unique field, and consumers should be aware of it.", + required = true + ) + private String nickname; + + @ApiModelProperty( + position = 3, + name = "dateofborn", + dataType = "String", + value = "Date of Born of the user.", + example = "i.e. 01/12/1978. Format should be dd/MM/yyyy.", + required = false + ) + private Date dateofborn; + + @ApiModelProperty( + position = 4, + name = "gender", + dataType = "String", + value = "Gender of the user.", + example = "i.e. M. 'M' stands for Male, 'F' Female, 'N' Not Informed", + allowableValues = "{@code M, F, N}", + required = false + ) + private String gender; + + @ApiModelProperty( + position = 5, + name = "state", + dataType = "String", + value = "state of the user.", + example = "i.e. SP. State should be 2 characteres (UF)", + required = true + ) + private String state; + + @ApiModelProperty( + position = 6, + name = "city", + dataType = "String", + value = "city of the user.", + example = "i.e. 'Governador Valadares'.", + required = true + ) + private String city; + + @ApiModelProperty( + position = 7, + name = "institutiontype", + dataType = "String", + value = "institution type of the user.", + example = "i.e. 'E'. E stands for 'School', D 'Civil Defense', N 'No governamental', O 'others'", + allowableValues = "{@code E, D, N, O}", + required = false + ) + private String institutiontype; + + @ApiModelProperty( + position = 8, + name = "institution", + dataType = "String", + value = "institution of the user.", + example = "i.e. 'Colegio Imaginario'.", + required = false + ) + private String institution; + + @ApiModelProperty( + position = 9, + name = "securityquestion", + dataType = "String", + value = "security question of the user.", + example = "i.e. 'What is my favorite color?'.", + required = false + ) + private String securityquestion; + + @ApiModelProperty( + position = 10, + name = "securityanswer", + dataType = "String", + value = "security answer of the user.", + example = "i.e. 'Blue'.", + required = false + ) + private String securityanswer; + + @ApiModelProperty( + position = 11, + name = "termsofusage", + dataType = "String", + value = "terms of usage of the user.", + example = "i.e. true.", + required = true + ) + private boolean termsofusage; + + @ApiModelProperty( + position = 12, + name = "active", + dataType = "Integer", + value = "whether user is active or not.", + example = "i.e. true.", + required = true + ) + private Integer active; + + + @ApiModelProperty( + position = 13, + name = "institutiontype", + dataType = "String", + value = "institution type of the user.", + example = "i.e. 'ROLE_ADMIN' means system administrator, 'ROLE_INSTITUTION' means institution administrator, 'ROLE_CLIENT' means regular users", + allowableValues = "{@code ROLE_ADMIN, ROLE_INSTITUTION, ROLE_CLIENT}", + required = false + ) + Roles role; - @ApiModelProperty(position = 3) + @ApiModelProperty( + position = 14, + name = "eduCemadenOrganization", + dataType = "EduCemadenOrganizations", + value = "which Educational Cemaden Organization the user belongs.", + required = false + ) EduCemadenOrganizations eduCemadenOrganization; - @ApiModelProperty(position = 4) - List rolesProviderActivationKeys; + @ApiModelProperty( + position = 15, + name = "providerActivationKey", + dataType = "UsersProviderActivationKey", + value = "If this user can provide an activation key for other users ('ROLE_INSTITUTION'), this field will store the values.", + required = false + ) + UsersProviderActivationKey providerActivationKey; } diff --git a/src/main/java/org/waterproofingdata/wpdauth/model/EduCemadenOrganizations.java b/src/main/java/org/waterproofingdata/wpdauth/model/EduCemadenOrganizations.java index 3312631..cf52a6d 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/model/EduCemadenOrganizations.java +++ b/src/main/java/org/waterproofingdata/wpdauth/model/EduCemadenOrganizations.java @@ -47,4 +47,7 @@ public class EduCemadenOrganizations { private String responsible; private String activationkey; + + @Column(nullable = false) + private String email; } diff --git a/src/main/java/org/waterproofingdata/wpdauth/model/ForgotPasswordsKeys.java b/src/main/java/org/waterproofingdata/wpdauth/model/ForgotPasswordsKeys.java index e08ffd3..334a004 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/model/ForgotPasswordsKeys.java +++ b/src/main/java/org/waterproofingdata/wpdauth/model/ForgotPasswordsKeys.java @@ -20,7 +20,7 @@ public class ForgotPasswordsKeys { private Integer id; @Column(nullable = false) - private String email; + private String username; @Column(nullable = false) private String key; diff --git a/src/main/java/org/waterproofingdata/wpdauth/model/Users.java b/src/main/java/org/waterproofingdata/wpdauth/model/Users.java index 3275976..55b09b3 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/model/Users.java +++ b/src/main/java/org/waterproofingdata/wpdauth/model/Users.java @@ -1,5 +1,6 @@ package org.waterproofingdata.wpdauth.model; +import java.sql.Date; import java.util.List; import javax.persistence.Entity; @@ -31,20 +32,48 @@ public class Users { @Column(unique = true, nullable = false) private String username; + @Size(min = 4, max = 255, message = "Minimum name length: 4 characters") + @Column(unique = true, nullable = false) + private String nickname; + @Size(min = 8, message = "Minimum password length: 8 characters") @Column(nullable = false) private String password; + + @Size(min = 10, max = 10, message = "Date of Born should be dd/MM/yyyy") + @Column(nullable = true) + private Date dateofborn; - @Column(unique = true, nullable = false) - private String email; - - @Size(min = 4, max = 255, message = "Minimum firstname length: 4 characters") + @Size(min = 1, max = 1, message = "Gender should be M (Male), F (Female), N (Not Informed)") @Column(nullable = true) - private String firstname; + private String gender; + + @Size(min = 2, max = 2, message = "State should be 2 characteres (UF)") + @Column(nullable = false) + private String state; + + @Size(min = 4, max = 255, message = "Minimum name length: 4 characters") + @Column(nullable = false) + private String city; - @Size(min = 4, max = 255, message = "Minimum surname length: 4 characters") + @Size(min = 1, max = 1, message = "Institution type should be E (School), D (Civil Defense), N (No governamental), O (others)") @Column(nullable = true) - private String surname; + private String institutiontype; + + @Size(min = 4, max = 255, message = "Minimum name length: 4 characters") + @Column(nullable = true) + private String institution; + + @Size(min = 4, max = 255, message = "Minimum name length: 4 characters") + @Column(nullable = true) + private String securityquestion; + + @Size(min = 4, max = 255, message = "Minimum name length: 4 characters") + @Column(nullable = true) + private String securityanswer; + + @Column(nullable = false) + private Boolean termsofusage; @Column(nullable = true) private String avatar; diff --git a/src/main/java/org/waterproofingdata/wpdauth/model/UsersEducemadenOrganizations.java b/src/main/java/org/waterproofingdata/wpdauth/model/UsersEducemadenOrganizations.java new file mode 100644 index 0000000..28447b1 --- /dev/null +++ b/src/main/java/org/waterproofingdata/wpdauth/model/UsersEducemadenOrganizations.java @@ -0,0 +1,33 @@ +package org.waterproofingdata.wpdauth.model; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Entity(name = "users_educemaden_organizations") +@Getter +@Setter +@NoArgsConstructor +public class UsersEducemadenOrganizations { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(nullable = false, name="users_id") + private Integer usersid; + + @Column(nullable = false, name="educemaden_organizations_id") + private Integer educemadenorganizationsid; + + @Column(nullable = false) + private String activationkey; + + @Column(nullable = false) + private Integer active; +} diff --git a/src/main/java/org/waterproofingdata/wpdauth/model/UsersRolesproviderActivationKey.java b/src/main/java/org/waterproofingdata/wpdauth/model/UsersProviderActivationKey.java similarity index 76% rename from src/main/java/org/waterproofingdata/wpdauth/model/UsersRolesproviderActivationKey.java rename to src/main/java/org/waterproofingdata/wpdauth/model/UsersProviderActivationKey.java index eedabbe..4019c63 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/model/UsersRolesproviderActivationKey.java +++ b/src/main/java/org/waterproofingdata/wpdauth/model/UsersProviderActivationKey.java @@ -11,11 +11,11 @@ import lombok.NoArgsConstructor; import lombok.Setter; -@Entity(name = "users_rolesprovider_activationkey") +@Entity(name = "users_provider_activationkey") @Getter @Setter @NoArgsConstructor -public class UsersRolesproviderActivationKey { +public class UsersProviderActivationKey { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @@ -23,9 +23,6 @@ public class UsersRolesproviderActivationKey { @Column(nullable = false, name="users_id") private Integer usersid; - @Column(nullable = false, name="roles_id") - private Integer rolesid; - @Column(nullable = false) private String activationkey; } diff --git a/src/main/java/org/waterproofingdata/wpdauth/repository/EduCemadenOrganizationsRepository.java b/src/main/java/org/waterproofingdata/wpdauth/repository/EduCemadenOrganizationsRepository.java index be6c1fd..8190c58 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/repository/EduCemadenOrganizationsRepository.java +++ b/src/main/java/org/waterproofingdata/wpdauth/repository/EduCemadenOrganizationsRepository.java @@ -10,6 +10,8 @@ import org.waterproofingdata.wpdauth.model.EduCemadenOrganizations; public interface EduCemadenOrganizationsRepository extends JpaRepository { EduCemadenOrganizations findByPhone(String phone); + EduCemadenOrganizations findByEmail(String email); + @Query(value = "SELECT e.*, ueo.activationkey FROM auth.educemaden_organizations e INNER JOIN auth.users_educemaden_organizations ueo ON e.id = ueo.educemaden_organizations_id WHERE ueo.users_id = ?1", nativeQuery = true) EduCemadenOrganizations findByUserId(Integer userid); diff --git a/src/main/java/org/waterproofingdata/wpdauth/repository/ForgotPasswordsKeysRepository.java b/src/main/java/org/waterproofingdata/wpdauth/repository/ForgotPasswordsKeysRepository.java index 63175ae..d183c27 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/repository/ForgotPasswordsKeysRepository.java +++ b/src/main/java/org/waterproofingdata/wpdauth/repository/ForgotPasswordsKeysRepository.java @@ -5,6 +5,6 @@ import org.springframework.data.jpa.repository.Query; import org.waterproofingdata.wpdauth.model.ForgotPasswordsKeys; public interface ForgotPasswordsKeysRepository extends JpaRepository { - @Query(value = "SELECT f.* FROM auth.forgotpassword_keys f WHERE f.email = ?1 AND f.key = ?2 AND f.created_at >= current_date::timestamp AND f.created_at < current_date::timestamp + interval '1 day' ORDER BY f.id DESC LIMIT 1", nativeQuery = true) - ForgotPasswordsKeys findTodayRecordByEmailANDKey(String email, String key); + @Query(value = "SELECT f.* FROM auth.forgotpassword_keys f WHERE f.username = ?1 AND f.key = ?2 AND f.created_at >= current_date::timestamp AND f.created_at < current_date::timestamp + interval '1 day' ORDER BY f.id DESC LIMIT 1", nativeQuery = true) + ForgotPasswordsKeys findTodayRecordByUsernameANDKey(String username, String key); } diff --git a/src/main/java/org/waterproofingdata/wpdauth/repository/UsersEducemadenOrganizationsRepository.java b/src/main/java/org/waterproofingdata/wpdauth/repository/UsersEducemadenOrganizationsRepository.java new file mode 100644 index 0000000..d43a9e4 --- /dev/null +++ b/src/main/java/org/waterproofingdata/wpdauth/repository/UsersEducemadenOrganizationsRepository.java @@ -0,0 +1,13 @@ +package org.waterproofingdata.wpdauth.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.waterproofingdata.wpdauth.model.UsersEducemadenOrganizations; + +public interface UsersEducemadenOrganizationsRepository extends JpaRepository { + + UsersEducemadenOrganizations findByActivationkey(String activationkey); + + @Query(value = "SELECT * FROM auth.users_educemaden_organizations WHERE users_id = ?1 AND active = 1", nativeQuery = true) + UsersEducemadenOrganizations findByUserIdAndActivated(Integer userid); +} diff --git a/src/main/java/org/waterproofingdata/wpdauth/repository/UsersProviderActivationKeyRepository.java b/src/main/java/org/waterproofingdata/wpdauth/repository/UsersProviderActivationKeyRepository.java new file mode 100644 index 0000000..516dff3 --- /dev/null +++ b/src/main/java/org/waterproofingdata/wpdauth/repository/UsersProviderActivationKeyRepository.java @@ -0,0 +1,10 @@ +package org.waterproofingdata.wpdauth.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.waterproofingdata.wpdauth.model.UsersProviderActivationKey; + +public interface UsersProviderActivationKeyRepository extends JpaRepository { + UsersProviderActivationKey findByActivationkey(String activationkey); + + UsersProviderActivationKey findByUsersid(Integer usersid); +} diff --git a/src/main/java/org/waterproofingdata/wpdauth/repository/UsersRepository.java b/src/main/java/org/waterproofingdata/wpdauth/repository/UsersRepository.java index 49df281..e26ba98 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/repository/UsersRepository.java +++ b/src/main/java/org/waterproofingdata/wpdauth/repository/UsersRepository.java @@ -12,10 +12,11 @@ public interface UsersRepository extends JpaRepository { Users findByUsername(String username); - boolean existsByEmail(String email); + boolean existsByNickname(String nickname); + + @Query(value = "SELECT nickname || rank() OVER (PARTITION BY nickname) nickname_unique FROM auth.users WHERE nickname = ?1", nativeQuery = true) + String findSuggestedNickname(String nickname); - Users findByEmail(String email); - @Transactional @Query(value = "UPDATE auth.users SET active = ?2 WHERE username = ?1", nativeQuery = true) void activateByUsername(String username, Integer active); diff --git a/src/main/java/org/waterproofingdata/wpdauth/repository/UsersRolesproviderActivationKeyRepository.java b/src/main/java/org/waterproofingdata/wpdauth/repository/UsersRolesproviderActivationKeyRepository.java deleted file mode 100644 index 9fad1b4..0000000 --- a/src/main/java/org/waterproofingdata/wpdauth/repository/UsersRolesproviderActivationKeyRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.waterproofingdata.wpdauth.repository; - -import java.util.List; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.waterproofingdata.wpdauth.model.UsersRolesproviderActivationKey; - -public interface UsersRolesproviderActivationKeyRepository extends JpaRepository { - List findByUsersid(Integer usersid); -} diff --git a/src/main/java/org/waterproofingdata/wpdauth/service/ForgotPasswordsService.java b/src/main/java/org/waterproofingdata/wpdauth/service/ForgotPasswordsService.java index 0e0d19a..a3f0bdd 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/service/ForgotPasswordsService.java +++ b/src/main/java/org/waterproofingdata/wpdauth/service/ForgotPasswordsService.java @@ -13,6 +13,7 @@ import org.waterproofingdata.wpdauth.exception.CustomException; import org.waterproofingdata.wpdauth.model.ForgotPasswordsKeys; import org.waterproofingdata.wpdauth.model.ForgotPasswordsQuestions; import org.waterproofingdata.wpdauth.model.ForgotPasswordsQuestionsUsersAnswers; +import org.waterproofingdata.wpdauth.model.Roles; import org.waterproofingdata.wpdauth.model.Users; import org.waterproofingdata.wpdauth.repository.ForgotPasswordsKeysRepository; import org.waterproofingdata.wpdauth.repository.ForgotPasswordsQuestionsRepository; @@ -43,10 +44,10 @@ public class ForgotPasswordsService { @Autowired private JwtTokenProvider jwtTokenProvider; - public void sendKeyByEmail(String email) { - Users user = usersRepository.findByEmail(email); + public void sendKeyByEmail(String email, String username) { + Users user = usersRepository.findByUsername(username); if (user == null) { - throw new CustomException("The user email doesn't exist", HttpStatus.NOT_FOUND); + throw new CustomException("The username doesn't exist", HttpStatus.NOT_FOUND); } Random rand = new Random(); @@ -54,7 +55,7 @@ public class ForgotPasswordsService { //System.out.printf("%04d%n", rand.nextInt(10000)); ForgotPasswordsKeys entity = new ForgotPasswordsKeys(); - entity.setEmail(email); + entity.setUsername(username); entity.setKey(key); forgotPasswordsKeysRepository.save(entity); @@ -66,25 +67,25 @@ public class ForgotPasswordsService { mailSender.send(message); } - public String loginByEmailAndKey(String email, String key) { - ForgotPasswordsKeys entity = forgotPasswordsKeysRepository.findTodayRecordByEmailANDKey(email, key); + public String loginByUsernameAndKey(String username, String key) { + ForgotPasswordsKeys entity = forgotPasswordsKeysRepository.findTodayRecordByUsernameANDKey(username, key); if (entity == null) { - throw new CustomException("The email and forgot key don't exist", HttpStatus.NOT_FOUND); + throw new CustomException("The username and forgot key don't exist", HttpStatus.NOT_FOUND); } - Users user = usersRepository.findByEmail(email); + Users user = usersRepository.findByUsername(username); if (user == null) { - throw new CustomException("The user email doesn't exist", HttpStatus.NOT_FOUND); - } - - String username = user.getUsername(); - return jwtTokenProvider.createToken(username, usersRepository.findByUsername(username).getRoles()); + throw new CustomException("The username doesn't exist", HttpStatus.NOT_FOUND); + } + + List roles = user.getRoles(); + return jwtTokenProvider.createToken(username, roles); } - public void passwordUpdateByEmail(String email, String newPassword) { - Users user = usersRepository.findByEmail(email); + public void passwordUpdateByUsername(String username, String newPassword) { + Users user = usersRepository.findByUsername(username); if (user == null) { - throw new CustomException("The user email doesn't exist", HttpStatus.NOT_FOUND); + throw new CustomException("The username doesn't exist", HttpStatus.NOT_FOUND); } user.setPassword(passwordEncoder.encode(newPassword)); usersRepository.save(user); @@ -106,11 +107,12 @@ public class ForgotPasswordsService { forgotPasswordsQuestionsUsersAnswersRepository.save(forgotPasswordQuestionsUsersAnswer); } - public String loginByEmailAndAnswers(String email, List answers) { - Users user = usersRepository.findByEmail(email); + public String loginByUsernameAndAnswers(String username, List answers) { + Users user = usersRepository.findByUsername(username); if (user == null) { - throw new CustomException("The user email doesn't exist", HttpStatus.NOT_FOUND); + throw new CustomException("The username doesn't exist", HttpStatus.NOT_FOUND); } + List roles = user.getRoles(); int correctAnswers = 0; for (ForgotPasswordsQuestionsUsersAnswers answer : answers) { @@ -127,7 +129,6 @@ public class ForgotPasswordsService { throw new CustomException("Invalid answers supplied to login. Must have at least 2 correct ones.", HttpStatus.UNPROCESSABLE_ENTITY); } - String username = user.getUsername(); - return jwtTokenProvider.createToken(username, usersRepository.findByUsername(username).getRoles()); + return jwtTokenProvider.createToken(username, roles); } } diff --git a/src/main/java/org/waterproofingdata/wpdauth/service/UsersService.java b/src/main/java/org/waterproofingdata/wpdauth/service/UsersService.java index 7020838..c3f7ebc 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/service/UsersService.java +++ b/src/main/java/org/waterproofingdata/wpdauth/service/UsersService.java @@ -6,6 +6,8 @@ import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.AuthenticationException; @@ -15,10 +17,13 @@ import org.springframework.stereotype.Service; import org.waterproofingdata.wpdauth.exception.CustomException; import org.waterproofingdata.wpdauth.model.EduCemadenOrganizations; import org.waterproofingdata.wpdauth.model.Users; -import org.waterproofingdata.wpdauth.model.UsersRolesproviderActivationKey; +import org.waterproofingdata.wpdauth.model.Roles; +import org.waterproofingdata.wpdauth.model.UsersEducemadenOrganizations; +import org.waterproofingdata.wpdauth.model.UsersProviderActivationKey; import org.waterproofingdata.wpdauth.repository.EduCemadenOrganizationsRepository; +import org.waterproofingdata.wpdauth.repository.UsersEducemadenOrganizationsRepository; import org.waterproofingdata.wpdauth.repository.UsersRepository; -import org.waterproofingdata.wpdauth.repository.UsersRolesproviderActivationKeyRepository; +import org.waterproofingdata.wpdauth.repository.UsersProviderActivationKeyRepository; import org.waterproofingdata.wpdauth.security.JwtTokenProvider; @Service @@ -30,7 +35,10 @@ public class UsersService { private EduCemadenOrganizationsRepository eduCemadenOrganizationsRepository; @Autowired - private UsersRolesproviderActivationKeyRepository usersRolesproviderActivationKeyRepository; + private UsersEducemadenOrganizationsRepository usersEducemadenOrganizationsRepository; + + @Autowired + private UsersProviderActivationKeyRepository usersProviderActivationKeyRepository; @Autowired private PasswordEncoder passwordEncoder; @@ -41,9 +49,20 @@ public class UsersService { @Autowired private AuthenticationManager authenticationManager; + @Autowired + private JavaMailSender mailSender; + public boolean existsByUsername(String username) { return usersRepository.existsByUsername(username); } + + public Users search(String username) { + Users user = usersRepository.findByUsername(username); + if (user == null) { + throw new CustomException("The user doesn't exist", HttpStatus.NOT_FOUND); + } + return user; + } public String login(String username, String password) { try { @@ -56,28 +75,122 @@ public class UsersService { } public String signup(Users user) { - if (!existsByUsername(user.getUsername())) { - user.setPassword(passwordEncoder.encode(user.getPassword())); - user.setActive(0); - usersRepository.save(user); - return jwtTokenProvider.createToken(user.getUsername(), user.getRoles()); - } - else { - throw new CustomException("Username is already in use", HttpStatus.UNPROCESSABLE_ENTITY); - } - } + if (user.getUsername().length() == 0) { + throw new CustomException("Username must be provided", HttpStatus.UNPROCESSABLE_ENTITY); + } + + if (!existsByUsername(user.getUsername())) { + if (user.getNickname().length() == 0) { + throw new CustomException("Nickname must be provided", HttpStatus.UNPROCESSABLE_ENTITY); + } + else if (usersRepository.existsByNickname(user.getNickname())) { + String nickname_unique = usersRepository.findSuggestedNickname(user.getNickname()); + throw new CustomException(String.format("Nickname already exists. Would you like to use '%s'?", nickname_unique), HttpStatus.UNPROCESSABLE_ENTITY); + } + if (user.getPassword().length() == 0) { + throw new CustomException("Password must be provided", HttpStatus.UNPROCESSABLE_ENTITY); + } + if (user.getState().length() == 0) { + throw new CustomException("State must be provided", HttpStatus.UNPROCESSABLE_ENTITY); + } + if (user.getCity().length() == 0) { + throw new CustomException("City must be provided", HttpStatus.UNPROCESSABLE_ENTITY); + } + if (user.getTermsofusage() != true) { + throw new CustomException("Terms of usage must be accepted", HttpStatus.UNPROCESSABLE_ENTITY); + } + if (user.getRoles().size() != 1) { + throw new CustomException("Only one user.role must be provided", HttpStatus.UNPROCESSABLE_ENTITY); + } - public void activate(String username, String activationkey) { - String uuid = UUID.randomUUID().toString(); - //userRepository.activateByUsername(username); + user.setPassword(passwordEncoder.encode(user.getPassword())); + user.setActive(0); + usersRepository.save(user); + return jwtTokenProvider.createToken(user.getUsername(), user.getRoles()); + } + else { + throw new CustomException("Username is already in use", HttpStatus.UNPROCESSABLE_ENTITY); + } } - public Users search(String username) { - Users user = usersRepository.findByUsername(username); - if (user == null) { - throw new CustomException("The user doesn't exist", HttpStatus.NOT_FOUND); - } - return user; + public void sendAdminKeyByEmailCemaden(String emailcemaden, String username) { + Users user = search(username); + EduCemadenOrganizations eduCemadenOrganization = eduCemadenOrganizationsRepository.findByEmail(emailcemaden); + if (eduCemadenOrganization == null) { + throw new CustomException("Email Cemaden not found.", HttpStatus.NOT_FOUND); + } + + String uuid = UUID.randomUUID().toString(); + SimpleMailMessage message = new SimpleMailMessage(); + message.setFrom("noreply@wp6.com"); + message.setTo(emailcemaden); + message.setSubject("Envio de código para alteração de senha"); + message.setText(String.format("Olá! O usuário '%s' solicitou a ativação dele para ADMIN dessa Instituição, por isso você está recebendo esse código: '%s'. Se estiver correto, informe esse código ao solicitante e peça para entrar no aplicativo para prosseguir.", user.getNickname(), uuid)); + mailSender.send(message); + + UsersEducemadenOrganizations userEducemadenOrg = new UsersEducemadenOrganizations(); + userEducemadenOrg.setUsersid(user.getId()); + userEducemadenOrg.setEducemadenorganizationsid(eduCemadenOrganization.getId()); + userEducemadenOrg.setActivationkey(uuid); + userEducemadenOrg.setActive(0); + usersEducemadenOrganizationsRepository.save(userEducemadenOrg); + } + + public void activate(String username, String activationkey) { + Users user = search(username); + if (user.getActive() != 0) { + throw new CustomException("User should be inactive to be activated", HttpStatus.UNPROCESSABLE_ENTITY); + } + if (user.getRoles().size() != 1) { + throw new CustomException("User must have only one user.role", HttpStatus.UNPROCESSABLE_ENTITY); + } + + if (user.getRoles().get(0) == Roles.ROLE_INSTITUTION) { + UsersEducemadenOrganizations userEducemadenOrganization = usersEducemadenOrganizationsRepository.findByActivationkey(activationkey); + if (userEducemadenOrganization == null) { + throw new CustomException("ROLE_INSTITUTION Activationkey not found.", HttpStatus.NOT_FOUND); + } + else if (user.getId() != userEducemadenOrganization.getUsersid()) { + throw new CustomException("Activationkey does not belong to the informed user", HttpStatus.UNPROCESSABLE_ENTITY); + } + + userEducemadenOrganization.setActive(1); + usersEducemadenOrganizationsRepository.save(userEducemadenOrganization); + + usersRepository.activateByUsername(username, 1); + + String uuid = UUID.randomUUID().toString(); + UsersProviderActivationKey userRolesProviderActivationKey = new UsersProviderActivationKey(); + userRolesProviderActivationKey.setUsersid(user.getId()); + userRolesProviderActivationKey.setActivationkey(uuid); + usersProviderActivationKeyRepository.save(userRolesProviderActivationKey); + } + else if (user.getRoles().get(0) == Roles.ROLE_CLIENT) { + UsersProviderActivationKey userAdmProviderActivationKey = usersProviderActivationKeyRepository.findByActivationkey(activationkey); + if (userAdmProviderActivationKey == null) { + throw new CustomException("Activationkey not found.", HttpStatus.NOT_FOUND); + } + + UsersEducemadenOrganizations userAdmEducemadenOrganization = usersEducemadenOrganizationsRepository.findByUserIdAndActivated(user.getId()); + if (userAdmEducemadenOrganization == null) { + throw new CustomException("ROLE_INSTITUTION Activationkey not found.", HttpStatus.NOT_FOUND); + } + + usersRepository.activateByUsername(username, 1); + + UsersEducemadenOrganizations userEducemadenOrg = new UsersEducemadenOrganizations(); + userEducemadenOrg.setUsersid(user.getId()); + userEducemadenOrg.setEducemadenorganizationsid(userAdmEducemadenOrganization.getEducemadenorganizationsid()); + userEducemadenOrg.setActivationkey(activationkey); + userEducemadenOrg.setActive(1); + usersEducemadenOrganizationsRepository.save(userEducemadenOrg); + } + else if (user.getRoles().get(0) == Roles.ROLE_ADMIN) { + throw new CustomException("Admin users should be activated through database.", HttpStatus.UNPROCESSABLE_ENTITY); + } + else { + throw new CustomException("There is a problem with this User registration and it can not be activated.", HttpStatus.UNPROCESSABLE_ENTITY); + } } public Users whoami(HttpServletRequest req) { @@ -88,8 +201,8 @@ public class UsersService { return eduCemadenOrganizationsRepository.findByUserId(userid); } - public List findRolesproviderActivationKeysById(Integer usersid) { - return usersRolesproviderActivationKeyRepository.findByUsersid(usersid); + public UsersProviderActivationKey findProviderActivationKeyById(Integer usersid) { + return usersProviderActivationKeyRepository.findByUsersid(usersid); } public String refresh(String username) { diff --git a/src/test/java/org/waterproofingdata/wpdauth/integrationtest/UsersServiceIntegrationTest.java b/src/test/java/org/waterproofingdata/wpdauth/integrationtest/UsersServiceIntegrationTest.java index f4e652b..fc6c976 100644 --- a/src/test/java/org/waterproofingdata/wpdauth/integrationtest/UsersServiceIntegrationTest.java +++ b/src/test/java/org/waterproofingdata/wpdauth/integrationtest/UsersServiceIntegrationTest.java @@ -47,10 +47,12 @@ public class UsersServiceIntegrationTest { public void testRandomUserSignup() { Users u = new Users(); String uName = String.format("user%s", UUID.randomUUID().toString()); - String uEmail = String.format("%s@email.com", uName); u.setUsername(uName); + u.setNickname(uName); u.setPassword(UUID.randomUUID().toString()); - u.setEmail(uEmail); + u.setState("SP"); + u.setCity("São Paulo"); + u.setTermsofusage(true); u.setRoles(new ArrayList(Arrays.asList(Roles.ROLE_CLIENT))); String uJson = new Gson().toJson(u);