任务三
This commit is contained in:
+5
-2
@@ -1,6 +1,9 @@
|
||||
package biz
|
||||
|
||||
import "github.com/google/wire"
|
||||
import (
|
||||
"github.com/google/wire"
|
||||
"kra/internal/biz/system"
|
||||
)
|
||||
|
||||
// ProviderSet is biz providers.
|
||||
var ProviderSet = wire.NewSet(NewAdminUsecase)
|
||||
var ProviderSet = wire.NewSet(system.NewUserUsecase)
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrUserNotFound = errors.New("用户不存在")
|
||||
ErrUserAlreadyExists = errors.New("用户名已注册")
|
||||
ErrPasswordWrong = errors.New("密码错误")
|
||||
ErrOldPasswordWrong = errors.New("原密码错误")
|
||||
ErrUserNoAuthority = errors.New("该用户无此角色")
|
||||
ErrDefaultRouterEmpty = errors.New("找不到默认路由,无法切换本角色")
|
||||
)
|
||||
|
||||
// User 用户实体
|
||||
type User struct {
|
||||
ID uint
|
||||
UUID uuid.UUID
|
||||
Username string
|
||||
Password string
|
||||
NickName string
|
||||
SideMode string
|
||||
HeaderImg string
|
||||
BaseColor string
|
||||
AuthorityId uint
|
||||
Phone string
|
||||
Email string
|
||||
Enable int
|
||||
OriginSetting json.RawMessage
|
||||
Authority *Authority
|
||||
Authorities []*Authority
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
// Authority 角色实体
|
||||
type Authority struct {
|
||||
AuthorityId uint
|
||||
AuthorityName string
|
||||
ParentId *uint
|
||||
DefaultRouter string
|
||||
}
|
||||
|
||||
// UserRepo 用户仓储接口
|
||||
type UserRepo interface {
|
||||
Create(ctx context.Context, user *User) error
|
||||
Update(ctx context.Context, user *User) error
|
||||
UpdateSelf(ctx context.Context, user *User) error
|
||||
UpdateSelfSetting(ctx context.Context, id uint, setting json.RawMessage) error
|
||||
Delete(ctx context.Context, id uint) error
|
||||
FindByID(ctx context.Context, id uint) (*User, error)
|
||||
FindByIDWithAuthorities(ctx context.Context, id uint) (*User, error)
|
||||
FindByUUID(ctx context.Context, uuid string) (*User, error)
|
||||
FindByUUIDWithAuthorities(ctx context.Context, uuid string) (*User, error)
|
||||
FindByUsername(ctx context.Context, username string) (*User, error)
|
||||
FindByUsernameWithAuthorities(ctx context.Context, username string) (*User, error)
|
||||
List(ctx context.Context, page, pageSize int, filters map[string]string) ([]*User, int64, error)
|
||||
UpdatePassword(ctx context.Context, id uint, password string) error
|
||||
UpdateAuthorityID(ctx context.Context, id uint, authorityId uint) error
|
||||
SetUserAuthorities(ctx context.Context, adminAuthorityID, userId uint, authorityIds []uint) error
|
||||
CheckUserHasAuthority(ctx context.Context, userId, authorityId uint) (bool, error)
|
||||
GetAuthorityMenuRouters(ctx context.Context, authorityId uint) ([]string, error)
|
||||
GetAuthorityDefaultRouter(ctx context.Context, authorityId uint) (string, error)
|
||||
}
|
||||
|
||||
// UserUsecase 用户用例
|
||||
type UserUsecase struct {
|
||||
repo UserRepo
|
||||
}
|
||||
|
||||
// NewUserUsecase 创建用户用例
|
||||
func NewUserUsecase(repo UserRepo) *UserUsecase {
|
||||
return &UserUsecase{repo: repo}
|
||||
}
|
||||
|
||||
// Register 用户注册
|
||||
func (uc *UserUsecase) Register(ctx context.Context, user *User) (*User, error) {
|
||||
// 检查用户名是否已存在
|
||||
existing, _ := uc.repo.FindByUsername(ctx, user.Username)
|
||||
if existing != nil {
|
||||
return nil, ErrUserAlreadyExists
|
||||
}
|
||||
|
||||
// 密码加密
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
user.Password = string(hashedPassword)
|
||||
user.UUID = uuid.New()
|
||||
|
||||
if err := uc.repo.Create(ctx, user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// Login 用户登录(预加载Authorities)
|
||||
func (uc *UserUsecase) Login(ctx context.Context, username, password string) (*User, error) {
|
||||
user, err := uc.repo.FindByUsernameWithAuthorities(ctx, username)
|
||||
if err != nil {
|
||||
return nil, ErrUserNotFound
|
||||
}
|
||||
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
|
||||
return nil, ErrPasswordWrong
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// ChangePassword 修改密码
|
||||
func (uc *UserUsecase) ChangePassword(ctx context.Context, id uint, oldPassword, newPassword string) error {
|
||||
user, err := uc.repo.FindByID(ctx, id)
|
||||
if err != nil {
|
||||
return ErrUserNotFound
|
||||
}
|
||||
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(oldPassword)); err != nil {
|
||||
return ErrOldPasswordWrong
|
||||
}
|
||||
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return uc.repo.UpdatePassword(ctx, id, string(hashedPassword))
|
||||
}
|
||||
|
||||
// ResetPassword 重置密码
|
||||
func (uc *UserUsecase) ResetPassword(ctx context.Context, id uint, newPassword string) error {
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return uc.repo.UpdatePassword(ctx, id, string(hashedPassword))
|
||||
}
|
||||
|
||||
// GetUserInfo 获取用户信息(预加载Authorities)
|
||||
func (uc *UserUsecase) GetUserInfo(ctx context.Context, uuid string) (*User, error) {
|
||||
return uc.repo.FindByUUIDWithAuthorities(ctx, uuid)
|
||||
}
|
||||
|
||||
// GetUserByID 通过ID获取用户
|
||||
func (uc *UserUsecase) GetUserByID(ctx context.Context, id uint) (*User, error) {
|
||||
return uc.repo.FindByID(ctx, id)
|
||||
}
|
||||
|
||||
// FindUserById 通过ID获取用户(GVA兼容)
|
||||
func (uc *UserUsecase) FindUserById(ctx context.Context, id uint) (*User, error) {
|
||||
return uc.repo.FindByID(ctx, id)
|
||||
}
|
||||
|
||||
// FindUserByUuid 通过UUID获取用户(GVA兼容)
|
||||
func (uc *UserUsecase) FindUserByUuid(ctx context.Context, uuid string) (*User, error) {
|
||||
return uc.repo.FindByUUID(ctx, uuid)
|
||||
}
|
||||
|
||||
// GetUserList 获取用户列表
|
||||
func (uc *UserUsecase) GetUserList(ctx context.Context, page, pageSize int, filters map[string]string) ([]*User, int64, error) {
|
||||
return uc.repo.List(ctx, page, pageSize, filters)
|
||||
}
|
||||
|
||||
// SetUserInfo 设置用户信息(管理员用)
|
||||
func (uc *UserUsecase) SetUserInfo(ctx context.Context, user *User) error {
|
||||
return uc.repo.Update(ctx, user)
|
||||
}
|
||||
|
||||
// SetSelfInfo 设置自己的信息(用户用)
|
||||
func (uc *UserUsecase) SetSelfInfo(ctx context.Context, user *User) error {
|
||||
return uc.repo.UpdateSelf(ctx, user)
|
||||
}
|
||||
|
||||
// SetSelfSetting 设置自己的配置
|
||||
func (uc *UserUsecase) SetSelfSetting(ctx context.Context, id uint, setting json.RawMessage) error {
|
||||
return uc.repo.UpdateSelfSetting(ctx, id, setting)
|
||||
}
|
||||
|
||||
// DeleteUser 删除用户
|
||||
func (uc *UserUsecase) DeleteUser(ctx context.Context, id uint) error {
|
||||
return uc.repo.Delete(ctx, id)
|
||||
}
|
||||
|
||||
// SetUserAuthority 设置用户角色(切换角色)
|
||||
func (uc *UserUsecase) SetUserAuthority(ctx context.Context, id uint, authorityId uint) error {
|
||||
// 检查用户是否拥有该角色
|
||||
hasAuthority, err := uc.repo.CheckUserHasAuthority(ctx, id, authorityId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !hasAuthority {
|
||||
return ErrUserNoAuthority
|
||||
}
|
||||
|
||||
// 获取角色的默认路由
|
||||
defaultRouter, err := uc.repo.GetAuthorityDefaultRouter(ctx, authorityId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 获取角色的菜单路由列表
|
||||
menuRouters, err := uc.repo.GetAuthorityMenuRouters(ctx, authorityId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 检查默认路由是否在菜单中
|
||||
hasMenu := false
|
||||
for _, router := range menuRouters {
|
||||
if router == defaultRouter {
|
||||
hasMenu = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !hasMenu {
|
||||
return ErrDefaultRouterEmpty
|
||||
}
|
||||
|
||||
return uc.repo.UpdateAuthorityID(ctx, id, authorityId)
|
||||
}
|
||||
|
||||
// SetUserAuthorities 设置用户多角色
|
||||
func (uc *UserUsecase) SetUserAuthorities(ctx context.Context, adminAuthorityID, userId uint, authorityIds []uint) error {
|
||||
return uc.repo.SetUserAuthorities(ctx, adminAuthorityID, userId, authorityIds)
|
||||
}
|
||||
Reference in New Issue
Block a user