diff options
| author | Bobby <[email protected]> | 2026-03-07 08:52:35 +0530 |
|---|---|---|
| committer | Bobby <[email protected]> | 2026-03-07 08:52:35 +0530 |
| commit | 82409d6b83de1baab69c166af8f04c6e9fe9069f (patch) | |
| tree | 678b3ee2242b20da49c8cf1ff0ec509d0c8ef1e1 /shrine/services/auth.go | |
| parent | a97d1ad37463107b462958d92f596ebb80254b77 (diff) | |
| download | pagoda-82409d6b83de1baab69c166af8f04c6e9fe9069f.tar.xz pagoda-82409d6b83de1baab69c166af8f04c6e9fe9069f.zip | |
feat: Implement letter service with CRUD operations and message handling
- Added letter service to manage letters, including listing, creating, and editing letters and messages.
- Implemented functionality for sending and receiving messages within letters.
- Introduced pagination for letter listings and message retrieval.
- Added attachment upload capabilities for letters.
- Created detailed responses for letter and message retrieval.
feat: Introduce stats service for user statistics
- Added a service to retrieve user statistics, including newest and online citizens.
feat: Create ticket service for user support tickets
- Implemented ticket management service with functionalities to create, reply, and update tickets.
- Added support for ticket categories and their management.
feat: Add verification service for user account verification
- Implemented functionality to send verification emails for account activation.
feat: Develop warning service for user warnings
- Added service to issue warnings to users, deactivate warnings, and list user warnings.
feat: Create email templates for account status notifications
- Added HTML templates for account ban and disable notifications.
feat: Define request and response types for account, ticket, letter, and warning services
- Created structured request and response types for various services to ensure consistent data handling.
feat: Implement utility functions for authentication and sanitization
- Added functions for validating user hierarchy and sanitizing HTML input.
- Implemented token generation and hashing utilities for secure operations.
Diffstat (limited to 'shrine/services/auth.go')
| -rw-r--r-- | shrine/services/auth.go | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/shrine/services/auth.go b/shrine/services/auth.go new file mode 100644 index 0000000..28e63c4 --- /dev/null +++ b/shrine/services/auth.go @@ -0,0 +1,108 @@ +package services + +import ( + "shrine/enums" + "shrine/messages" + "shrine/models" + "shrine/repositories" + "shrine/types/account" + "shrine/types/common" + "shrine/types/hypertext" + "shrine/utils/crypto" +) + +func Register(request account.RegisterRequest) (*common.MessageResponse, *hypertext.ServiceError) { + citizen := models.User{ + Username: request.Username, + Email: request.Email, + DisplayName: request.DisplayName, + } + + if err := citizen.SetPassword(request.Password); err != nil { + return nil, fail(enums.BadRequest, err.Error()) + } + + if err := repositories.CreateUser(&citizen); err != nil { + return nil, mapRegistrationError(err) + } + + if serviceErr := SendVerification(&citizen, enums.Activation); serviceErr != nil { + return nil, serviceErr + } + + return &common.MessageResponse{Message: messages.AccountCreated}, nil +} + +func Authenticate(request account.LoginRequest) (*models.User, *hypertext.ServiceError) { + citizen, err := repositories.FindUserByUsername(request.Username) + if err != nil { + return nil, fail(enums.Unauthorized, messages.InvalidUsernameOrPassword) + } + + if citizen.ClearExpiredDisable() { + repositories.UpdateUser(citizen) + } + + if !citizen.CanAuthenticate() { + return nil, fail(enums.Forbidden, messages.AccountBannedOrDisabled) + } + + if !citizen.CheckPassword(request.Password) { + return nil, fail(enums.Unauthorized, messages.InvalidUsernameOrPassword) + } + + if !citizen.IsVerified() { + return nil, fail(enums.Forbidden, messages.EmailNotVerified) + } + + return citizen, nil +} + +func VerifyAccount(request account.VerifyRequest) (*common.MessageResponse, *hypertext.ServiceError) { + if request.Token == "" { + return nil, fail(enums.BadRequest, messages.VerificationTokenRequired) + } + + verificationType := enums.VerificationType(request.Type) + citizen, err := repositories.FindUserByVerification(crypto.HashToken(request.Token), verificationType) + if err != nil { + return nil, fail(enums.BadRequest, messages.VerificationLinkInvalid) + } + + switch verificationType { + case enums.Activation: + citizen.VerifyEmail() + default: + return nil, fail(enums.BadRequest, messages.InvalidVerificationType) + } + + if err := repositories.UpdateUser(citizen); err != nil { + return nil, fail(enums.Internal, messages.FailedVerifyAccount) + } + + return &common.MessageResponse{Message: messages.EmailVerified}, nil +} + +func ResendActivation(request account.ResendActivationRequest) (*common.MessageResponse, *hypertext.ServiceError) { + citizen, err := repositories.FindUserByEmail(request.Email) + if err != nil { + return nil, fail(enums.BadRequest, messages.NoAccountWithEmail) + } + + if citizen.IsVerified() { + return nil, fail(enums.BadRequest, messages.AccountAlreadyVerified) + } + + if serviceErr := SendVerification(citizen, enums.Activation); serviceErr != nil { + return nil, serviceErr + } + + return &common.MessageResponse{Message: messages.VerificationEmailSent}, nil +} + +func RevokeToken(tokenHash string) (*common.MessageResponse, *hypertext.ServiceError) { + if err := repositories.DeleteToken(tokenHash); err != nil { + return nil, fail(enums.Internal, messages.FailedEndSession) + } + return &common.MessageResponse{Message: messages.LoggedOut}, nil +}
\ No newline at end of file |
