feat: group admin users by role

This commit is contained in:
OpenClaw Agent
2026-09-17 03:35:20 +08:00
parent 7507ffa02b
commit 9f57addec8
2 changed files with 72 additions and 3 deletions
+66
View File
@@ -271,3 +271,69 @@ func (a *App) adminUpdateUser(c *gin.Context) {
a.audit(operator.ID, "user.update", "user", strconv.FormatUint(uint64(u.ID), 10), strings.Join(changes, ","))
c.JSON(200, u)
}
func (a *App) adminUserCredits(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
c.Status(400)
return
}
var account CreditAccount
if err := a.db.Where("user_id = ?", id).First(&account).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
c.JSON(404, gin.H{"error": "credit account not found"})
return
}
c.JSON(500, gin.H{"error": err.Error()})
return
}
var tasks int64
if err := a.db.Model(&Task{}).Where("user_id = ?", id).Count(&tasks).Error; err != nil {
c.JSON(500, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"balance": account.Balance, "reserved": account.Reserved, "available": account.Balance - account.Reserved, "tasks": tasks})
}
func (a *App) adminAdjustCredits(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
c.Status(400)
return
}
var in struct {
Amount int64 `json:"amount"`
}
if c.BindJSON(&in) != nil || in.Amount == 0 {
c.JSON(400, gin.H{"error": "amount cannot be zero"})
return
}
operator := c.MustGet("user").(*User)
err = a.db.Transaction(func(tx *gorm.DB) error {
var account CreditAccount
if err := tx.Where("user_id = ?", id).First(&account).Error; err != nil {
return err
}
if in.Amount < 0 && account.Balance+in.Amount < account.Reserved {
return errors.New("cannot reduce balance below reserved credits")
}
account.Balance += in.Amount
if account.Balance < 0 {
return errors.New("insufficient balance")
}
if err := tx.Save(&account).Error; err != nil {
return err
}
typ, reason := "grant", "admin credit adjustment"
if in.Amount < 0 {
typ, reason = "admin_debit", "admin credit deduction"
}
return tx.Create(&CreditTransaction{UserID: uint(id), Type: typ, Amount: in.Amount, BalanceAfter: account.Balance, ReferenceType: "admin", ReferenceID: strconv.FormatUint(uint64(operator.ID), 10), Reason: reason}).Error
})
if err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
a.audit(operator.ID, "user.credits.adjust", "user", strconv.FormatUint(id, 10), "amount="+strconv.FormatInt(in.Amount, 10))
c.JSON(200, gin.H{"ok": true})
}