services

package
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 19, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package services contains business logic for TinyVault.

Index

Constants

View Source
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
)
View Source
const (
	AuthProviderGitHub = "github"
	AuthProviderEmail  = "email"
)

Auth provider constants

View Source
const (
	// APITokenLength is the length of API tokens in bytes.
	APITokenLength = 32
)

Variables

View Source
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

View Source
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.

View Source
var ErrDuplicateProjectName = errors.New("a project with this name already exists")

ErrDuplicateProjectName is returned when a project name already exists for the user

Functions

func HasScope

func HasScope(scopes []string, required string) bool

HasScope checks if a token has a specific scope.

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

type APITokenWithUser struct {
	APIToken
	User *User
}

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) Cleanup

func (s *AuditService) Cleanup(ctx context.Context, olderThan time.Duration) error

Cleanup removes audit logs older than the specified duration.

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

func (s *AuthService) CleanupLoginAttempts(ctx context.Context, retention time.Duration) error

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

func (s *AuthService) DeleteAllSessions(ctx context.Context, userID uuid.UUID) error

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

func (s *AuthService) IsAccountLocked(ctx context.Context, email string) (bool, error)

IsAccountLocked checks if an account is locked due to too many failed login attempts.

func (*AuthService) ListActiveSessions

func (s *AuthService) ListActiveSessions(ctx context.Context, userID uuid.UUID) ([]*Session, error)

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

type GitHubUser struct {
	ID        int64
	Email     string
	Username  string
	Name      string
	AvatarURL string
}

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) Count

func (s *ProjectService) Count(ctx context.Context, ownerID uuid.UUID) (int64, error)

Count returns the number of projects for an owner.

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) Delete

func (s *ProjectService) Delete(ctx context.Context, id uuid.UUID) error

Delete soft-deletes a project.

func (*ProjectService) GetByID

func (s *ProjectService) GetByID(ctx context.Context, id uuid.UUID) (*Project, error)

GetByID retrieves a project by ID.

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

func (s *ProjectService) GetDecryptedDEK(ctx context.Context, projectID uuid.UUID) ([]byte, error)

GetDecryptedDEK retrieves and decrypts the DEK for a project.

func (*ProjectService) List

func (s *ProjectService) List(ctx context.Context, ownerID uuid.UUID, limit, offset int32) ([]*Project, error)

List retrieves all projects for an owner.

func (*ProjectService) Update

func (s *ProjectService) Update(ctx context.Context, id uuid.UUID, name, description string) (*Project, error)

Update updates a project's name and description.

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) Count

func (s *SecretService) Count(ctx context.Context, projectID uuid.UUID) (int64, error)

Count returns the number of secrets in a project.

func (*SecretService) CountByOwner added in v0.2.0

func (s *SecretService) CountByOwner(ctx context.Context, ownerID uuid.UUID) (int64, error)

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) Delete

func (s *SecretService) Delete(ctx context.Context, projectID uuid.UUID, key string) error

Delete removes a secret.

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

func (s *SecretService) GetAll(ctx context.Context, projectID uuid.UUID) (map[string][]byte, error)

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).

func (*SecretService) ListKeys

func (s *SecretService) ListKeys(ctx context.Context, projectID uuid.UUID) ([]string, error)

ListKeys retrieves all secret keys for a project.

func (*SecretService) Update

func (s *SecretService) Update(ctx context.Context, projectID uuid.UUID, key string, value []byte) (*Secret, error)

Update updates a secret's value.

func (*SecretService) Upsert

func (s *SecretService) Upsert(ctx context.Context, projectID uuid.UUID, key string, value []byte) (*Secret, error)

Upsert creates or updates a secret.

type SecretWithValue

type SecretWithValue struct {
	Secret
	Value []byte `json:"value"`
}

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

type SessionWithUser struct {
	Session
	User *User
}

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

func (s *TokenService) ListActive(ctx context.Context, userID uuid.UUID) ([]*APIToken, error)

ListActive lists all active (non-expired, non-revoked) tokens for a user.

func (*TokenService) Revoke

func (s *TokenService) Revoke(ctx context.Context, tokenID, userID uuid.UUID) error

Revoke revokes an API token.

func (*TokenService) RevokeAll

func (s *TokenService) RevokeAll(ctx context.Context, userID uuid.UUID) error

RevokeAll revokes all API 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

func (s *UserService) GetByEmail(ctx context.Context, email string) (*User, error)

GetByEmail retrieves a user by their email.

func (*UserService) GetByGitHubID

func (s *UserService) GetByGitHubID(ctx context.Context, githubID int64) (*User, error)

GetByGitHubID retrieves a user by their GitHub ID.

func (*UserService) GetByID

func (s *UserService) GetByID(ctx context.Context, id uuid.UUID) (*User, error)

GetByID retrieves a user by their 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

func (s *UserService) LinkGitHub(ctx context.Context, id uuid.UUID, githubID int64) error

LinkGitHub links a GitHub account to an existing user.

func (*UserService) UnlinkGitHub added in v0.1.9

func (s *UserService) UnlinkGitHub(ctx context.Context, id uuid.UUID) error

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL