Extract shared service layer for sandbox, API key, and template operations
Moves business logic from API handlers into internal/service/ so that both the REST API and the upcoming dashboard can share the same operations without duplicating code. API handlers now delegate to the service layer and only handle HTTP-specific concerns (request parsing, response formatting).
This commit is contained in:
58
internal/service/apikey.go
Normal file
58
internal/service/apikey.go
Normal file
@ -0,0 +1,58 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"git.omukk.dev/wrenn/sandbox/internal/auth"
|
||||
"git.omukk.dev/wrenn/sandbox/internal/db"
|
||||
"git.omukk.dev/wrenn/sandbox/internal/id"
|
||||
)
|
||||
|
||||
// APIKeyService provides API key operations shared between the REST API and the dashboard.
|
||||
type APIKeyService struct {
|
||||
DB *db.Queries
|
||||
}
|
||||
|
||||
// APIKeyCreateResult holds the result of creating an API key, including the
|
||||
// plaintext key which is only available at creation time.
|
||||
type APIKeyCreateResult struct {
|
||||
Row db.TeamApiKey
|
||||
Plaintext string
|
||||
}
|
||||
|
||||
// Create generates a new API key for the given team.
|
||||
func (s *APIKeyService) Create(ctx context.Context, teamID, userID, name string) (APIKeyCreateResult, error) {
|
||||
if name == "" {
|
||||
name = "Unnamed API Key"
|
||||
}
|
||||
|
||||
plaintext, hash, err := auth.GenerateAPIKey()
|
||||
if err != nil {
|
||||
return APIKeyCreateResult{}, fmt.Errorf("generate key: %w", err)
|
||||
}
|
||||
|
||||
row, err := s.DB.InsertAPIKey(ctx, db.InsertAPIKeyParams{
|
||||
ID: id.NewAPIKeyID(),
|
||||
TeamID: teamID,
|
||||
Name: name,
|
||||
KeyHash: hash,
|
||||
KeyPrefix: auth.APIKeyPrefix(plaintext),
|
||||
CreatedBy: userID,
|
||||
})
|
||||
if err != nil {
|
||||
return APIKeyCreateResult{}, fmt.Errorf("insert key: %w", err)
|
||||
}
|
||||
|
||||
return APIKeyCreateResult{Row: row, Plaintext: plaintext}, nil
|
||||
}
|
||||
|
||||
// List returns all API keys belonging to the given team.
|
||||
func (s *APIKeyService) List(ctx context.Context, teamID string) ([]db.TeamApiKey, error) {
|
||||
return s.DB.ListAPIKeysByTeam(ctx, teamID)
|
||||
}
|
||||
|
||||
// Delete removes an API key by ID, scoped to the given team.
|
||||
func (s *APIKeyService) Delete(ctx context.Context, keyID, teamID string) error {
|
||||
return s.DB.DeleteAPIKey(ctx, db.DeleteAPIKeyParams{ID: keyID, TeamID: teamID})
|
||||
}
|
||||
Reference in New Issue
Block a user