182 lines
5.8 KiB
Go
182 lines
5.8 KiB
Go
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 Authority struct {
|
|
AuthorityID uint
|
|
AuthorityName string
|
|
ParentID *uint
|
|
DataScope int
|
|
DefaultRouter string
|
|
Children []*Authority
|
|
}
|
|
|
|
type UserRepo interface {
|
|
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)
|
|
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
|
|
}
|
|
|
|
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
|
|
}
|
|
uc.fallbackDefaultRouter(ctx, u)
|
|
return u, nil
|
|
}
|
|
|
|
func (uc *SystemUsecase) 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
|
|
}
|
|
|
|
func (uc *SystemUsecase) fallbackDefaultRouter(ctx context.Context, user *User) {
|
|
if user == nil || user.Authority.DefaultRouter == "" {
|
|
return
|
|
}
|
|
menus, err := uc.repo.MenusByAuthority(ctx, user.AuthorityID)
|
|
if err != nil || !menuNameExists(menus, user.Authority.DefaultRouter) {
|
|
user.Authority.DefaultRouter = "404"
|
|
}
|
|
}
|
|
|
|
func menuNameExists(menus []*Menu, name string) bool {
|
|
for _, menu := range menus {
|
|
if menu.Name == name || menuNameExists(menu.Children, name) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
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, authorityIDs []uint) (*User, error) {
|
|
if user.AuthorityID == 0 && len(authorityIDs) > 0 {
|
|
user.AuthorityID = authorityIDs[0]
|
|
}
|
|
authorityIDs = includeAuthority(authorityIDs, user.AuthorityID)
|
|
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 *SystemUsecase) UpdateUser(ctx context.Context, user *User, authorityIDs []uint) error {
|
|
authorityIDs = includeAuthority(authorityIDs, user.AuthorityID)
|
|
return uc.repo.UpdateUserWithAuthorities(ctx, user, authorityIDs)
|
|
}
|
|
|
|
func (uc *SystemUsecase) UpdateSelfUser(ctx context.Context, user *User) error {
|
|
return uc.repo.UpdateSelfUser(ctx, user)
|
|
}
|
|
|
|
func includeAuthority(ids []uint, primary uint) []uint {
|
|
if primary == 0 {
|
|
return ids
|
|
}
|
|
for _, id := range ids {
|
|
if id == primary {
|
|
return ids
|
|
}
|
|
}
|
|
return append(ids, primary)
|
|
}
|
|
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)
|
|
}
|