Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 56 additions & 52 deletions cmd/app/auth_commands.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package main provides the CLI command definitions for the application.
package main

import (
Expand All @@ -7,9 +8,9 @@ import (

"github.com/allisson/secrets/cmd/app/commands"
"github.com/allisson/secrets/internal/app"
"github.com/allisson/secrets/internal/config"
)

// getAuthCommands returns the authentication-related CLI commands.
func getAuthCommands() []*cli.Command {
return []*cli.Command{
{
Expand All @@ -36,23 +37,24 @@ func getAuthCommands() []*cli.Command {
},
},
Action: func(ctx context.Context, cmd *cli.Command) error {
cfg := config.Load()
container := app.NewContainer(cfg)
defer func() { _ = container.Shutdown(ctx) }()

tokenizationUseCase, err := container.TokenizationUseCase()
if err != nil {
return err
}

return commands.RunCleanExpiredTokens(
return commands.ExecuteWithContainer(
ctx,
tokenizationUseCase,
container.Logger(),
commands.DefaultIO().Writer,
int(cmd.Int("days")),
cmd.Bool("dry-run"),
cmd.String("format"),
func(ctx context.Context, container *app.Container) error {
tokenizationUseCase, err := container.TokenizationUseCase()
if err != nil {
return err
}

return commands.RunCleanExpiredTokens(
ctx,
tokenizationUseCase,
container.Logger(),
commands.DefaultIO().Writer,
int(cmd.Int("days")),
cmd.Bool("dry-run"),
cmd.String("format"),
)
},
)
},
},
Expand Down Expand Up @@ -85,24 +87,25 @@ func getAuthCommands() []*cli.Command {
},
},
Action: func(ctx context.Context, cmd *cli.Command) error {
cfg := config.Load()
container := app.NewContainer(cfg)
defer func() { _ = container.Shutdown(ctx) }()

clientUseCase, err := container.ClientUseCase()
if err != nil {
return err
}

return commands.RunCreateClient(
return commands.ExecuteWithContainer(
ctx,
clientUseCase,
container.Logger(),
cmd.String("name"),
cmd.Bool("active"),
cmd.String("policies"),
cmd.String("format"),
commands.DefaultIO(),
func(ctx context.Context, container *app.Container) error {
clientUseCase, err := container.ClientUseCase()
if err != nil {
return err
}

return commands.RunCreateClient(
ctx,
clientUseCase,
container.Logger(),
cmd.String("name"),
cmd.Bool("active"),
cmd.String("policies"),
cmd.String("format"),
commands.DefaultIO(),
)
},
)
},
},
Expand Down Expand Up @@ -141,25 +144,26 @@ func getAuthCommands() []*cli.Command {
},
},
Action: func(ctx context.Context, cmd *cli.Command) error {
cfg := config.Load()
container := app.NewContainer(cfg)
defer func() { _ = container.Shutdown(ctx) }()

clientUseCase, err := container.ClientUseCase()
if err != nil {
return err
}

return commands.RunUpdateClient(
return commands.ExecuteWithContainer(
ctx,
clientUseCase,
container.Logger(),
commands.DefaultIO(),
cmd.String("id"),
cmd.String("name"),
cmd.Bool("active"),
cmd.String("policies"),
cmd.String("format"),
func(ctx context.Context, container *app.Container) error {
clientUseCase, err := container.ClientUseCase()
if err != nil {
return err
}

return commands.RunUpdateClient(
ctx,
clientUseCase,
container.Logger(),
commands.DefaultIO(),
cmd.String("id"),
cmd.String("name"),
cmd.Bool("active"),
cmd.String("policies"),
cmd.String("format"),
)
},
)
},
},
Expand Down
2 changes: 2 additions & 0 deletions cmd/app/commands.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// Package main provides the CLI command definitions for the application.
package main

import (
"github.com/urfave/cli/v3"
)

// getCommands aggregates and returns all CLI commands for the application.
func getCommands(version string) []*cli.Command {
cmds := []*cli.Command{}
cmds = append(cmds, getSystemCommands(version)...)
Expand Down
68 changes: 33 additions & 35 deletions cmd/app/commands/clean_audit_logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,33 @@ import (
authUseCase "github.com/allisson/secrets/internal/auth/usecase"
)

// CleanAuditLogsResult holds the result of the audit log cleanup operation.
type CleanAuditLogsResult struct {
Count int64 `json:"count"`
Days int `json:"days"`
DryRun bool `json:"dry_run"`
}

// ToText returns a human-readable representation of the cleanup result.
func (r *CleanAuditLogsResult) ToText() string {
if r.DryRun {
return fmt.Sprintf(
"Dry-run mode: Would delete %d audit log(s) older than %d day(s)",
r.Count,
r.Days,
)
}
return fmt.Sprintf("Successfully deleted %d audit log(s) older than %d day(s)", r.Count, r.Days)
}

// ToJSON returns a JSON representation of the cleanup result.
func (r *CleanAuditLogsResult) ToJSON() string {
jsonBytes, _ := json.MarshalIndent(r, "", " ")
return string(jsonBytes)
}

// RunCleanAuditLogs deletes audit logs older than the specified number of days.
// Supports dry-run mode and multiple output formats.
func RunCleanAuditLogs(
ctx context.Context,
auditLogUseCase authUseCase.AuditLogUseCase,
Expand All @@ -35,12 +62,13 @@ func RunCleanAuditLogs(
return fmt.Errorf("failed to delete audit logs: %w", err)
}

// Output result based on format
if format == "json" {
outputCleanAuditLogsJSON(writer, count, days, dryRun)
} else {
outputCleanAuditLogsText(writer, count, days, dryRun)
// Output result
result := &CleanAuditLogsResult{
Count: count,
Days: days,
DryRun: dryRun,
}
WriteOutput(writer, format, result)

logger.Info("cleanup completed",
slog.Int64("count", count),
Expand All @@ -50,33 +78,3 @@ func RunCleanAuditLogs(

return nil
}

// outputCleanAuditLogsText outputs the result in human-readable text format.
func outputCleanAuditLogsText(writer io.Writer, count int64, days int, dryRun bool) {
if dryRun {
_, _ = fmt.Fprintf(
writer,
"Dry-run mode: Would delete %d audit log(s) older than %d day(s)\n",
count,
days,
)
} else {
_, _ = fmt.Fprintf(writer, "Successfully deleted %d audit log(s) older than %d day(s)\n", count, days)
}
}

// outputCleanAuditLogsJSON outputs the result in JSON format for machine consumption.
func outputCleanAuditLogsJSON(writer io.Writer, count int64, days int, dryRun bool) {
result := map[string]interface{}{
"count": count,
"days": days,
"dry_run": dryRun,
}

jsonBytes, err := json.MarshalIndent(result, "", " ")
if err != nil {
return
}

_, _ = fmt.Fprintln(writer, string(jsonBytes))
}
77 changes: 37 additions & 40 deletions cmd/app/commands/clean_expired_tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,37 @@ import (
tokenizationUseCase "github.com/allisson/secrets/internal/tokenization/usecase"
)

// CleanExpiredTokensResult holds the result of the expired token cleanup operation.
type CleanExpiredTokensResult struct {
Count int64 `json:"count"`
Days int `json:"days"`
DryRun bool `json:"dry_run"`
}

// ToText returns a human-readable representation of the cleanup result.
func (r *CleanExpiredTokensResult) ToText() string {
if r.DryRun {
return fmt.Sprintf(
"Dry-run mode: Would delete %d expired token(s) older than %d day(s)",
r.Count,
r.Days,
)
}
return fmt.Sprintf(
"Successfully deleted %d expired token(s) older than %d day(s)",
r.Count,
r.Days,
)
}

// ToJSON returns a JSON representation of the cleanup result.
func (r *CleanExpiredTokensResult) ToJSON() string {
jsonBytes, _ := json.MarshalIndent(r, "", " ")
return string(jsonBytes)
}

// RunCleanExpiredTokens deletes expired tokens older than the specified number of days.
// Supports dry-run mode and multiple output formats.
func RunCleanExpiredTokens(
ctx context.Context,
tokenizationUseCase tokenizationUseCase.TokenizationUseCase,
Expand All @@ -35,12 +66,13 @@ func RunCleanExpiredTokens(
return fmt.Errorf("failed to cleanup expired tokens: %w", err)
}

// Output result based on format
if format == "json" {
outputCleanExpiredJSON(writer, count, days, dryRun)
} else {
outputCleanExpiredText(writer, count, days, dryRun)
// Output result
result := &CleanExpiredTokensResult{
Count: count,
Days: days,
DryRun: dryRun,
}
WriteOutput(writer, format, result)

logger.Info("cleanup completed",
slog.Int64("count", count),
Expand All @@ -50,38 +82,3 @@ func RunCleanExpiredTokens(

return nil
}

// outputCleanExpiredText outputs the result in human-readable text format.
func outputCleanExpiredText(writer io.Writer, count int64, days int, dryRun bool) {
if dryRun {
_, _ = fmt.Fprintf(
writer,
"Dry-run mode: Would delete %d expired token(s) older than %d day(s)\n",
count,
days,
)
} else {
_, _ = fmt.Fprintf(
writer,
"Successfully deleted %d expired token(s) older than %d day(s)\n",
count,
days,
)
}
}

// outputCleanExpiredJSON outputs the result in JSON format for machine consumption.
func outputCleanExpiredJSON(writer io.Writer, count int64, days int, dryRun bool) {
result := map[string]interface{}{
"count": count,
"days": days,
"dry_run": dryRun,
}

jsonBytes, err := json.MarshalIndent(result, "", " ")
if err != nil {
return
}

_, _ = fmt.Fprintln(writer, string(jsonBytes))
}
8 changes: 4 additions & 4 deletions cmd/app/commands/clean_expired_tokens_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,25 @@ func TestRunCleanExpiredTokens(t *testing.T) {

t.Run("text-output", func(t *testing.T) {
mockUseCase := &tokenizationMocks.MockTokenizationUseCase{}
mockUseCase.On("CleanupExpired", ctx, days, false).Return(int64(10), nil)
mockUseCase.On("CleanupExpired", ctx, days, false).Return(int64(100), nil)

var out bytes.Buffer
err := RunCleanExpiredTokens(ctx, mockUseCase, logger, &out, days, false, "text")

require.NoError(t, err)
require.Contains(t, out.String(), "Successfully deleted 10 expired token(s)")
require.Contains(t, out.String(), "Successfully deleted 100 expired token(s)")
mockUseCase.AssertExpectations(t)
})

t.Run("json-output", func(t *testing.T) {
mockUseCase := &tokenizationMocks.MockTokenizationUseCase{}
mockUseCase.On("CleanupExpired", ctx, days, true).Return(int64(5), nil)
mockUseCase.On("CleanupExpired", ctx, days, true).Return(int64(50), nil)

var out bytes.Buffer
err := RunCleanExpiredTokens(ctx, mockUseCase, logger, &out, days, true, "json")

require.NoError(t, err)
require.Contains(t, out.String(), `"count": 5`)
require.Contains(t, out.String(), `"count": 50`)
require.Contains(t, out.String(), `"dry_run": true`)
mockUseCase.AssertExpectations(t)
})
Expand Down
Loading
Loading