346 lines
10 KiB
Go
346 lines
10 KiB
Go
package system
|
||
|
||
import (
|
||
"encoding/json"
|
||
|
||
"kra/internal/biz/system"
|
||
"kra/internal/server/middleware"
|
||
types "kra/internal/service/types/system"
|
||
"kra/pkg/jwt"
|
||
|
||
"github.com/go-kratos/kratos/v2/errors"
|
||
khttp "github.com/go-kratos/kratos/v2/transport/http"
|
||
)
|
||
|
||
// RouterGroup 路由组接口
|
||
type RouterGroup struct {
|
||
Public *khttp.Router // 公开路由(无需认证)
|
||
Private *khttp.Router // 私有路由(需要JWT认证)
|
||
PrivateWithRecord *khttp.Router // 私有路由 + 操作记录
|
||
}
|
||
|
||
// UserService 用户服务
|
||
type UserService struct {
|
||
uc *system.UserUsecase
|
||
jwtPkg *jwt.JWT
|
||
}
|
||
|
||
// NewUserService 创建用户服务
|
||
func NewUserService(uc *system.UserUsecase, jwtPkg *jwt.JWT) *UserService {
|
||
return &UserService{uc: uc, jwtPkg: jwtPkg}
|
||
}
|
||
|
||
// Login 用户登录
|
||
func (s *UserService) Login(ctx khttp.Context) error {
|
||
var req types.LoginRequest
|
||
if err := ctx.Bind(&req); err != nil {
|
||
return err
|
||
}
|
||
user, err := s.uc.Login(ctx, req.Username, req.Password)
|
||
if err != nil {
|
||
return errors.Unauthorized("LOGIN_FAILED", err.Error())
|
||
}
|
||
if user.Enable != 1 {
|
||
return errors.Forbidden("USER_DISABLED", "用户被禁止登录")
|
||
}
|
||
claims := s.jwtPkg.CreateClaims(jwt.BaseClaims{
|
||
UUID: user.UUID.String(),
|
||
ID: user.ID,
|
||
Username: user.Username,
|
||
NickName: user.NickName,
|
||
AuthorityID: user.AuthorityId,
|
||
})
|
||
token, err := s.jwtPkg.CreateToken(claims.BaseClaims)
|
||
if err != nil {
|
||
return errors.InternalServer("TOKEN_ERROR", "生成token失败")
|
||
}
|
||
return ctx.Result(200, &types.LoginReply{
|
||
User: toTypesUserInfo(user),
|
||
Token: token,
|
||
ExpiresAt: claims.ExpiresAt.UnixMilli(),
|
||
})
|
||
}
|
||
|
||
// Register 用户注册
|
||
func (s *UserService) Register(ctx khttp.Context) error {
|
||
var req types.RegisterRequest
|
||
if err := ctx.Bind(&req); err != nil {
|
||
return err
|
||
}
|
||
user := &system.User{
|
||
Username: req.Username,
|
||
Password: req.Password,
|
||
NickName: req.NickName,
|
||
HeaderImg: req.HeaderImg,
|
||
AuthorityId: req.AuthorityId,
|
||
Phone: req.Phone,
|
||
Email: req.Email,
|
||
Enable: req.Enable,
|
||
}
|
||
created, err := s.uc.Register(ctx, user)
|
||
if err != nil {
|
||
return errors.BadRequest("REGISTER_FAILED", err.Error())
|
||
}
|
||
return ctx.Result(200, &types.UserInfoReply{User: toTypesUserInfo(created)})
|
||
}
|
||
|
||
// ChangePassword 修改密码
|
||
func (s *UserService) ChangePassword(ctx khttp.Context) error {
|
||
var req types.ChangePasswordRequest
|
||
if err := ctx.Bind(&req); err != nil {
|
||
return err
|
||
}
|
||
userID := middleware.GetUserID(ctx)
|
||
if userID == 0 {
|
||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||
}
|
||
if err := s.uc.ChangePassword(ctx, userID, req.Password, req.NewPassword); err != nil {
|
||
return errors.BadRequest("CHANGE_PASSWORD_FAILED", err.Error())
|
||
}
|
||
return ctx.Result(200, nil)
|
||
}
|
||
|
||
// ResetPassword 重置密码
|
||
func (s *UserService) ResetPassword(ctx khttp.Context) error {
|
||
var req types.ResetPasswordRequest
|
||
if err := ctx.Bind(&req); err != nil {
|
||
return err
|
||
}
|
||
if err := s.uc.ResetPassword(ctx, req.ID, req.Password); err != nil {
|
||
return errors.BadRequest("RESET_PASSWORD_FAILED", err.Error())
|
||
}
|
||
return ctx.Result(200, nil)
|
||
}
|
||
|
||
// GetUserInfo 获取用户信息
|
||
func (s *UserService) GetUserInfo(ctx khttp.Context) error {
|
||
claims, ok := middleware.GetClaims(ctx)
|
||
if !ok {
|
||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||
}
|
||
user, err := s.uc.GetUserInfo(ctx, claims.UUID)
|
||
if err != nil {
|
||
return errors.NotFound("USER_NOT_FOUND", err.Error())
|
||
}
|
||
return ctx.Result(200, &types.GetUserInfoReply{UserInfo: toTypesUserInfo(user)})
|
||
}
|
||
|
||
// GetUserList 获取用户列表
|
||
func (s *UserService) GetUserList(ctx khttp.Context) error {
|
||
var req types.GetUserListRequest
|
||
if err := ctx.Bind(&req); err != nil {
|
||
return err
|
||
}
|
||
filters := make(map[string]string)
|
||
if req.Username != "" {
|
||
filters["username"] = req.Username
|
||
}
|
||
if req.NickName != "" {
|
||
filters["nick_name"] = req.NickName
|
||
}
|
||
if req.Phone != "" {
|
||
filters["phone"] = req.Phone
|
||
}
|
||
if req.Email != "" {
|
||
filters["email"] = req.Email
|
||
}
|
||
users, total, err := s.uc.GetUserList(ctx, req.Page, req.PageSize, filters)
|
||
if err != nil {
|
||
return errors.InternalServer("LIST_ERROR", err.Error())
|
||
}
|
||
list := make([]types.UserInfo, len(users))
|
||
for i, u := range users {
|
||
list[i] = toTypesUserInfo(u)
|
||
}
|
||
return ctx.Result(200, &types.GetUserListReply{List: list, Total: total, Page: req.Page, PageSize: req.PageSize})
|
||
}
|
||
|
||
// SetUserInfo 设置用户信息
|
||
func (s *UserService) SetUserInfo(ctx khttp.Context) error {
|
||
var req types.SetUserInfoRequest
|
||
if err := ctx.Bind(&req); err != nil {
|
||
return err
|
||
}
|
||
user := &system.User{
|
||
ID: req.ID,
|
||
NickName: req.NickName,
|
||
HeaderImg: req.HeaderImg,
|
||
Phone: req.Phone,
|
||
Email: req.Email,
|
||
Enable: req.Enable,
|
||
}
|
||
if err := s.uc.SetUserInfo(ctx, user); err != nil {
|
||
return errors.BadRequest("SET_USER_INFO_FAILED", err.Error())
|
||
}
|
||
if len(req.AuthorityIds) > 0 {
|
||
adminAuthorityID := middleware.GetAuthorityID(ctx)
|
||
if err := s.uc.SetUserAuthorities(ctx, adminAuthorityID, req.ID, req.AuthorityIds); err != nil {
|
||
return errors.BadRequest("SET_USER_AUTHORITIES_FAILED", err.Error())
|
||
}
|
||
}
|
||
return ctx.Result(200, nil)
|
||
}
|
||
|
||
// SetSelfInfo 设置自己信息
|
||
func (s *UserService) SetSelfInfo(ctx khttp.Context) error {
|
||
var req types.SetSelfInfoRequest
|
||
if err := ctx.Bind(&req); err != nil {
|
||
return err
|
||
}
|
||
userID := middleware.GetUserID(ctx)
|
||
if userID == 0 {
|
||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||
}
|
||
user := &system.User{
|
||
ID: userID,
|
||
NickName: req.NickName,
|
||
HeaderImg: req.HeaderImg,
|
||
Phone: req.Phone,
|
||
Email: req.Email,
|
||
}
|
||
if err := s.uc.SetSelfInfo(ctx, user); err != nil {
|
||
return errors.BadRequest("SET_SELF_INFO_FAILED", err.Error())
|
||
}
|
||
return ctx.Result(200, nil)
|
||
}
|
||
|
||
// SetSelfSetting 设置自己配置
|
||
func (s *UserService) SetSelfSetting(ctx khttp.Context) error {
|
||
var req types.SetSelfSettingRequest
|
||
if err := ctx.Bind(&req); err != nil {
|
||
return err
|
||
}
|
||
userID := middleware.GetUserID(ctx)
|
||
if userID == 0 {
|
||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||
}
|
||
setting := json.RawMessage(req.Setting)
|
||
if err := s.uc.SetSelfSetting(ctx, userID, setting); err != nil {
|
||
return errors.BadRequest("SET_SELF_SETTING_FAILED", err.Error())
|
||
}
|
||
return ctx.Result(200, nil)
|
||
}
|
||
|
||
// DeleteUser 删除用户
|
||
func (s *UserService) DeleteUser(ctx khttp.Context) error {
|
||
var req types.DeleteUserRequest
|
||
if err := ctx.Bind(&req); err != nil {
|
||
return err
|
||
}
|
||
currentUserID := middleware.GetUserID(ctx)
|
||
if currentUserID == req.ID {
|
||
return errors.BadRequest("DELETE_FAILED", "无法删除自己")
|
||
}
|
||
if err := s.uc.DeleteUser(ctx, req.ID); err != nil {
|
||
return errors.BadRequest("DELETE_FAILED", err.Error())
|
||
}
|
||
return ctx.Result(200, nil)
|
||
}
|
||
|
||
// SetUserAuthority 设置用户角色
|
||
func (s *UserService) SetUserAuthority(ctx khttp.Context) error {
|
||
var req types.SetUserAuthorityRequest
|
||
if err := ctx.Bind(&req); err != nil {
|
||
return err
|
||
}
|
||
userID := middleware.GetUserID(ctx)
|
||
if userID == 0 {
|
||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||
}
|
||
if err := s.uc.SetUserAuthority(ctx, userID, req.AuthorityId); err != nil {
|
||
return errors.BadRequest("SET_AUTHORITY_FAILED", err.Error())
|
||
}
|
||
// 重新生成token
|
||
claims, ok := middleware.GetClaims(ctx)
|
||
if !ok {
|
||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||
}
|
||
claims.AuthorityID = req.AuthorityId
|
||
token, err := s.jwtPkg.CreateToken(claims.BaseClaims)
|
||
if err != nil {
|
||
return errors.InternalServer("TOKEN_ERROR", "生成token失败")
|
||
}
|
||
return ctx.Result(200, &types.SetUserAuthorityReply{Token: token, ExpiresAt: claims.ExpiresAt.UnixMilli()})
|
||
}
|
||
|
||
// SetUserAuthorities 设置用户多角色
|
||
func (s *UserService) SetUserAuthorities(ctx khttp.Context) error {
|
||
var req types.SetUserAuthoritiesRequest
|
||
if err := ctx.Bind(&req); err != nil {
|
||
return err
|
||
}
|
||
adminAuthorityID := middleware.GetAuthorityID(ctx)
|
||
if err := s.uc.SetUserAuthorities(ctx, adminAuthorityID, req.ID, req.AuthorityIds); err != nil {
|
||
return errors.BadRequest("SET_AUTHORITIES_FAILED", err.Error())
|
||
}
|
||
return ctx.Result(200, nil)
|
||
}
|
||
|
||
// toTypesUserInfo 转换用户信息为types格式
|
||
func toTypesUserInfo(user *system.User) types.UserInfo {
|
||
if user == nil {
|
||
return types.UserInfo{}
|
||
}
|
||
info := types.UserInfo{
|
||
ID: user.ID,
|
||
UUID: user.UUID.String(),
|
||
Username: user.Username,
|
||
NickName: user.NickName,
|
||
SideMode: user.SideMode,
|
||
HeaderImg: user.HeaderImg,
|
||
BaseColor: user.BaseColor,
|
||
AuthorityId: user.AuthorityId,
|
||
Phone: user.Phone,
|
||
Email: user.Email,
|
||
Enable: user.Enable,
|
||
}
|
||
if user.OriginSetting != nil {
|
||
info.OriginSetting = string(user.OriginSetting)
|
||
}
|
||
if user.Authority != nil {
|
||
auth := toTypesAuthorityInfo(user.Authority)
|
||
info.Authority = &auth
|
||
}
|
||
if len(user.Authorities) > 0 {
|
||
info.Authorities = make([]types.AuthorityInfo, len(user.Authorities))
|
||
for i, a := range user.Authorities {
|
||
info.Authorities[i] = toTypesAuthorityInfo(a)
|
||
}
|
||
}
|
||
return info
|
||
}
|
||
|
||
// toTypesAuthorityInfo 转换角色信息为types格式
|
||
func toTypesAuthorityInfo(auth *system.Authority) types.AuthorityInfo {
|
||
if auth == nil {
|
||
return types.AuthorityInfo{}
|
||
}
|
||
return types.AuthorityInfo{
|
||
AuthorityId: auth.AuthorityId,
|
||
AuthorityName: auth.AuthorityName,
|
||
ParentId: auth.ParentId,
|
||
DefaultRouter: auth.DefaultRouter,
|
||
}
|
||
}
|
||
|
||
// RegisterRoutes 注册用户路由
|
||
func (s *UserService) RegisterRoutes(rg *RouterGroup) {
|
||
// 公开路由(无需认证)
|
||
rg.Public.POST("/base/login", s.Login)
|
||
|
||
// 私有路由 + 操作记录(写操作)
|
||
rg.PrivateWithRecord.POST("/user/admin_register", s.Register)
|
||
rg.PrivateWithRecord.POST("/user/changePassword", s.ChangePassword)
|
||
rg.PrivateWithRecord.POST("/user/setUserAuthority", s.SetUserAuthority)
|
||
rg.PrivateWithRecord.DELETE("/user/deleteUser", s.DeleteUser)
|
||
rg.PrivateWithRecord.PUT("/user/setUserInfo", s.SetUserInfo)
|
||
rg.PrivateWithRecord.PUT("/user/setSelfInfo", s.SetSelfInfo)
|
||
rg.PrivateWithRecord.POST("/user/setUserAuthorities", s.SetUserAuthorities)
|
||
rg.PrivateWithRecord.POST("/user/resetPassword", s.ResetPassword)
|
||
rg.PrivateWithRecord.PUT("/user/setSelfSetting", s.SetSelfSetting)
|
||
|
||
// 私有路由(读操作,不记录)
|
||
rg.Private.POST("/user/getUserList", s.GetUserList)
|
||
rg.Private.GET("/user/getUserInfo", s.GetUserInfo)
|
||
}
|