Documentation
¶
Overview ¶
Package services contains business logic for TinyVault.
Index ¶
- Constants
- Variables
- func HasScope(scopes []string, required string) bool
- type APIToken
- type APITokenWithUser
- type AuditAction
- type AuditLog
- type AuditResourceType
- type AuditService
- func (s *AuditService) Cleanup(ctx context.Context, olderThan time.Duration) error
- func (s *AuditService) CountByUserActionSince(ctx context.Context, userID uuid.UUID, action AuditAction, since time.Time) (int64, error)
- func (s *AuditService) CountByUserSince(ctx context.Context, userID uuid.UUID, since time.Time) (int64, error)
- func (s *AuditService) ListByResource(ctx context.Context, resourceType AuditResourceType, resourceID uuid.UUID, ...) ([]*AuditLog, error)
- func (s *AuditService) ListByUser(ctx context.Context, userID uuid.UUID, limit, offset int32) ([]*AuditLog, error)
- func (s *AuditService) Log(ctx context.Context, params LogParams) error
- func (s *AuditService) LogAsync(params LogParams)
- type AuthService
- func (s *AuthService) CleanupExpiredSessions(ctx context.Context) error
- func (s *AuthService) CleanupLoginAttempts(ctx context.Context, retention time.Duration) error
- func (s *AuthService) CreateSession(ctx context.Context, userID uuid.UUID, ipAddress, userAgent string) (*Session, error)
- func (s *AuthService) DeleteAllSessions(ctx context.Context, userID uuid.UUID) error
- func (s *AuthService) DeleteSession(ctx context.Context, token string) error
- func (s *AuthService) IsAccountLocked(ctx context.Context, email string) (bool, error)
- func (s *AuthService) ListActiveSessions(ctx context.Context, userID uuid.UUID) ([]*Session, error)
- func (s *AuthService) RecordLoginAttempt(ctx context.Context, email, ipAddress string, success bool)
- func (s *AuthService) ValidateSession(ctx context.Context, token string) (*SessionWithUser, error)
- type GitHubUser
- type LogParams
- type Project
- type ProjectService
- func (s *ProjectService) Count(ctx context.Context, ownerID uuid.UUID) (int64, error)
- func (s *ProjectService) Create(ctx context.Context, ownerID uuid.UUID, name, description string) (*Project, error)
- func (s *ProjectService) Delete(ctx context.Context, id uuid.UUID) error
- func (s *ProjectService) GetByID(ctx context.Context, id uuid.UUID) (*Project, error)
- func (s *ProjectService) GetByIDWithOwner(ctx context.Context, id, ownerID uuid.UUID) (*Project, error)
- func (s *ProjectService) GetDecryptedDEK(ctx context.Context, projectID uuid.UUID) ([]byte, error)
- func (s *ProjectService) List(ctx context.Context, ownerID uuid.UUID, limit, offset int32) ([]*Project, error)
- func (s *ProjectService) Update(ctx context.Context, id uuid.UUID, name, description string) (*Project, error)
- type Secret
- type SecretService
- func (s *SecretService) Count(ctx context.Context, projectID uuid.UUID) (int64, error)
- func (s *SecretService) CountByOwner(ctx context.Context, ownerID uuid.UUID) (int64, error)
- func (s *SecretService) Create(ctx context.Context, projectID uuid.UUID, key string, value []byte) (*Secret, error)
- func (s *SecretService) Delete(ctx context.Context, projectID uuid.UUID, key string) error
- func (s *SecretService) Get(ctx context.Context, projectID uuid.UUID, key string) (*SecretWithValue, error)
- func (s *SecretService) GetAll(ctx context.Context, projectID uuid.UUID) (map[string][]byte, error)
- func (s *SecretService) List(ctx context.Context, projectID uuid.UUID, limit, offset int32) ([]*Secret, error)
- func (s *SecretService) ListKeys(ctx context.Context, projectID uuid.UUID) ([]string, error)
- func (s *SecretService) Update(ctx context.Context, projectID uuid.UUID, key string, value []byte) (*Secret, error)
- func (s *SecretService) Upsert(ctx context.Context, projectID uuid.UUID, key string, value []byte) (*Secret, error)
- type SecretWithValue
- type Session
- type SessionWithUser
- type TokenService
- func (s *TokenService) Create(ctx context.Context, userID uuid.UUID, name string, scopes []string, ...) (*APIToken, error)
- func (s *TokenService) List(ctx context.Context, userID uuid.UUID, limit, offset int32) ([]*APIToken, error)
- func (s *TokenService) ListActive(ctx context.Context, userID uuid.UUID) ([]*APIToken, error)
- func (s *TokenService) Revoke(ctx context.Context, tokenID, userID uuid.UUID) error
- func (s *TokenService) RevokeAll(ctx context.Context, userID uuid.UUID) error
- func (s *TokenService) Validate(ctx context.Context, token string) (*APITokenWithUser, error)
- type User
- type UserService
- func (s *UserService) AuthenticateByEmail(ctx context.Context, email, password string) (*User, error)
- func (s *UserService) CanUnlinkGitHub(user *User) bool
- func (s *UserService) CreateFromEmail(ctx context.Context, email, password, username string) (*User, error)
- func (s *UserService) CreateOrUpdate(ctx context.Context, gu *GitHubUser) (*User, error)
- func (s *UserService) GetByEmail(ctx context.Context, email string) (*User, error)
- func (s *UserService) GetByGitHubID(ctx context.Context, githubID int64) (*User, error)
- func (s *UserService) GetByID(ctx context.Context, id uuid.UUID) (*User, error)
- func (s *UserService) HasGitHub(user *User) bool
- func (s *UserService) HasPassword(user *User) bool
- func (s *UserService) LinkGitHub(ctx context.Context, id uuid.UUID, githubID int64) error
- func (s *UserService) UnlinkGitHub(ctx context.Context, id uuid.UUID) error
- func (s *UserService) UpdatePassword(ctx context.Context, id uuid.UUID, currentPass, newPass string) error
- func (s *UserService) UpdateProfile(ctx context.Context, id uuid.UUID, email, username string) (*User, error)
Constants ¶
const ( // SessionDuration is the default session lifetime. SessionDuration = 7 * 24 * time.Hour // 7 days // SessionTokenLength is the length of session tokens in bytes. SessionTokenLength = 32 )
const ( AuthProviderGitHub = "github" AuthProviderEmail = "email" )
Auth provider constants
const (
// APITokenLength is the length of API tokens in bytes.
APITokenLength = 32
)
Variables ¶
var ( ErrEmailExists = errors.New("email already registered") ErrUsernameExists = errors.New("username already taken") ErrInvalidCredentials = errors.New("invalid email or password") ErrUserNotFound = errors.New("user not found") )
Errors
var ErrAccountLocked = fmt.Errorf("account temporarily locked due to too many failed login attempts")
ErrAccountLocked is returned when an account is temporarily locked due to too many failed login attempts.
var ErrDuplicateProjectName = errors.New("a project with this name already exists")
ErrDuplicateProjectName is returned when a project name already exists for the user
Functions ¶
Types ¶
type APIToken ¶
type APIToken struct {
ID uuid.UUID
UserID uuid.UUID
Name string
Token string // Only set when creating
Scopes []string
LastUsedAt *time.Time
ExpiresAt *time.Time
CreatedAt time.Time
}
APIToken represents an API token.
type APITokenWithUser ¶
APITokenWithUser represents an API token with user data.
type AuditAction ¶
type AuditAction string
AuditAction defines the types of actions that can be audited.
const ( ActionSecretRead AuditAction = "secret.read" ActionSecretCreate AuditAction = "secret.create" ActionSecretUpdate AuditAction = "secret.update" ActionSecretDelete AuditAction = "secret.delete" ActionProjectCreate AuditAction = "project.create" ActionProjectUpdate AuditAction = "project.update" ActionProjectDelete AuditAction = "project.delete" ActionTokenCreate AuditAction = "token.create" ActionTokenRevoke AuditAction = "token.revoke" ActionUserLogin AuditAction = "user.login" ActionUserLogout AuditAction = "user.logout" ActionUserCreate AuditAction = "user.create" ActionProfileUpdate AuditAction = "user.profile_update" ActionPasswordChange AuditAction = "user.password_change" ActionGitHubUnlink AuditAction = "user.github_unlink" )
type AuditLog ¶
type AuditLog struct {
ID uuid.UUID
UserID *uuid.UUID
Action string
ResourceType string
ResourceID *uuid.UUID
ResourceName *string
IPAddress string
UserAgent string
Metadata map[string]any
CreatedAt time.Time
}
AuditLog represents an audit log entry.
type AuditResourceType ¶
type AuditResourceType string
AuditResourceType defines the types of resources that can be audited.
const ( ResourceSecret AuditResourceType = "secret" ResourceProject AuditResourceType = "project" ResourceToken AuditResourceType = "api_token" ResourceUser AuditResourceType = "user" ResourceSession AuditResourceType = "session" )
type AuditService ¶
type AuditService struct {
// contains filtered or unexported fields
}
AuditService handles audit logging.
func NewAuditService ¶
func NewAuditService(pool *pgxpool.Pool) *AuditService
NewAuditService creates a new AuditService.
func (*AuditService) CountByUserActionSince ¶ added in v0.1.9
func (s *AuditService) CountByUserActionSince(ctx context.Context, userID uuid.UUID, action AuditAction, since time.Time) (int64, error)
CountByUserActionSince counts audit logs for a user and specific action since a given time.
func (*AuditService) CountByUserSince ¶ added in v0.1.9
func (s *AuditService) CountByUserSince(ctx context.Context, userID uuid.UUID, since time.Time) (int64, error)
CountByUserSince counts audit logs for a user since a given time.
func (*AuditService) ListByResource ¶
func (s *AuditService) ListByResource(ctx context.Context, resourceType AuditResourceType, resourceID uuid.UUID, limit, offset int32) ([]*AuditLog, error)
ListByResource retrieves audit logs for a specific resource.
func (*AuditService) ListByUser ¶
func (s *AuditService) ListByUser(ctx context.Context, userID uuid.UUID, limit, offset int32) ([]*AuditLog, error)
ListByUser retrieves audit logs for a user.
func (*AuditService) Log ¶
func (s *AuditService) Log(ctx context.Context, params LogParams) error
Log creates a new audit log entry.
func (*AuditService) LogAsync ¶
func (s *AuditService) LogAsync(params LogParams)
LogAsync creates an audit log entry asynchronously.
type AuthService ¶
type AuthService struct {
// contains filtered or unexported fields
}
AuthService handles authentication and session management.
func NewAuthService ¶
func NewAuthService(pool *pgxpool.Pool, userService *UserService, maxAttempts int, lockoutDuration time.Duration) *AuthService
NewAuthService creates a new AuthService.
func (*AuthService) CleanupExpiredSessions ¶
func (s *AuthService) CleanupExpiredSessions(ctx context.Context) error
CleanupExpiredSessions removes expired sessions from the database.
func (*AuthService) CleanupLoginAttempts ¶
CleanupLoginAttempts removes old login attempts from the database.
func (*AuthService) CreateSession ¶
func (s *AuthService) CreateSession(ctx context.Context, userID uuid.UUID, ipAddress, userAgent string) (*Session, error)
CreateSession creates a new session for a user.
func (*AuthService) DeleteAllSessions ¶
DeleteAllSessions deletes all sessions for a user.
func (*AuthService) DeleteSession ¶
func (s *AuthService) DeleteSession(ctx context.Context, token string) error
DeleteSession deletes a session by token.
func (*AuthService) IsAccountLocked ¶
IsAccountLocked checks if an account is locked due to too many failed login attempts.
func (*AuthService) ListActiveSessions ¶
ListActiveSessions lists all active sessions for a user.
func (*AuthService) RecordLoginAttempt ¶
func (s *AuthService) RecordLoginAttempt(ctx context.Context, email, ipAddress string, success bool)
RecordLoginAttempt records a login attempt.
func (*AuthService) ValidateSession ¶
func (s *AuthService) ValidateSession(ctx context.Context, token string) (*SessionWithUser, error)
ValidateSession validates a session token and returns the session with user.
type GitHubUser ¶
GitHubUser represents a GitHub user from OAuth.
type LogParams ¶
type LogParams struct {
UserID *uuid.UUID
Action AuditAction
ResourceType AuditResourceType
ResourceID *uuid.UUID
ResourceName string
IPAddress string
UserAgent string
Metadata map[string]any
}
LogParams contains parameters for creating an audit log.
type Project ¶
type Project struct {
ID uuid.UUID `json:"id"`
OwnerID uuid.UUID `json:"owner_id"`
Name string `json:"name"`
Description *string `json:"description,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Project represents a TinyVault project.
type ProjectService ¶
type ProjectService struct {
// contains filtered or unexported fields
}
ProjectService handles project-related business logic.
func NewProjectService ¶
func NewProjectService(pool *pgxpool.Pool, masterKey []byte) *ProjectService
NewProjectService creates a new ProjectService.
func (*ProjectService) Create ¶
func (s *ProjectService) Create(ctx context.Context, ownerID uuid.UUID, name, description string) (*Project, error)
Create creates a new project with a new Data Encryption Key.
func (*ProjectService) GetByIDWithOwner ¶
func (s *ProjectService) GetByIDWithOwner(ctx context.Context, id, ownerID uuid.UUID) (*Project, error)
GetByIDWithOwner retrieves a project by ID, ensuring it belongs to the owner.
func (*ProjectService) GetDecryptedDEK ¶
GetDecryptedDEK retrieves and decrypts the DEK for a project.
type Secret ¶
type Secret struct {
ID uuid.UUID `json:"id"`
ProjectID uuid.UUID `json:"project_id"`
Key string `json:"key"`
Version int32 `json:"version"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Secret represents a TinyVault secret (without the value for listing).
type SecretService ¶
type SecretService struct {
// contains filtered or unexported fields
}
SecretService handles secret-related business logic.
func NewSecretService ¶
func NewSecretService(pool *pgxpool.Pool, projectService *ProjectService) *SecretService
NewSecretService creates a new SecretService.
func (*SecretService) CountByOwner ¶ added in v0.2.0
CountByOwner returns the total number of secrets across all projects owned by a user.
func (*SecretService) Create ¶
func (s *SecretService) Create(ctx context.Context, projectID uuid.UUID, key string, value []byte) (*Secret, error)
Create creates a new secret with encrypted value.
func (*SecretService) Get ¶
func (s *SecretService) Get(ctx context.Context, projectID uuid.UUID, key string) (*SecretWithValue, error)
Get retrieves a secret by key and decrypts its value.
func (*SecretService) GetAll ¶
GetAll retrieves all secrets with decrypted values for a project. Use with caution - only for CLI 'env' command.
func (*SecretService) List ¶
func (s *SecretService) List(ctx context.Context, projectID uuid.UUID, limit, offset int32) ([]*Secret, error)
List retrieves all secrets for a project (without values).
type SecretWithValue ¶
SecretWithValue represents a secret with its decrypted value.
type Session ¶
type Session struct {
ID uuid.UUID
UserID uuid.UUID
Token string // Only set when creating
IPAddress string
UserAgent string
ExpiresAt time.Time
CreatedAt time.Time
LastActiveAt time.Time
}
Session represents a user session.
type SessionWithUser ¶
SessionWithUser represents a session with user data.
type TokenService ¶
type TokenService struct {
// contains filtered or unexported fields
}
TokenService handles API token management.
func NewTokenService ¶
func NewTokenService(pool *pgxpool.Pool) *TokenService
NewTokenService creates a new TokenService.
func (*TokenService) Create ¶
func (s *TokenService) Create(ctx context.Context, userID uuid.UUID, name string, scopes []string, expiresAt *time.Time) (*APIToken, error)
Create creates a new API token for a user.
func (*TokenService) List ¶
func (s *TokenService) List(ctx context.Context, userID uuid.UUID, limit, offset int32) ([]*APIToken, error)
List lists all API tokens for a user.
func (*TokenService) ListActive ¶
ListActive lists all active (non-expired, non-revoked) tokens for a user.
func (*TokenService) Validate ¶
func (s *TokenService) Validate(ctx context.Context, token string) (*APITokenWithUser, error)
Validate validates an API token and returns the token with user data.
type User ¶
type User struct {
ID uuid.UUID
GitHubID *int64
Email string
Username string
Name *string
AvatarURL *string
PasswordHash *string
AuthProvider string
EmailVerified bool
}
User represents a TinyVault user.
type UserService ¶
type UserService struct {
// contains filtered or unexported fields
}
UserService handles user-related business logic.
func NewUserService ¶
func NewUserService(pool *pgxpool.Pool) *UserService
NewUserService creates a new UserService.
func (*UserService) AuthenticateByEmail ¶
func (s *UserService) AuthenticateByEmail(ctx context.Context, email, password string) (*User, error)
AuthenticateByEmail validates email/password and returns the user if valid.
func (*UserService) CanUnlinkGitHub ¶ added in v0.1.9
func (s *UserService) CanUnlinkGitHub(user *User) bool
CanUnlinkGitHub checks if a user can unlink their GitHub account. Returns false if no password is set (would lock them out).
func (*UserService) CreateFromEmail ¶
func (s *UserService) CreateFromEmail(ctx context.Context, email, password, username string) (*User, error)
CreateFromEmail creates a new user with email/password authentication.
func (*UserService) CreateOrUpdate ¶
func (s *UserService) CreateOrUpdate(ctx context.Context, gu *GitHubUser) (*User, error)
CreateOrUpdate creates a new user or updates an existing one from GitHub OAuth.
func (*UserService) GetByEmail ¶
GetByEmail retrieves a user by their email.
func (*UserService) GetByGitHubID ¶
GetByGitHubID retrieves a user by their GitHub ID.
func (*UserService) HasGitHub ¶ added in v0.1.9
func (s *UserService) HasGitHub(user *User) bool
HasGitHub checks if a user has GitHub linked.
func (*UserService) HasPassword ¶ added in v0.1.9
func (s *UserService) HasPassword(user *User) bool
HasPassword checks if a user has a password set.
func (*UserService) LinkGitHub ¶ added in v0.1.9
LinkGitHub links a GitHub account to an existing user.
func (*UserService) UnlinkGitHub ¶ added in v0.1.9
UnlinkGitHub removes GitHub account from a user (only if they have a password).
func (*UserService) UpdatePassword ¶ added in v0.1.9
func (s *UserService) UpdatePassword(ctx context.Context, id uuid.UUID, currentPass, newPass string) error
UpdatePassword updates a user's password.
func (*UserService) UpdateProfile ¶ added in v0.1.9
func (s *UserService) UpdateProfile(ctx context.Context, id uuid.UUID, email, username string) (*User, error)
UpdateProfile updates a user's profile information.