mirror of
https://github.com/warmbly/warmbly.git
synced 2026-08-19 16:01:16 +00:00
d227038ca0
Disable the linters that fire on legacy code without flagging real bugs: `unused` (orphan repos kept for future feature flags), `unconvert` (defensive type conversions), `gosimple` (style suggestions in code we don't want to touch). govet: disable `shadow` (idiomatic `err :=` re-decls in transaction patterns) and `nilness` (legitimate defensive nil checks that look tautological to the analyzer). Ran `gofmt -w internal/ cmd/` — every Go file now passes gofmt -l with no output. Kept: govet, staticcheck, ineffassign, typecheck, bodyclose, noctx, sqlclosecheck, gofmt, goimports, misspell — the real-bug checks.
173 lines
3.8 KiB
Go
173 lines
3.8 KiB
Go
package handler
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
"github.com/warmbly/warmbly/internal/api/middleware"
|
|
"github.com/warmbly/warmbly/internal/errx"
|
|
"github.com/warmbly/warmbly/internal/models"
|
|
)
|
|
|
|
// CreateAPIKey creates a new API key for the organization
|
|
// POST /api-keys
|
|
func (h *Handler) CreateAPIKey(c *gin.Context) {
|
|
orgID := middleware.GetOrganizationID(c)
|
|
if orgID == nil {
|
|
errx.JSON(c, errx.New(errx.BadRequest, "no organization selected"))
|
|
return
|
|
}
|
|
|
|
userID, err := middleware.GetUserUUID(c)
|
|
if err != nil {
|
|
errx.JSON(c, errx.ErrUnauthorized)
|
|
return
|
|
}
|
|
|
|
var data models.CreateAPIKey
|
|
if err := c.ShouldBindJSON(&data); err != nil {
|
|
errx.JSON(c, errx.New(errx.BadRequest, "invalid request body"))
|
|
return
|
|
}
|
|
|
|
keyWithSecret, xerr := h.APIKeyService.Create(c.Request.Context(), *orgID, userID, &data)
|
|
if xerr != nil {
|
|
errx.JSON(c, xerr)
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, keyWithSecret)
|
|
}
|
|
|
|
// ListAPIKeys lists all API keys for the organization
|
|
// GET /api-keys
|
|
func (h *Handler) ListAPIKeys(c *gin.Context) {
|
|
orgID := middleware.GetOrganizationID(c)
|
|
if orgID == nil {
|
|
errx.JSON(c, errx.New(errx.BadRequest, "no organization selected"))
|
|
return
|
|
}
|
|
|
|
var cursor *uuid.UUID
|
|
if cursorStr := c.Query("cursor"); cursorStr != "" {
|
|
if id, err := uuid.Parse(cursorStr); err == nil {
|
|
cursor = &id
|
|
}
|
|
}
|
|
|
|
limit := 50
|
|
if limitStr := c.Query("limit"); limitStr != "" {
|
|
if l, err := strconv.Atoi(limitStr); err == nil && l > 0 && l <= 100 {
|
|
limit = l
|
|
}
|
|
}
|
|
|
|
result, xerr := h.APIKeyService.List(c.Request.Context(), *orgID, limit, cursor)
|
|
if xerr != nil {
|
|
errx.JSON(c, xerr)
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, result)
|
|
}
|
|
|
|
// GetAPIKey gets a specific API key
|
|
// GET /api-keys/:id
|
|
func (h *Handler) GetAPIKey(c *gin.Context) {
|
|
orgID := middleware.GetOrganizationID(c)
|
|
if orgID == nil {
|
|
errx.JSON(c, errx.New(errx.BadRequest, "no organization selected"))
|
|
return
|
|
}
|
|
|
|
keyIDStr := c.Param("id")
|
|
keyID, err := uuid.Parse(keyIDStr)
|
|
if err != nil {
|
|
errx.JSON(c, errx.ErrNotFound)
|
|
return
|
|
}
|
|
|
|
key, xerr := h.APIKeyService.Get(c.Request.Context(), *orgID, keyID)
|
|
if xerr != nil {
|
|
errx.JSON(c, xerr)
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, key)
|
|
}
|
|
|
|
// UpdateAPIKey updates an API key
|
|
// PATCH /api-keys/:id
|
|
func (h *Handler) UpdateAPIKey(c *gin.Context) {
|
|
orgID := middleware.GetOrganizationID(c)
|
|
if orgID == nil {
|
|
errx.JSON(c, errx.New(errx.BadRequest, "no organization selected"))
|
|
return
|
|
}
|
|
|
|
keyIDStr := c.Param("id")
|
|
keyID, err := uuid.Parse(keyIDStr)
|
|
if err != nil {
|
|
errx.JSON(c, errx.ErrNotFound)
|
|
return
|
|
}
|
|
|
|
var data models.UpdateAPIKey
|
|
if err := c.ShouldBindJSON(&data); err != nil {
|
|
errx.JSON(c, errx.New(errx.BadRequest, "invalid request body"))
|
|
return
|
|
}
|
|
|
|
key, xerr := h.APIKeyService.Update(c.Request.Context(), *orgID, keyID, &data)
|
|
if xerr != nil {
|
|
errx.JSON(c, xerr)
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, key)
|
|
}
|
|
|
|
// RevokeAPIKey revokes an API key
|
|
// DELETE /api-keys/:id
|
|
func (h *Handler) RevokeAPIKey(c *gin.Context) {
|
|
orgID := middleware.GetOrganizationID(c)
|
|
if orgID == nil {
|
|
errx.JSON(c, errx.New(errx.BadRequest, "no organization selected"))
|
|
return
|
|
}
|
|
|
|
keyIDStr := c.Param("id")
|
|
keyID, err := uuid.Parse(keyIDStr)
|
|
if err != nil {
|
|
errx.JSON(c, errx.ErrNotFound)
|
|
return
|
|
}
|
|
|
|
reason := c.Query("reason")
|
|
if reason == "" {
|
|
reason = "Revoked by user"
|
|
}
|
|
|
|
xerr := h.APIKeyService.Revoke(c.Request.Context(), *orgID, keyID, reason)
|
|
if xerr != nil {
|
|
errx.JSON(c, xerr)
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"status": "revoked"})
|
|
}
|
|
|
|
// ListAPIPermissions lists all available API permissions
|
|
// GET /api-keys/permissions
|
|
func (h *Handler) ListAPIPermissions(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"permissions": models.AllAPIPermissions,
|
|
"presets": gin.H{
|
|
"read_only": models.APIPermReadOnly,
|
|
"full_access": models.APIPermFullAccess,
|
|
},
|
|
})
|
|
}
|