Add admin-configurable device cap per user

- Add max_devices column to users table (default: 10)
- Add UpdateUserMaxDevices database query
- Add CountUserDevices database query
- Add UpdateUserMaxDevices handler with validation (1-100 devices)
- Add PUT /api/auth/users/:id/max-devices endpoint (admin only)
- Update UserList struct to include max_devices field
- Validate user ID format and max_devices range
- Return appropriate errors for invalid requests
This commit is contained in:
2026-01-31 13:06:21 -05:00
parent 7ead4109ef
commit 5039071ea3
+46 -9
View File
@@ -473,15 +473,16 @@ func (h *AuthHandler) ListUsers(c echo.Context) error {
}
type UserList struct {
ID string `json:"id"`
Email string `json:"email"`
Username string `json:"username"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Theme string `json:"theme"`
Role string `json:"role"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
ID string `json:"id"`
Email string `json:"email"`
Username string `json:"username"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Theme string `json:"theme"`
Role string `json:"role"`
MaxDevices int32 `json:"max_devices"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
var userList []UserList
@@ -855,6 +856,42 @@ func (h *AuthHandler) GetScanSettings(c echo.Context) error {
})
}
type UpdateUserMaxDevicesRequest struct {
MaxDevices int32 `json:"max_devices" validate:"required,min=1,max=100"`
}
// UpdateUserMaxDevices handles PUT /api/auth/users/:id/max-devices (admin only)
func (h *AuthHandler) UpdateUserMaxDevices(c echo.Context) error {
userID := c.Param("id")
if userID == "" {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "user id required"})
}
var req UpdateUserMaxDevicesRequest
if err := c.Bind(&req); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid request"})
}
if err := c.Validate(&req); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
}
userUUID, err := uuid.Parse(userID)
if err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid user id"})
}
err = h.db.UpdateUserMaxDevices(c.Request().Context(), database.UpdateUserMaxDevicesParams{
ID: pgtype.UUID{Bytes: userUUID, Valid: true},
MaxDevices: pgtype.Int4{Int32: req.MaxDevices, Valid: true},
})
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
}
return c.JSON(http.StatusOK, map[string]string{"message": "max devices updated"})
}
// AdminMiddleware checks if the user has admin role
func AdminMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {