Files
CalendarApi/internal/service/apikey.go
Michilis 41f6ae916f first commit
Made-with: Cursor
2026-02-28 02:17:55 +00:00

85 lines
2.2 KiB
Go

package service
import (
"context"
"crypto/rand"
"encoding/hex"
"encoding/json"
"github.com/calendarapi/internal/middleware"
"github.com/calendarapi/internal/models"
"github.com/calendarapi/internal/repository"
"github.com/calendarapi/internal/utils"
"github.com/google/uuid"
)
type APIKeyService struct {
queries *repository.Queries
}
func NewAPIKeyService(queries *repository.Queries) *APIKeyService {
return &APIKeyService{queries: queries}
}
func (s *APIKeyService) Create(ctx context.Context, userID uuid.UUID, name string, scopes map[string][]string) (*models.APIKeyResponse, error) {
if name == "" {
return nil, models.NewValidationError("name is required")
}
rawToken := make([]byte, 32)
if _, err := rand.Read(rawToken); err != nil {
return nil, models.ErrInternal
}
token := hex.EncodeToString(rawToken)
hash := middleware.SHA256Hash(token)
scopesJSON, err := json.Marshal(scopes)
if err != nil {
return nil, models.ErrInternal
}
keyID := uuid.New()
key, err := s.queries.CreateAPIKey(ctx, repository.CreateAPIKeyParams{
ID: utils.ToPgUUID(keyID),
UserID: utils.ToPgUUID(userID),
Name: name,
KeyHash: hash,
Scopes: scopesJSON,
})
if err != nil {
return nil, models.ErrInternal
}
return &models.APIKeyResponse{
ID: utils.FromPgUUID(key.ID),
Name: key.Name,
CreatedAt: utils.FromPgTimestamptz(key.CreatedAt),
Token: token,
}, nil
}
func (s *APIKeyService) List(ctx context.Context, userID uuid.UUID) ([]models.APIKeyResponse, error) {
keys, err := s.queries.ListAPIKeysByUser(ctx, utils.ToPgUUID(userID))
if err != nil {
return nil, models.ErrInternal
}
result := make([]models.APIKeyResponse, len(keys))
for i, k := range keys {
result[i] = models.APIKeyResponse{
ID: utils.FromPgUUID(k.ID),
Name: k.Name,
CreatedAt: utils.FromPgTimestamptz(k.CreatedAt),
RevokedAt: utils.FromPgTimestamptzPtr(k.RevokedAt),
}
}
return result, nil
}
func (s *APIKeyService) Revoke(ctx context.Context, userID uuid.UUID, keyID uuid.UUID) error {
return s.queries.RevokeAPIKey(ctx, repository.RevokeAPIKeyParams{
ID: utils.ToPgUUID(keyID),
UserID: utils.ToPgUUID(userID),
})
}