initial commit
This commit is contained in:
25
internal/domain/auth/account.go
Normal file
25
internal/domain/auth/account.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"base/internal/pkg/oauth"
|
||||
)
|
||||
|
||||
type Account struct {
|
||||
ID uuid.UUID
|
||||
UserID uuid.UUID
|
||||
Provider oauth.Provider
|
||||
Password *string
|
||||
AccessToken *string
|
||||
RefreshToken *string
|
||||
AccessTokenExpiry *time.Time
|
||||
RefreshTokenExpiry *time.Time
|
||||
Scope []string
|
||||
Meta json.RawMessage
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
17
internal/domain/auth/events.go
Normal file
17
internal/domain/auth/events.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// AccountCreatedEvent represents the event when an account is created
|
||||
type AccountCreatedEvent struct {
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
Email string `json:"email"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
PhoneNumber string `json:"phone_number"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
33
internal/domain/auth/query.go
Normal file
33
internal/domain/auth/query.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package auth
|
||||
|
||||
// UserQueryOption represents options for querying users
|
||||
type UserQueryOption func(*UserQueryOptions)
|
||||
|
||||
// UserQueryOptions holds options for user queries
|
||||
type UserQueryOptions struct {
|
||||
LoadRoles bool
|
||||
LoadAccounts bool
|
||||
}
|
||||
|
||||
// WithRoles enables loading of user roles
|
||||
func WithRoles() UserQueryOption {
|
||||
return func(opts *UserQueryOptions) {
|
||||
opts.LoadRoles = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithAccounts enables loading of user accounts
|
||||
func WithAccounts() UserQueryOption {
|
||||
return func(opts *UserQueryOptions) {
|
||||
opts.LoadAccounts = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithRelations enables loading of all relations
|
||||
func WithRelations() UserQueryOption {
|
||||
return func(opts *UserQueryOptions) {
|
||||
opts.LoadRoles = true
|
||||
opts.LoadAccounts = true
|
||||
}
|
||||
}
|
||||
|
||||
51
internal/domain/auth/repository.go
Normal file
51
internal/domain/auth/repository.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type UserRepository interface {
|
||||
Create(ctx context.Context, user *User) error
|
||||
CreateWithAccount(ctx context.Context, user *User, account *Account) error
|
||||
UpsertWithAccount(ctx context.Context, email string, user *User, account *Account) (isNewUser bool, err error)
|
||||
FindByID(ctx context.Context, id uuid.UUID, opts ...UserQueryOption) (*User, error)
|
||||
FindByEmail(ctx context.Context, email string, opts ...UserQueryOption) (*User, error)
|
||||
Update(ctx context.Context, user *User) error
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
List(ctx context.Context, limit, offset int, opts ...UserQueryOption) ([]*User, error)
|
||||
Count(ctx context.Context) (int64, error)
|
||||
UserRoles(ctx context.Context, userID uuid.UUID) ([]Role, error)
|
||||
UserAccounts(ctx context.Context, userID uuid.UUID) ([]Account, error)
|
||||
}
|
||||
|
||||
type RoleRepository interface {
|
||||
Create(ctx context.Context, role *Role) error
|
||||
FindByID(ctx context.Context, id uuid.UUID) (*Role, error)
|
||||
FindByName(ctx context.Context, name string) (*Role, error)
|
||||
Update(ctx context.Context, role *Role) error
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
List(ctx context.Context, limit, offset int) ([]*Role, error)
|
||||
Count(ctx context.Context) (int64, error)
|
||||
}
|
||||
|
||||
type AccountRepository interface {
|
||||
Create(ctx context.Context, account *Account) error
|
||||
FindByID(ctx context.Context, id uuid.UUID) (*Account, error)
|
||||
FindByUserID(ctx context.Context, userID uuid.UUID) ([]*Account, error)
|
||||
Update(ctx context.Context, account *Account) error
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
List(ctx context.Context, limit, offset int) ([]*Account, error)
|
||||
Count(ctx context.Context) (int64, error)
|
||||
}
|
||||
|
||||
type UserRoleRepository interface {
|
||||
Create(ctx context.Context, userID, roleID uuid.UUID) error
|
||||
FindByUserID(ctx context.Context, userID uuid.UUID) ([]*Role, error)
|
||||
FindByRoleID(ctx context.Context, roleID uuid.UUID) ([]*User, error)
|
||||
Delete(ctx context.Context, userID, roleID uuid.UUID) error
|
||||
DeleteByUserID(ctx context.Context, userID uuid.UUID) error
|
||||
DeleteByRoleID(ctx context.Context, roleID uuid.UUID) error
|
||||
Exists(ctx context.Context, userID, roleID uuid.UUID) (bool, error)
|
||||
}
|
||||
15
internal/domain/auth/role.go
Normal file
15
internal/domain/auth/role.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Role struct {
|
||||
ID uuid.UUID
|
||||
Name string
|
||||
Description string
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
65
internal/domain/auth/user.go
Normal file
65
internal/domain/auth/user.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
//go:generate stringer -type=UserStatus
|
||||
type UserStatus int
|
||||
|
||||
const (
|
||||
UserStatusActive UserStatus = iota
|
||||
UserStatusInactive
|
||||
UserStatusPending
|
||||
UserStatusDeleted
|
||||
)
|
||||
|
||||
// User represents a user aggregate root
|
||||
// The repository handles loading of related entities (Roles, Accounts)
|
||||
// This keeps the domain entity pure and decoupled from infrastructure
|
||||
type User struct {
|
||||
ID uuid.UUID
|
||||
FirstName string
|
||||
LastName string
|
||||
PhoneNumber string
|
||||
Email string
|
||||
EmailVerified bool
|
||||
Status UserStatus
|
||||
InvitationCode string
|
||||
Roles []Role
|
||||
Accounts []Account
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt time.Time
|
||||
}
|
||||
|
||||
// HasRole checks if the user has a specific role
|
||||
func (u *User) HasRole(roleName string) bool {
|
||||
for _, role := range u.Roles {
|
||||
if role.Name == roleName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetRoleNames returns a slice of role names
|
||||
func (u *User) GetRoleNames() []string {
|
||||
names := make([]string, len(u.Roles))
|
||||
for i, role := range u.Roles {
|
||||
names[i] = role.Name
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// HasAccount checks if the user has an account for the given provider
|
||||
func (u *User) HasAccount(provider string) bool {
|
||||
for _, account := range u.Accounts {
|
||||
if account.Provider.String() == provider {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user