Documentation
¶
Overview ¶
Package store provides database access and persistence for DBBat.
Index ¶
- Constants
- Variables
- func ExtractSourceIP(addr net.Addr) string
- type APIKey
- type APIKeyFilter
- type AccessGrant
- type AuditEvent
- type AuditFilter
- type AuditLog
- type Connection
- type ConnectionFilter
- type DSNComponents
- type Database
- type DatabaseUpdate
- type Grant
- type GrantFilter
- type MigrationInfo
- type OAuthState
- type Options
- type Query
- type QueryFilter
- type QueryParameters
- type QueryRow
- type QueryRowModel
- type QueryRowsCursor
- type QueryRowsResult
- type QueryWithRows
- type Store
- func (s *Store) CleanupExpiredOAuthStates(ctx context.Context) (int64, error)
- func (s *Store) Close()
- func (s *Store) CloseConnection(ctx context.Context, uid uuid.UUID) error
- func (s *Store) ConsumeOAuthState(ctx context.Context, stateToken string) (*OAuthState, error)
- func (s *Store) CreateAPIKey(ctx context.Context, userID uuid.UUID, name string, expiresAt *time.Time, ...) (*APIKey, string, error)
- func (s *Store) CreateAPIKeyWithValue(ctx context.Context, userID uuid.UUID, name string, plainKey string, ...) (*APIKey, error)
- func (s *Store) CreateConnection(ctx context.Context, userID, databaseID uuid.UUID, sourceIP string) (*Connection, error)
- func (s *Store) CreateDatabase(ctx context.Context, db *Database, encryptionKey []byte) (*Database, error)
- func (s *Store) CreateGrant(ctx context.Context, grant *Grant) (*Grant, error)
- func (s *Store) CreateOAuthState(ctx context.Context, state *OAuthState) (*OAuthState, error)
- func (s *Store) CreateQuery(ctx context.Context, query *Query) (*Query, error)
- func (s *Store) CreateUser(ctx context.Context, username, passwordHash string, roles []string) (*User, error)
- func (s *Store) CreateUserIdentity(ctx context.Context, identity *UserIdentity) (*UserIdentity, error)
- func (s *Store) CreateWebSession(ctx context.Context, userID uuid.UUID) (*APIKey, string, error)
- func (s *Store) DB() *bun.DB
- func (s *Store) DeleteDatabase(ctx context.Context, uid uuid.UUID) error
- func (s *Store) DeleteUser(ctx context.Context, uid uuid.UUID) error
- func (s *Store) DeleteUserIdentity(ctx context.Context, uid uuid.UUID) error
- func (s *Store) DropAllTables(ctx context.Context) error
- func (s *Store) EnsureDefaultAdmin(ctx context.Context, passwordHash string) error
- func (s *Store) GetAPIKeyByID(ctx context.Context, id uuid.UUID) (*APIKey, error)
- func (s *Store) GetAPIKeyByPrefix(ctx context.Context, prefix string) (*APIKey, error)
- func (s *Store) GetActiveGrant(ctx context.Context, userID, databaseID uuid.UUID) (*Grant, error)
- func (s *Store) GetDatabaseByName(ctx context.Context, name string) (*Database, error)
- func (s *Store) GetDatabaseByOracleServiceName(ctx context.Context, serviceName string) (*Database, error)
- func (s *Store) GetDatabaseByUID(ctx context.Context, uid uuid.UUID) (*Database, error)
- func (s *Store) GetGrantByUID(ctx context.Context, uid uuid.UUID) (*Grant, error)
- func (s *Store) GetQuery(ctx context.Context, uid uuid.UUID) (*Query, error)
- func (s *Store) GetQueryRows(ctx context.Context, queryUID uuid.UUID, cursor string, limit int) (*QueryRowsResult, error)
- func (s *Store) GetQueryWithRows(ctx context.Context, uid uuid.UUID) (*QueryWithRows, error)
- func (s *Store) GetUserByIdentity(ctx context.Context, provider, providerID string) (*User, error)
- func (s *Store) GetUserByUID(ctx context.Context, uid uuid.UUID) (*User, error)
- func (s *Store) GetUserByUsername(ctx context.Context, username string) (*User, error)
- func (s *Store) GetUserIdentities(ctx context.Context, userID uuid.UUID) ([]UserIdentity, error)
- func (s *Store) GetUserIdentity(ctx context.Context, uid uuid.UUID) (*UserIdentity, error)
- func (s *Store) Health(ctx context.Context) error
- func (s *Store) IncrementAPIKeyUsage(ctx context.Context, id uuid.UUID) error
- func (s *Store) IncrementBytesTransferred(_ context.Context, _ uuid.UUID, _ int64) error
- func (s *Store) IncrementConnectionStats(ctx context.Context, uid uuid.UUID, bytes int64) error
- func (s *Store) IncrementQueryCount(_ context.Context, _ uuid.UUID) error
- func (s *Store) ListAPIKeys(ctx context.Context, filter APIKeyFilter) ([]APIKey, error)
- func (s *Store) ListAuditEvents(ctx context.Context, filter AuditFilter) ([]AuditEvent, error)
- func (s *Store) ListConnections(ctx context.Context, filter ConnectionFilter) ([]Connection, error)
- func (s *Store) ListDatabases(ctx context.Context) ([]Database, error)
- func (s *Store) ListGrants(ctx context.Context, filter GrantFilter) ([]Grant, error)
- func (s *Store) ListQueries(ctx context.Context, filter QueryFilter) ([]Query, error)
- func (s *Store) ListUsers(ctx context.Context) ([]User, error)
- func (s *Store) LogAuditEvent(ctx context.Context, event *AuditEvent) error
- func (s *Store) MatchesStorageDSN(host string, port int, databaseName string) bool
- func (s *Store) Migrate(ctx context.Context) error
- func (s *Store) MigrationStatus(ctx context.Context) ([]MigrationInfo, error)
- func (s *Store) RevokeAPIKey(ctx context.Context, id uuid.UUID, revokedBy uuid.UUID) error
- func (s *Store) RevokeGrant(ctx context.Context, uid uuid.UUID, revokedBy uuid.UUID) error
- func (s *Store) Rollback(ctx context.Context) error
- func (s *Store) SetAuthCache(authCache *cache.AuthCache)
- func (s *Store) StoreQueryRows(ctx context.Context, queryUID uuid.UUID, rows []QueryRow) error
- func (s *Store) UpdateConnectionActivity(ctx context.Context, uid uuid.UUID) error
- func (s *Store) UpdateDatabase(ctx context.Context, uid uuid.UUID, updates DatabaseUpdate, ...) error
- func (s *Store) UpdateQueryCompletion(ctx context.Context, uid uuid.UUID, durationMs *float64, rowsAffected *int64, ...) error
- func (s *Store) UpdateUser(ctx context.Context, uid uuid.UUID, updates UserUpdate) error
- func (s *Store) VerifyAPIKey(ctx context.Context, plainKey string) (*APIKey, error)
- type User
- type UserIdentity
- type UserUpdate
Constants ¶
const ( // APIKeyPrefix is the prefix for regular API keys APIKeyPrefix = "dbb_" // WebKeyPrefix is the prefix for web session keys WebKeyPrefix = "web_" // APIKeyRandomLength is the length of the random part of the key APIKeyRandomLength = 32 // APIKeyPrefixLength is the length of the prefix stored for identification APIKeyPrefixLength = 8 // WebSessionMaxDuration is the maximum duration for web sessions (1 hour) WebSessionMaxDuration = time.Hour )
API key constants
const ( RoleAdmin = "admin" RoleViewer = "viewer" RoleConnector = "connector" )
Role constants for user authorization
const ( ControlReadOnly = "read_only" ControlBlockCopy = "block_copy" ControlBlockDDL = "block_ddl" )
Control constants for grant restrictions
const ( ProtocolPostgreSQL = "postgresql" ProtocolOracle = "oracle" )
Protocol constants for database connections
const ( KeyTypeAPI = "api" // Regular API key (dbb_ prefix) KeyTypeWeb = "web" // Web session key (web_ prefix) )
API key type constants
const ( // MaxQueryRowsLimit is the maximum number of rows that can be returned per request MaxQueryRowsLimit = 1000 // MaxQueryRowsDataSize is the maximum data size (1MB) that can be returned per request MaxQueryRowsDataSize = 1024 * 1024 // DefaultQueryRowsLimit is the default number of rows returned if not specified DefaultQueryRowsLimit = 100 )
const (
IdentityTypeSlack = "slack"
)
Identity provider constants
Variables ¶
var ( ErrAPIKeyNotFound = errors.New("API key not found") ErrAPIKeyRevoked = errors.New("API key has been revoked") ErrAPIKeyExpired = errors.New("API key has expired") ErrAPIKeyTooShort = errors.New("API key too short") )
API key errors
var ( ErrUserNotFound = errors.New("user not found") ErrDatabaseNotFound = errors.New("database not found") ErrGrantNotFound = errors.New("grant not found") ErrNoActiveGrant = errors.New("no active grant found") ErrGrantAlreadyRevoked = errors.New("grant not found or already revoked") ErrConnectionNotFound = errors.New("connection not found or already closed") ErrQueryNotFound = errors.New("query not found") ErrInvalidCursor = errors.New("invalid cursor") ErrTargetMatchesStorage = errors.New("target database cannot match DBBat storage database") ErrIdentityNotFound = errors.New("identity not found") ErrOAuthStateNotFound = errors.New("oauth state not found") )
Store errors.
var ValidControls = []string{ ControlReadOnly, ControlBlockCopy, ControlBlockDDL, }
ValidControls lists all valid control values
Functions ¶
func ExtractSourceIP ¶
ExtractSourceIP extracts the IP address from a net.Addr
Types ¶
type APIKey ¶
type APIKey struct {
bun.BaseModel `bun:"table:api_keys,alias:ak"`
ID uuid.UUID `bun:"id,pk,type:uuid,default:gen_random_uuid()" json:"id"`
UserID uuid.UUID `bun:"user_id,notnull,type:uuid" json:"user_id"`
Name string `bun:"name,notnull" json:"name"`
KeyHash string `bun:"key_hash,notnull" json:"-"`
KeyPrefix string `bun:"key_prefix,notnull" json:"key_prefix"`
KeyType string `bun:"key_type,notnull,default:'api'" json:"key_type"`
ExpiresAt *time.Time `bun:"expires_at" json:"expires_at"`
LastUsedAt *time.Time `bun:"last_used_at" json:"last_used_at"`
RequestCount int64 `bun:"request_count,notnull,default:0" json:"request_count"`
CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp" json:"created_at"`
RevokedAt *time.Time `bun:"revoked_at" json:"revoked_at"`
RevokedBy *uuid.UUID `bun:"revoked_by,type:uuid" json:"revoked_by"`
O5LogonSalt []byte `bun:"o5logon_salt" json:"-"`
O5LogonVerifier []byte `bun:"o5logon_verifier" json:"-"` // encrypted with dbbat master key
}
APIKey represents an API key for authentication
func (*APIKey) IsWebSession ¶
IsWebSession returns true if this is a web session key
type APIKeyFilter ¶
type APIKeyFilter struct {
UserID *uuid.UUID
KeyType *string // Filter by key type (api, web)
IncludeAll bool // Include revoked/expired keys
Limit int
Offset int
}
APIKeyFilter represents filters for listing API keys
type AccessGrant ¶
type AccessGrant struct {
bun.BaseModel `bun:"table:access_grants,alias:ag"`
UID uuid.UUID `bun:"uid,pk,type:uuid,default:gen_random_uuid()" json:"uid"`
UserID uuid.UUID `bun:"user_id,notnull,type:uuid" json:"user_id"`
DatabaseID uuid.UUID `bun:"database_id,notnull,type:uuid" json:"database_id"`
Controls []string `bun:"controls,array" json:"controls"` // Array of controls: read_only, block_copy, block_ddl
GrantedBy uuid.UUID `bun:"granted_by,notnull,type:uuid" json:"granted_by"`
StartsAt time.Time `bun:"starts_at,notnull" json:"starts_at"`
ExpiresAt time.Time `bun:"expires_at,notnull" json:"expires_at"`
RevokedAt *time.Time `bun:"revoked_at" json:"revoked_at"`
RevokedBy *uuid.UUID `bun:"revoked_by,type:uuid" json:"revoked_by"`
MaxQueryCounts *int64 `bun:"max_query_counts" json:"max_query_counts"`
MaxBytesTransferred *int64 `bun:"max_bytes_transferred" json:"max_bytes_transferred"`
CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp" json:"created_at"`
// Computed fields (not stored in DB)
QueryCount int64 `bun:"-" json:"query_count"`
BytesTransferred int64 `bun:"-" json:"bytes_transferred"`
}
AccessGrant represents an access grant
func (*AccessGrant) HasControl ¶
func (g *AccessGrant) HasControl(control string) bool
HasControl checks if the grant has a specific control enabled
func (*AccessGrant) IsReadOnly ¶
func (g *AccessGrant) IsReadOnly() bool
IsReadOnly returns true if the grant has read_only control
func (*AccessGrant) ShouldBlockCopy ¶
func (g *AccessGrant) ShouldBlockCopy() bool
ShouldBlockCopy returns true if COPY commands should be blocked
func (*AccessGrant) ShouldBlockDDL ¶
func (g *AccessGrant) ShouldBlockDDL() bool
ShouldBlockDDL returns true if DDL commands should be blocked
type AuditFilter ¶
type AuditFilter struct {
EventType *string
UserID *uuid.UUID
PerformedBy *uuid.UUID
StartTime *time.Time
EndTime *time.Time
BeforeUID *uuid.UUID // Cursor: return events with UID < this value
Limit int
Offset int
}
AuditFilter represents filters for listing audit events
type AuditLog ¶
type AuditLog struct {
bun.BaseModel `bun:"table:audit_log,alias:al"`
UID uuid.UUID `bun:"uid,pk,type:uuid" json:"uid"` // UUIDv7 set in Go
EventType string `bun:"event_type,notnull" json:"event_type"`
UserID *uuid.UUID `bun:"user_id,type:uuid" json:"user_id"`
PerformedBy *uuid.UUID `bun:"performed_by,type:uuid" json:"performed_by"`
Details json.RawMessage `bun:"details,type:jsonb" json:"details"`
CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp" json:"created_at"`
}
AuditLog represents an audit log entry
type Connection ¶
type Connection struct {
bun.BaseModel `bun:"table:connections,alias:c"`
UID uuid.UUID `bun:"uid,pk,type:uuid" json:"uid"` // UUIDv7 set in Go
UserID uuid.UUID `bun:"user_id,notnull,type:uuid" json:"user_id"`
DatabaseID uuid.UUID `bun:"database_id,notnull,type:uuid" json:"database_id"`
SourceIP string `bun:"source_ip,notnull,type:inet" json:"source_ip"`
ConnectedAt time.Time `bun:"connected_at,notnull,default:current_timestamp" json:"connected_at"`
LastActivityAt time.Time `bun:"last_activity_at,notnull,default:current_timestamp" json:"last_activity_at"`
DisconnectedAt *time.Time `bun:"disconnected_at" json:"disconnected_at"`
Queries int64 `bun:"queries,notnull,default:0" json:"queries"`
BytesTransferred int64 `bun:"bytes_transferred,notnull,default:0" json:"bytes_transferred"`
}
Connection represents a connection through the proxy
type ConnectionFilter ¶
type ConnectionFilter struct {
UserID *uuid.UUID
DatabaseID *uuid.UUID
BeforeUID *uuid.UUID // Cursor: return connections with UID < this value
Limit int
Offset int
}
ConnectionFilter represents filters for listing connections
type DSNComponents ¶
DSNComponents holds parsed PostgreSQL DSN components for comparison
type Database ¶
type Database struct {
bun.BaseModel `bun:"table:databases,alias:d"`
UID uuid.UUID `bun:"uid,pk,type:uuid,default:gen_random_uuid()" json:"uid"`
Name string `bun:"name,notnull,unique" json:"name"`
Description string `bun:"description" json:"description"`
Host string `bun:"host,notnull" json:"host"`
Port int `bun:"port,notnull,default:5432" json:"port"`
DatabaseName string `bun:"database_name,notnull" json:"database_name"`
Username string `bun:"username,notnull" json:"username"`
Password string `bun:"-" json:"-"` // Decrypted, not stored
PasswordEncrypted []byte `bun:"password_encrypted,notnull" json:"-"` // Encrypted form
SSLMode string `bun:"ssl_mode,notnull,default:'prefer'" json:"ssl_mode"`
Protocol string `bun:"protocol,notnull,default:'postgresql'" json:"protocol"`
OracleServiceName *string `bun:"oracle_service_name" json:"oracle_service_name,omitempty"`
CreatedBy *uuid.UUID `bun:"created_by,type:uuid" json:"created_by"`
CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,notnull,default:current_timestamp" json:"updated_at"`
DeletedAt *time.Time `bun:"deleted_at,soft_delete" json:"-"`
}
Database represents a target database configuration
func (*Database) DecryptPassword ¶
DecryptPassword decrypts a database password using AAD bound to the database UID.
type DatabaseUpdate ¶
type DatabaseUpdate struct {
Description *string
Host *string
Port *int
DatabaseName *string
Username *string
Password *string // Plaintext password to encrypt
SSLMode *string
Protocol *string
OracleServiceName *string
}
DatabaseUpdate represents fields that can be updated
type GrantFilter ¶
GrantFilter represents filters for listing grants
type MigrationInfo ¶
MigrationInfo contains information about a migration
type OAuthState ¶ added in v0.4.0
type OAuthState struct {
bun.BaseModel `bun:"table:oauth_states,alias:os"`
UID uuid.UUID `bun:"uid,pk,type:uuid,default:gen_random_uuid()" json:"uid"`
State string `bun:"state,notnull,unique" json:"state"`
Provider string `bun:"provider,notnull" json:"provider"`
RedirectURL string `bun:"redirect_url" json:"redirect_url,omitempty"`
Metadata json.RawMessage `bun:"metadata,type:jsonb" json:"metadata,omitempty"`
ExpiresAt time.Time `bun:"expires_at,notnull" json:"expires_at"`
CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp" json:"created_at"`
}
OAuthState represents a temporary OAuth state for CSRF protection
type Options ¶
type Options struct {
// DropTablesFirst drops all tables before running migrations (for test mode)
DropTablesFirst bool
}
Options configures Store creation.
type Query ¶
type Query struct {
bun.BaseModel `bun:"table:queries,alias:q"`
UID uuid.UUID `bun:"uid,pk,type:uuid" json:"uid"` // UUIDv7 set in Go
ConnectionID uuid.UUID `bun:"connection_id,notnull,type:uuid" json:"connection_id"`
SQLText string `bun:"sql_text,notnull" json:"sql_text"`
Parameters *QueryParameters `bun:"parameters,type:jsonb" json:"parameters,omitempty"`
ExecutedAt time.Time `bun:"executed_at,notnull,default:current_timestamp" json:"executed_at"`
DurationMs *float64 `bun:"duration_ms,type:numeric(10,3)" json:"duration_ms"`
RowsAffected *int64 `bun:"rows_affected" json:"rows_affected"`
Error *string `bun:"error" json:"error"`
CopyFormat *string `bun:"copy_format" json:"copy_format,omitempty"` // 'text', 'csv', 'binary', or nil for non-COPY
CopyDirection *string `bun:"copy_direction" json:"copy_direction,omitempty"` // 'in', 'out', or nil for non-COPY
}
Query represents a query execution record
type QueryFilter ¶
type QueryFilter struct {
ConnectionID *uuid.UUID
UserID *uuid.UUID
DatabaseID *uuid.UUID
StartTime *time.Time
EndTime *time.Time
BeforeUID *uuid.UUID // Cursor: return queries with UID < this value (for stable pagination)
Limit int
Offset int
}
QueryFilter represents filters for listing queries
type QueryParameters ¶
type QueryParameters struct {
Values []string `json:"values"` // Decoded string representation
Raw []string `json:"raw,omitempty"` // Base64-encoded raw bytes
FormatCodes []int16 `json:"format_codes,omitempty"` // 0=text, 1=binary
TypeOIDs []uint32 `json:"type_oids,omitempty"` // PostgreSQL type OIDs
}
QueryParameters stores parameter values for prepared statements
type QueryRow ¶
type QueryRow struct {
RowNumber int `json:"row_number"`
RowData json.RawMessage `json:"row_data"`
RowSizeBytes int64 `json:"row_size_bytes"`
}
QueryRow is an alias for API compatibility (without bun.BaseModel for simpler usage)
type QueryRowModel ¶
type QueryRowModel struct {
bun.BaseModel `bun:"table:query_rows,alias:qr"`
UID uuid.UUID `bun:"uid,pk,type:uuid" json:"uid"` // UUIDv7 set in Go
QueryID uuid.UUID `bun:"query_id,notnull,type:uuid" json:"query_id"`
RowNumber int `bun:"row_number,notnull" json:"row_number"`
RowData json.RawMessage `bun:"row_data,notnull,type:jsonb" json:"row_data"`
RowSizeBytes int64 `bun:"row_size_bytes,notnull" json:"row_size_bytes"`
}
QueryRowModel represents a single row from query results or COPY data
type QueryRowsCursor ¶
type QueryRowsCursor struct {
Offset int64 `json:"offset"`
}
QueryRowsCursor represents the pagination cursor state
type QueryRowsResult ¶
type QueryRowsResult struct {
Rows []QueryRow `json:"rows"`
NextCursor string `json:"next_cursor,omitempty"`
HasMore bool `json:"has_more"`
TotalRows int64 `json:"total_rows"`
}
QueryRowsResult contains paginated query rows
type QueryWithRows ¶
QueryWithRows combines a query with its result rows
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store provides access to the database
func (*Store) CleanupExpiredOAuthStates ¶ added in v0.4.0
CleanupExpiredOAuthStates removes all expired OAuth states.
func (*Store) CloseConnection ¶
CloseConnection sets the disconnected_at timestamp
func (*Store) ConsumeOAuthState ¶ added in v0.4.0
ConsumeOAuthState retrieves and deletes an OAuth state in one operation. It only matches states that have not yet expired.
func (*Store) CreateAPIKey ¶
func (s *Store) CreateAPIKey(ctx context.Context, userID uuid.UUID, name string, expiresAt *time.Time, encryptionKey ...[]byte) (*APIKey, string, error)
CreateAPIKey creates a new API key for a user. Returns the created APIKey and the plain text key (only shown once). If encryptionKey is provided (non-nil), an O5LOGON verifier is computed and stored for Oracle proxy authentication.
func (*Store) CreateAPIKeyWithValue ¶ added in v0.5.0
func (s *Store) CreateAPIKeyWithValue(ctx context.Context, userID uuid.UUID, name string, plainKey string, expiresAt *time.Time, encryptionKey ...[]byte) (*APIKey, error)
CreateAPIKeyWithValue creates an API key with a specific plaintext value. Used for test mode provisioning where stable, predictable keys are needed. If encryptionKey is provided, an O5LOGON verifier is computed and stored.
func (*Store) CreateConnection ¶
func (s *Store) CreateConnection(ctx context.Context, userID, databaseID uuid.UUID, sourceIP string) (*Connection, error)
CreateConnection creates a new connection record
func (*Store) CreateDatabase ¶
func (s *Store) CreateDatabase(ctx context.Context, db *Database, encryptionKey []byte) (*Database, error)
CreateDatabase creates a new database configuration. It uses a transaction to ensure the password is encrypted with AAD bound to the database UID. Returns ErrTargetMatchesStorage if the target database matches the DBBat storage database.
func (*Store) CreateGrant ¶
CreateGrant creates a new access grant
func (*Store) CreateOAuthState ¶ added in v0.4.0
func (s *Store) CreateOAuthState(ctx context.Context, state *OAuthState) (*OAuthState, error)
CreateOAuthState persists a new OAuth state for CSRF protection.
func (*Store) CreateQuery ¶
CreateQuery creates a new query record
func (*Store) CreateUser ¶
func (s *Store) CreateUser(ctx context.Context, username, passwordHash string, roles []string) (*User, error)
CreateUser creates a new user with the specified roles
func (*Store) CreateUserIdentity ¶ added in v0.4.0
func (s *Store) CreateUserIdentity(ctx context.Context, identity *UserIdentity) (*UserIdentity, error)
CreateUserIdentity creates a new user identity link.
func (*Store) CreateWebSession ¶
CreateWebSession creates a new web session key for a user Web sessions have a fixed 1-hour expiration and use the web_ prefix Returns the created APIKey and the plain text key (only shown once)
func (*Store) DeleteDatabase ¶
DeleteDatabase deletes a database
func (*Store) DeleteUser ¶
DeleteUser deletes a user
func (*Store) DeleteUserIdentity ¶ added in v0.4.0
DeleteUserIdentity soft-deletes a user identity.
func (*Store) DropAllTables ¶
DropAllTables drops all application tables and types (for test mode) This should be called BEFORE migrations to ensure a fresh start
func (*Store) EnsureDefaultAdmin ¶
EnsureDefaultAdmin creates a default admin user if no users exist
func (*Store) GetAPIKeyByID ¶
GetAPIKeyByID retrieves an API key by its ID
func (*Store) GetAPIKeyByPrefix ¶
GetAPIKeyByPrefix retrieves all API keys with a given prefix Since prefix is unique, this returns at most one key
func (*Store) GetActiveGrant ¶
GetActiveGrant retrieves an active grant for a user and database
func (*Store) GetDatabaseByName ¶
GetDatabaseByName retrieves a database by name
func (*Store) GetDatabaseByOracleServiceName ¶ added in v0.4.0
func (s *Store) GetDatabaseByOracleServiceName(ctx context.Context, serviceName string) (*Database, error)
GetDatabaseByOracleServiceName retrieves an Oracle database by its service name.
func (*Store) GetDatabaseByUID ¶
GetDatabaseByUID retrieves a database by UID
func (*Store) GetGrantByUID ¶
GetGrantByUID retrieves a grant by UID
func (*Store) GetQueryRows ¶
func (s *Store) GetQueryRows(ctx context.Context, queryUID uuid.UUID, cursor string, limit int) (*QueryRowsResult, error)
GetQueryRows retrieves paginated rows for a query with cursor-based pagination
func (*Store) GetQueryWithRows ¶
GetQueryWithRows retrieves a query with its result rows
func (*Store) GetUserByIdentity ¶ added in v0.4.0
GetUserByIdentity retrieves a user by their external identity (provider + provider_id).
func (*Store) GetUserByUID ¶
GetUserByUID retrieves a user by UID
func (*Store) GetUserByUsername ¶
GetUserByUsername retrieves a user by username
func (*Store) GetUserIdentities ¶ added in v0.4.0
GetUserIdentities retrieves all identities for a given user.
func (*Store) GetUserIdentity ¶ added in v0.4.0
GetUserIdentity retrieves a single user identity by UID.
func (*Store) IncrementAPIKeyUsage ¶
IncrementAPIKeyUsage updates the last_used_at and increments request_count
func (*Store) IncrementBytesTransferred ¶
IncrementBytesTransferred increments the bytes transferred for tracking quota usage.
func (*Store) IncrementConnectionStats ¶
IncrementConnectionStats increments the query count by 1 and adds bytes to bytes_transferred
func (*Store) IncrementQueryCount ¶
IncrementQueryCount increments the query count for tracking quota usage. This is called from the connections/queries tracking.
func (*Store) ListAPIKeys ¶
ListAPIKeys retrieves API keys with optional filters
func (*Store) ListAuditEvents ¶
func (s *Store) ListAuditEvents(ctx context.Context, filter AuditFilter) ([]AuditEvent, error)
ListAuditEvents retrieves audit events with optional filters
func (*Store) ListConnections ¶
func (s *Store) ListConnections(ctx context.Context, filter ConnectionFilter) ([]Connection, error)
ListConnections retrieves connections with optional filters
func (*Store) ListDatabases ¶
ListDatabases retrieves all databases
func (*Store) ListGrants ¶
ListGrants retrieves grants with optional filters
func (*Store) ListQueries ¶
ListQueries retrieves queries with optional filters
func (*Store) LogAuditEvent ¶
func (s *Store) LogAuditEvent(ctx context.Context, event *AuditEvent) error
LogAuditEvent creates a new audit log entry
func (*Store) MatchesStorageDSN ¶
MatchesStorageDSN checks if a target database configuration matches the storage DSN. Returns true if the target appears to be the same database as DBBat storage.
func (*Store) MigrationStatus ¶
func (s *Store) MigrationStatus(ctx context.Context) ([]MigrationInfo, error)
MigrationStatus returns the status of all migrations
func (*Store) RevokeAPIKey ¶
RevokeAPIKey revokes an API key
func (*Store) RevokeGrant ¶
RevokeGrant revokes a grant
func (*Store) SetAuthCache ¶ added in v0.1.0
SetAuthCache sets the authentication cache for API key verification.
func (*Store) StoreQueryRows ¶
StoreQueryRows stores result rows for a query
func (*Store) UpdateConnectionActivity ¶
UpdateConnectionActivity updates the last_activity_at timestamp
func (*Store) UpdateDatabase ¶
func (s *Store) UpdateDatabase(ctx context.Context, uid uuid.UUID, updates DatabaseUpdate, encryptionKey []byte) error
UpdateDatabase updates a database. Returns ErrTargetMatchesStorage if the update would cause the target to match the DBBat storage database.
func (*Store) UpdateQueryCompletion ¶ added in v0.4.0
func (s *Store) UpdateQueryCompletion(ctx context.Context, uid uuid.UUID, durationMs *float64, rowsAffected *int64, queryError *string) error
UpdateQueryCompletion updates a query with duration, rows affected, and error.
func (*Store) UpdateUser ¶
UpdateUser updates a user
type User ¶
type User struct {
bun.BaseModel `bun:"table:users,alias:u"`
UID uuid.UUID `bun:"uid,pk,type:uuid,default:gen_random_uuid()" json:"uid"`
Username string `bun:"username,notnull,unique" json:"username"`
PasswordHash string `bun:"password_hash,notnull" json:"-"`
Roles []string `bun:"roles,array" json:"roles"`
RateLimitExempt bool `bun:"rate_limit_exempt,notnull,default:false" json:"rate_limit_exempt"`
PasswordChangedAt *time.Time `bun:"password_changed_at" json:"-"`
CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,notnull,default:current_timestamp" json:"updated_at"`
DeletedAt *time.Time `bun:"deleted_at,soft_delete" json:"-"`
}
User represents a DBBat user
func (*User) HasChangedPassword ¶
HasChangedPassword returns true if the user has changed their initial password
func (*User) IsConnector ¶
IsConnector returns true if the user has the connector role
type UserIdentity ¶ added in v0.4.0
type UserIdentity struct {
bun.BaseModel `bun:"table:user_identities,alias:ui"`
UID uuid.UUID `bun:"uid,pk,type:uuid,default:gen_random_uuid()" json:"uid"`
UserID uuid.UUID `bun:"user_id,notnull,type:uuid" json:"user_id"`
Provider string `bun:"provider,notnull" json:"provider"`
ProviderID string `bun:"provider_id,notnull" json:"provider_id"`
Email string `bun:"email" json:"email,omitempty"`
DisplayName string `bun:"display_name" json:"display_name,omitempty"`
Metadata json.RawMessage `bun:"metadata,type:jsonb" json:"metadata,omitempty"`
CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,notnull,default:current_timestamp" json:"updated_at"`
DeletedAt *time.Time `bun:"deleted_at,soft_delete" json:"-"`
}
UserIdentity represents a link between a user and an external identity provider
type UserUpdate ¶
UserUpdate represents fields that can be updated