mirror of
https://github.com/lukaszraczylo/gohoarder.git
synced 2026-10-12 00:45:16 +00:00
The automated update changed only go.mod, so the build failed on the old v2 imports. This commit moves the code to the v3 API. The commit replaces BodyParser with Bind().Body, Static with the static middleware, and ListenTLS with ListenConfig. It also updates the tests for TestConfig. Fixes #179
136 lines
3.5 KiB
Go
136 lines
3.5 KiB
Go
package app
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/gofiber/fiber/v3"
|
|
"github.com/lukaszraczylo/gohoarder/pkg/auth"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
// GenerateAPIKeyRequest represents a request to generate a new API key
|
|
type GenerateAPIKeyRequest struct {
|
|
ExpiresInMin *int `json:"expires_in_min"`
|
|
Name string `json:"name"`
|
|
Role string `json:"role"`
|
|
}
|
|
|
|
// handleGenerateAPIKey generates a new API key
|
|
func (a *App) handleGenerateAPIKey(c fiber.Ctx) error {
|
|
c.Set("Content-Type", "application/json")
|
|
|
|
var req GenerateAPIKeyRequest
|
|
if err := c.Bind().Body(&req); err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
|
"error": "invalid JSON in request body",
|
|
})
|
|
}
|
|
|
|
// Validate request
|
|
if req.Name == "" {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
|
"error": "name is required",
|
|
})
|
|
}
|
|
|
|
// Parse role (default to readonly if not specified)
|
|
var role auth.Role
|
|
switch req.Role {
|
|
case "admin":
|
|
role = auth.RoleAdmin
|
|
case "readwrite":
|
|
role = auth.RoleReadWrite
|
|
case "readonly", "":
|
|
role = auth.RoleReadOnly
|
|
default:
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
|
"error": "invalid role, must be 'admin', 'readwrite', or 'readonly'",
|
|
})
|
|
}
|
|
|
|
// Calculate expiration
|
|
var expiresIn *time.Duration
|
|
if req.ExpiresInMin != nil {
|
|
duration := time.Duration(*req.ExpiresInMin) * time.Minute
|
|
expiresIn = &duration
|
|
}
|
|
|
|
// Generate key
|
|
apiKey, rawKey, err := a.authManager.GenerateAPIKey(req.Name, role, expiresIn)
|
|
if err != nil {
|
|
log.Error().Err(err).Str("name", req.Name).Msg("Failed to generate API key")
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"error": "failed to generate API key",
|
|
})
|
|
}
|
|
|
|
log.Info().
|
|
Str("key_id", apiKey.ID).
|
|
Str("name", apiKey.Name).
|
|
Str("role", string(apiKey.Role)).
|
|
Msg("API key generated")
|
|
|
|
// Return the key info and raw key (only time it's shown!)
|
|
return c.Status(fiber.StatusCreated).JSON(fiber.Map{
|
|
"key": rawKey, // IMPORTANT: This is the only time the raw key is shown
|
|
"key_id": apiKey.ID,
|
|
"name": apiKey.Name,
|
|
"role": apiKey.Role,
|
|
"expires": apiKey.ExpiresAt,
|
|
"message": "Save this key now! It will not be shown again.",
|
|
})
|
|
}
|
|
|
|
// handleListAPIKeys lists all API keys
|
|
func (a *App) handleListAPIKeys(c fiber.Ctx) error {
|
|
c.Set("Content-Type", "application/json")
|
|
|
|
keys := a.authManager.ListAPIKeys()
|
|
|
|
// Convert to response format (excluding hashed keys)
|
|
response := make([]fiber.Map, len(keys))
|
|
for i, key := range keys {
|
|
response[i] = fiber.Map{
|
|
"id": key.ID,
|
|
"name": key.Name,
|
|
"role": key.Role,
|
|
"created_at": key.CreatedAt,
|
|
"expires_at": key.ExpiresAt,
|
|
"last_used_at": key.LastUsedAt,
|
|
"permissions": key.Permissions,
|
|
}
|
|
}
|
|
|
|
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
|
"keys": response,
|
|
"total": len(response),
|
|
})
|
|
}
|
|
|
|
// handleRevokeAPIKey revokes an API key
|
|
func (a *App) handleRevokeAPIKey(c fiber.Ctx) error {
|
|
c.Set("Content-Type", "application/json")
|
|
|
|
keyID := c.Params("key_id")
|
|
if keyID == "" {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
|
"error": "key_id parameter is required",
|
|
})
|
|
}
|
|
|
|
err := a.authManager.RevokeAPIKey(keyID)
|
|
if err != nil {
|
|
log.Warn().Err(err).Str("key_id", keyID).Msg("Failed to revoke API key")
|
|
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
|
|
"error": "API key not found",
|
|
})
|
|
}
|
|
|
|
log.Info().Str("key_id", keyID).Msg("API key revoked")
|
|
|
|
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
|
"message": "API key revoked successfully",
|
|
"key_id": keyID,
|
|
})
|
|
}
|