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 }