kra/internal/service/system/user.go

346 lines
10 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)
}