- Added the go-nanoid library for generating unique IDs, enhancing user ID management. - Refactored user provider methods to improve clarity and consistency, including updates to user retrieval and authentication processes. - Adjusted user model fields to align with new ID generation strategy, ensuring compliance with best practices. - Cleaned up code by removing obsolete test files and improving overall structure for better maintainability.
171 lines
6.1 KiB
Go
171 lines
6.1 KiB
Go
package user
|
|
|
|
import (
|
|
"github.com/yaoapp/gou/store"
|
|
)
|
|
|
|
// Error messages
|
|
const (
|
|
ErrUserNotFound = "user not found"
|
|
ErrRoleNotFound = "role not found"
|
|
ErrTypeNotFound = "type not found"
|
|
ErrOAuthAccountNotFound = "oauth account not found"
|
|
ErrInvalidIdentifierType = "invalid identifier type: %s"
|
|
ErrNoPasswordHash = "no password hash found"
|
|
ErrFailedToGenerateUserID = "failed to generate user_id: %w"
|
|
ErrFailedToGeneratePassword = "failed to generate password: %w"
|
|
ErrInvalidUserIDInOAuth = "invalid user_id in oauth account"
|
|
|
|
ErrFailedToGetUser = "failed to get user: %w"
|
|
ErrFailedToGetRole = "failed to get role: %w"
|
|
ErrFailedToGetType = "failed to get type: %w"
|
|
ErrFailedToGetOAuthAccount = "failed to get oauth account: %w"
|
|
ErrFailedToCreateUser = "failed to create user: %w"
|
|
ErrFailedToCreateRole = "failed to create role: %w"
|
|
ErrFailedToCreateType = "failed to create type: %w"
|
|
ErrFailedToCreateOAuth = "failed to create oauth account: %w"
|
|
ErrFailedToUpdateUser = "failed to update user: %w"
|
|
ErrFailedToUpdateRole = "failed to update role: %w"
|
|
ErrFailedToUpdateType = "failed to update type: %w"
|
|
ErrFailedToUpdateOAuth = "failed to update oauth account: %w"
|
|
ErrFailedToDeleteUser = "failed to delete user: %w"
|
|
ErrFailedToDeleteRole = "failed to delete role: %w"
|
|
ErrFailedToDeleteType = "failed to delete type: %w"
|
|
ErrFailedToDeleteOAuth = "failed to delete oauth account: %w"
|
|
)
|
|
|
|
// Default field lists - used when not configured
|
|
var (
|
|
// DefaultPublicUserFields contains fields that can be safely returned to users
|
|
DefaultPublicUserFields = []interface{}{
|
|
"id", "user_id", "preferred_username", "email", "email_verified", "name", "given_name", "family_name",
|
|
"middle_name", "nickname", "profile", "picture", "website", "gender", "birthdate", "zoneinfo", "locale",
|
|
"phone_number", "phone_number_verified", "address", "theme", "status", "role_id", "type_id",
|
|
"mfa_enabled", "last_login_at", "metadata", "created_at", "updated_at",
|
|
}
|
|
|
|
// DefaultBasicUserFields contains minimal fields for basic user info
|
|
DefaultBasicUserFields = []interface{}{
|
|
"id", "user_id", "preferred_username", "email", "email_verified", "name", "given_name", "family_name",
|
|
"picture", "status", "role_id", "type_id",
|
|
}
|
|
|
|
// DefaultAuthUserFields contains fields needed for authentication
|
|
DefaultAuthUserFields = []interface{}{
|
|
"id", "user_id", "preferred_username", "email", "password_hash", "status", "role_id", "type_id",
|
|
"email_verified", "phone_number_verified", "mfa_enabled", "last_login_at",
|
|
}
|
|
|
|
// DefaultMFAUserFields contains fields needed for MFA authentication
|
|
DefaultMFAUserFields = []interface{}{
|
|
"id", "user_id", "mfa_enabled", "mfa_secret", "mfa_issuer", "mfa_algorithm",
|
|
"mfa_digits", "mfa_period", "mfa_recovery_hash", "mfa_enabled_at",
|
|
}
|
|
)
|
|
|
|
// DefaultUser provides a default implementation of UserProvider
|
|
type DefaultUser struct {
|
|
prefix string
|
|
model string
|
|
roleModel string
|
|
typeModel string
|
|
oauthAccountModel string
|
|
cache store.Store
|
|
|
|
// ID Generation Configuration
|
|
idStrategy IDStrategy
|
|
idPrefix string
|
|
|
|
// Field lists
|
|
publicUserFields []interface{} // configurable
|
|
basicUserFields []interface{} // configurable
|
|
authUserFields []interface{} // fixed for security
|
|
mfaUserFields []interface{} // fixed for security
|
|
}
|
|
|
|
// IDStrategy defines the strategy for generating user IDs
|
|
type IDStrategy string
|
|
|
|
// Available ID generation strategies
|
|
const (
|
|
NanoIDStrategy IDStrategy = "nanoid" // Short, URL-safe, readable (e.g., "Kx9mP2aQ7nR3")
|
|
UUIDStrategy IDStrategy = "uuid" // Traditional UUID (for compatibility)
|
|
)
|
|
|
|
// DefaultUserOptions provides options for the DefaultUser
|
|
type DefaultUserOptions struct {
|
|
Prefix string
|
|
Model string // bind to a specific user model
|
|
RoleModel string // bind to a specific role model
|
|
TypeModel string // bind to a specific type model
|
|
OAuthAccountModel string // bind to a specific oauth account model
|
|
Cache store.Store
|
|
|
|
// ID Generation Strategy
|
|
IDStrategy IDStrategy // strategy for generating user IDs (default: NanoIDStrategy)
|
|
IDPrefix string // prefix for generated IDs (e.g., "user", "member", default: "")
|
|
|
|
// Configurable field lists (use defaults if not specified)
|
|
PublicUserFields []interface{} // fields returned in public APIs
|
|
BasicUserFields []interface{} // minimal fields for basic user info
|
|
// Note: AuthUserFields and MFAUserFields are fixed for security reasons
|
|
}
|
|
|
|
// NewDefaultUser creates a new DefaultUser
|
|
func NewDefaultUser(options *DefaultUserOptions) *DefaultUser {
|
|
// Set default model names if not specified
|
|
model := options.Model
|
|
if model == "" {
|
|
model = "__yao.user"
|
|
}
|
|
|
|
roleModel := options.RoleModel
|
|
if roleModel == "" {
|
|
roleModel = "__yao.user_role"
|
|
}
|
|
|
|
typeModel := options.TypeModel
|
|
if typeModel == "" {
|
|
typeModel = "__yao.user_type"
|
|
}
|
|
|
|
oauthAccountModel := options.OAuthAccountModel
|
|
if oauthAccountModel == "" {
|
|
oauthAccountModel = "__yao.user_oauth_account"
|
|
}
|
|
|
|
// Set ID generation strategy with defaults
|
|
idStrategy := options.IDStrategy
|
|
if idStrategy == "" {
|
|
idStrategy = NanoIDStrategy // Default to NanoID for better UX
|
|
}
|
|
|
|
// Set ID prefix (default is empty string)
|
|
idPrefix := options.IDPrefix
|
|
|
|
// Set configurable field lists with defaults if not specified
|
|
publicUserFields := options.PublicUserFields
|
|
if publicUserFields == nil {
|
|
publicUserFields = DefaultPublicUserFields
|
|
}
|
|
|
|
basicUserFields := options.BasicUserFields
|
|
if basicUserFields == nil {
|
|
basicUserFields = DefaultBasicUserFields
|
|
}
|
|
|
|
return &DefaultUser{
|
|
prefix: options.Prefix,
|
|
model: model,
|
|
roleModel: roleModel,
|
|
typeModel: typeModel,
|
|
oauthAccountModel: oauthAccountModel,
|
|
cache: options.Cache,
|
|
idStrategy: idStrategy,
|
|
idPrefix: idPrefix,
|
|
publicUserFields: publicUserFields,
|
|
basicUserFields: basicUserFields,
|
|
authUserFields: DefaultAuthUserFields, // fixed for security
|
|
mfaUserFields: DefaultMFAUserFields, // fixed for security
|
|
}
|
|
}
|