first commit
Made-with: Cursor
This commit is contained in:
84
internal/service/apikey.go
Normal file
84
internal/service/apikey.go
Normal file
@@ -0,0 +1,84 @@
|
||||
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),
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user