Restructure the projec and start adding projects

Signed-off-by: Nikolai Rodionov <iam@allanger.xyz>
This commit is contained in:
2026-05-19 10:55:53 +02:00
parent f04f5b923f
commit 1c3df23bf9
19 changed files with 270 additions and 167 deletions

View File

@@ -1,42 +0,0 @@
package v1
import (
"context"
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/controllers"
accounts "gitea.badhouseplants.net/softplayer/softplayer-go-proto/pkg/accounts/v1"
"google.golang.org/protobuf/types/known/emptypb"
)
func NewAccountServer(
accountsCtrl *controllers.AccountController,
authorizationCtrl *controllers.AuthController,
) *AccountsServer {
return &AccountsServer{
accountsCtrl: accountsCtrl,
authorizationCtrl: authorizationCtrl,
}
}
//var _ accounts.AccountsServiceServer = (*AccountsServer)(nil)
type AccountsServer struct {
accounts.UnimplementedAccountsServiceServer
accountsCtrl *controllers.AccountController
authorizationCtrl *controllers.AuthController
}
// IsEmailVerified implements [v1.AccountsServiceServer].
func (a *AccountsServer) IsEmailVerified(context.Context, *accounts.IsEmailVerifiedRequest) (*accounts.IsEmailVerifiedResponse, error) {
panic("unimplemented")
}
// RemoveSession implements [v1.AccountsServiceServer].
func (a *AccountsServer) RemoveSession(context.Context, *accounts.RemoveSessionRequest) (*emptypb.Empty, error) {
panic("unimplemented")
}
// TokenAuthorization implements [v1.AccountsServiceServer].
func (a *AccountsServer) TokenAuthorization(context.Context, *emptypb.Empty) (*emptypb.Empty, error) {
panic("unimplemented")
}

View File

@@ -7,10 +7,10 @@ import (
"strings" "strings"
"time" "time"
v1 "gitea.badhouseplants.net/softplayer/softplayer-backend/api/v1" v1 "gitea.badhouseplants.net/softplayer/softplayer-backend/internal/api/v1"
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/controllers"
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/helpers/logger" "gitea.badhouseplants.net/softplayer/softplayer-backend/internal/helpers/logger"
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/helpers/postgres" "gitea.badhouseplants.net/softplayer/softplayer-backend/internal/helpers/postgres"
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/services"
accounts "gitea.badhouseplants.net/softplayer/softplayer-go-proto/pkg/accounts/v1" accounts "gitea.badhouseplants.net/softplayer/softplayer-go-proto/pkg/accounts/v1"
test "gitea.badhouseplants.net/softplayer/softplayer-go-proto/pkg/test/v1" test "gitea.badhouseplants.net/softplayer/softplayer-go-proto/pkg/test/v1"
tokens "gitea.badhouseplants.net/softplayer/softplayer-go-proto/pkg/tokens/v1" tokens "gitea.badhouseplants.net/softplayer/softplayer-go-proto/pkg/tokens/v1"
@@ -68,7 +68,7 @@ func (cmd *Server) Run(ctx context.Context) error {
Addr: cmd.RedisHost, Addr: cmd.RedisHost,
}) })
authController := controllers.NewAuthController( authController := services.NewAuthController(
[]byte(cmd.JWTSecret), []byte(cmd.JWTSecret),
cmd.AccessTokenTTL, cmd.AccessTokenTTL,
cmd.RefreshTokenTTL, cmd.RefreshTokenTTL,
@@ -97,12 +97,12 @@ func (cmd *Server) Run(ctx context.Context) error {
reflection.Register(grpcServer) reflection.Register(grpcServer)
} }
tokenCtrl := &controllers.TokenController{ tokenCtrl := &services.TokenController{
DB: db, DB: db,
Redis: rdb, Redis: rdb,
} }
accountCtrl := &controllers.AccountController{ accountCtrl := &services.AccountController{
HashCost: cmd.HashCost, HashCost: cmd.HashCost,
DB: db, DB: db,
DevMode: cmd.DevMode, DevMode: cmd.DevMode,

View File

@@ -0,0 +1,89 @@
package v1
import (
"context"
"errors"
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/services"
accounts "gitea.badhouseplants.net/softplayer/softplayer-go-proto/pkg/accounts/v1"
"github.com/golang/protobuf/ptypes/empty"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
)
func NewAccountServer(
accountsCtrl *services.AccountController,
authorizationCtrl *services.AuthController,
) *AccountsServer {
return &AccountsServer{
accountsCtrl: accountsCtrl,
authorizationCtrl: authorizationCtrl,
}
}
//var _ accounts.AccountsServiceServer = (*AccountsServer)(nil)
type AccountsServer struct {
accounts.UnimplementedAccountsServiceServer
accountsCtrl *services.AccountController
authorizationCtrl *services.AuthController
}
func (srv *AccountsServer) RefreshToken(ctx context.Context, in *empty.Empty) (*empty.Empty, error) {
claims, err := services.ClaimsFromContext(ctx)
if err != nil {
return nil, status.Error(codes.Aborted, "Context is invalid")
}
if claims.TokenType != services.TokenTypeRefresh {
return nil, status.Error(codes.Unauthenticated, "Invalid token")
}
session, err := srv.authorizationCtrl.GetSession(ctx, claims.TokenID)
if err != nil {
if errors.Is(err, services.ErrSessionNotFound) {
return nil, status.Error(codes.Unauthenticated, "Session doesn't exists")
}
return nil, status.Error(codes.Internal, "Somethings is broken on our side")
}
if session.UserID != claims.UserID {
return nil, status.Error(codes.Unauthenticated, "Invalid session")
}
accessToken, _, err := srv.authorizationCtrl.GenerateToken(&services.JWTData{
UserID: claims.UserID,
TokenType: services.TokenTypeAccess,
TokenAud: services.TokenAudWeb,
})
if err != nil {
return nil, status.Error(codes.Aborted, "Couldn't generate an access token")
}
refreshToken, tokenID, err := srv.authorizationCtrl.GenerateToken(&services.JWTData{
UserID: claims.UserID,
TokenType: services.TokenTypeRefresh,
TokenAud: services.TokenAudWeb,
})
if err != nil {
return nil, status.Error(codes.Aborted, "Couldn't generate an access token")
}
newSession := &services.Session{UserID: session.UserID}
if err := srv.authorizationCtrl.SaveSession(ctx, tokenID, newSession); err != nil {
return nil, status.Error(codes.Aborted, "Couldn't store session")
}
header := metadata.New(map[string]string{
"X-Access-Token": accessToken,
"X-Refresh-Token": refreshToken,
})
if err := grpc.SetHeader(ctx, header); err != nil {
return nil, status.Error(codes.Aborted, "Couldn't set metadata")
}
return &emptypb.Empty{}, nil
}

View File

@@ -3,15 +3,15 @@ package v1
import ( import (
"context" "context"
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/controllers" "gitea.badhouseplants.net/softplayer/softplayer-backend/internal/services"
accounts "gitea.badhouseplants.net/softplayer/softplayer-go-proto/pkg/accounts/v1" accounts "gitea.badhouseplants.net/softplayer/softplayer-go-proto/pkg/accounts/v1"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
) )
func NewPublicAccountServer( func NewPublicAccountServer(
accountsCtrl *controllers.AccountController, accountsCtrl *services.AccountController,
authorizationCtrl *controllers.AuthController, authorizationCtrl *services.AuthController,
) *PublicAccountService { ) *PublicAccountService {
return &PublicAccountService{ return &PublicAccountService{
accountsCtrl: accountsCtrl, accountsCtrl: accountsCtrl,
@@ -21,8 +21,8 @@ func NewPublicAccountServer(
type PublicAccountService struct { type PublicAccountService struct {
accounts.UnimplementedPublicAccountsServiceServer accounts.UnimplementedPublicAccountsServiceServer
accountsCtrl *controllers.AccountController accountsCtrl *services.AccountController
authorizationCtrl *controllers.AuthController authorizationCtrl *services.AuthController
} }
func (a *PublicAccountService) SignIn(ctx context.Context, in *accounts.SignInRequest) (*accounts.SignInResponse, error) { func (a *PublicAccountService) SignIn(ctx context.Context, in *accounts.SignInRequest) (*accounts.SignInResponse, error) {
@@ -30,25 +30,25 @@ func (a *PublicAccountService) SignIn(ctx context.Context, in *accounts.SignInRe
if err != nil { if err != nil {
return nil, status.Error(codes.Aborted, "Couldn't create a user") return nil, status.Error(codes.Aborted, "Couldn't create a user")
} }
accessToken, _, err := a.authorizationCtrl.GenerateToken(&controllers.JWTData{ accessToken, _, err := a.authorizationCtrl.GenerateToken(&services.JWTData{
UserID: id, UserID: id,
TokenType: controllers.TokenTypeAccess, TokenType: services.TokenTypeAccess,
TokenAud: controllers.TokenAudWeb, TokenAud: services.TokenAudWeb,
}) })
if err != nil { if err != nil {
return nil, status.Error(codes.Aborted, "Couldn't generate an access token") return nil, status.Error(codes.Aborted, "Couldn't generate an access token")
} }
refreshToken, tokenID, err := a.authorizationCtrl.GenerateToken(&controllers.JWTData{ refreshToken, tokenID, err := a.authorizationCtrl.GenerateToken(&services.JWTData{
UserID: id, UserID: id,
TokenType: controllers.TokenTypeRefresh, TokenType: services.TokenTypeRefresh,
TokenAud: controllers.TokenAudWeb, TokenAud: services.TokenAudWeb,
}) })
if err != nil { if err != nil {
return nil, status.Error(codes.Aborted, "Couldn't generate an access token") return nil, status.Error(codes.Aborted, "Couldn't generate an access token")
} }
session := &controllers.Session{UserID: id} session := &services.Session{UserID: id}
if err := a.authorizationCtrl.SaveSession(ctx, tokenID, session); err != nil { if err := a.authorizationCtrl.SaveSession(ctx, tokenID, session); err != nil {
return nil, status.Error(codes.Aborted, "Couldn't store session") return nil, status.Error(codes.Aborted, "Couldn't store session")
@@ -63,7 +63,7 @@ func (a *PublicAccountService) SignIn(ctx context.Context, in *accounts.SignInRe
// Create a new account in Softplayer // Create a new account in Softplayer
func (a *PublicAccountService) SignUp(ctx context.Context, in *accounts.SignUpRequest) (*accounts.SignUpResponse, error) { func (a *PublicAccountService) SignUp(ctx context.Context, in *accounts.SignUpRequest) (*accounts.SignUpResponse, error) {
data := &controllers.AccountData{ data := &services.AccountData{
Password: in.GetPassword(), Password: in.GetPassword(),
Email: in.GetEmail(), Email: in.GetEmail(),
Name: in.PersonalData.GetName(), Name: in.PersonalData.GetName(),
@@ -74,25 +74,25 @@ func (a *PublicAccountService) SignUp(ctx context.Context, in *accounts.SignUpRe
return nil, status.Error(codes.Aborted, "Couldn't create a user") return nil, status.Error(codes.Aborted, "Couldn't create a user")
} }
accessToken, _, err := a.authorizationCtrl.GenerateToken(&controllers.JWTData{ accessToken, _, err := a.authorizationCtrl.GenerateToken(&services.JWTData{
UserID: id, UserID: id,
TokenType: controllers.TokenTypeAccess, TokenType: services.TokenTypeAccess,
TokenAud: controllers.TokenAudWeb, TokenAud: services.TokenAudWeb,
}) })
if err != nil { if err != nil {
return nil, status.Error(codes.Aborted, "Couldn't generate an access token") return nil, status.Error(codes.Aborted, "Couldn't generate an access token")
} }
refreshToken, tokenID, err := a.authorizationCtrl.GenerateToken(&controllers.JWTData{ refreshToken, tokenID, err := a.authorizationCtrl.GenerateToken(&services.JWTData{
UserID: id, UserID: id,
TokenType: controllers.TokenTypeRefresh, TokenType: services.TokenTypeRefresh,
TokenAud: controllers.TokenAudWeb, TokenAud: services.TokenAudWeb,
}) })
if err != nil { if err != nil {
return nil, status.Error(codes.Aborted, "Couldn't generate an access token") return nil, status.Error(codes.Aborted, "Couldn't generate an access token")
} }
session := &controllers.Session{UserID: id} session := &services.Session{UserID: id}
if err := a.authorizationCtrl.SaveSession(ctx, tokenID, session); err != nil { if err := a.authorizationCtrl.SaveSession(ctx, tokenID, session); err != nil {
return nil, status.Error(codes.Aborted, "Couldn't store session") return nil, status.Error(codes.Aborted, "Couldn't store session")

View File

@@ -4,7 +4,7 @@ import (
"context" "context"
"errors" "errors"
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/controllers" "gitea.badhouseplants.net/softplayer/softplayer-backend/internal/services"
tokens "gitea.badhouseplants.net/softplayer/softplayer-go-proto/pkg/tokens/v1" tokens "gitea.badhouseplants.net/softplayer/softplayer-go-proto/pkg/tokens/v1"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
@@ -17,13 +17,13 @@ import (
type PublicTokensServer struct { type PublicTokensServer struct {
tokens.UnimplementedPublicTokensServiceServer tokens.UnimplementedPublicTokensServiceServer
tokenCtrl *controllers.TokenController tokenCtrl *services.TokenController
authorizationCtrl *controllers.AuthController authorizationCtrl *services.AuthController
} }
func NewPublicTokensServer( func NewPublicTokensServer(
tokenCtrl *controllers.TokenController, tokenCtrl *services.TokenController,
authorizationCtrl *controllers.AuthController, authorizationCtrl *services.AuthController,
) *PublicTokensServer { ) *PublicTokensServer {
return &PublicTokensServer{ return &PublicTokensServer{
tokenCtrl: tokenCtrl, tokenCtrl: tokenCtrl,
@@ -34,19 +34,19 @@ func NewPublicTokensServer(
func (srv *PublicTokensServer) AuthenticateWithToken(ctx context.Context, in *tokens.AuthenticateWithTokenRequest) (*emptypb.Empty, error) { func (srv *PublicTokensServer) AuthenticateWithToken(ctx context.Context, in *tokens.AuthenticateWithTokenRequest) (*emptypb.Empty, error) {
tokenAuthRes, err := srv.tokenCtrl.AuthenticateWithToken(ctx, in.TokenValue.Token) tokenAuthRes, err := srv.tokenCtrl.AuthenticateWithToken(ctx, in.TokenValue.Token)
if err != nil { if err != nil {
if errors.Is(err, controllers.ErrBadToken) { if errors.Is(err, services.ErrBadToken) {
return nil, status.Error(codes.Unauthenticated, "Token is not valid") return nil, status.Error(codes.Unauthenticated, "Token is not valid")
} }
if errors.Is(err, controllers.ErrServerError) { if errors.Is(err, services.ErrServerError) {
return nil, status.Error(codes.Internal, "Something is broken on our side") return nil, status.Error(codes.Internal, "Something is broken on our side")
} }
return nil, status.Error(codes.Aborted, "Couldn't authorize") return nil, status.Error(codes.Aborted, "Couldn't authorize")
} }
jwtData := &controllers.JWTData{ jwtData := &services.JWTData{
UserID: tokenAuthRes.UserID, UserID: tokenAuthRes.UserID,
TokenType: controllers.TokenTypeAccess, TokenType: services.TokenTypeAccess,
TokenAud: controllers.TokenAudToken, TokenAud: services.TokenAudToken,
Scope: tokenAuthRes.Scope, Scope: tokenAuthRes.Scope,
} }
accessToken, _, err := srv.authorizationCtrl.GenerateToken(jwtData) accessToken, _, err := srv.authorizationCtrl.GenerateToken(jwtData)

View File

@@ -4,7 +4,7 @@ import (
"context" "context"
"errors" "errors"
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/controllers" "gitea.badhouseplants.net/softplayer/softplayer-backend/internal/services"
tokens "gitea.badhouseplants.net/softplayer/softplayer-go-proto/pkg/tokens/v1" tokens "gitea.badhouseplants.net/softplayer/softplayer-go-proto/pkg/tokens/v1"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
@@ -18,13 +18,13 @@ import (
// TokensServer implements the Token Service // TokensServer implements the Token Service
type TokensServer struct { type TokensServer struct {
tokens.UnimplementedTokensServiceServer tokens.UnimplementedTokensServiceServer
tokenCtrl *controllers.TokenController tokenCtrl *services.TokenController
authorizationCtrl *controllers.AuthController authorizationCtrl *services.AuthController
} }
func NewTokensServer( func NewTokensServer(
tokenCtrl *controllers.TokenController, tokenCtrl *services.TokenController,
authorizationCtrl *controllers.AuthController, authorizationCtrl *services.AuthController,
) *TokensServer { ) *TokensServer {
return &TokensServer{ return &TokensServer{
tokenCtrl: tokenCtrl, tokenCtrl: tokenCtrl,
@@ -34,7 +34,7 @@ func NewTokensServer(
// CreateToken implements [v1.TokensServiceServer]. // CreateToken implements [v1.TokensServiceServer].
func (srv *TokensServer) CreateToken(ctx context.Context, in *tokens.CreateTokenRequest) (*tokens.CreateTokenResponse, error) { func (srv *TokensServer) CreateToken(ctx context.Context, in *tokens.CreateTokenRequest) (*tokens.CreateTokenResponse, error) {
claims, err := controllers.ClaimsFromContext(ctx) claims, err := services.ClaimsFromContext(ctx)
if err != nil { if err != nil {
return nil, status.Error(codes.Aborted, "Context is invalid") return nil, status.Error(codes.Aborted, "Context is invalid")
} }
@@ -50,7 +50,7 @@ func (srv *TokensServer) CreateToken(ctx context.Context, in *tokens.CreateToken
permissions[service] = methods.GetMethods() permissions[service] = methods.GetMethods()
} }
tokenData := &controllers.TokenData{ tokenData := &services.TokenData{
Name: in.TokenMetadata.GetName(), Name: in.TokenMetadata.GetName(),
UserID: claims.UserID, UserID: claims.UserID,
ExpiresAt: in.TokenMetadata.ExpiresAt.AsTime(), ExpiresAt: in.TokenMetadata.ExpiresAt.AsTime(),
@@ -59,7 +59,7 @@ func (srv *TokensServer) CreateToken(ctx context.Context, in *tokens.CreateToken
token, tokenID, err := srv.tokenCtrl.Create(ctx, tokenData) token, tokenID, err := srv.tokenCtrl.Create(ctx, tokenData)
if err != nil { if err != nil {
if errors.Is(err, controllers.ErrServerError) { if errors.Is(err, services.ErrServerError) {
return nil, status.Error(codes.Internal, "Something is broken on our side") return nil, status.Error(codes.Internal, "Something is broken on our side")
} }
return nil, status.Error(codes.Aborted, "Couldn't create a token") return nil, status.Error(codes.Aborted, "Couldn't create a token")
@@ -75,7 +75,7 @@ func (srv *TokensServer) CreateToken(ctx context.Context, in *tokens.CreateToken
// ForceTokenExpiration implements [v1.TokensServiceServer]. // ForceTokenExpiration implements [v1.TokensServiceServer].
func (srv *TokensServer) ForceTokenExpiration(ctx context.Context, in *tokens.ForceTokenExpirationRequest) (*emptypb.Empty, error) { func (srv *TokensServer) ForceTokenExpiration(ctx context.Context, in *tokens.ForceTokenExpirationRequest) (*emptypb.Empty, error) {
claims, err := controllers.ClaimsFromContext(ctx) claims, err := services.ClaimsFromContext(ctx)
if err != nil { if err != nil {
return nil, status.Error(codes.Aborted, "Context is invalid") return nil, status.Error(codes.Aborted, "Context is invalid")
} }
@@ -84,14 +84,14 @@ func (srv *TokensServer) ForceTokenExpiration(ctx context.Context, in *tokens.Fo
} }
if err := srv.tokenCtrl.VerifyTokenOwner(ctx, claims.UserID, in.TokenUuid.Uuid); err != nil { if err := srv.tokenCtrl.VerifyTokenOwner(ctx, claims.UserID, in.TokenUuid.Uuid); err != nil {
if errors.Is(err, controllers.ErrServerError) { if errors.Is(err, services.ErrServerError) {
return nil, status.Error(codes.Internal, "Something is broken on our side") return nil, status.Error(codes.Internal, "Something is broken on our side")
} }
return nil, status.Error(codes.Aborted, "User is now allowed to manipulate this token") return nil, status.Error(codes.Aborted, "User is now allowed to manipulate this token")
} }
if err := srv.tokenCtrl.ForceExpiration(ctx, in.TokenUuid.GetUuid()); err != nil { if err := srv.tokenCtrl.ForceExpiration(ctx, in.TokenUuid.GetUuid()); err != nil {
if errors.Is(err, controllers.ErrServerError) { if errors.Is(err, services.ErrServerError) {
return nil, status.Error(codes.Internal, "Something is broken on our side") return nil, status.Error(codes.Internal, "Something is broken on our side")
} }
return nil, status.Error(codes.Aborted, "Couldn't create a token") return nil, status.Error(codes.Aborted, "Couldn't create a token")
@@ -101,7 +101,7 @@ func (srv *TokensServer) ForceTokenExpiration(ctx context.Context, in *tokens.Fo
// GetToken implements [v1.TokensServiceServer]. // GetToken implements [v1.TokensServiceServer].
func (srv *TokensServer) GetToken(ctx context.Context, in *tokens.GetTokenRequest) (*tokens.GetTokenResponse, error) { func (srv *TokensServer) GetToken(ctx context.Context, in *tokens.GetTokenRequest) (*tokens.GetTokenResponse, error) {
claims, err := controllers.ClaimsFromContext(ctx) claims, err := services.ClaimsFromContext(ctx)
if err != nil { if err != nil {
return nil, status.Error(codes.Aborted, "Context is invalid") return nil, status.Error(codes.Aborted, "Context is invalid")
} }
@@ -109,7 +109,7 @@ func (srv *TokensServer) GetToken(ctx context.Context, in *tokens.GetTokenReques
return nil, status.Error(codes.Aborted, "Context is invalid") return nil, status.Error(codes.Aborted, "Context is invalid")
} }
if err := srv.tokenCtrl.VerifyTokenOwner(ctx, claims.UserID, in.TokenUuid.Uuid); err != nil { if err := srv.tokenCtrl.VerifyTokenOwner(ctx, claims.UserID, in.TokenUuid.Uuid); err != nil {
if errors.Is(err, controllers.ErrServerError) { if errors.Is(err, services.ErrServerError) {
return nil, status.Error(codes.Internal, "Something is broken on our side") return nil, status.Error(codes.Internal, "Something is broken on our side")
} }
return nil, status.Error(codes.Aborted, "User is now allowed to manipulate this token") return nil, status.Error(codes.Aborted, "User is now allowed to manipulate this token")
@@ -117,7 +117,7 @@ func (srv *TokensServer) GetToken(ctx context.Context, in *tokens.GetTokenReques
token, err := srv.tokenCtrl.Get(ctx, in.TokenUuid.Uuid, claims.UserID) token, err := srv.tokenCtrl.Get(ctx, in.TokenUuid.Uuid, claims.UserID)
if err != nil { if err != nil {
if errors.Is(err, controllers.ErrServerError) { if errors.Is(err, services.ErrServerError) {
return nil, status.Error(codes.Internal, "Something is broken on our side") return nil, status.Error(codes.Internal, "Something is broken on our side")
} }
return nil, status.Error(codes.Aborted, "Couldn't list tokens") return nil, status.Error(codes.Aborted, "Couldn't list tokens")
@@ -141,7 +141,7 @@ func (srv *TokensServer) GetToken(ctx context.Context, in *tokens.GetTokenReques
// ListTokens implements [v1.TokensServiceServer]. // ListTokens implements [v1.TokensServiceServer].
func (srv *TokensServer) ListTokens(in *emptypb.Empty, stream grpc.ServerStreamingServer[tokens.ListTokensResponse]) error { func (srv *TokensServer) ListTokens(in *emptypb.Empty, stream grpc.ServerStreamingServer[tokens.ListTokensResponse]) error {
claims, err := controllers.ClaimsFromContext(stream.Context()) claims, err := services.ClaimsFromContext(stream.Context())
if err != nil { if err != nil {
return status.Error(codes.Aborted, "Context is invalid") return status.Error(codes.Aborted, "Context is invalid")
} }
@@ -151,7 +151,7 @@ func (srv *TokensServer) ListTokens(in *emptypb.Empty, stream grpc.ServerStreami
tokensRes, err := srv.tokenCtrl.List(stream.Context(), claims.UserID) tokensRes, err := srv.tokenCtrl.List(stream.Context(), claims.UserID)
if err != nil { if err != nil {
if errors.Is(err, controllers.ErrServerError) { if errors.Is(err, services.ErrServerError) {
return status.Error(codes.Internal, "Something is broken on our side") return status.Error(codes.Internal, "Something is broken on our side")
} }
return status.Error(codes.Aborted, "Couldn't list tokens") return status.Error(codes.Aborted, "Couldn't list tokens")
@@ -179,7 +179,7 @@ func (srv *TokensServer) ListTokens(in *emptypb.Empty, stream grpc.ServerStreami
// RegenerateToken implements [v1.TokensServiceServer]. // RegenerateToken implements [v1.TokensServiceServer].
func (srv *TokensServer) RegenerateToken(ctx context.Context, in *tokens.RegenerateTokenRequest) (*tokens.RegenerateTokenResponse, error) { func (srv *TokensServer) RegenerateToken(ctx context.Context, in *tokens.RegenerateTokenRequest) (*tokens.RegenerateTokenResponse, error) {
claims, err := controllers.ClaimsFromContext(ctx) claims, err := services.ClaimsFromContext(ctx)
if err != nil { if err != nil {
return nil, status.Error(codes.Aborted, "Context is invalid") return nil, status.Error(codes.Aborted, "Context is invalid")
} }
@@ -187,7 +187,7 @@ func (srv *TokensServer) RegenerateToken(ctx context.Context, in *tokens.Regener
return nil, status.Error(codes.Aborted, "Context is invalid") return nil, status.Error(codes.Aborted, "Context is invalid")
} }
if err := srv.tokenCtrl.VerifyTokenOwner(ctx, claims.UserID, in.TokenUuid.Uuid); err != nil { if err := srv.tokenCtrl.VerifyTokenOwner(ctx, claims.UserID, in.TokenUuid.Uuid); err != nil {
if errors.Is(err, controllers.ErrServerError) { if errors.Is(err, services.ErrServerError) {
return nil, status.Error(codes.Internal, "Something is broken on our side") return nil, status.Error(codes.Internal, "Something is broken on our side")
} }
return nil, status.Error(codes.Aborted, "User is now allowed to manipulate this token") return nil, status.Error(codes.Aborted, "User is now allowed to manipulate this token")
@@ -195,7 +195,7 @@ func (srv *TokensServer) RegenerateToken(ctx context.Context, in *tokens.Regener
tokenVal, err := srv.tokenCtrl.Regenerate(ctx, in.TokenUuid.GetUuid()) tokenVal, err := srv.tokenCtrl.Regenerate(ctx, in.TokenUuid.GetUuid())
if err != nil { if err != nil {
if errors.Is(err, controllers.ErrServerError) { if errors.Is(err, services.ErrServerError) {
return nil, status.Error(codes.Internal, "Something is broken on our side") return nil, status.Error(codes.Internal, "Something is broken on our side")
} }
return nil, status.Error(codes.Aborted, "Couldn't list tokens") return nil, status.Error(codes.Aborted, "Couldn't list tokens")
@@ -209,7 +209,7 @@ func (srv *TokensServer) RegenerateToken(ctx context.Context, in *tokens.Regener
// UpdateToken implements [v1.TokensServiceServer]. // UpdateToken implements [v1.TokensServiceServer].
func (srv *TokensServer) UpdateToken(ctx context.Context, in *tokens.UpdateTokenRequest) (*tokens.UpdateTokenResponse, error) { func (srv *TokensServer) UpdateToken(ctx context.Context, in *tokens.UpdateTokenRequest) (*tokens.UpdateTokenResponse, error) {
claims, err := controllers.ClaimsFromContext(ctx) claims, err := services.ClaimsFromContext(ctx)
if err != nil { if err != nil {
return nil, status.Error(codes.Aborted, "Context is invalid") return nil, status.Error(codes.Aborted, "Context is invalid")
} }
@@ -218,7 +218,7 @@ func (srv *TokensServer) UpdateToken(ctx context.Context, in *tokens.UpdateToken
} }
if err := srv.tokenCtrl.VerifyTokenOwner(ctx, claims.UserID, in.TokenUuid.Uuid); err != nil { if err := srv.tokenCtrl.VerifyTokenOwner(ctx, claims.UserID, in.TokenUuid.Uuid); err != nil {
if errors.Is(err, controllers.ErrServerError) { if errors.Is(err, services.ErrServerError) {
return nil, status.Error(codes.Internal, "Something is broken on our side") return nil, status.Error(codes.Internal, "Something is broken on our side")
} }
return nil, status.Error(codes.Aborted, "User is now allowed to manipulate this token") return nil, status.Error(codes.Aborted, "User is now allowed to manipulate this token")
@@ -231,12 +231,12 @@ func (srv *TokensServer) UpdateToken(ctx context.Context, in *tokens.UpdateToken
for service, methods := range in.TokenPermissions.Permissions { for service, methods := range in.TokenPermissions.Permissions {
permissions[service] = methods.GetMethods() permissions[service] = methods.GetMethods()
} }
tokenData := &controllers.TokenData{ tokenData := &services.TokenData{
Name: in.TokenMetadata.Name, Name: in.TokenMetadata.Name,
Scopes: permissions, Scopes: permissions,
} }
if err := srv.tokenCtrl.Update(ctx, tokenData); err != nil { if err := srv.tokenCtrl.Update(ctx, tokenData); err != nil {
if errors.Is(err, controllers.ErrServerError) { if errors.Is(err, services.ErrServerError) {
return nil, status.Error(codes.Internal, "Something is broken on our side") return nil, status.Error(codes.Internal, "Something is broken on our side")
} }
return nil, status.Error(codes.Aborted, "Couldn't list tokens") return nil, status.Error(codes.Aborted, "Couldn't list tokens")

View File

@@ -11,9 +11,9 @@ type ProjectData struct {
Name string Name string
Slug string Slug string
Description string Description string
OwnerID string CreatedBy string
CreatedAt string CreatedAt time.Time
ArchivedAt time.Time ArchivedAt sql.NullTime
Blocked bool Blocked bool
UpdatedAt time.Time UpdatedAt time.Time
UpdatedBy string UpdatedBy string

View File

@@ -0,0 +1,26 @@
package repository_test
import (
"database/sql"
"testing"
"time"
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/repository"
"github.com/google/uuid"
)
func TestProjectsRepository_Success(t *testing.T) {
createdBy := uuid.NewString()
_ = &repository.ProjectData{
UUID: uuid.NewString(),
Name: "test-1",
Slug: "test_1",
Description: "Test Project Number 1",
CreatedBy: createdBy,
CreatedAt: time.Now(),
ArchivedAt: sql.NullTime{Time: time.Now()},
Blocked: false,
UpdatedAt: time.Now(),
UpdatedBy: createdBy,
}
}

View File

@@ -0,0 +1,22 @@
package repository
import (
"context"
"database/sql"
)
func StartTransaction(ctx context.Context, db *sql.DB) (*sql.Tx, error) {
tx, err := db.BeginTx(ctx, nil)
if err != nil {
return nil, err
}
return tx, nil
}
func CommitTransaction(ctx context.Context, tx *sql.Tx) error {
return tx.Commit()
}
func RollBackTransaction(ctx context.Context, tx *sql.Tx) error {
return tx.Rollback()
}

View File

@@ -1,4 +1,4 @@
package controllers package services
import ( import (
"context" "context"

View File

@@ -1,4 +1,4 @@
package controllers_test package services_test
import ( import (
"context" "context"
@@ -8,8 +8,8 @@ import (
"testing" "testing"
"time" "time"
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/controllers"
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/helpers/postgres" "gitea.badhouseplants.net/softplayer/softplayer-backend/internal/helpers/postgres"
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/services"
"github.com/google/uuid" "github.com/google/uuid"
_ "github.com/jackc/pgx/v5/stdlib" _ "github.com/jackc/pgx/v5/stdlib"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
@@ -40,8 +40,8 @@ func newTestRedisConnection() *redis.Client {
}) })
} }
func newTestAccountController(ctx context.Context) *controllers.AccountController { func newTestAccountController(ctx context.Context) *services.AccountController {
return &controllers.AccountController{ return &services.AccountController{
DB: newTestDBConnection(ctx), DB: newTestDBConnection(ctx),
Redis: newTestRedisConnection(), Redis: newTestRedisConnection(),
DevMode: true, DevMode: true,
@@ -67,7 +67,7 @@ func newTestUniqueEmail(prefix string) string {
func TestIntegrationAccountCreate_Success(t *testing.T) { func TestIntegrationAccountCreate_Success(t *testing.T) {
ctrl := newTestAccountController(t.Context()) ctrl := newTestAccountController(t.Context())
accountData := &controllers.AccountData{ accountData := &services.AccountData{
Password: "qwertyu9", Password: "qwertyu9",
Email: newTestUniqueEmail("accounts"), Email: newTestUniqueEmail("accounts"),
Surname: "Doe", Surname: "Doe",
@@ -81,7 +81,7 @@ func TestIntegrationAccountCreate_Success(t *testing.T) {
func TestIntegrationAccountCreate_ExistingAccountErr(t *testing.T) { func TestIntegrationAccountCreate_ExistingAccountErr(t *testing.T) {
ctrl := newTestAccountController(t.Context()) ctrl := newTestAccountController(t.Context())
email := newTestUniqueEmail("accounts") email := newTestUniqueEmail("accounts")
accountData := &controllers.AccountData{ accountData := &services.AccountData{
Password: "qwertyu9", Password: "qwertyu9",
Email: email, Email: email,
Surname: "Doe", Surname: "Doe",
@@ -94,13 +94,13 @@ func TestIntegrationAccountCreate_ExistingAccountErr(t *testing.T) {
id, err = ctrl.Create(t.Context(), accountData) id, err = ctrl.Create(t.Context(), accountData)
assert.Empty(t, id) assert.Empty(t, id)
assert.Error(t, err) assert.Error(t, err)
assert.ErrorIs(t, err, controllers.ErrEmailUsed) assert.ErrorIs(t, err, services.ErrEmailUsed)
} }
func TestIntegrationAccountLogin_Success(t *testing.T) { func TestIntegrationAccountLogin_Success(t *testing.T) {
ctrl := newTestAccountController(t.Context()) ctrl := newTestAccountController(t.Context())
email := newTestUniqueEmail("accounts") email := newTestUniqueEmail("accounts")
accountData := &controllers.AccountData{ accountData := &services.AccountData{
Password: "qwertyu9", Password: "qwertyu9",
Email: email, Email: email,
} }
@@ -117,7 +117,7 @@ func TestIntegrationAccountLogin_Success(t *testing.T) {
func TestIntegrationAccountLogin_WrongPassword(t *testing.T) { func TestIntegrationAccountLogin_WrongPassword(t *testing.T) {
ctrl := newTestAccountController(t.Context()) ctrl := newTestAccountController(t.Context())
email := newTestUniqueEmail("accounts") email := newTestUniqueEmail("accounts")
accountData := &controllers.AccountData{ accountData := &services.AccountData{
Password: "qwertyu9", Password: "qwertyu9",
Email: email, Email: email,
} }
@@ -129,13 +129,13 @@ func TestIntegrationAccountLogin_WrongPassword(t *testing.T) {
id, err = ctrl.Login(t.Context(), accountData.Email, "Wrong Password") id, err = ctrl.Login(t.Context(), accountData.Email, "Wrong Password")
assert.Empty(t, id) assert.Empty(t, id)
assert.Error(t, err) assert.Error(t, err)
assert.ErrorIs(t, err, controllers.ErrWrongPassword) assert.ErrorIs(t, err, services.ErrWrongPassword)
} }
func TestIntegrationAccountLogin_WrongEmail(t *testing.T) { func TestIntegrationAccountLogin_WrongEmail(t *testing.T) {
ctrl := newTestAccountController(t.Context()) ctrl := newTestAccountController(t.Context())
email := newTestUniqueEmail("accounts") email := newTestUniqueEmail("accounts")
accountData := &controllers.AccountData{ accountData := &services.AccountData{
Password: "qwertyu9", Password: "qwertyu9",
Email: email, Email: email,
} }
@@ -147,5 +147,5 @@ func TestIntegrationAccountLogin_WrongEmail(t *testing.T) {
id, err = ctrl.Login(t.Context(), "some@email.com", "Wrong Password") id, err = ctrl.Login(t.Context(), "some@email.com", "Wrong Password")
assert.Empty(t, id) assert.Empty(t, id)
assert.Error(t, err) assert.Error(t, err)
assert.ErrorIs(t, err, controllers.ErrUserNotFound) assert.ErrorIs(t, err, services.ErrUserNotFound)
} }

View File

@@ -1,4 +1,4 @@
package controllers package services
import ( import (
"context" "context"

View File

@@ -1,10 +1,10 @@
package controllers_test package services_test
import ( import (
"testing" "testing"
"time" "time"
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/controllers" "gitea.badhouseplants.net/softplayer/softplayer-backend/internal/services"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@@ -16,24 +16,24 @@ var (
) )
func TestGenerateInvalidTokenType(t *testing.T) { func TestGenerateInvalidTokenType(t *testing.T) {
data := &controllers.JWTData{ data := &services.JWTData{
UserID: testUserID, UserID: testUserID,
TokenType: "invalid_type", TokenType: "invalid_type",
} }
authCtrl := controllers.NewAuthController([]byte("test"), testAccessTTL, testRefreshTTL, nil) authCtrl := services.NewAuthController([]byte("test"), testAccessTTL, testRefreshTTL, nil)
token, _, err := authCtrl.GenerateToken(data) token, _, err := authCtrl.GenerateToken(data)
assert.Equal(t, "", token) assert.Equal(t, "", token)
assert.ErrorIs(t, controllers.ErrUnknownTokenType, err) assert.ErrorIs(t, services.ErrUnknownTokenType, err)
} }
func TestGenerateValidateAccessToken(t *testing.T) { func TestGenerateValidateAccessToken(t *testing.T) {
data := &controllers.JWTData{ data := &services.JWTData{
UserID: testUserID, UserID: testUserID,
TokenType: controllers.TokenTypeAccess, TokenType: services.TokenTypeAccess,
} }
authCtrl := controllers.NewAuthController([]byte("test"), testAccessTTL, testRefreshTTL, nil) authCtrl := services.NewAuthController([]byte("test"), testAccessTTL, testRefreshTTL, nil)
now := time.Now() now := time.Now()
token, _, err := authCtrl.GenerateToken(data) token, _, err := authCtrl.GenerateToken(data)
assert.NoError(t, err) assert.NoError(t, err)
@@ -43,18 +43,18 @@ func TestGenerateValidateAccessToken(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, testUserID, claims.UserID) assert.Equal(t, testUserID, claims.UserID)
assert.NotEmpty(t, claims.TokenID) assert.NotEmpty(t, claims.TokenID)
assert.Equal(t, controllers.TokenTypeAccess, claims.TokenType) assert.Equal(t, services.TokenTypeAccess, claims.TokenType)
assert.Equal(t, now.Add(testAccessTTL).Unix(), claims.ExpiresAt.Unix()) assert.Equal(t, now.Add(testAccessTTL).Unix(), claims.ExpiresAt.Unix())
assert.Equal(t, now.Unix(), claims.IssuedAt.Unix()) assert.Equal(t, now.Unix(), claims.IssuedAt.Unix())
assert.Equal(t, now.Unix(), claims.NotBefore.Unix()) assert.Equal(t, now.Unix(), claims.NotBefore.Unix())
} }
func TestGenerateValidateRefreshToken(t *testing.T) { func TestGenerateValidateRefreshToken(t *testing.T) {
data := &controllers.JWTData{ data := &services.JWTData{
UserID: testUserID, UserID: testUserID,
TokenType: controllers.TokenTypeRefresh, TokenType: services.TokenTypeRefresh,
} }
authCtrl := controllers.NewAuthController([]byte("test"), testAccessTTL, testRefreshTTL, nil) authCtrl := services.NewAuthController([]byte("test"), testAccessTTL, testRefreshTTL, nil)
now := time.Now() now := time.Now()
token, _, err := authCtrl.GenerateToken(data) token, _, err := authCtrl.GenerateToken(data)
assert.NoError(t, err) assert.NoError(t, err)
@@ -64,7 +64,7 @@ func TestGenerateValidateRefreshToken(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, testUserID, claims.UserID) assert.Equal(t, testUserID, claims.UserID)
assert.NotEmpty(t, claims.TokenID) assert.NotEmpty(t, claims.TokenID)
assert.Equal(t, controllers.TokenTypeRefresh, claims.TokenType) assert.Equal(t, services.TokenTypeRefresh, claims.TokenType)
assert.Equal(t, now.Add(testRefreshTTL).Unix(), claims.ExpiresAt.Unix()) assert.Equal(t, now.Add(testRefreshTTL).Unix(), claims.ExpiresAt.Unix())
assert.Equal(t, now.Unix(), claims.IssuedAt.Unix()) assert.Equal(t, now.Unix(), claims.IssuedAt.Unix())
assert.Equal(t, now.Unix(), claims.NotBefore.Unix()) assert.Equal(t, now.Unix(), claims.NotBefore.Unix())

View File

@@ -1,13 +1,21 @@
package controllers package services
import "context" import (
"context"
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/helpers/logger"
)
type ProjectsController struct{} type ProjectsController struct{}
type ProjectData struct{} type ProjectData struct{}
// Create a new project // Create a new project
// It should create a project and set an owner to it
func (ctrl *ProjectsController) Create(ctx context.Context, data *ProjectData) (id string, err error) { func (ctrl *ProjectsController) Create(ctx context.Context, data *ProjectData) (id string, err error) {
log := logger.FromContext(ctx)
log.V(2).Info("Creating a project")
return "", nil return "", nil
} }

View File

@@ -1,6 +1,6 @@
// Package controllers for token management // Package controllers for token management
// This a token controller, that implements the logic around tokens // This a token controller, that implements the logic around tokens
package controllers package services
import ( import (
"context" "context"

View File

@@ -1,4 +1,4 @@
package controllers_test package services_test
import ( import (
"context" "context"
@@ -6,13 +6,13 @@ import (
"testing" "testing"
"time" "time"
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/controllers" "gitea.badhouseplants.net/softplayer/softplayer-backend/internal/services"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func newTestTokensController(ctx context.Context) *controllers.TokenController { func newTestTokensController(ctx context.Context) *services.TokenController {
return &controllers.TokenController{ return &services.TokenController{
DB: newTestDBConnection(ctx), DB: newTestDBConnection(ctx),
Redis: newTestRedisConnection(), Redis: newTestRedisConnection(),
} }
@@ -21,14 +21,14 @@ func newTestTokensController(ctx context.Context) *controllers.TokenController {
func TestIntegrationCreateToken_Success(t *testing.T) { func TestIntegrationCreateToken_Success(t *testing.T) {
// Create a user for the token // Create a user for the token
ctrlAccount := newTestAccountController(t.Context()) ctrlAccount := newTestAccountController(t.Context())
accountData := &controllers.AccountData{ accountData := &services.AccountData{
Password: "qwertyu9", Password: "qwertyu9",
Email: newTestUniqueEmail("accounts"), Email: newTestUniqueEmail("accounts"),
} }
id, err := ctrlAccount.Create(t.Context(), accountData) id, err := ctrlAccount.Create(t.Context(), accountData)
assert.NoError(t, err) assert.NoError(t, err)
tokenData := &controllers.TokenData{ tokenData := &services.TokenData{
Name: "Test Token", Name: "Test Token",
UserID: id, UserID: id,
ExpiresAt: time.Now().Add(time.Second * 5), ExpiresAt: time.Now().Add(time.Second * 5),
@@ -45,7 +45,7 @@ func TestIntegrationCreateToken_Success(t *testing.T) {
} }
func TestIntegrationCreateToken_UserNotExist(t *testing.T) { func TestIntegrationCreateToken_UserNotExist(t *testing.T) {
tokenData := &controllers.TokenData{ tokenData := &services.TokenData{
Name: "Test Token", Name: "Test Token",
UserID: uuid.NewString(), UserID: uuid.NewString(),
ExpiresAt: time.Now().Add(time.Second * 5), ExpiresAt: time.Now().Add(time.Second * 5),
@@ -58,7 +58,7 @@ func TestIntegrationCreateToken_UserNotExist(t *testing.T) {
tokenVal, tokenID, err := ctrl.Create(t.Context(), tokenData) tokenVal, tokenID, err := ctrl.Create(t.Context(), tokenData)
assert.Error(t, err) assert.Error(t, err)
assert.ErrorIs(t, err, controllers.ErrUserNotFound) assert.ErrorIs(t, err, services.ErrUserNotFound)
assert.Empty(t, tokenID) assert.Empty(t, tokenID)
assert.Empty(t, tokenVal) assert.Empty(t, tokenVal)
} }
@@ -66,7 +66,7 @@ func TestIntegrationCreateToken_UserNotExist(t *testing.T) {
func TestIntegrationGetToken_Success(t *testing.T) { func TestIntegrationGetToken_Success(t *testing.T) {
// Create a user for the token // Create a user for the token
ctrlAccount := newTestAccountController(t.Context()) ctrlAccount := newTestAccountController(t.Context())
accountData := &controllers.AccountData{ accountData := &services.AccountData{
Password: "qwertyu9", Password: "qwertyu9",
Email: newTestUniqueEmail("accounts"), Email: newTestUniqueEmail("accounts"),
} }
@@ -75,7 +75,7 @@ func TestIntegrationGetToken_Success(t *testing.T) {
userID, err := ctrlAccount.Create(t.Context(), accountData) userID, err := ctrlAccount.Create(t.Context(), accountData)
assert.NoError(t, err) assert.NoError(t, err)
tokenData := &controllers.TokenData{ tokenData := &services.TokenData{
Name: "Test Token", Name: "Test Token",
UserID: userID, UserID: userID,
ExpiresAt: time.Now().Add(time.Second * 5), ExpiresAt: time.Now().Add(time.Second * 5),
@@ -101,7 +101,7 @@ func TestIntegrationGetToken_NotExists(t *testing.T) {
ctrl := newTestTokensController(t.Context()) ctrl := newTestTokensController(t.Context())
token, err := ctrl.Get(t.Context(), uuid.NewString(), uuid.NewString()) token, err := ctrl.Get(t.Context(), uuid.NewString(), uuid.NewString())
assert.Error(t, err) assert.Error(t, err)
assert.ErrorIs(t, err, controllers.ErrTokenNotFound) assert.ErrorIs(t, err, services.ErrTokenNotFound)
assert.Empty(t, token) assert.Empty(t, token)
} }
@@ -109,14 +109,14 @@ func TestIntegrationGetToken_WrongRequest(t *testing.T) {
ctrl := newTestTokensController(t.Context()) ctrl := newTestTokensController(t.Context())
token, err := ctrl.Get(t.Context(), "test", "test") token, err := ctrl.Get(t.Context(), "test", "test")
assert.Error(t, err) assert.Error(t, err)
assert.ErrorIs(t, err, controllers.ErrServerError) assert.ErrorIs(t, err, services.ErrServerError)
assert.Empty(t, token) assert.Empty(t, token)
} }
func TestIntegrationVerifyTokenOwner_Success(t *testing.T) { func TestIntegrationVerifyTokenOwner_Success(t *testing.T) {
// Create a user for the token // Create a user for the token
ctrlAccount := newTestAccountController(t.Context()) ctrlAccount := newTestAccountController(t.Context())
accountData := &controllers.AccountData{ accountData := &services.AccountData{
Password: "qwertyu9", Password: "qwertyu9",
Email: newTestUniqueEmail("accounts"), Email: newTestUniqueEmail("accounts"),
} }
@@ -124,7 +124,7 @@ func TestIntegrationVerifyTokenOwner_Success(t *testing.T) {
userID, err := ctrlAccount.Create(t.Context(), accountData) userID, err := ctrlAccount.Create(t.Context(), accountData)
assert.NoError(t, err) assert.NoError(t, err)
tokenData := &controllers.TokenData{ tokenData := &services.TokenData{
Name: "Test Token", Name: "Test Token",
UserID: userID, UserID: userID,
ExpiresAt: time.Now().Add(time.Second * 5), ExpiresAt: time.Now().Add(time.Second * 5),
@@ -142,12 +142,12 @@ func TestIntegrationVerifyTokenOwner_Success(t *testing.T) {
func TestIntegrationVerifyTokenOwner_WrongOwner(t *testing.T) { func TestIntegrationVerifyTokenOwner_WrongOwner(t *testing.T) {
// Create a user for the token // Create a user for the token
ctrlAccount := newTestAccountController(t.Context()) ctrlAccount := newTestAccountController(t.Context())
accountData := &controllers.AccountData{ accountData := &services.AccountData{
Password: "qwertyu9", Password: "qwertyu9",
Email: newTestUniqueEmail("accounts"), Email: newTestUniqueEmail("accounts"),
} }
secondAccountData := &controllers.AccountData{ secondAccountData := &services.AccountData{
Password: "qwertyu9", Password: "qwertyu9",
Email: newTestUniqueEmail("accounts"), Email: newTestUniqueEmail("accounts"),
} }
@@ -157,7 +157,7 @@ func TestIntegrationVerifyTokenOwner_WrongOwner(t *testing.T) {
secondUserID, err := ctrlAccount.Create(t.Context(), secondAccountData) secondUserID, err := ctrlAccount.Create(t.Context(), secondAccountData)
assert.NoError(t, err) assert.NoError(t, err)
tokenData := &controllers.TokenData{ tokenData := &services.TokenData{
Name: "Test Token", Name: "Test Token",
UserID: userID, UserID: userID,
ExpiresAt: time.Now().Add(time.Second * 5), ExpiresAt: time.Now().Add(time.Second * 5),
@@ -169,13 +169,13 @@ func TestIntegrationVerifyTokenOwner_WrongOwner(t *testing.T) {
ctrl := newTestTokensController(t.Context()) ctrl := newTestTokensController(t.Context())
_, tokenID, err := ctrl.Create(t.Context(), tokenData) _, tokenID, err := ctrl.Create(t.Context(), tokenData)
assert.NoError(t, err) assert.NoError(t, err)
assert.ErrorIs(t, ctrl.VerifyTokenOwner(t.Context(), secondUserID, tokenID), controllers.ErrUserTokenMismatch) assert.ErrorIs(t, ctrl.VerifyTokenOwner(t.Context(), secondUserID, tokenID), services.ErrUserTokenMismatch)
} }
func TestIntegrationForceExpiration_Success(t *testing.T) { func TestIntegrationForceExpiration_Success(t *testing.T) {
// Create a user for the token // Create a user for the token
ctrlAccount := newTestAccountController(t.Context()) ctrlAccount := newTestAccountController(t.Context())
accountData := &controllers.AccountData{ accountData := &services.AccountData{
Password: "qwertyu9", Password: "qwertyu9",
Email: newTestUniqueEmail("accounts"), Email: newTestUniqueEmail("accounts"),
} }
@@ -183,7 +183,7 @@ func TestIntegrationForceExpiration_Success(t *testing.T) {
userID, err := ctrlAccount.Create(t.Context(), accountData) userID, err := ctrlAccount.Create(t.Context(), accountData)
assert.NoError(t, err) assert.NoError(t, err)
tokenData := &controllers.TokenData{ tokenData := &services.TokenData{
Name: "Test Token", Name: "Test Token",
UserID: userID, UserID: userID,
ExpiresAt: time.Now().Add(time.Second * 5), ExpiresAt: time.Now().Add(time.Second * 5),
@@ -205,7 +205,7 @@ func TestIntegrationForceExpiration_Success(t *testing.T) {
func TestIntegrationRegenerateToken_Success(t *testing.T) { func TestIntegrationRegenerateToken_Success(t *testing.T) {
// Create a user for the token // Create a user for the token
ctrlAccount := newTestAccountController(t.Context()) ctrlAccount := newTestAccountController(t.Context())
accountData := &controllers.AccountData{ accountData := &services.AccountData{
Password: "qwertyu9", Password: "qwertyu9",
Email: newTestUniqueEmail("accounts"), Email: newTestUniqueEmail("accounts"),
} }
@@ -214,7 +214,7 @@ func TestIntegrationRegenerateToken_Success(t *testing.T) {
userID, err := ctrlAccount.Create(t.Context(), accountData) userID, err := ctrlAccount.Create(t.Context(), accountData)
assert.NoError(t, err) assert.NoError(t, err)
tokenData := &controllers.TokenData{ tokenData := &services.TokenData{
Name: "Test Token", Name: "Test Token",
UserID: userID, UserID: userID,
ExpiresAt: time.Now().Add(time.Second * 5), ExpiresAt: time.Now().Add(time.Second * 5),
@@ -255,7 +255,7 @@ func TestIntegrationRegenerateToken_Success(t *testing.T) {
func TestIntegrationListTokens_Success(t *testing.T) { func TestIntegrationListTokens_Success(t *testing.T) {
// Create a user for the token // Create a user for the token
ctrlAccount := newTestAccountController(t.Context()) ctrlAccount := newTestAccountController(t.Context())
accountData := &controllers.AccountData{ accountData := &services.AccountData{
Password: "qwertyu9", Password: "qwertyu9",
Email: newTestUniqueEmail("accounts"), Email: newTestUniqueEmail("accounts"),
} }
@@ -263,7 +263,7 @@ func TestIntegrationListTokens_Success(t *testing.T) {
userID, err := ctrlAccount.Create(t.Context(), accountData) userID, err := ctrlAccount.Create(t.Context(), accountData)
assert.NoError(t, err) assert.NoError(t, err)
tokenDataOne := &controllers.TokenData{ tokenDataOne := &services.TokenData{
Name: "Test Token", Name: "Test Token",
UserID: userID, UserID: userID,
ExpiresAt: time.Now().Add(time.Second * 5), ExpiresAt: time.Now().Add(time.Second * 5),
@@ -271,7 +271,7 @@ func TestIntegrationListTokens_Success(t *testing.T) {
"Test": {"test", "test2"}, "Test": {"test", "test2"},
}, },
} }
tokenDataTwo := &controllers.TokenData{ tokenDataTwo := &services.TokenData{
Name: "Test Token again", Name: "Test Token again",
UserID: userID, UserID: userID,
ExpiresAt: time.Now().Add(time.Second * 5), ExpiresAt: time.Now().Add(time.Second * 5),
@@ -293,14 +293,14 @@ func TestIntegrationListTokens_Success(t *testing.T) {
func TestIntegrationAuthenticateWithToken_Success(t *testing.T) { func TestIntegrationAuthenticateWithToken_Success(t *testing.T) {
ctrlAccount := newTestAccountController(t.Context()) ctrlAccount := newTestAccountController(t.Context())
accountData := &controllers.AccountData{ accountData := &services.AccountData{
Password: "qwertyu9", Password: "qwertyu9",
Email: newTestUniqueEmail("accounts"), Email: newTestUniqueEmail("accounts"),
} }
id, err := ctrlAccount.Create(t.Context(), accountData) id, err := ctrlAccount.Create(t.Context(), accountData)
assert.NoError(t, err) assert.NoError(t, err)
tokenData := &controllers.TokenData{ tokenData := &services.TokenData{
Name: "Test Token", Name: "Test Token",
UserID: id, UserID: id,
ExpiresAt: time.Now().Add(time.Second * 5), ExpiresAt: time.Now().Add(time.Second * 5),
@@ -330,19 +330,19 @@ func TestIntegrationAuthenticateWithToken_UnknownToken(t *testing.T) {
auth, err := ctrl.AuthenticateWithToken(t.Context(), "dummy") auth, err := ctrl.AuthenticateWithToken(t.Context(), "dummy")
assert.Error(t, err) assert.Error(t, err)
assert.Nil(t, auth) assert.Nil(t, auth)
assert.ErrorIs(t, err, controllers.ErrTokenNotFound) assert.ErrorIs(t, err, services.ErrTokenNotFound)
} }
func TestIntegrationAuthenticateWithToken_Expired(t *testing.T) { func TestIntegrationAuthenticateWithToken_Expired(t *testing.T) {
ctrlAccount := newTestAccountController(t.Context()) ctrlAccount := newTestAccountController(t.Context())
accountData := &controllers.AccountData{ accountData := &services.AccountData{
Password: "qwertyu9", Password: "qwertyu9",
Email: newTestUniqueEmail("accounts"), Email: newTestUniqueEmail("accounts"),
} }
id, err := ctrlAccount.Create(t.Context(), accountData) id, err := ctrlAccount.Create(t.Context(), accountData)
assert.NoError(t, err) assert.NoError(t, err)
tokenData := &controllers.TokenData{ tokenData := &services.TokenData{
Name: "Test Token", Name: "Test Token",
UserID: id, UserID: id,
ExpiresAt: time.Now().Add(time.Second * 5), ExpiresAt: time.Now().Add(time.Second * 5),
@@ -365,19 +365,19 @@ func TestIntegrationAuthenticateWithToken_Expired(t *testing.T) {
auth, err = ctrl.AuthenticateWithToken(t.Context(), tokenVal) auth, err = ctrl.AuthenticateWithToken(t.Context(), tokenVal)
assert.Error(t, err) assert.Error(t, err)
assert.Nil(t, auth) assert.Nil(t, auth)
assert.ErrorIs(t, err, controllers.ErrBadToken) assert.ErrorIs(t, err, services.ErrBadToken)
} }
func TestIntegrationAuthenticateWithToken_Revoked(t *testing.T) { func TestIntegrationAuthenticateWithToken_Revoked(t *testing.T) {
ctrlAccount := newTestAccountController(t.Context()) ctrlAccount := newTestAccountController(t.Context())
accountData := &controllers.AccountData{ accountData := &services.AccountData{
Password: "qwertyu9", Password: "qwertyu9",
Email: newTestUniqueEmail("accounts"), Email: newTestUniqueEmail("accounts"),
} }
id, err := ctrlAccount.Create(t.Context(), accountData) id, err := ctrlAccount.Create(t.Context(), accountData)
assert.NoError(t, err) assert.NoError(t, err)
tokenData := &controllers.TokenData{ tokenData := &services.TokenData{
Name: "Test Token", Name: "Test Token",
UserID: id, UserID: id,
ExpiresAt: time.Now().Add(time.Second * 5), ExpiresAt: time.Now().Add(time.Second * 5),
@@ -399,5 +399,5 @@ func TestIntegrationAuthenticateWithToken_Revoked(t *testing.T) {
auth, err = ctrl.AuthenticateWithToken(t.Context(), tokenVal) auth, err = ctrl.AuthenticateWithToken(t.Context(), tokenVal)
assert.Error(t, err) assert.Error(t, err)
assert.Nil(t, auth) assert.Nil(t, auth)
assert.ErrorIs(t, err, controllers.ErrBadToken) assert.ErrorIs(t, err, services.ErrBadToken)
} }