优化结构
This commit is contained in:
@@ -1,177 +0,0 @@
|
||||
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 UserRepo interface {
|
||||
FindUserByUsername(context.Context, string) (*User, error)
|
||||
FindUserByID(context.Context, uint) (*User, error)
|
||||
FindUserByUUID(context.Context, string) (*User, error)
|
||||
HasAuthorityMenu(context.Context, uint, string) (bool, error)
|
||||
MenusByAuthority(context.Context, uint) ([]*Menu, error)
|
||||
ListUsers(context.Context, int, int, *UserListFilter) ([]*User, int64, error)
|
||||
CreateUser(context.Context, *User) (*User, error)
|
||||
CreateUserWithAuthorities(context.Context, *User, []uint) (*User, error)
|
||||
UpdateUser(context.Context, *User) error
|
||||
UpdateSelfUser(context.Context, *User) error
|
||||
UpdateUserWithAuthorities(context.Context, *User, []uint) 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)
|
||||
FillDepartmentNamePaths(context.Context, *User) error
|
||||
}
|
||||
|
||||
type UserUsecase struct{ repo UserRepo }
|
||||
|
||||
func NewUserUsecase(repo UserRepo) *UserUsecase { return &UserUsecase{repo: repo} }
|
||||
|
||||
func (uc *UserUsecase) 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
|
||||
}
|
||||
uc.fallbackDefaultRouter(ctx, u)
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (uc *UserUsecase) User(ctx context.Context, id uint) (*User, error) {
|
||||
user, err := uc.repo.FindUserByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_ = uc.repo.FillDepartmentNamePaths(ctx, user)
|
||||
uc.fallbackDefaultRouter(ctx, user)
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// UserByUUID resolves the identity from the UUID embedded in the JWT rather
|
||||
// than from the mutable numeric ID used by administrative records.
|
||||
func (uc *UserUsecase) UserByUUID(ctx context.Context, uuid string) (*User, error) {
|
||||
user, err := uc.repo.FindUserByUUID(ctx, uuid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_ = uc.repo.FillDepartmentNamePaths(ctx, user)
|
||||
uc.fallbackDefaultRouter(ctx, user)
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (uc *UserUsecase) fallbackDefaultRouter(ctx context.Context, user *User) {
|
||||
if user == nil {
|
||||
return
|
||||
}
|
||||
hasMenu, err := uc.repo.HasAuthorityMenu(ctx, user.AuthorityID, user.Authority.DefaultRouter)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !hasMenu {
|
||||
user.Authority.DefaultRouter = "404"
|
||||
}
|
||||
}
|
||||
|
||||
func (uc *UserUsecase) Menus(ctx context.Context, authorityID uint) ([]*Menu, error) {
|
||||
return uc.repo.MenusByAuthority(ctx, authorityID)
|
||||
}
|
||||
|
||||
func (uc *UserUsecase) ListUsers(ctx context.Context, page, pageSize int, filter *UserListFilter) ([]*User, int64, error) {
|
||||
return uc.repo.ListUsers(ctx, page, pageSize, filter)
|
||||
}
|
||||
func (uc *UserUsecase) CreateUser(ctx context.Context, user *User, authorityIDs []uint) (*User, error) {
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
user.Password = string(hash)
|
||||
return uc.repo.CreateUserWithAuthorities(ctx, user, authorityIDs)
|
||||
}
|
||||
func (uc *UserUsecase) UpdateUser(ctx context.Context, user *User, authorityIDs []uint) error {
|
||||
// Role associations are updated first only when authorityIds was supplied,
|
||||
// and then updates the basic user fields as a separate operation. Preserve
|
||||
// that ordering and partial-failure behavior instead of coupling both writes
|
||||
// into the data-layer transaction used by lower-level callers.
|
||||
if len(authorityIDs) > 0 {
|
||||
if err := uc.repo.SetUserAuthorities(ctx, user.ID, authorityIDs); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return uc.repo.UpdateUser(ctx, user)
|
||||
}
|
||||
|
||||
func (uc *UserUsecase) UpdateSelfUser(ctx context.Context, user *User) error {
|
||||
return uc.repo.UpdateSelfUser(ctx, user)
|
||||
}
|
||||
|
||||
func (uc *UserUsecase) DeleteUser(ctx context.Context, id uint) error {
|
||||
return uc.repo.DeleteUser(ctx, id)
|
||||
}
|
||||
func (uc *UserUsecase) 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 *UserUsecase) 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 *UserUsecase) Authorities(ctx context.Context) ([]*Authority, error) {
|
||||
return uc.repo.ListAuthorities(ctx)
|
||||
}
|
||||
func (uc *UserUsecase) SetUserAuthorities(ctx context.Context, id uint, authorityIDs []uint) error {
|
||||
if len(authorityIDs) == 0 {
|
||||
return ErrInvalidCredentials
|
||||
}
|
||||
return uc.repo.SetUserAuthorities(ctx, id, authorityIDs)
|
||||
}
|
||||
func (uc *UserUsecase) SetUserAuthority(ctx context.Context, id, authorityID uint) error {
|
||||
return uc.repo.SetUserAuthority(ctx, id, authorityID)
|
||||
}
|
||||
func (uc *UserUsecase) SetUserSetting(ctx context.Context, id uint, setting map[string]any) error {
|
||||
return uc.repo.SetUserSetting(ctx, id, setting)
|
||||
}
|
||||
Reference in New Issue
Block a user