diff options
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 |
