package useCases import ( "RenewCMS/internal/domain/apikey" "RenewCMS/internal/domain/audit" "context" "time" ) type CreateAPIKeyUseCase struct { apiKeyRepository apikey.Repository keyGenerator apikey.KeyGenerator now func() time.Time recorder audit.Recorder } type CreateAPIKeyCommand struct { UserID uint32 Name string ExpiresAt *time.Time } type CreatedAPIKey struct { Key apikey.APIKey RawKey string } func NewCreateAPIKeyUseCase(apiKeyRepository apikey.Repository, keyGenerator apikey.KeyGenerator, now func() time.Time, recorder audit.Recorder) *CreateAPIKeyUseCase { return &CreateAPIKeyUseCase{apiKeyRepository, keyGenerator, now, recorder} } func (c *CreateAPIKeyUseCase) CreateAPIKey(ctx context.Context, command CreateAPIKeyCommand) (CreatedAPIKey, error) { now := c.now() if command.ExpiresAt != nil && !command.ExpiresAt.After(now) { return CreatedAPIKey{}, apikey.ErrExpiryNotInFuture } rawKey, prefix, hashedKey := c.keyGenerator.Generate() stored, err := c.apiKeyRepository.Create(apikey.APIKey{ UserID: command.UserID, Name: command.Name, Prefix: prefix, HashedKey: hashedKey, ExpiresAt: command.ExpiresAt, CreatedAt: now, }) if err != nil { return CreatedAPIKey{}, err } event := audit.NewEvent(audit.ActionAPIKeyCreate, audit.CategoryAPIKeys) event.Target = audit.APIKeyTarget(stored.ID, stored.Name) c.recorder.Record(ctx, event) return CreatedAPIKey{Key: stored, RawKey: rawKey}, nil }