From 64db382546b10168bdbd147356012d4126a1e9b2 Mon Sep 17 00:00:00 2001 From: Nikolai Rodionov Date: Wed, 10 Jun 2026 16:02:23 +0200 Subject: [PATCH] Return correct errors in public accounts service Signed-off-by: Nikolai Rodionov --- "\\" | 123 +++++++++++++++++++++++++++++ internal/api/v1/public_accounts.go | 7 ++ 2 files changed, 130 insertions(+) create mode 100644 "\\" diff --git "a/\\" "b/\\" new file mode 100644 index 0000000..af9f83d --- /dev/null +++ "b/\\" @@ -0,0 +1,123 @@ +package v1 + +import ( + "context" + "errors" + + "gitea.badhouseplants.net/softplayer/softplayer-backend/internal/services" + accounts "gitea.badhouseplants.net/softplayer/softplayer-go-proto/pkg/accounts/v1" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func NewPublicAccountServer( + accountsCtrl *services.AccountController, + authorizationCtrl *services.AuthController, +) *PublicAccountService { + return &PublicAccountService{ + accountsCtrl: accountsCtrl, + authorizationCtrl: authorizationCtrl, + } +} + +type PublicAccountService struct { + accounts.UnimplementedPublicAccountsServiceServer + accountsCtrl *services.AccountController + authorizationCtrl *services.AuthController +} + +func (a *PublicAccountService) SignIn(ctx context.Context, in *accounts.SignInRequest) (*accounts.SignInResponse, error) { + id, err := a.accountsCtrl.Login(ctx, in.GetEmail(), in.GetPassword()) + if err != nil { + if errors.Is(err, services.ErrUserNotFound) { + return nil, status.Error(codes.NotFound, "User not found") + } + return nil, status.Error(codes.Aborted, "Couldn't create a user") + } + accessToken, _, err := a.authorizationCtrl.GenerateToken(&services.JWTData{ + UserID: id, + TokenType: services.TokenTypeAccess, + TokenAud: services.TokenAudWeb, + }) + if err != nil { + return nil, status.Error(codes.Aborted, "Couldn't generate an access token") + } + + refreshToken, tokenID, err := a.authorizationCtrl.GenerateToken(&services.JWTData{ + UserID: id, + TokenType: services.TokenTypeRefresh, + TokenAud: services.TokenAudWeb, + }) + if err != nil { + return nil, status.Error(codes.Aborted, "Couldn't generate an access token") + } + + session := &services.Session{UserID: id} + + if err := a.authorizationCtrl.SaveSession(ctx, tokenID, session); err != nil { + return nil, status.Error(codes.Aborted, "Couldn't store session") + } + return &accounts.SignInResponse{ + TokenPair: &accounts.TokenPair{ + AccessToken: accessToken, + RefreshToken: refreshToken, + }, + }, nil +} + +// Create a new account in Softplayer +func (a *PublicAccountService) SignUp(ctx context.Context, in *accounts.SignUpRequest) (*accounts.SignUpResponse, error) { + data := &services.AccountData{ + Password: in.GetPassword(), + Email: in.GetEmail(), + Name: in.PersonalData.GetName(), + Surname: in.PersonalData.GetSurname(), + } + id, err := a.accountsCtrl.Create(ctx, data) + if err != nil { + if errors.Is(err, services.ErrEmailUsed) { + return nil, status.Error(codes.AlreadyExists, "Email is already used by another account") + } + return nil, status.Error(codes.Aborted, "Couldn't create a user") + } + + accessToken, _, err := a.authorizationCtrl.GenerateToken(&services.JWTData{ + UserID: id, + TokenType: services.TokenTypeAccess, + TokenAud: services.TokenAudWeb, + }) + if err != nil { + return nil, status.Error(codes.Aborted, "Couldn't generate an access token") + } + + refreshToken, tokenID, err := a.authorizationCtrl.GenerateToken(&services.JWTData{ + UserID: id, + TokenType: services.TokenTypeRefresh, + TokenAud: services.TokenAudWeb, + }) + if err != nil { + return nil, status.Error(codes.Aborted, "Couldn't generate an access token") + } + + session := &services.Session{UserID: id} + + if err := a.authorizationCtrl.SaveSession(ctx, tokenID, session); err != nil { + return nil, status.Error(codes.Aborted, "Couldn't store session") + } + + return &accounts.SignUpResponse{ + TokenPair: &accounts.TokenPair{ + AccessToken: accessToken, + RefreshToken: refreshToken, + }, + }, nil +} + +// Check if an email is already used by an account +func (a *PublicAccountService) IsEmailAvailable(ctx context.Context, in *accounts.IsEmailUsedRequest) (*accounts.IsEmailUsedResponse, error) { + exists, err := a.accountsCtrl.IsExist(ctx, in.GetEmail()) + if err != nil { + return nil, status.Error(codes.Aborted, "Couldn't check email availability") + } + return &accounts.IsEmailUsedResponse{Used: exists}, nil +} diff --git a/internal/api/v1/public_accounts.go b/internal/api/v1/public_accounts.go index a043a0a..af9f83d 100644 --- a/internal/api/v1/public_accounts.go +++ b/internal/api/v1/public_accounts.go @@ -2,6 +2,7 @@ package v1 import ( "context" + "errors" "gitea.badhouseplants.net/softplayer/softplayer-backend/internal/services" accounts "gitea.badhouseplants.net/softplayer/softplayer-go-proto/pkg/accounts/v1" @@ -28,6 +29,9 @@ type PublicAccountService struct { func (a *PublicAccountService) SignIn(ctx context.Context, in *accounts.SignInRequest) (*accounts.SignInResponse, error) { id, err := a.accountsCtrl.Login(ctx, in.GetEmail(), in.GetPassword()) if err != nil { + if errors.Is(err, services.ErrUserNotFound) { + return nil, status.Error(codes.NotFound, "User not found") + } return nil, status.Error(codes.Aborted, "Couldn't create a user") } accessToken, _, err := a.authorizationCtrl.GenerateToken(&services.JWTData{ @@ -71,6 +75,9 @@ func (a *PublicAccountService) SignUp(ctx context.Context, in *accounts.SignUpRe } id, err := a.accountsCtrl.Create(ctx, data) if err != nil { + if errors.Is(err, services.ErrEmailUsed) { + return nil, status.Error(codes.AlreadyExists, "Email is already used by another account") + } return nil, status.Error(codes.Aborted, "Couldn't create a user") }