feat: set session token, improved paths

This commit is contained in:
Jean Jacques Avril 2025-01-04 11:27:08 +00:00
parent 89422726bf
commit 02af66b585
No known key found for this signature in database
4 changed files with 54 additions and 23 deletions

View File

@ -22,7 +22,7 @@ class AuthService {
/// Route to generate a token
@Route.post('/login')
Future<Response> generateToken(Request request) async {
Future<Response> login(Request request) async {
return requestToJson(request)
.flatMap(validateJsonKeys(['email', 'password']))
.flatMap((json) => decodeJson(json, LoginRequestDTO.fromJson))
@ -59,8 +59,8 @@ class AuthService {
}
/// Route to revoke a token
@Route.post('/revoke')
Future<Response> revokeToken(Request request) async {
@Route.post('/logout')
Future<Response> logout(Request request) async {
return requestToJson(request)
.flatMap(validateJsonKeys(['token']))
.flatMap((json) => decodeJson(json, TokenRequestDTO.fromJson))

View File

@ -11,7 +11,7 @@ Router _$AuthServiceRouter(AuthService service) {
router.add(
'POST',
r'/login',
service.generateToken,
service.login,
);
router.add(
'POST',
@ -20,8 +20,8 @@ Router _$AuthServiceRouter(AuthService service) {
);
router.add(
'POST',
r'/revoke',
service.revokeToken,
r'/logout',
service.logout,
);
return router;
}

View File

@ -2,6 +2,7 @@ package services
import (
"actatempus_backend/internal/application/services/dto"
mappers "actatempus_backend/internal/application/services/mapper"
"actatempus_backend/internal/domain/app_error"
"actatempus_backend/internal/domain/entities"
"actatempus_backend/internal/domain/repository"
@ -32,7 +33,7 @@ func NewAuthService(authRepo repository.AuthRepository,
func (s *AuthService) RegisterRoutes(router *gin.RouterGroup) {
router.POST("/login", s.Login)
router.POST("/validate", s.Validate)
router.POST("/revoke", s.Revoke)
router.POST("/logout", s.Logout)
}
// Login handles user login and token generation.
@ -47,24 +48,14 @@ func (s *AuthService) Login(c *gin.Context) {
loginRequest.Email,
s.userRepository.FindByEmail(c.Request.Context()),
E.Chain[error](
func(user entities.User) E.Either[error, entities.User] {
hashedPassword := data.GenerateSecureHash(loginRequest.Password)
if user.Password != hashedPassword {
return E.Left[entities.User, error](app_error.NewAuthError("Invalid password"))
}
return E.Right[error](user)
},
validatePassword(loginRequest.Password),
),
E.Chain(func(user entities.User) E.Either[error, dto.TokenResponseDTO] {
return F.Pipe2(
return F.Pipe3(
user.ID,
s.authRepository.GenerateToken(c.Request.Context()),
E.Map[error](func(token string) dto.TokenResponseDTO {
return dto.TokenResponseDTO{
Token: token,
UserID: user.ID,
}
}),
E.Map[error](setSessionTokenCookie(c, user)),
E.Map[error](mappers.ToTokenDTO(user)),
)
}),
E.Fold(
@ -97,14 +88,16 @@ func (s *AuthService) Validate(c *gin.Context) {
)
}
// Revoke handles token revocation.
func (s *AuthService) Revoke(c *gin.Context) {
// Logout and token revocation.
func (s *AuthService) Logout(c *gin.Context) {
var tokenRequest dto.TokenRequestDTO
if err := c.ShouldBindJSON(&tokenRequest); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
deleteSessionTokenCookie(c)
F.Pipe2(
s.authRepository.RevokeToken(c.Request.Context())(tokenRequest.Token),
E.Map[error](func(userID string) gin.H {
@ -116,3 +109,26 @@ func (s *AuthService) Revoke(c *gin.Context) {
),
)
}
func setSessionTokenCookie(c *gin.Context, user entities.User) func(token string) string {
return func(token string) string {
c.SetCookie("session_token", token, 3600, "/", "localhost", false, true)
c.SetCookie("user_id", user.ID, 3600, "/", "localhost", false, true)
return token
}
}
func deleteSessionTokenCookie(c *gin.Context) {
c.SetCookie("session_token", "", -1, "/", "localhost", false, true)
c.SetCookie("user_id", "", -1, "/", "localhost", false, true)
}
func validatePassword(password string) func(user entities.User) E.Either[error, entities.User] {
return func(user entities.User) E.Either[error, entities.User] {
hashedPassword := data.GenerateSecureHash(password)
if user.Password != hashedPassword {
return E.Left[entities.User, error](app_error.NewAuthError("Invalid password"))
}
return E.Right[error](user)
}
}

View File

@ -0,0 +1,15 @@
package mappers
import (
"actatempus_backend/internal/application/services/dto"
"actatempus_backend/internal/domain/entities"
)
func ToTokenDTO(user entities.User) func(string) dto.TokenResponseDTO {
return func(token string) dto.TokenResponseDTO {
return dto.TokenResponseDTO{
Token: token,
UserID: user.ID,
}
}
}