小程序一些功能更新
This commit is contained in:
193
internal/logic/admin_account.go
Normal file
193
internal/logic/admin_account.go
Normal file
@@ -0,0 +1,193 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
v1 "tool-api/api/admin/v1"
|
||||
"tool-api/internal/consts"
|
||||
)
|
||||
|
||||
// ============================================================================
|
||||
// 管理员账号管理(T17)
|
||||
// ============================================================================
|
||||
|
||||
// AdminList 管理员列表
|
||||
func AdminList(ctx context.Context) (*v1.AdminListRes, error) {
|
||||
records, err := g.Model(consts.TableAdminUsers).OrderAsc("id").All()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list := make([]v1.AdminItem, 0, len(records))
|
||||
for _, r := range records {
|
||||
list = append(list, v1.AdminItem{
|
||||
Id: r["id"].Int64(),
|
||||
Account: r["account"].String(),
|
||||
NickName: r["nick_name"].String(),
|
||||
RoleName: r["role_name"].String(),
|
||||
RoleValue: r["role_value"].String(),
|
||||
Status: r["status"].Int(),
|
||||
CreatedAt: r["created_at"].String(),
|
||||
})
|
||||
}
|
||||
return &v1.AdminListRes{List: list}, nil
|
||||
}
|
||||
|
||||
// lastSuperGuard 保护「最后一个启用中的超级管理员」:
|
||||
// 若该管理员当前是启用中的超管,而改动后会失去「启用中的超管」身份(降角色或停用),
|
||||
// 且库中仅剩这一个,则拒绝——避免把自己锁在门外。
|
||||
func lastSuperGuard(ctx context.Context, id int64, newRole string, newStatus int) error {
|
||||
rec, err := g.Model(consts.TableAdminUsers).Where("id", id).One()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rec.IsEmpty() {
|
||||
return nil
|
||||
}
|
||||
isEnabledSuper := rec["role_value"].String() == consts.AdminRoleSuper &&
|
||||
rec["status"].Int() == consts.AdminStatusEnabled
|
||||
if !isEnabledSuper {
|
||||
return nil
|
||||
}
|
||||
stillSuper := newRole == consts.AdminRoleSuper && newStatus == consts.AdminStatusEnabled
|
||||
if stillSuper {
|
||||
return nil
|
||||
}
|
||||
count, err := g.Model(consts.TableAdminUsers).
|
||||
Where("role_value", consts.AdminRoleSuper).
|
||||
Where("status", consts.AdminStatusEnabled).
|
||||
Count()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if count <= 1 {
|
||||
return gerror.New("至少保留一个启用中的超级管理员")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AdminSave 新增/修改管理员。编辑不清空密码(除非显式传入新密码)。
|
||||
func AdminSave(ctx context.Context, req *v1.AdminSaveReq) (*v1.AdminSaveRes, error) {
|
||||
if req.Id > 0 {
|
||||
rec, err := g.Model(consts.TableAdminUsers).Where("id", req.Id).One()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rec.IsEmpty() {
|
||||
return nil, gerror.New("管理员不存在")
|
||||
}
|
||||
if err = lastSuperGuard(ctx, req.Id, req.RoleValue, rec["status"].Int()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data := g.Map{
|
||||
"nick_name": req.NickName,
|
||||
"role_name": roleNameOf(req.RoleValue),
|
||||
"role_value": req.RoleValue,
|
||||
}
|
||||
pwdChanged := strings.TrimSpace(req.Password) != ""
|
||||
if pwdChanged {
|
||||
hash, herr := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
||||
if herr != nil {
|
||||
return nil, herr
|
||||
}
|
||||
data["password"] = string(hash)
|
||||
}
|
||||
if _, err = g.Model(consts.TableAdminUsers).Where("id", req.Id).Data(data).Update(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
WriteAudit(ctx, AuditEntry{
|
||||
Action: "admin.update",
|
||||
TargetType: "admin",
|
||||
TargetId: strconv.FormatInt(req.Id, 10),
|
||||
Before: g.Map{
|
||||
"nick_name": rec["nick_name"].String(),
|
||||
"role_value": rec["role_value"].String(),
|
||||
},
|
||||
After: g.Map{
|
||||
"nick_name": req.NickName,
|
||||
"role_value": req.RoleValue,
|
||||
"pwd_changed": pwdChanged,
|
||||
},
|
||||
Result: consts.AuditResultSuccess,
|
||||
})
|
||||
return &v1.AdminSaveRes{}, nil
|
||||
}
|
||||
|
||||
account := strings.TrimSpace(req.Account)
|
||||
if account == "" {
|
||||
return nil, gerror.New("请填写登录账号")
|
||||
}
|
||||
if strings.TrimSpace(req.Password) == "" {
|
||||
return nil, gerror.New("请填写登录密码")
|
||||
}
|
||||
count, err := g.Model(consts.TableAdminUsers).Where("account", account).Count()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if count > 0 {
|
||||
return nil, gerror.New("账号已存在")
|
||||
}
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newId, err := g.Model(consts.TableAdminUsers).Data(g.Map{
|
||||
"account": account,
|
||||
"password": string(hash),
|
||||
"nick_name": req.NickName,
|
||||
"role_name": roleNameOf(req.RoleValue),
|
||||
"role_value": req.RoleValue,
|
||||
"status": consts.AdminStatusEnabled,
|
||||
"created_at": gtime.Now(),
|
||||
}).InsertAndGetId()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
WriteAudit(ctx, AuditEntry{
|
||||
Action: "admin.create",
|
||||
TargetType: "admin",
|
||||
TargetId: strconv.FormatInt(newId, 10),
|
||||
After: g.Map{
|
||||
"account": account,
|
||||
"nick_name": req.NickName,
|
||||
"role_value": req.RoleValue,
|
||||
},
|
||||
Result: consts.AuditResultSuccess,
|
||||
})
|
||||
return &v1.AdminSaveRes{}, nil
|
||||
}
|
||||
|
||||
// AdminStatus 启停管理员
|
||||
func AdminStatus(ctx context.Context, id int64, status int) (*v1.AdminStatusRes, error) {
|
||||
if status != consts.AdminStatusEnabled && status != consts.AdminStatusDisabled {
|
||||
return nil, gerror.New("状态非法")
|
||||
}
|
||||
rec, err := g.Model(consts.TableAdminUsers).Where("id", id).One()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rec.IsEmpty() {
|
||||
return nil, gerror.New("管理员不存在")
|
||||
}
|
||||
if err = lastSuperGuard(ctx, id, rec["role_value"].String(), status); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err = g.Model(consts.TableAdminUsers).Where("id", id).Data(g.Map{"status": status}).Update(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
WriteAudit(ctx, AuditEntry{
|
||||
Action: "admin.status",
|
||||
TargetType: "admin",
|
||||
TargetId: strconv.FormatInt(id, 10),
|
||||
Before: g.Map{"status": rec["status"].Int()},
|
||||
After: g.Map{"status": status},
|
||||
Result: consts.AuditResultSuccess,
|
||||
})
|
||||
return &v1.AdminStatusRes{}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user