add a powershell script that supports starting MES, WMS, WMSClient, Workstation and Dashboard projects with one command, includes build and run logic for backend services and npm dev for dashboard
291 lines
8.7 KiB
Go
291 lines
8.7 KiB
Go
package logic
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
|
|
tokenx "bj_power_mes/common/token"
|
|
"bj_power_mes/ent"
|
|
"bj_power_mes/ent/permission"
|
|
"bj_power_mes/ent/role"
|
|
"bj_power_mes/ent/user"
|
|
|
|
"golang.org/x/crypto/bcrypt"
|
|
)
|
|
|
|
// ------ 请求/返回 DTO ------
|
|
|
|
type LoginReq struct {
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
}
|
|
|
|
type LoginResp struct {
|
|
AccessToken string `json:"accessToken"`
|
|
RefreshToken string `json:"refreshToken"`
|
|
AccessExpire int64 `json:"accessExpire"`
|
|
}
|
|
|
|
type RefreshReq struct {
|
|
RefreshToken string `json:"refreshToken"`
|
|
}
|
|
|
|
type UserInfoResp struct {
|
|
UserId int `json:"userId"`
|
|
Username string `json:"username"`
|
|
Name string `json:"name"`
|
|
RoleId int `json:"roleId"`
|
|
RoleCode string `json:"roleCode"`
|
|
RoleName string `json:"roleName"`
|
|
Menus []permissionItem `json:"menus"`
|
|
PermissionCodes []string `json:"permissionCodes"`
|
|
}
|
|
|
|
type ChangePasswordReq struct {
|
|
OldPassword string `json:"oldPassword"`
|
|
NewPassword string `json:"newPassword"`
|
|
}
|
|
|
|
type permissionItem struct {
|
|
Code string `json:"code"`
|
|
Name string `json:"name"`
|
|
Path string `json:"path"`
|
|
Icon string `json:"icon"`
|
|
}
|
|
|
|
// currentToken 生成 access + refresh 双 token
|
|
func (s *Service) issueTokens(usr *ent.User, roleEntity *ent.Role) (LoginResp, error) {
|
|
claims := tokenx.Claims{UserId: usr.ID, Username: usr.Username, Name: usr.Name, RoleId: usr.RoleId}
|
|
if roleEntity != nil {
|
|
claims.RoleCode = roleEntity.Code
|
|
claims.RoleName = roleEntity.Name
|
|
} else {
|
|
claims.RoleCode = ""
|
|
claims.RoleName = ""
|
|
}
|
|
access, err := tokenx.Issue(s.ctx.Config.Auth.AccessSecret, time.Duration(s.ctx.Config.Auth.AccessExpire)*time.Second, claims)
|
|
if err != nil {
|
|
return LoginResp{}, err
|
|
}
|
|
refresh, err := tokenx.Issue(s.ctx.Config.Auth.AccessSecret, time.Duration(s.ctx.Config.Auth.RefreshExpire)*time.Second, claims)
|
|
if err != nil {
|
|
return LoginResp{}, err
|
|
}
|
|
return LoginResp{AccessToken: access, RefreshToken: refresh, AccessExpire: s.ctx.Config.Auth.AccessExpire}, nil
|
|
}
|
|
|
|
// Login 登录
|
|
func (s *Service) Login(ctx context.Context, req LoginReq) (LoginResp, error) {
|
|
var resp LoginResp
|
|
usr, err := s.ctx.EntClient.User.Query().Where(user.Username(req.Username)).First(ctx)
|
|
if err != nil {
|
|
return resp, errors.New("用户名或密码错误")
|
|
}
|
|
if usr.Status != "ENABLED" {
|
|
return resp, errors.New("账号已禁用")
|
|
}
|
|
if bcrypt.CompareHashAndPassword([]byte(usr.Password), []byte(req.Password)) != nil {
|
|
return resp, errors.New("用户名或密码错误")
|
|
}
|
|
roleEntity, _ := s.ctx.EntClient.Role.Get(ctx, usr.RoleId)
|
|
return s.issueTokens(usr, roleEntity)
|
|
}
|
|
|
|
// Refresh 刷新访问令牌(滑动续签)
|
|
func (s *Service) Refresh(ctx context.Context, req RefreshReq) (LoginResp, error) {
|
|
var resp LoginResp
|
|
claims, err := tokenx.Parse(s.ctx.Config.Auth.AccessSecret, req.RefreshToken)
|
|
if err != nil {
|
|
return resp, errors.New("刷新令牌无效或已过期")
|
|
}
|
|
usr, err := s.ctx.EntClient.User.Get(ctx, claims.UserId)
|
|
if err != nil {
|
|
return resp, errors.New("用户不存在")
|
|
}
|
|
if usr.Status != "ENABLED" {
|
|
return resp, errors.New("账号已禁用")
|
|
}
|
|
roleEntity, _ := s.ctx.EntClient.Role.Get(ctx, usr.RoleId)
|
|
return s.issueTokens(usr, roleEntity)
|
|
}
|
|
|
|
// UserInfo 当前用户信息 + 菜单权限
|
|
func (s *Service) UserInfo(ctx context.Context, userId int) (UserInfoResp, error) {
|
|
var out UserInfoResp
|
|
usr, err := s.ctx.EntClient.User.Get(ctx, userId)
|
|
if err != nil {
|
|
return out, err
|
|
}
|
|
out.UserId = usr.ID
|
|
out.Username = usr.Username
|
|
out.Name = usr.Name
|
|
out.RoleId = usr.RoleId
|
|
|
|
roleEntity, err := s.ctx.EntClient.Role.Get(ctx, usr.RoleId)
|
|
if err != nil {
|
|
roleEntity = nil
|
|
}
|
|
if roleEntity != nil {
|
|
out.RoleCode = roleEntity.Code
|
|
out.RoleName = roleEntity.Name
|
|
out.PermissionCodes = roleEntity.PermissionCodes
|
|
}
|
|
// 取所拥有权限对应的菜单
|
|
perms, err := s.ctx.EntClient.Permission.Query().
|
|
Where(permission.Type("MENU")).
|
|
Order(ent.Asc(permission.FieldSort)).All(ctx)
|
|
if err != nil {
|
|
return out, nil
|
|
}
|
|
owned := map[string]bool{}
|
|
for _, c := range out.PermissionCodes {
|
|
owned[c] = true
|
|
}
|
|
for _, p := range perms {
|
|
if roleEntity == nil {
|
|
continue
|
|
}
|
|
if roleEntity.Code == "SUPER_ADMIN" || owned[p.Code] || owned["*"] {
|
|
out.Menus = append(out.Menus, permissionItem{Code: p.Code, Name: p.Name, Path: p.Path, Icon: p.Icon})
|
|
}
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
// ChangePassword 当前登录用户修改自己的密码
|
|
func (s *Service) ChangePassword(ctx context.Context, userId int, req ChangePasswordReq) error {
|
|
if userId <= 0 {
|
|
return errors.New("未登录")
|
|
}
|
|
if req.OldPassword == "" || req.NewPassword == "" {
|
|
return errors.New("请输入旧密码与新密码")
|
|
}
|
|
if len(req.NewPassword) < 6 {
|
|
return errors.New("新密码长度至少 6 位")
|
|
}
|
|
usr, err := s.ctx.EntClient.User.Get(ctx, userId)
|
|
if err != nil {
|
|
return errors.New("用户不存在")
|
|
}
|
|
if bcrypt.CompareHashAndPassword([]byte(usr.Password), []byte(req.OldPassword)) != nil {
|
|
return errors.New("旧密码不正确")
|
|
}
|
|
hash, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return s.ctx.EntClient.User.UpdateOneID(userId).SetPassword(string(hash)).Exec(ctx)
|
|
}
|
|
|
|
// ------ 用户 / 角色 / 权限 管理 ------
|
|
|
|
type UserReq struct {
|
|
Id int `json:"id"`
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
Name string `json:"name"`
|
|
RoleId int `json:"roleId"`
|
|
Status string `json:"status"`
|
|
}
|
|
|
|
func (s *Service) CreateUser(ctx context.Context, req UserReq) error {
|
|
hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
status := req.Status
|
|
if status == "" {
|
|
status = "ENABLED"
|
|
}
|
|
return s.ctx.EntClient.User.Create().
|
|
SetUsername(req.Username).
|
|
SetPassword(string(hash)).
|
|
SetName(req.Name).
|
|
SetRoleId(req.RoleId).
|
|
SetStatus(status).
|
|
Exec(ctx)
|
|
}
|
|
|
|
func (s *Service) UpdateUser(ctx context.Context, req UserReq) error {
|
|
u := s.ctx.EntClient.User.UpdateOneID(req.Id).SetRoleId(req.RoleId).SetName(req.Name)
|
|
if req.Password != "" {
|
|
hash, _ := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
|
u.SetPassword(string(hash))
|
|
}
|
|
if req.Status != "" {
|
|
u.SetStatus(req.Status)
|
|
}
|
|
return u.Exec(ctx)
|
|
}
|
|
|
|
func (s *Service) DeleteUser(ctx context.Context, id int) error {
|
|
if id == 1 {
|
|
return errors.New("不能删除超级管理员")
|
|
}
|
|
return s.ctx.EntClient.User.DeleteOneID(id).Exec(ctx)
|
|
}
|
|
|
|
func (s *Service) ListUsers(ctx context.Context) ([]*ent.User, error) {
|
|
return s.ctx.EntClient.User.Query().Order(ent.Asc(user.FieldID)).All(ctx)
|
|
}
|
|
|
|
type RoleReq struct {
|
|
Id int `json:"id"`
|
|
Name string `json:"name"`
|
|
Code string `json:"code"`
|
|
Remark string `json:"remark"`
|
|
PermissionCodes []string `json:"permissionCodes"`
|
|
}
|
|
|
|
func (s *Service) CreateRole(ctx context.Context, req RoleReq) error {
|
|
return s.ctx.EntClient.Role.Create().
|
|
SetName(req.Name).SetCode(req.Code).SetRemark(req.Remark).
|
|
SetPermissionCodes(req.PermissionCodes).Exec(ctx)
|
|
}
|
|
|
|
func (s *Service) UpdateRole(ctx context.Context, req RoleReq) error {
|
|
return s.ctx.EntClient.Role.UpdateOneID(req.Id).
|
|
SetName(req.Name).SetCode(req.Code).SetRemark(req.Remark).
|
|
SetPermissionCodes(req.PermissionCodes).Exec(ctx)
|
|
}
|
|
|
|
func (s *Service) DeleteRole(ctx context.Context, id int) error {
|
|
return s.ctx.EntClient.Role.DeleteOneID(id).Exec(ctx)
|
|
}
|
|
|
|
func (s *Service) ListRoles(ctx context.Context) ([]*ent.Role, error) {
|
|
return s.ctx.EntClient.Role.Query().Order(ent.Asc(role.FieldID)).All(ctx)
|
|
}
|
|
|
|
type PermissionReq struct {
|
|
Id int `json:"id"`
|
|
Code string `json:"code"`
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
Path string `json:"path"`
|
|
Icon string `json:"icon"`
|
|
Sort int `json:"sort"`
|
|
Remark string `json:"remark"`
|
|
}
|
|
|
|
func (s *Service) CreatePermission(ctx context.Context, req PermissionReq) error {
|
|
return s.ctx.EntClient.Permission.Create().
|
|
SetCode(req.Code).SetName(req.Name).SetType(req.Type).
|
|
SetPath(req.Path).SetIcon(req.Icon).SetSort(req.Sort).SetRemark(req.Remark).Exec(ctx)
|
|
}
|
|
|
|
func (s *Service) UpdatePermission(ctx context.Context, req PermissionReq) error {
|
|
return s.ctx.EntClient.Permission.UpdateOneID(req.Id).
|
|
SetCode(req.Code).SetName(req.Name).SetType(req.Type).
|
|
SetPath(req.Path).SetIcon(req.Icon).SetSort(req.Sort).SetRemark(req.Remark).Exec(ctx)
|
|
}
|
|
|
|
func (s *Service) DeletePermission(ctx context.Context, id int) error {
|
|
return s.ctx.EntClient.Permission.DeleteOneID(id).Exec(ctx)
|
|
}
|
|
|
|
func (s *Service) ListPermissions(ctx context.Context) ([]*ent.Permission, error) {
|
|
return s.ctx.EntClient.Permission.Query().Order(ent.Asc(permission.FieldSort), ent.Asc(permission.FieldID)).All(ctx)
|
|
}
|