Skip to content

Commit aa48261

Browse files
committed
Sign up form
1 parent 94ac502 commit aa48261

File tree

15 files changed

+412
-53
lines changed

15 files changed

+412
-53
lines changed

src/main/java/com/github/throyer/common/springboot/configurations/SpringSecurityConfiguration.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ protected void configure(HttpSecurity http) throws Exception {
128128
.permitAll()
129129
.antMatchers(GET, "/app")
130130
.permitAll()
131+
.antMatchers(GET, "/app/register")
132+
.permitAll()
133+
.antMatchers(POST, "/app/register")
134+
.permitAll()
131135
.anyRequest()
132136
.authenticated()
133137
.and()

src/main/java/com/github/throyer/common/springboot/controllers/api/UsersController.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import com.github.throyer.common.springboot.domain.services.user.FindUserService;
1111
import com.github.throyer.common.springboot.domain.services.user.RemoveUserService;
1212
import com.github.throyer.common.springboot.domain.services.user.UpdateUserService;
13-
import com.github.throyer.common.springboot.domain.services.user.dto.CreateUser;
13+
import com.github.throyer.common.springboot.domain.services.user.dto.CreateUserApi;
1414
import com.github.throyer.common.springboot.domain.services.user.dto.SearchUser;
1515
import com.github.throyer.common.springboot.domain.services.user.dto.UpdateUser;
1616
import com.github.throyer.common.springboot.domain.services.user.dto.UserDetails;
@@ -63,7 +63,7 @@ public ResponseEntity<UserDetails> show(@PathVariable Long id) {
6363

6464
@PostMapping
6565
@ResponseStatus(CREATED)
66-
public ResponseEntity<UserDetails> save(@Validated @RequestBody CreateUser body) {
66+
public ResponseEntity<UserDetails> save(@Validated @RequestBody CreateUserApi body) {
6767
return createService.create(body);
6868
}
6969

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.github.throyer.common.springboot.controllers.app;
2+
3+
import com.github.throyer.common.springboot.domain.models.shared.Toast;
4+
import com.github.throyer.common.springboot.domain.models.shared.Type;
5+
import com.github.throyer.common.springboot.domain.services.user.CreateUserService;
6+
7+
import com.github.throyer.common.springboot.domain.services.user.dto.CreateUserApp;
8+
import com.github.throyer.common.springboot.utils.Toasts;
9+
import java.util.List;
10+
import javax.validation.Valid;
11+
import org.springframework.beans.factory.annotation.Autowired;
12+
import org.springframework.stereotype.Controller;
13+
import org.springframework.ui.Model;
14+
import org.springframework.validation.BindingResult;
15+
import org.springframework.web.bind.annotation.GetMapping;
16+
import org.springframework.web.bind.annotation.PostMapping;
17+
import org.springframework.web.bind.annotation.RequestMapping;
18+
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
19+
20+
@Controller
21+
@RequestMapping("/app/register")
22+
public class RegisterController {
23+
24+
@Autowired
25+
private CreateUserService service;
26+
27+
@GetMapping(produces = "text/html")
28+
public String index(Model model) {
29+
model.addAttribute("user", new CreateUserApp());
30+
return "app/register/index";
31+
}
32+
33+
@PostMapping(produces = "text/html")
34+
public String create(
35+
@Valid CreateUserApp user,
36+
BindingResult result,
37+
RedirectAttributes redirect,
38+
Model model
39+
) {
40+
return service.create(user, result, redirect, model);
41+
}
42+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.github.throyer.common.springboot.domain.models.shared;
2+
3+
import lombok.Data;
4+
5+
@Data
6+
public class Toast {
7+
8+
private String message;
9+
private String type;
10+
11+
private Toast(String message, String type) {
12+
this.message = message;
13+
this.type = type;
14+
}
15+
16+
public static Toast of(String message, Type type) {
17+
return new Toast(message, type.name);
18+
}
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.github.throyer.common.springboot.domain.models.shared;
2+
3+
public enum Type {
4+
5+
PRIMARY("bg-primary text-light"),
6+
SECONDARY("bg-secondary text-light"),
7+
SUCCESS("bg-success text-light"),
8+
INFO("bg-info text-light"),
9+
WARNING("bg-warning"),
10+
DANGER("bg-danger text-light"),
11+
LIGHT("bg-light"),
12+
DARK("bg-dark text-light");
13+
14+
public String name;
15+
16+
Type(String name) {
17+
this.name = name;
18+
}
19+
}
Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
package com.github.throyer.common.springboot.domain.services.user;
22

3-
import static com.github.throyer.common.springboot.domain.validation.EmailValidations.validateEmailUniqueness;
3+
import com.github.throyer.common.springboot.domain.models.shared.Toast;
4+
import com.github.throyer.common.springboot.domain.models.shared.Type;
45
import static com.github.throyer.common.springboot.utils.Responses.created;
56

67
import java.util.List;
78

89
import com.github.throyer.common.springboot.domain.repositories.RoleRepository;
910
import com.github.throyer.common.springboot.domain.repositories.UserRepository;
10-
import com.github.throyer.common.springboot.domain.services.user.dto.CreateUser;
11+
import com.github.throyer.common.springboot.domain.services.user.dto.CreateUserApi;
12+
import com.github.throyer.common.springboot.domain.services.user.dto.CreateUserApp;
1113
import com.github.throyer.common.springboot.domain.services.user.dto.UserDetails;
14+
import com.github.throyer.common.springboot.utils.Toasts;
1215

1316
import org.springframework.beans.factory.annotation.Autowired;
1417
import org.springframework.http.ResponseEntity;
1518
import org.springframework.stereotype.Service;
19+
import org.springframework.ui.Model;
20+
import org.springframework.validation.BindingResult;
21+
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
1622

1723
@Service
1824
public class CreateUserService {
@@ -21,23 +27,49 @@ public class CreateUserService {
2127
UserRepository userRepository;
2228

2329
@Autowired
24-
RoleRepository roles;
30+
RoleRepository roleRepository;
2531

26-
public ResponseEntity<UserDetails> create(CreateUser create) {
27-
28-
validateEmailUniqueness(create);
32+
public ResponseEntity<UserDetails> create(CreateUserApi create) {
33+
34+
create.validate();
35+
36+
var body = create.user();
2937

30-
var body = create.toUser();
38+
var role = roleRepository.findOptionalByInitials("USER")
39+
.orElseThrow();
3140

32-
body.setRoles(
33-
List.of(
34-
roles.findOptionalByInitials("USER")
35-
.orElseThrow()
36-
)
37-
);
41+
body.setRoles(List.of(role));
3842

3943
var user = userRepository.save(body);
4044

4145
return created(new UserDetails(user), "users");
4246
}
47+
48+
public String create(
49+
CreateUserApp create,
50+
BindingResult result,
51+
RedirectAttributes redirect,
52+
Model model
53+
) {
54+
create.validate(result);
55+
56+
if (result.hasErrors()) {
57+
model.addAttribute("user", create);
58+
Toasts.add(model, result);
59+
return "app/register/index";
60+
}
61+
62+
var user = create.user();
63+
64+
var role = roleRepository.findOptionalByInitials("USER")
65+
.orElseThrow();
66+
67+
user.setRoles(List.of(role));
68+
69+
userRepository.save(user);
70+
71+
Toasts.add(redirect, "Cadastro realizado com sucesso.", Type.SUCCESS);
72+
73+
return "redirect:/app/login";
74+
}
4375
}
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,48 @@
11
package com.github.throyer.common.springboot.domain.services.user.dto;
22

3+
import static com.github.throyer.common.springboot.domain.validation.EmailValidations.validateEmailUniqueness;
4+
35
import javax.validation.constraints.Email;
46
import javax.validation.constraints.NotEmpty;
5-
import javax.validation.constraints.NotNull;
67
import javax.validation.constraints.Pattern;
78

89
import com.github.throyer.common.springboot.domain.builders.UserBuilder;
910
import com.github.throyer.common.springboot.domain.models.entity.User;
1011
import com.github.throyer.common.springboot.domain.models.shared.HasEmail;
12+
import lombok.Data;
1113

12-
public class CreateUser implements HasEmail {
14+
@Data
15+
public class CreateUserApi implements HasEmail {
1316

1417
public static final String DEFAULT_PASSWORD = "mudar123";
1518
public static final String STRONG_PASSWORD = "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$ %^&*-]).{8,}$";
1619
public static final String STRONG_PASSWORD_MESSAGE = "No mínimo 8 caracteres, com no mínimo um número, um caractere especial, uma letra maiúscula e uma letra minúscula.";
1720

18-
19-
@NotNull(message = "O nome não pode ser NULL.")
2021
@NotEmpty(message = "Por favor, forneça um nome.")
2122
private String name;
2223

23-
@NotNull(message = "O e-mail não pode ser NULL.")
24+
@NotEmpty(message = "Por favor, forneça um e-mail.")
2425
@Email(message = "Por favor, forneça um e-mail valido.")
2526
private String email;
2627

2728
@NotEmpty(message = "Por favor, forneça uma senha.")
28-
@NotNull(message = "A senha não pode ser NULL.")
2929
@Pattern(regexp = STRONG_PASSWORD, message = STRONG_PASSWORD_MESSAGE)
3030
private String password = DEFAULT_PASSWORD;
3131

32-
public CreateUser() { }
33-
34-
public CreateUser(String name, String email, String password) {
32+
public CreateUserApi(String name, String email, String password) {
3533
setName(name);
3634
setEmail(email);
3735
setPassword(password);
3836
}
3937

40-
public String getName() {
41-
return name;
42-
}
43-
44-
public void setName(String name) {
45-
this.name = name;
46-
}
47-
48-
@Override
49-
public String getEmail() {
50-
return email;
38+
public void validate() {
39+
validateEmailUniqueness(this);
5140
}
52-
53-
public void setEmail(String email) {
54-
this.email = email;
55-
}
56-
57-
public String getPassword() {
58-
return password;
59-
}
60-
61-
public void setPassword(String password) {
62-
this.password = password;
63-
}
64-
65-
public User toUser() {
41+
42+
public User user() {
6643
return new UserBuilder(name)
6744
.setEmail(email)
68-
.setPassword(password)
69-
.build();
45+
.setPassword(password)
46+
.build();
7047
}
7148
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.github.throyer.common.springboot.domain.services.user.dto;
2+
3+
import static com.github.throyer.common.springboot.domain.validation.EmailValidations.validateEmailUniqueness;
4+
5+
import com.github.throyer.common.springboot.domain.builders.UserBuilder;
6+
7+
import com.github.throyer.common.springboot.domain.models.entity.User;
8+
import com.github.throyer.common.springboot.domain.models.shared.HasEmail;
9+
10+
import static com.github.throyer.common.springboot.domain.services.user.dto.CreateUserApi.STRONG_PASSWORD;
11+
import static com.github.throyer.common.springboot.domain.services.user.dto.CreateUserApi.STRONG_PASSWORD_MESSAGE;
12+
13+
import javax.validation.constraints.Email;
14+
import javax.validation.constraints.NotEmpty;
15+
import javax.validation.constraints.Pattern;
16+
17+
import lombok.Data;
18+
19+
import org.springframework.validation.BindingResult;
20+
import org.springframework.validation.ObjectError;
21+
22+
@Data
23+
public class CreateUserApp implements HasEmail {
24+
25+
private static final String CONFIRM_ERROR_MESSAGE = "Valor informado na confirmação de senha invalido.";
26+
27+
@NotEmpty(message = "Por favor, forneça um nome.")
28+
private String name;
29+
30+
@NotEmpty(message = "Por favor, forneça um e-mail.")
31+
@Email(message = "Por favor, forneça um e-mail valido.")
32+
private String email;
33+
34+
@NotEmpty(message = "Por favor, forneça uma senha.")
35+
@Pattern(regexp = STRONG_PASSWORD, message = STRONG_PASSWORD_MESSAGE)
36+
private String password;
37+
38+
@NotEmpty(message = "Por favor, confirme a senha.")
39+
private String confirmPassword;
40+
41+
public void validate(BindingResult result) {
42+
if (!getConfirmPassword().equals(getPassword())) {
43+
result.addError(new ObjectError("confirmPassowrd", CONFIRM_ERROR_MESSAGE));
44+
}
45+
46+
validateEmailUniqueness(this, result);
47+
}
48+
49+
public User user() {
50+
return new UserBuilder(name)
51+
.setEmail(email)
52+
.setPassword(password)
53+
.build();
54+
}
55+
}

src/main/java/com/github/throyer/common/springboot/domain/validation/EmailValidations.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
import org.springframework.beans.factory.annotation.Autowired;
99
import org.springframework.stereotype.Component;
10+
import org.springframework.validation.BindingResult;
11+
import org.springframework.validation.ObjectError;
1012

1113
@Component
1214
public class EmailValidations {
@@ -29,6 +31,12 @@ public static void validateEmailUniqueness(HasEmail entity) {
2931
}
3032
}
3133

34+
public static void validateEmailUniqueness(HasEmail entity, BindingResult result) {
35+
if (repository.existsByEmail(entity.getEmail())) {
36+
result.addError(new ObjectError(FIELD, MESSAGE));
37+
}
38+
}
39+
3240
public static void validateEmailUniquenessOnModify(HasEmail newEntity, HasEmail actualEntity) {
3341

3442
var newEmail = newEntity.getEmail();
@@ -42,4 +50,22 @@ public static void validateEmailUniquenessOnModify(HasEmail newEntity, HasEmail
4250
throw new EmailNotUniqueException(EMAIL_ERROR);
4351
}
4452
}
45-
}
53+
54+
public static void validateEmailUniquenessOnModify(
55+
HasEmail newEntity,
56+
HasEmail actualEntity,
57+
BindingResult result
58+
) {
59+
60+
var newEmail = newEntity.getEmail();
61+
var actualEmail = actualEntity.getEmail();
62+
63+
var changedEmail = !actualEmail.equals(newEmail);
64+
65+
var emailAlreadyUsed = repository.existsByEmail(newEmail);
66+
67+
if (changedEmail && emailAlreadyUsed) {
68+
result.addError(new ObjectError(FIELD, MESSAGE));
69+
}
70+
}
71+
}

0 commit comments

Comments
 (0)