package biz import ( "context" "time" "golang.org/x/crypto/bcrypt" ) type User struct { ID uint CreatedAt time.Time UpdatedAt time.Time UUID string Username string Password string NickName string HeaderImg string AuthorityID uint Authority Authority Authorities []Authority DeptID uint Department *Department Departments []Department Positions []Position Phone string Email string Enable int OriginSetting map[string]any MustChangePassword bool PasswordUpdatedAt *time.Time } type UserListFilter struct { Username, NickName, Phone, Email, OrderKey string Desc bool } type DatabaseConfig struct { Driver, Host, Port, User, Password, Name, Path, Config, Template, AdminPassword string APIs []*API } type Authority struct { AuthorityID uint AuthorityName string ParentID *uint DataScope int DefaultRouter string } type SystemRepo interface { IsInitialized(context.Context) (bool, error) Initialize(context.Context, *DatabaseConfig) error FindUserByUsername(context.Context, string) (*User, error) FindUserByID(context.Context, uint) (*User, error) MenusByAuthority(context.Context, uint) ([]*Menu, error) ListUsers(context.Context, int, int, *UserListFilter) ([]*User, int64, error) CreateUser(context.Context, *User) (*User, error) UpdateUser(context.Context, *User) error DeleteUser(context.Context, uint) error UpdatePassword(context.Context, uint, string, bool) error SetUserAuthorities(context.Context, uint, []uint) error SetUserAuthority(context.Context, uint, uint) error SetUserSetting(context.Context, uint, map[string]any) error ListAuthorities(context.Context) ([]*Authority, error) PersistConfig(context.Context) error PersistAdminConfig(context.Context, []byte) error ReloadConfig(context.Context) error } type SystemUsecase struct { repo SystemRepo cache Cache files FileStorage } func NewSystemUsecase(repo SystemRepo, cache Cache, files FileStorage) *SystemUsecase { return &SystemUsecase{repo: repo, cache: cache, files: files} } func (uc *SystemUsecase) CacheGet(ctx context.Context, key string) (string, bool, error) { return uc.cache.Get(ctx, key) } func (uc *SystemUsecase) CacheSet(ctx context.Context, key, value string, expiration time.Duration) error { return uc.cache.Set(ctx, key, value, expiration) } func (uc *SystemUsecase) CacheDelete(ctx context.Context, key string) error { return uc.cache.Delete(ctx, key) } func (uc *SystemUsecase) CacheIncrement(ctx context.Context, key string, expiration time.Duration) (int64, error) { return uc.cache.Increment(ctx, key, expiration) } func (uc *SystemUsecase) IsInitialized(ctx context.Context) (bool, error) { return uc.repo.IsInitialized(ctx) } func (uc *SystemUsecase) Initialize(ctx context.Context, config *DatabaseConfig) error { if config == nil || len(config.AdminPassword) < 6 { return ErrInvalidCredentials } return uc.repo.Initialize(ctx, config) } func (uc *SystemUsecase) PersistConfig(ctx context.Context) error { return uc.repo.PersistConfig(ctx) } func (uc *SystemUsecase) PersistAdminConfig(ctx context.Context, value []byte) error { return uc.repo.PersistAdminConfig(ctx, value) } func (uc *SystemUsecase) ReloadConfig(ctx context.Context) error { return uc.repo.ReloadConfig(ctx) } func (uc *SystemUsecase) Login(ctx context.Context, username, password string) (*User, error) { u, err := uc.repo.FindUserByUsername(ctx, username) if err != nil || bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password)) != nil { return nil, ErrInvalidCredentials } return u, nil } func (uc *SystemUsecase) User(ctx context.Context, id uint) (*User, error) { return uc.repo.FindUserByID(ctx, id) } func (uc *SystemUsecase) Menus(ctx context.Context, authorityID uint) ([]*Menu, error) { return uc.repo.MenusByAuthority(ctx, authorityID) } func (uc *SystemUsecase) ListUsers(ctx context.Context, page, pageSize int, filter *UserListFilter) ([]*User, int64, error) { return uc.repo.ListUsers(ctx, page, pageSize, filter) } func (uc *SystemUsecase) CreateUser(ctx context.Context, user *User) (*User, error) { hash, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost) if err != nil { return nil, err } user.Password = string(hash) return uc.repo.CreateUser(ctx, user) } func (uc *SystemUsecase) UpdateUser(ctx context.Context, user *User) error { return uc.repo.UpdateUser(ctx, user) } func (uc *SystemUsecase) DeleteUser(ctx context.Context, id uint) error { return uc.repo.DeleteUser(ctx, id) } func (uc *SystemUsecase) ResetPassword(ctx context.Context, id uint, password string) error { hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return err } return uc.repo.UpdatePassword(ctx, id, string(hash), false) } func (uc *SystemUsecase) ChangePassword(ctx context.Context, id uint, oldPassword, newPassword string) error { user, err := uc.repo.FindUserByID(ctx, id) if err != nil { return err } if bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(oldPassword)) != nil { return ErrInvalidCredentials } hash, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost) if err != nil { return err } return uc.repo.UpdatePassword(ctx, id, string(hash), true) } func (uc *SystemUsecase) Authorities(ctx context.Context) ([]*Authority, error) { return uc.repo.ListAuthorities(ctx) } func (uc *SystemUsecase) SetUserAuthorities(ctx context.Context, id uint, authorityIDs []uint) error { if len(authorityIDs) == 0 { return ErrInvalidCredentials } return uc.repo.SetUserAuthorities(ctx, id, authorityIDs) } func (uc *SystemUsecase) SetUserAuthority(ctx context.Context, id, authorityID uint) error { return uc.repo.SetUserAuthority(ctx, id, authorityID) } func (uc *SystemUsecase) SetUserSetting(ctx context.Context, id uint, setting map[string]any) error { return uc.repo.SetUserSetting(ctx, id, setting) }