// Copyright 2026 MarketAlly. All rights reserved. // Business Source License 1.1 - See LICENSE file for details. package vault import ( "context" "git.marketally.com/gitcaddy/gitcaddy-vault/services" vault_service "code.gitcaddy.com/server/v3/services/vault" ) // Ensure VaultPlugin implements the vault service Plugin interface var _ vault_service.Plugin = (*VaultPlugin)(nil) // ListSecrets lists all secrets for a repository func (p *VaultPlugin) ListSecrets(ctx context.Context, repoID int64, includeDeleted bool) ([]vault_service.Secret, error) { secrets, err := services.ListSecrets(ctx, repoID, includeDeleted) if err != nil { return nil, err } result := make([]vault_service.Secret, len(secrets)) for i, s := range secrets { result[i] = vault_service.Secret{ ID: s.ID, RepoID: s.RepoID, Name: s.Name, Description: s.Description, Type: string(s.Type), CurrentVersion: s.CurrentVersion, CreatedUnix: int64(s.CreatedUnix), UpdatedUnix: int64(s.UpdatedUnix), DeletedUnix: int64(s.DeletedUnix), } } return result, nil } // GetSecret returns a secret by name func (p *VaultPlugin) GetSecret(ctx context.Context, repoID int64, name string) (*vault_service.Secret, error) { s, err := services.GetSecret(ctx, repoID, name) if err != nil { if err == services.ErrSecretNotFound { return nil, vault_service.ErrSecretNotFound } return nil, err } return &vault_service.Secret{ ID: s.ID, RepoID: s.RepoID, Name: s.Name, Description: s.Description, Type: string(s.Type), CurrentVersion: s.CurrentVersion, CreatedUnix: int64(s.CreatedUnix), UpdatedUnix: int64(s.UpdatedUnix), DeletedUnix: int64(s.DeletedUnix), }, nil } // GetSecretValue returns the decrypted value of a secret func (p *VaultPlugin) GetSecretValue(ctx context.Context, repoID int64, name string, version int) (string, error) { return services.GetSecretValue(ctx, repoID, name, version) } // CreateSecret creates a new secret func (p *VaultPlugin) CreateSecret(ctx context.Context, repoID int64, opts vault_service.CreateSecretOptions) (*vault_service.Secret, error) { s, err := services.CreateSecret(ctx, repoID, services.CreateSecretOptions{ Name: opts.Name, Description: opts.Description, Type: opts.Type, Value: opts.Value, CreatorID: opts.CreatorID, }, nil) if err != nil { if err == services.ErrSecretExists { return nil, vault_service.ErrSecretExists } return nil, err } return &vault_service.Secret{ ID: s.ID, RepoID: s.RepoID, Name: s.Name, Description: s.Description, Type: string(s.Type), CurrentVersion: s.CurrentVersion, CreatedUnix: int64(s.CreatedUnix), UpdatedUnix: int64(s.UpdatedUnix), DeletedUnix: int64(s.DeletedUnix), }, nil } // UpdateSecret updates an existing secret func (p *VaultPlugin) UpdateSecret(ctx context.Context, repoID int64, name string, opts vault_service.UpdateSecretOptions) (*vault_service.Secret, error) { s, err := services.UpdateSecret(ctx, repoID, name, services.UpdateSecretOptions{ Type: opts.Type, Value: opts.Value, Comment: opts.Comment, UpdaterID: opts.UpdaterID, }) if err != nil { if err == services.ErrSecretNotFound { return nil, vault_service.ErrSecretNotFound } return nil, err } return &vault_service.Secret{ ID: s.ID, RepoID: s.RepoID, Name: s.Name, Description: s.Description, Type: string(s.Type), CurrentVersion: s.CurrentVersion, CreatedUnix: int64(s.CreatedUnix), UpdatedUnix: int64(s.UpdatedUnix), DeletedUnix: int64(s.DeletedUnix), }, nil } // DeleteSecret soft-deletes a secret func (p *VaultPlugin) DeleteSecret(ctx context.Context, repoID int64, name string, userID int64) error { err := services.DeleteSecret(ctx, repoID, name, userID) if err == services.ErrSecretNotFound { return vault_service.ErrSecretNotFound } return err } // RestoreSecret restores a soft-deleted secret func (p *VaultPlugin) RestoreSecret(ctx context.Context, repoID int64, name string) error { err := services.RestoreSecret(ctx, repoID, name) if err == services.ErrSecretNotFound { return vault_service.ErrSecretNotFound } return err } // RollbackSecret rolls back a secret to a previous version func (p *VaultPlugin) RollbackSecret(ctx context.Context, repoID int64, name string, version int, userID int64) error { err := services.RollbackSecret(ctx, repoID, name, version, userID) if err == services.ErrSecretNotFound { return vault_service.ErrSecretNotFound } if err == services.ErrVersionNotFound { return vault_service.ErrSecretNotFound // Map to generic not found } return err } // ListVersions lists all versions of a secret func (p *VaultPlugin) ListVersions(ctx context.Context, repoID int64, name string) ([]vault_service.SecretVersion, error) { versions, err := services.ListVersions(ctx, repoID, name) if err != nil { if err == services.ErrSecretNotFound { return nil, vault_service.ErrSecretNotFound } return nil, err } result := make([]vault_service.SecretVersion, len(versions)) for i, v := range versions { result[i] = vault_service.SecretVersion{ ID: v.ID, SecretID: v.SecretID, Version: v.Version, CreatorID: v.CreatedBy, Comment: v.Comment, CreatedUnix: int64(v.CreatedUnix), } } return result, nil } // ListTokens lists all tokens for a repository func (p *VaultPlugin) ListTokens(ctx context.Context, repoID int64) ([]vault_service.Token, error) { tokens, err := services.ListTokens(ctx, repoID) if err != nil { return nil, err } result := make([]vault_service.Token, len(tokens)) for i, t := range tokens { result[i] = vault_service.Token{ ID: t.ID, RepoID: t.RepoID, Description: t.Description, Scope: string(t.Scope), CreatedUnix: int64(t.CreatedUnix), ExpiresUnix: int64(t.ExpiresUnix), LastUsedUnix: int64(t.LastUsedUnix), UsedCount: t.UsedCount, IsRevoked: t.IsRevoked(), IsExpired: t.IsExpired(), } } return result, nil } // CreateToken creates a new CI/CD token func (p *VaultPlugin) CreateToken(ctx context.Context, repoID int64, opts vault_service.CreateTokenOptions) (*vault_service.Token, string, error) { t, rawToken, err := services.CreateToken(ctx, repoID, services.CreateTokenOptions{ Description: opts.Description, Scope: opts.Scope, TTL: opts.TTL, CreatorID: opts.CreatorID, }, nil) if err != nil { return nil, "", err } return &vault_service.Token{ ID: t.ID, RepoID: t.RepoID, Description: t.Description, Scope: string(t.Scope), CreatedUnix: int64(t.CreatedUnix), ExpiresUnix: int64(t.ExpiresUnix), LastUsedUnix: int64(t.LastUsedUnix), UsedCount: t.UsedCount, IsRevoked: t.IsRevoked(), IsExpired: t.IsExpired(), }, rawToken, nil } // RevokeToken revokes a token func (p *VaultPlugin) RevokeToken(ctx context.Context, repoID, tokenID int64) error { err := services.RevokeToken(ctx, repoID, tokenID) if err == services.ErrTokenNotFound { return vault_service.ErrTokenNotFound } return err } // ValidateToken validates a token for a specific action func (p *VaultPlugin) ValidateToken(ctx context.Context, rawToken, action, secretName string) (*vault_service.Token, error) { t, err := services.ValidateToken(ctx, rawToken, action, secretName) if err != nil { switch err { case services.ErrTokenNotFound, services.ErrInvalidToken: return nil, vault_service.ErrInvalidToken case services.ErrTokenExpired: return nil, vault_service.ErrTokenExpired case services.ErrTokenRevoked: return nil, vault_service.ErrTokenNotFound case services.ErrAccessDenied: return nil, vault_service.ErrAccessDenied default: return nil, err } } return &vault_service.Token{ ID: t.ID, RepoID: t.RepoID, Description: t.Description, Scope: string(t.Scope), CreatedUnix: int64(t.CreatedUnix), ExpiresUnix: int64(t.ExpiresUnix), LastUsedUnix: int64(t.LastUsedUnix), UsedCount: t.UsedCount, IsRevoked: t.IsRevoked(), IsExpired: t.IsExpired(), }, nil } // ListAuditEntries lists audit entries for a repository func (p *VaultPlugin) ListAuditEntries(ctx context.Context, repoID int64, page, pageSize int) ([]vault_service.AuditEntry, int64, error) { entries, total, err := services.ListAuditEntries(ctx, repoID, page, pageSize) if err != nil { return nil, 0, err } result := make([]vault_service.AuditEntry, len(entries)) for i, e := range entries { result[i] = vault_service.AuditEntry{ ID: e.ID, RepoID: e.RepoID, Action: string(e.Action), UserID: e.UserID, IPAddress: e.IPAddress, Success: e.Success, FailReason: e.FailReason, Timestamp: int64(e.Timestamp), } } return result, total, nil }