Skip to content

Commit e2cf81d

Browse files
authored
Merge pull request #16 from APSfurizon/authentication
Implement Authentication
2 parents 2151161 + c73af76 commit e2cf81d

File tree

114 files changed

+2540
-520
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

114 files changed

+2540
-520
lines changed

application/pom.xml

+4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838
<groupId>org.springframework.boot</groupId>
3939
<artifactId>spring-boot-starter-oauth2-client</artifactId>
4040
</dependency>
41+
<dependency>
42+
<groupId>org.springframework.boot</groupId>
43+
<artifactId>spring-boot-configuration-processor</artifactId>
44+
</dependency>
4145
<dependency>
4246
<groupId>io.micrometer</groupId>
4347
<artifactId>micrometer-registry-prometheus</artifactId>

application/src/main/java/net/furizon/backend/BackendApplication.java

+2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
import org.springframework.boot.SpringApplication;
44
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
56

67
@SpringBootApplication
8+
@ConfigurationPropertiesScan
79
public class BackendApplication {
810
public static void main(String[] args) {
911
SpringApplication.run(BackendApplication.class, args);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package net.furizon.backend.feature.authentication;
2+
3+
import lombok.Builder;
4+
import lombok.Data;
5+
import lombok.RequiredArgsConstructor;
6+
import org.jetbrains.annotations.NotNull;
7+
8+
@Builder
9+
@Data
10+
@RequiredArgsConstructor
11+
public class Authentication {
12+
private final long id;
13+
14+
@NotNull
15+
private final String email;
16+
17+
private final boolean isVerified;
18+
19+
private final boolean isTwoFactorEnabled;
20+
21+
private final boolean isDisabled;
22+
23+
private final boolean isFrom0Auth;
24+
25+
@NotNull
26+
private final String hashedPassword;
27+
28+
private final long userId;
29+
}

application/src/main/java/net/furizon/backend/feature/authentication/AuthenticationController.java

-34
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package net.furizon.backend.feature.authentication;
2+
3+
public enum AuthenticationErrorCode {
4+
EMAIL_ALREADY_REGISTERED,
5+
EMAIL_NOT_REGISTERED,
6+
EMAIL_INVALID,
7+
INVALID_CREDENTIALS,
8+
AUTHENTICATION_IS_DISABLED
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package net.furizon.backend.feature.authentication;
2+
3+
import java.util.regex.Pattern;
4+
5+
public class Const {
6+
public static final String EMAIL_REGEX = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}$";
7+
8+
public static final Pattern EMAIL_PATTERN = Pattern.compile(EMAIL_REGEX);
9+
}

application/src/main/java/net/furizon/backend/feature/authentication/action/JooqRemoveSessionAction.java

-7
This file was deleted.

application/src/main/java/net/furizon/backend/feature/authentication/action/RemoveSessionAction.java

-4
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package net.furizon.backend.feature.authentication.action.createAuthentication;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
5+
public interface CreateAuthenticationAction {
6+
void invoke(
7+
long userId,
8+
@NotNull String email,
9+
@NotNull String password
10+
);
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package net.furizon.backend.feature.authentication.action.createAuthentication;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import net.furizon.backend.infrastructure.security.SecurityConfig;
5+
import net.furizon.jooq.infrastructure.command.SqlCommand;
6+
import org.jetbrains.annotations.NotNull;
7+
import org.jooq.util.postgres.PostgresDSL;
8+
import org.springframework.security.crypto.password.PasswordEncoder;
9+
import org.springframework.stereotype.Component;
10+
11+
import static net.furizon.jooq.generated.Tables.AUTHENTICATIONS;
12+
13+
@Component
14+
@RequiredArgsConstructor
15+
public class JooqCreateAuthenticationAction implements CreateAuthenticationAction {
16+
private final SqlCommand sqlCommand;
17+
18+
private final PasswordEncoder encoder;
19+
20+
private final SecurityConfig securityConfig;
21+
22+
@Override
23+
public void invoke(
24+
long userId,
25+
@NotNull String email,
26+
@NotNull String password
27+
) {
28+
sqlCommand.execute(
29+
PostgresDSL
30+
.insertInto(
31+
AUTHENTICATIONS,
32+
AUTHENTICATIONS.USER_ID,
33+
AUTHENTICATIONS.AUTHENTICATION_EMAIL,
34+
AUTHENTICATIONS.AUTHENTICATION_HASHED_PASSWORD
35+
)
36+
.values(
37+
userId,
38+
email,
39+
encoder.encode(securityConfig.getPasswordSalt() + password)
40+
)
41+
);
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package net.furizon.backend.feature.authentication.controller;
2+
3+
import jakarta.servlet.http.HttpServletRequest;
4+
import jakarta.validation.Valid;
5+
import lombok.RequiredArgsConstructor;
6+
import net.furizon.backend.feature.authentication.dto.LoginRequest;
7+
import net.furizon.backend.feature.authentication.dto.LoginResponse;
8+
import net.furizon.backend.feature.authentication.dto.LogoutUserResponse;
9+
import net.furizon.backend.feature.authentication.dto.RegisterUserRequest;
10+
import net.furizon.backend.feature.authentication.dto.RegisterUserResponse;
11+
import net.furizon.backend.feature.authentication.usecase.LoginUserUseCase;
12+
import net.furizon.backend.feature.authentication.usecase.LogoutUserUseCase;
13+
import net.furizon.backend.feature.authentication.usecase.RegisterUserUseCase;
14+
import net.furizon.backend.infrastructure.security.FurizonUser;
15+
import net.furizon.backend.infrastructure.usecase.UseCaseExecutor;
16+
import org.jetbrains.annotations.NotNull;
17+
import org.jetbrains.annotations.Nullable;
18+
import org.springframework.http.HttpHeaders;
19+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
20+
import org.springframework.web.bind.annotation.PostMapping;
21+
import org.springframework.web.bind.annotation.RequestBody;
22+
import org.springframework.web.bind.annotation.RequestHeader;
23+
import org.springframework.web.bind.annotation.RequestMapping;
24+
import org.springframework.web.bind.annotation.RestController;
25+
26+
@RestController
27+
@RequestMapping("/api/v1/authentication")
28+
@RequiredArgsConstructor
29+
public class AuthenticationController {
30+
private final UseCaseExecutor executor;
31+
32+
@PostMapping("/login")
33+
public LoginResponse loginUser(
34+
@Valid @RequestBody final LoginRequest loginRequest,
35+
@RequestHeader(value = HttpHeaders.USER_AGENT, required = false) @Nullable String userAgent,
36+
HttpServletRequest httpServletRequest
37+
) {
38+
return executor.execute(
39+
LoginUserUseCase.class,
40+
new LoginUserUseCase.Input(
41+
loginRequest.getEmail(),
42+
loginRequest.getPassword(),
43+
httpServletRequest.getRemoteAddr(),
44+
userAgent
45+
)
46+
);
47+
}
48+
49+
@PostMapping("/logout")
50+
public LogoutUserResponse logoutUser(
51+
@AuthenticationPrincipal @NotNull final FurizonUser user
52+
) {
53+
executor.execute(
54+
LogoutUserUseCase.class,
55+
new LogoutUserUseCase.Input(user.getSessionId())
56+
);
57+
58+
return LogoutUserResponse.SUCCESS;
59+
}
60+
61+
62+
@PostMapping("/register")
63+
public RegisterUserResponse registerUser(
64+
@Valid @RequestBody final RegisterUserRequest registerUserRequest
65+
) {
66+
executor.execute(
67+
RegisterUserUseCase.class,
68+
registerUserRequest
69+
);
70+
71+
return RegisterUserResponse.SUCCESS;
72+
}
73+
}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
11
package net.furizon.backend.feature.authentication.dto;
22

3+
import jakarta.validation.constraints.Email;
4+
import jakarta.validation.constraints.NotEmpty;
5+
import jakarta.validation.constraints.NotNull;
6+
import jakarta.validation.constraints.Size;
37
import lombok.Data;
48

9+
import static net.furizon.backend.feature.authentication.Const.EMAIL_REGEX;
10+
511
@Data
612
public class LoginRequest {
13+
@NotNull
14+
@NotEmpty
15+
@Email(regexp = EMAIL_REGEX)
16+
private final String email;
717

18+
@NotNull
19+
@NotEmpty
20+
@Size(min = 6)
21+
private final String password;
822
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package net.furizon.backend.feature.authentication.dto;
2+
3+
import lombok.Data;
4+
import org.jetbrains.annotations.NotNull;
5+
6+
@Data
7+
public class LoginResponse {
8+
private final long userId;
9+
10+
@NotNull
11+
private final String accessToken;
12+
}

application/src/main/java/net/furizon/backend/feature/authentication/dto/LogoutRequest.java

-8
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package net.furizon.backend.feature.authentication.dto;
2+
3+
import lombok.Data;
4+
5+
@Data
6+
public class LogoutUserResponse {
7+
public static final LogoutUserResponse SUCCESS = new LogoutUserResponse(true);
8+
9+
private final boolean success;
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package net.furizon.backend.feature.authentication.dto;
2+
3+
import jakarta.annotation.Nullable;
4+
import jakarta.validation.constraints.NotEmpty;
5+
import jakarta.validation.constraints.NotNull;
6+
import jakarta.validation.constraints.Past;
7+
import jakarta.validation.constraints.Size;
8+
import lombok.Data;
9+
10+
import java.time.LocalDate;
11+
12+
// Italian stuff needed by law for associations.
13+
// If for some reason you have to adopt this codebase in your country,
14+
// you probably must adapt or change the membership code
15+
@Data
16+
public class PersonalUserInformation {
17+
@NotNull
18+
@NotEmpty
19+
@Size(min = 2)
20+
private final String firstName;
21+
22+
@NotNull
23+
@NotEmpty
24+
@Size(min = 2)
25+
private final String lastName;
26+
27+
// Italian person "id". For non italian ppl leave this to null
28+
// If null, in documents this should appear as ""
29+
@Nullable
30+
@Size(min = 16, max = 16)
31+
private final String fiscalCode;
32+
33+
@NotNull
34+
@NotEmpty
35+
@Size(min = 2)
36+
private final String birthCity;
37+
38+
@Nullable
39+
@NotEmpty
40+
@Size(min = 2)
41+
private final String birthRegion;
42+
43+
@NotNull
44+
@NotEmpty
45+
@Size(min = 2)
46+
private final String birthCountry;
47+
48+
@NotNull
49+
@Past
50+
private final LocalDate birthday;
51+
52+
@NotNull
53+
@NotEmpty
54+
@Size(min = 2)
55+
private final String residenceAddress;
56+
57+
@NotNull
58+
@NotEmpty
59+
@Size(max = 16)
60+
private final String residenceZipCode;
61+
62+
@NotNull
63+
@NotEmpty
64+
@Size(min = 2)
65+
private final String residenceCity;
66+
67+
@Nullable
68+
@NotEmpty
69+
@Size(min = 2)
70+
private final String residenceRegion;
71+
72+
@NotNull
73+
@NotEmpty
74+
@Size(min = 2)
75+
private final String residenceCountry;
76+
77+
@NotNull
78+
@NotEmpty
79+
@Size(min = 2)
80+
private final String phoneNumber;
81+
}

0 commit comments

Comments
 (0)