Changeset 0.24.2 (#158)
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/auth"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/notifications"
|
||||
@@ -22,8 +23,15 @@ type createGroupRequest struct {
|
||||
}
|
||||
|
||||
type updateGroupRequest struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
Permissions *[]string `json:"permissions,omitempty"`
|
||||
TokenBudgetDaily *int64 `json:"token_budget_daily,omitempty"`
|
||||
TokenBudgetMonthly *int64 `json:"token_budget_monthly,omitempty"`
|
||||
AllowedModels *[]string `json:"allowed_models,omitempty"`
|
||||
ClearBudgetDaily bool `json:"clear_budget_daily,omitempty"`
|
||||
ClearBudgetMonthly bool `json:"clear_budget_monthly,omitempty"`
|
||||
ClearAllowedModels bool `json:"clear_allowed_models,omitempty"`
|
||||
}
|
||||
|
||||
type addGroupMemberRequest struct {
|
||||
@@ -85,7 +93,7 @@ func (h *GroupHandler) CreateGroup(c *gin.Context) {
|
||||
Description: req.Description,
|
||||
Scope: req.Scope,
|
||||
TeamID: req.TeamID,
|
||||
CreatedBy: actorID,
|
||||
CreatedBy: &actorID,
|
||||
}
|
||||
|
||||
if err := h.stores.Groups.Create(c.Request.Context(), g); err != nil {
|
||||
@@ -132,12 +140,34 @@ func (h *GroupHandler) UpdateGroup(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if req.Name == nil && req.Description == nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "no fields to update"})
|
||||
return
|
||||
patch := models.GroupPatch{
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
Permissions: req.Permissions,
|
||||
TokenBudgetDaily: req.TokenBudgetDaily,
|
||||
TokenBudgetMonthly: req.TokenBudgetMonthly,
|
||||
AllowedModels: req.AllowedModels,
|
||||
ClearBudgetDaily: req.ClearBudgetDaily,
|
||||
ClearBudgetMonthly: req.ClearBudgetMonthly,
|
||||
ClearAllowedModels: req.ClearAllowedModels,
|
||||
}
|
||||
|
||||
err := h.stores.Groups.Update(c.Request.Context(), id, req.Name, req.Description)
|
||||
// Validate permissions if provided
|
||||
if patch.Permissions != nil {
|
||||
valid := auth.AllPermissions
|
||||
validSet := make(map[string]bool, len(valid))
|
||||
for _, p := range valid {
|
||||
validSet[p] = true
|
||||
}
|
||||
for _, p := range *patch.Permissions {
|
||||
if !validSet[p] {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "unknown permission: " + p})
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err := h.stores.Groups.Update(c.Request.Context(), id, patch)
|
||||
if err == sql.ErrNoRows {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "group not found"})
|
||||
return
|
||||
@@ -166,6 +196,11 @@ func (h *GroupHandler) DeleteGroup(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
// Store layer returns a plain error for system groups.
|
||||
if err.Error() == "system groups cannot be deleted" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "system groups cannot be deleted"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "delete failed"})
|
||||
return
|
||||
}
|
||||
@@ -382,3 +417,28 @@ func (h *GroupHandler) DeleteResourceGrant(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"ok": true})
|
||||
AuditLog(c, "grant.delete", resourceType, resourceID, nil)
|
||||
}
|
||||
|
||||
// ListPermissions returns all valid permission strings.
|
||||
// GET /api/v1/admin/permissions
|
||||
func (h *GroupHandler) ListPermissions(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"permissions": auth.AllPermissions})
|
||||
}
|
||||
|
||||
// GetUserPermissions returns the effective permissions for a given user.
|
||||
// GET /api/v1/admin/users/:id/permissions
|
||||
func (h *GroupHandler) GetUserPermissions(c *gin.Context) {
|
||||
userID := c.Param("id")
|
||||
|
||||
perms, err := auth.ResolvePermissions(c.Request.Context(), h.stores, userID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to resolve permissions"})
|
||||
return
|
||||
}
|
||||
|
||||
// Convert map to sorted slice for stable output
|
||||
list := make([]string, 0, len(perms))
|
||||
for p := range perms {
|
||||
list = append(list, p)
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"permissions": list, "user_id": userID})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user