diff options
Diffstat (limited to 'nexus/services')
| -rw-r--r-- | nexus/services/account/account.go | 46 | ||||
| -rw-r--r-- | nexus/services/account/defaults.go | 3 | ||||
| -rw-r--r-- | nexus/services/account/messages.go | 7 | ||||
| -rw-r--r-- | nexus/services/auth/auth.go | 129 | ||||
| -rw-r--r-- | nexus/services/auth/defaults.go | 3 | ||||
| -rw-r--r-- | nexus/services/auth/messages.go | 17 | ||||
| -rw-r--r-- | nexus/services/character/character.go | 79 | ||||
| -rw-r--r-- | nexus/services/character/defaults.go | 3 | ||||
| -rw-r--r-- | nexus/services/character/messages.go | 11 |
9 files changed, 298 insertions, 0 deletions
diff --git a/nexus/services/account/account.go b/nexus/services/account/account.go new file mode 100644 index 0000000..a990659 --- /dev/null +++ b/nexus/services/account/account.go @@ -0,0 +1,46 @@ +package account
+
+import (
+ "fmt"
+ "nexus/models"
+ "nexus/repositories/account"
+ "nexus/utils/logger"
+ "nexus/utils/shortcuts"
+
+ "github.com/gofiber/fiber/v2"
+ "github.com/google/uuid"
+)
+
+func GetByID(id uuid.UUID) (*models.Account, *fiber.Error) {
+ a, err := account.FindByID(id)
+ if err != nil {
+ return nil, shortcuts.ServiceError(fiber.StatusNotFound, ErrAccountNotFound)
+ }
+ return a, nil
+}
+
+func Disable(id uuid.UUID) *fiber.Error {
+ if _, err := account.FindByID(id); err != nil {
+ return shortcuts.ServiceError(fiber.StatusNotFound, ErrAccountNotFound)
+ }
+
+ if err := account.Disable(id); err != nil {
+ logger.Errorf(LogPrefix, AccountDisableFailed, err)
+ return shortcuts.ServiceError(fiber.StatusInternalServerError, fmt.Sprintf(AccountDisableFailed, err))
+ }
+
+ return nil
+}
+
+func Delete(id uuid.UUID) *fiber.Error {
+ if _, err := account.FindByID(id); err != nil {
+ return shortcuts.ServiceError(fiber.StatusNotFound, ErrAccountNotFound)
+ }
+
+ if err := account.Delete(id); err != nil {
+ logger.Errorf(LogPrefix, AccountDeleteFailed, err)
+ return shortcuts.ServiceError(fiber.StatusInternalServerError, fmt.Sprintf(AccountDeleteFailed, err))
+ }
+
+ return nil
+}
diff --git a/nexus/services/account/defaults.go b/nexus/services/account/defaults.go new file mode 100644 index 0000000..ec8fedb --- /dev/null +++ b/nexus/services/account/defaults.go @@ -0,0 +1,3 @@ +package account
+
+const LogPrefix = "Account"
diff --git a/nexus/services/account/messages.go b/nexus/services/account/messages.go new file mode 100644 index 0000000..6bf6024 --- /dev/null +++ b/nexus/services/account/messages.go @@ -0,0 +1,7 @@ +package account
+
+const (
+ ErrAccountNotFound = "account not found"
+ AccountDisableFailed = "failed to disable account: %v"
+ AccountDeleteFailed = "failed to delete account: %v"
+)
diff --git a/nexus/services/auth/auth.go b/nexus/services/auth/auth.go new file mode 100644 index 0000000..c9c97c6 --- /dev/null +++ b/nexus/services/auth/auth.go @@ -0,0 +1,129 @@ +package auth
+
+import (
+ "fmt"
+ "nexus/config"
+ "nexus/models"
+ "nexus/repositories/account"
+ "nexus/repositories/session"
+ "nexus/types/auth"
+ "nexus/utils/logger"
+ "nexus/utils/shortcuts"
+ "nexus/utils/token"
+ "time"
+
+ "github.com/gofiber/fiber/v2"
+ "github.com/google/uuid"
+)
+
+func Register(req auth.RegisterRequest) (*models.Account, *fiber.Error) {
+ if existing, _ := account.FindByEmail(req.Email); existing != nil {
+ return nil, shortcuts.ServiceError(fiber.StatusConflict, ErrEmailTaken)
+ }
+
+ if existing, _ := account.FindByUsername(req.Username); existing != nil {
+ return nil, shortcuts.ServiceError(fiber.StatusConflict, ErrUsernameTaken)
+ }
+
+ a := &models.Account{
+ Username: req.Username,
+ Email: req.Email,
+ }
+
+ if err := a.SetPassword(req.Password); err != nil {
+ logger.Errorf(LogPrefix, PasswordHashFailed, err)
+ return nil, shortcuts.ServiceError(fiber.StatusInternalServerError, fmt.Sprintf(PasswordHashFailed, err))
+ }
+
+ if err := account.Create(a); err != nil {
+ logger.Errorf(LogPrefix, AccountCreateFailed, err)
+ return nil, shortcuts.ServiceError(fiber.StatusInternalServerError, fmt.Sprintf(AccountCreateFailed, err))
+ }
+
+ logger.Successf(LogPrefix, AccountCreated, a.Username)
+ return a, nil
+}
+
+func Login(req auth.LoginRequest, ip string, userAgent string) (*models.Session, *fiber.Error) {
+ a, err := account.FindByEmail(req.Email)
+ if err != nil || a == nil {
+ return nil, shortcuts.ServiceError(fiber.StatusUnauthorized, ErrInvalidCredentials)
+ }
+
+ if !a.IsActive {
+ return nil, shortcuts.ServiceError(fiber.StatusForbidden, ErrAccountDisabled)
+ }
+
+ if !a.CheckPassword(req.Password) {
+ return nil, shortcuts.ServiceError(fiber.StatusUnauthorized, ErrInvalidCredentials)
+ }
+
+ s, sessionErr := createSession(a.ID, ip, userAgent)
+ if sessionErr != nil {
+ return nil, sessionErr
+ }
+
+ logger.Successf(LogPrefix, LoginSuccess, a.Username)
+ return s, nil
+}
+
+func Refresh(refreshToken string, ip string, userAgent string) (*models.Session, *fiber.Error) {
+ s, err := session.FindByRefreshToken(refreshToken)
+ if err != nil || s == nil {
+ return nil, shortcuts.ServiceError(fiber.StatusUnauthorized, ErrInvalidToken)
+ }
+
+ if s.IsRefreshExpired() {
+ _ = session.Delete(s.ID)
+ return nil, shortcuts.ServiceError(fiber.StatusUnauthorized, ErrTokenExpired)
+ }
+
+ _ = session.Delete(s.ID)
+
+ return createSession(s.AccountID, ip, userAgent)
+}
+
+func Logout(authToken string) *fiber.Error {
+ s, err := session.FindByAuthToken(authToken)
+ if err != nil || s == nil {
+ return shortcuts.ServiceError(fiber.StatusUnauthorized, ErrInvalidToken)
+ }
+
+ if err := session.Delete(s.ID); err != nil {
+ logger.Errorf(LogPrefix, LogoutFailed, err)
+ return shortcuts.ServiceError(fiber.StatusInternalServerError, fmt.Sprintf(LogoutFailed, err))
+ }
+
+ return nil
+}
+
+func createSession(accountID uuid.UUID, ip string, userAgent string) (*models.Session, *fiber.Error) {
+ authToken, err := token.Generate()
+ if err != nil {
+ logger.Errorf(LogPrefix, TokenGenerateFailed, err)
+ return nil, shortcuts.ServiceError(fiber.StatusInternalServerError, fmt.Sprintf(TokenGenerateFailed, err))
+ }
+
+ refreshToken, err := token.Generate()
+ if err != nil {
+ logger.Errorf(LogPrefix, TokenGenerateFailed, err)
+ return nil, shortcuts.ServiceError(fiber.StatusInternalServerError, fmt.Sprintf(TokenGenerateFailed, err))
+ }
+
+ s := &models.Session{
+ AccountID: accountID,
+ AuthToken: authToken,
+ RefreshToken: refreshToken,
+ AuthExpiry: time.Now().Add(time.Duration(config.Token.AuthExpiry) * time.Minute),
+ RefreshExpiry: time.Now().Add(time.Duration(config.Token.RefreshExpiry) * 24 * time.Hour),
+ IPAddress: ip,
+ UserAgent: userAgent,
+ }
+
+ if err := session.Create(s); err != nil {
+ logger.Errorf(LogPrefix, SessionCreateFailed, err)
+ return nil, shortcuts.ServiceError(fiber.StatusInternalServerError, fmt.Sprintf(SessionCreateFailed, err))
+ }
+
+ return s, nil
+}
diff --git a/nexus/services/auth/defaults.go b/nexus/services/auth/defaults.go new file mode 100644 index 0000000..3a18c38 --- /dev/null +++ b/nexus/services/auth/defaults.go @@ -0,0 +1,3 @@ +package auth
+
+const LogPrefix = "Auth"
diff --git a/nexus/services/auth/messages.go b/nexus/services/auth/messages.go new file mode 100644 index 0000000..b13dfe6 --- /dev/null +++ b/nexus/services/auth/messages.go @@ -0,0 +1,17 @@ +package auth
+
+const (
+ ErrEmailTaken = "email is already taken"
+ ErrUsernameTaken = "username is already taken"
+ ErrInvalidCredentials = "invalid email or password"
+ ErrAccountDisabled = "account is disabled"
+ ErrInvalidToken = "invalid token"
+ ErrTokenExpired = "token has expired"
+ PasswordHashFailed = "failed to hash password: %v"
+ AccountCreateFailed = "failed to create account: %v"
+ AccountCreated = "account created: %s"
+ LoginSuccess = "login successful: %s"
+ LogoutFailed = "failed to logout: %v"
+ TokenGenerateFailed = "failed to generate token: %v"
+ SessionCreateFailed = "failed to create session: %v"
+)
diff --git a/nexus/services/character/character.go b/nexus/services/character/character.go new file mode 100644 index 0000000..c607d66 --- /dev/null +++ b/nexus/services/character/character.go @@ -0,0 +1,79 @@ +package character
+
+import (
+ "fmt"
+ "nexus/models"
+ "nexus/repositories/character"
+ "nexus/repositories/realm"
+ characterTypes "nexus/types/character"
+ "nexus/utils/logger"
+ "nexus/utils/shortcuts"
+
+ "github.com/gofiber/fiber/v2"
+ "github.com/google/uuid"
+)
+
+func GetAllForAccount(accountID uuid.UUID) ([]models.Character, *fiber.Error) {
+ characters, err := character.FindByAccountID(accountID)
+ if err != nil {
+ logger.Errorf(LogPrefix, CharactersFetchFailed, err)
+ return nil, shortcuts.ServiceError(fiber.StatusInternalServerError, fmt.Sprintf(CharactersFetchFailed, err))
+ }
+ return characters, nil
+}
+
+func GetByID(id uuid.UUID, accountID uuid.UUID) (*models.Character, *fiber.Error) {
+ c, err := character.FindByID(id)
+ if err != nil {
+ return nil, shortcuts.ServiceError(fiber.StatusNotFound, ErrCharacterNotFound)
+ }
+ if c.AccountID != accountID {
+ return nil, shortcuts.ServiceError(fiber.StatusNotFound, ErrCharacterNotFound)
+ }
+ return c, nil
+}
+
+func Create(accountID uuid.UUID, req characterTypes.CreateRequest) (*models.Character, *fiber.Error) {
+ r, err := realm.FindByID(req.RealmID)
+ if err != nil || r == nil {
+ return nil, shortcuts.ServiceError(fiber.StatusNotFound, ErrRealmNotFound)
+ }
+
+ if !r.IsOnline {
+ return nil, shortcuts.ServiceError(fiber.StatusServiceUnavailable, ErrRealmOffline)
+ }
+
+ c := &models.Character{
+ AccountID: accountID,
+ RealmID: req.RealmID,
+ Name: req.Name,
+ Race: req.Race,
+ StartingKingdom: req.StartingKingdom,
+ }
+
+ if err := character.Create(c); err != nil {
+ logger.Errorf(LogPrefix, CharacterCreateFailed, err)
+ return nil, shortcuts.ServiceError(fiber.StatusInternalServerError, fmt.Sprintf(CharacterCreateFailed, err))
+ }
+
+ logger.Successf(LogPrefix, CharacterCreated, c.Name)
+ return c, nil
+}
+
+func Delete(id uuid.UUID, accountID uuid.UUID) *fiber.Error {
+ c, err := character.FindByID(id)
+ if err != nil {
+ return shortcuts.ServiceError(fiber.StatusNotFound, ErrCharacterNotFound)
+ }
+
+ if c.AccountID != accountID {
+ return shortcuts.ServiceError(fiber.StatusNotFound, ErrCharacterNotFound)
+ }
+
+ if err := character.Delete(id); err != nil {
+ logger.Errorf(LogPrefix, CharacterDeleteFailed, err)
+ return shortcuts.ServiceError(fiber.StatusInternalServerError, fmt.Sprintf(CharacterDeleteFailed, err))
+ }
+
+ return nil
+}
diff --git a/nexus/services/character/defaults.go b/nexus/services/character/defaults.go new file mode 100644 index 0000000..f79094b --- /dev/null +++ b/nexus/services/character/defaults.go @@ -0,0 +1,3 @@ +package character
+
+const LogPrefix = "Character"
diff --git a/nexus/services/character/messages.go b/nexus/services/character/messages.go new file mode 100644 index 0000000..ba7ee07 --- /dev/null +++ b/nexus/services/character/messages.go @@ -0,0 +1,11 @@ +package character
+
+const (
+ ErrCharacterNotFound = "character not found"
+ ErrRealmNotFound = "realm not found"
+ ErrRealmOffline = "realm is currently offline"
+ CharactersFetchFailed = "failed to fetch characters: %v"
+ CharacterCreateFailed = "failed to create character: %v"
+ CharacterDeleteFailed = "failed to delete character: %v"
+ CharacterCreated = "character created: %s"
+)
|
