initial commit

This commit is contained in:
m.zare
2026-04-10 18:25:21 +03:30
commit 77ca6c34a3
263 changed files with 34470 additions and 0 deletions

View 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
}

View 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"`
}

View 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
}
}

View 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)
}

View 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
}

View 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
}