Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Authentication #16

Merged
merged 30 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
12b0690
Implement Authentication #1
mr-w1lde Nov 3, 2024
479bbf8
Implement Authentication #2
mr-w1lde Nov 3, 2024
0b19d71
Implement Authentication #3
mr-w1lde Nov 3, 2024
2dfaa2f
Add Pretix Sync Option to Disable + Some Fixes
mr-w1lde Nov 4, 2024
b5dc8d9
Add Pretix Sync Option to Disable + Some Fixes
mr-w1lde Nov 4, 2024
b65519e
Add Pretix Sync Option to Disable + Some Fixes
mr-w1lde Nov 4, 2024
884edc4
Add Pretix Sync Option to Disable + Some Fixes
mr-w1lde Nov 4, 2024
358d7bd
Implement Authentication #4
mr-w1lde Nov 4, 2024
f6a12d2
Implement Authentication #6
mr-w1lde Nov 4, 2024
df0db91
Implement Authentication #7
mr-w1lde Nov 4, 2024
14e5952
Implement Authentication #8
mr-w1lde Nov 5, 2024
22913f1
Implement Authentication #9
mr-w1lde Nov 5, 2024
7d3ce26
Implement Authentication #10
mr-w1lde Nov 5, 2024
b015920
Implement Authentication #11
mr-w1lde Nov 5, 2024
68df7ba
Implement Authentication #12
mr-w1lde Nov 5, 2024
8cff8dd
Implement Authentication #13
mr-w1lde Nov 5, 2024
1d8f397
Implement Authentication #13
mr-w1lde Nov 5, 2024
c52e2c8
Implement Virtual Threads
mr-w1lde Nov 6, 2024
86dd925
Revert "Implement Virtual Threads"
mr-w1lde Nov 6, 2024
a6b8a22
Revert "Revert "Implement Virtual Threads""
mr-w1lde Nov 6, 2024
8ed4cde
Implement Virtual Threads
mr-w1lde Nov 6, 2024
4630c35
Add Personal Info for Registration
mr-w1lde Nov 10, 2024
ad4e475
Updated and fixed db errors
stranck Nov 13, 2024
5b93f47
Updated fursonaname regex
stranck Nov 13, 2024
a960804
Update membership code
stranck Nov 13, 2024
24d8970
Moved membership year reset month/day to config
stranck Nov 14, 2024
cb8acd7
Allowed origins are now parametrized via env
Nov 14, 2024
63bc4ba
Merge branch 'authentication' of https://github.com/APSfurizon/fz-bac…
Nov 14, 2024
7e3a1f4
Merge branch 'master' into authentication
stranck Nov 14, 2024
c73af76
Fixed leftover after merge conflict
stranck Nov 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;

@SpringBootApplication
@ConfigurationPropertiesScan
public class BackendApplication {
public static void main(String[] args) {
SpringApplication.run(BackendApplication.class, args);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package net.furizon.backend.feature.authentication;

import lombok.Builder;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;

@Builder
@Data
@RequiredArgsConstructor
public class Authentication {
private final long id;

@NotNull
private final String email;

private final boolean isVerified;

private final boolean isTwoFactorEnabled;

private final boolean isDisabled;

private final boolean isFrom0Auth;

@NotNull
private final String hashedPassword;

private final long userId;
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package net.furizon.backend.feature.authentication;

public enum AuthenticationErrorCode {
EMAIL_ALREADY_REGISTERED,
EMAIL_NOT_REGISTERED,
EMAIL_INVALID,
INVALID_CREDENTIALS,
AUTHENTICATION_IS_DISABLED
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package net.furizon.backend.feature.authentication;

import java.util.regex.Pattern;

public class Const {
public static final String EMAIL_REGEX = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}$";

public static final Pattern EMAIL_PATTERN = Pattern.compile(EMAIL_REGEX);
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package net.furizon.backend.feature.authentication.action.createAuthentication;

import org.jetbrains.annotations.NotNull;

public interface CreateAuthenticationAction {
void invoke(
long userId,
@NotNull String email,
@NotNull String password
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package net.furizon.backend.feature.authentication.action.createAuthentication;

import lombok.RequiredArgsConstructor;
import net.furizon.backend.infrastructure.security.SecurityConfig;
import net.furizon.jooq.infrastructure.command.SqlCommand;
import org.jetbrains.annotations.NotNull;
import org.jooq.util.postgres.PostgresDSL;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import static net.furizon.jooq.generated.Tables.AUTHENTICATIONS;

@Component
@RequiredArgsConstructor
public class JooqCreateAuthenticationAction implements CreateAuthenticationAction {
private final SqlCommand sqlCommand;

private final PasswordEncoder encoder;

private final SecurityConfig securityConfig;

@Override
public void invoke(
long userId,
@NotNull String email,
@NotNull String password
) {
sqlCommand.execute(
PostgresDSL
.insertInto(
AUTHENTICATIONS,
AUTHENTICATIONS.USER_ID,
AUTHENTICATIONS.AUTHENTICATION_EMAIL,
AUTHENTICATIONS.AUTHENTICATION_HASHED_PASSWORD
)
.values(
userId,
email,
encoder.encode(securityConfig.getPasswordSalt() + password)
)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package net.furizon.backend.feature.authentication.controller;

import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import net.furizon.backend.feature.authentication.dto.LoginRequest;
import net.furizon.backend.feature.authentication.dto.LoginResponse;
import net.furizon.backend.feature.authentication.dto.LogoutUserResponse;
import net.furizon.backend.feature.authentication.dto.RegisterUserRequest;
import net.furizon.backend.feature.authentication.dto.RegisterUserResponse;
import net.furizon.backend.feature.authentication.usecase.LoginUserUseCase;
import net.furizon.backend.feature.authentication.usecase.LogoutUserUseCase;
import net.furizon.backend.feature.authentication.usecase.RegisterUserUseCase;
import net.furizon.backend.infrastructure.security.FurizonUser;
import net.furizon.backend.infrastructure.usecase.UseCaseExecutor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.http.HttpHeaders;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/v1/authentication")
@RequiredArgsConstructor
public class AuthenticationController {
private final UseCaseExecutor executor;

@PostMapping("/login")
public LoginResponse loginUser(
@RequestBody final LoginRequest loginRequest,
@RequestHeader(value = HttpHeaders.USER_AGENT, required = false) @Nullable String userAgent,
HttpServletRequest httpServletRequest
) {
return executor.execute(
LoginUserUseCase.class,
new LoginUserUseCase.Input(
loginRequest.getEmail(),
loginRequest.getPassword(),
httpServletRequest.getRemoteAddr(),
userAgent
)
);
}

@PostMapping("/logout")
public LogoutUserResponse logoutUser(
@AuthenticationPrincipal @NotNull final FurizonUser user
) {
executor.execute(
LogoutUserUseCase.class,
new LogoutUserUseCase.Input(user.getSessionId())
);

return LogoutUserResponse.SUCCESS;
}


@PostMapping("/register")
public RegisterUserResponse registerUser(
@RequestBody final RegisterUserRequest registerUserRequest
) {
executor.execute(
RegisterUserUseCase.class,
registerUserRequest
);

return RegisterUserResponse.SUCCESS;
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package net.furizon.backend.feature.authentication.dto;

import lombok.Data;
import org.jetbrains.annotations.NotNull;

@Data
public class LoginRequest {
@NotNull
private final String email;

@NotNull
private final String password;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package net.furizon.backend.feature.authentication.dto;

import lombok.Data;
import org.jetbrains.annotations.NotNull;

@Data
public class LoginResponse {
private final long userId;

@NotNull
private final String accessToken;
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package net.furizon.backend.feature.authentication.dto;

import lombok.Data;

@Data
public class LogoutUserResponse {
public static final LogoutUserResponse SUCCESS = new LogoutUserResponse(true);

private final boolean success;
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
package net.furizon.backend.feature.authentication.dto;

import lombok.Data;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

@Data
public class RegisterUserRequest {
@NotNull
private final String email;

@NotNull
private final String password;

@Nullable
private final String fursuitName;
mr-w1lde marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package net.furizon.backend.feature.authentication.dto;

import lombok.Data;

@Data
public class RegisterUserResponse {
public static final RegisterUserResponse SUCCESS = new RegisterUserResponse(true);

private final boolean success;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package net.furizon.backend.feature.authentication.finder;

import net.furizon.backend.feature.authentication.Authentication;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public interface AuthenticationFinder {
@Nullable
Authentication findByEmail(@NotNull String email);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package net.furizon.backend.feature.authentication.finder;

import lombok.RequiredArgsConstructor;
import net.furizon.backend.feature.authentication.Authentication;
import net.furizon.backend.feature.authentication.mapper.JooqAuthenticationMapper;
import net.furizon.jooq.infrastructure.query.SqlQuery;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jooq.exception.NoDataFoundException;
import org.jooq.util.postgres.PostgresDSL;
import org.springframework.stereotype.Component;

import static net.furizon.jooq.generated.tables.Authentications.AUTHENTICATIONS;

@Component
@RequiredArgsConstructor
public class JooqAuthenticationFinder implements AuthenticationFinder {
private final SqlQuery sqlQuery;

@Override
public @Nullable Authentication findByEmail(@NotNull String email) {
try {
return sqlQuery
.fetchSingle(
PostgresDSL
.select(
AUTHENTICATIONS.AUTHENTICATION_ID,
AUTHENTICATIONS.AUTHENTICATION_EMAIL,
AUTHENTICATIONS.AUTHENTICATION_EMAIL_VERIFIED,
AUTHENTICATIONS.AUTHENTICATION_2FA_ENABLED,
AUTHENTICATIONS.AUTHENTICATION_DISABLED,
AUTHENTICATIONS.AUTHENTICATION_FROM_OAUTH,
AUTHENTICATIONS.AUTHENTICATION_HASHED_PASSWORD,
AUTHENTICATIONS.USER_ID
)
.from(AUTHENTICATIONS)
.where(AUTHENTICATIONS.AUTHENTICATION_EMAIL.eq(email))
)
.map(JooqAuthenticationMapper::map);
} catch (NoDataFoundException e) {
return null;
}
}
}
Loading
Loading