Implement owner setup and browser authentication sessions
Some checks failed
CI / Backend (push) Failing after 1s
CI / Frontend (push) Successful in 13s
CI / Contracts and repository policy (push) Failing after 3s
CI / Container (push) Has been skipped

This commit is contained in:
Elijah 2026-07-16 19:45:40 -07:00
parent 077cf7601a
commit 715423ab8e
21 changed files with 2185 additions and 14 deletions

View file

@ -0,0 +1,409 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.31.1
// source: authentication.sql
package dbgen
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const createAuthenticationAuditEvent = `-- name: CreateAuthenticationAuditEvent :exec
INSERT INTO audit_events (
owner_id,
actor,
action,
resource_type,
resource_id,
outcome,
details,
occurred_at
)
VALUES (
$1::UUID,
$2::JSONB,
$3,
$4,
$5::UUID,
$6,
$7::JSONB,
$8
)
`
type CreateAuthenticationAuditEventParams struct {
OwnerID pgtype.UUID `db:"owner_id" json:"owner_id"`
Actor []byte `db:"actor" json:"actor"`
Action string `db:"action" json:"action"`
ResourceType *string `db:"resource_type" json:"resource_type"`
ResourceID pgtype.UUID `db:"resource_id" json:"resource_id"`
Outcome string `db:"outcome" json:"outcome"`
Details []byte `db:"details" json:"details"`
OccurredAt pgtype.Timestamptz `db:"occurred_at" json:"occurred_at"`
}
func (q *Queries) CreateAuthenticationAuditEvent(ctx context.Context, arg CreateAuthenticationAuditEventParams) error {
_, err := q.db.Exec(ctx, createAuthenticationAuditEvent,
arg.OwnerID,
arg.Actor,
arg.Action,
arg.ResourceType,
arg.ResourceID,
arg.Outcome,
arg.Details,
arg.OccurredAt,
)
return err
}
const createBrowserSession = `-- name: CreateBrowserSession :one
INSERT INTO sessions (
owner_id,
token_hash,
csrf_token_hash,
remote_address,
user_agent,
authenticated_at,
last_seen_at,
expires_at
)
VALUES (
$1::UUID,
$2,
$3,
NULLIF($4, '')::INET,
NULLIF($5, ''),
$6,
$6,
$7
)
RETURNING id::TEXT AS id
`
type CreateBrowserSessionParams struct {
OwnerID pgtype.UUID `db:"owner_id" json:"owner_id"`
TokenHash []byte `db:"token_hash" json:"token_hash"`
CsrfTokenHash []byte `db:"csrf_token_hash" json:"csrf_token_hash"`
RemoteAddress interface{} `db:"remote_address" json:"remote_address"`
UserAgent interface{} `db:"user_agent" json:"user_agent"`
AuthenticatedAt pgtype.Timestamptz `db:"authenticated_at" json:"authenticated_at"`
ExpiresAt pgtype.Timestamptz `db:"expires_at" json:"expires_at"`
}
func (q *Queries) CreateBrowserSession(ctx context.Context, arg CreateBrowserSessionParams) (string, error) {
row := q.db.QueryRow(ctx, createBrowserSession,
arg.OwnerID,
arg.TokenHash,
arg.CsrfTokenHash,
arg.RemoteAddress,
arg.UserAgent,
arg.AuthenticatedAt,
arg.ExpiresAt,
)
var id string
err := row.Scan(&id)
return id, err
}
const createInitialRootChange = `-- name: CreateInitialRootChange :exec
INSERT INTO changes (
owner_id,
event_type,
node_id,
node_revision,
content_revision,
resulting_state,
mutation_origin,
committed_at
)
VALUES (
$1::UUID,
'node.created',
$2::UUID,
1,
0,
$3::JSONB,
$4::JSONB,
$5
)
`
type CreateInitialRootChangeParams struct {
OwnerID pgtype.UUID `db:"owner_id" json:"owner_id"`
RootNodeID pgtype.UUID `db:"root_node_id" json:"root_node_id"`
ResultingState []byte `db:"resulting_state" json:"resulting_state"`
MutationOrigin []byte `db:"mutation_origin" json:"mutation_origin"`
CommittedAt pgtype.Timestamptz `db:"committed_at" json:"committed_at"`
}
func (q *Queries) CreateInitialRootChange(ctx context.Context, arg CreateInitialRootChangeParams) error {
_, err := q.db.Exec(ctx, createInitialRootChange,
arg.OwnerID,
arg.RootNodeID,
arg.ResultingState,
arg.MutationOrigin,
arg.CommittedAt,
)
return err
}
const createOwner = `-- name: CreateOwner :one
INSERT INTO users (username, username_key, display_name, password_hash)
VALUES (
$1,
$2,
$3,
$4
)
RETURNING id::TEXT AS id
`
type CreateOwnerParams struct {
Username string `db:"username" json:"username"`
UsernameKey string `db:"username_key" json:"username_key"`
DisplayName string `db:"display_name" json:"display_name"`
PasswordHash string `db:"password_hash" json:"password_hash"`
}
func (q *Queries) CreateOwner(ctx context.Context, arg CreateOwnerParams) (string, error) {
row := q.db.QueryRow(ctx, createOwner,
arg.Username,
arg.UsernameKey,
arg.DisplayName,
arg.PasswordHash,
)
var id string
err := row.Scan(&id)
return id, err
}
const createOwnerRootNode = `-- name: CreateOwnerRootNode :one
INSERT INTO nodes (
owner_id,
parent_id,
name,
name_key,
node_type,
size_bytes,
node_revision,
content_revision,
content_modified_at,
metadata_updated_at
)
VALUES (
$1::UUID,
NULL,
'Drive',
'drive',
'directory',
0,
1,
0,
$2,
$2
)
RETURNING id::TEXT AS id
`
type CreateOwnerRootNodeParams struct {
OwnerID pgtype.UUID `db:"owner_id" json:"owner_id"`
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
}
func (q *Queries) CreateOwnerRootNode(ctx context.Context, arg CreateOwnerRootNodeParams) (string, error) {
row := q.db.QueryRow(ctx, createOwnerRootNode, arg.OwnerID, arg.CreatedAt)
var id string
err := row.Scan(&id)
return id, err
}
const createRecoveryCode = `-- name: CreateRecoveryCode :exec
INSERT INTO recovery_codes (user_id, code_hash)
VALUES ($1::UUID, $2)
`
type CreateRecoveryCodeParams struct {
OwnerID pgtype.UUID `db:"owner_id" json:"owner_id"`
CodeHash []byte `db:"code_hash" json:"code_hash"`
}
func (q *Queries) CreateRecoveryCode(ctx context.Context, arg CreateRecoveryCodeParams) error {
_, err := q.db.Exec(ctx, createRecoveryCode, arg.OwnerID, arg.CodeHash)
return err
}
const getActiveBrowserSession = `-- name: GetActiveBrowserSession :one
SELECT
sessions.id::TEXT AS session_id,
sessions.owner_id::TEXT AS owner_id,
users.username,
users.display_name,
sessions.csrf_token_hash,
sessions.authenticated_at,
sessions.last_seen_at,
sessions.expires_at
FROM sessions
JOIN users ON users.id = sessions.owner_id
WHERE sessions.token_hash = $1
AND sessions.revoked_at IS NULL
AND sessions.expires_at > $2
LIMIT 1
`
type GetActiveBrowserSessionParams struct {
TokenHash []byte `db:"token_hash" json:"token_hash"`
NowAt pgtype.Timestamptz `db:"now_at" json:"now_at"`
}
type GetActiveBrowserSessionRow struct {
SessionID string `db:"session_id" json:"session_id"`
OwnerID string `db:"owner_id" json:"owner_id"`
Username string `db:"username" json:"username"`
DisplayName string `db:"display_name" json:"display_name"`
CsrfTokenHash []byte `db:"csrf_token_hash" json:"csrf_token_hash"`
AuthenticatedAt pgtype.Timestamptz `db:"authenticated_at" json:"authenticated_at"`
LastSeenAt pgtype.Timestamptz `db:"last_seen_at" json:"last_seen_at"`
ExpiresAt pgtype.Timestamptz `db:"expires_at" json:"expires_at"`
}
func (q *Queries) GetActiveBrowserSession(ctx context.Context, arg GetActiveBrowserSessionParams) (GetActiveBrowserSessionRow, error) {
row := q.db.QueryRow(ctx, getActiveBrowserSession, arg.TokenHash, arg.NowAt)
var i GetActiveBrowserSessionRow
err := row.Scan(
&i.SessionID,
&i.OwnerID,
&i.Username,
&i.DisplayName,
&i.CsrfTokenHash,
&i.AuthenticatedAt,
&i.LastSeenAt,
&i.ExpiresAt,
)
return i, err
}
const getAuthenticationInvariantCounts = `-- name: GetAuthenticationInvariantCounts :one
SELECT
(SELECT count(*) FROM users)::BIGINT AS owners,
(SELECT count(*) FROM nodes WHERE parent_id IS NULL)::BIGINT AS roots,
(SELECT count(*) FROM recovery_codes)::BIGINT AS recovery_codes,
(SELECT count(*) FROM changes)::BIGINT AS changes,
(SELECT count(*) FROM audit_events)::BIGINT AS audit_events,
(SELECT count(*) FROM sessions)::BIGINT AS sessions,
(SELECT count(*) FROM sessions WHERE revoked_at IS NULL)::BIGINT AS active_sessions
`
type GetAuthenticationInvariantCountsRow struct {
Owners int64 `db:"owners" json:"owners"`
Roots int64 `db:"roots" json:"roots"`
RecoveryCodes int64 `db:"recovery_codes" json:"recovery_codes"`
Changes int64 `db:"changes" json:"changes"`
AuditEvents int64 `db:"audit_events" json:"audit_events"`
Sessions int64 `db:"sessions" json:"sessions"`
ActiveSessions int64 `db:"active_sessions" json:"active_sessions"`
}
func (q *Queries) GetAuthenticationInvariantCounts(ctx context.Context) (GetAuthenticationInvariantCountsRow, error) {
row := q.db.QueryRow(ctx, getAuthenticationInvariantCounts)
var i GetAuthenticationInvariantCountsRow
err := row.Scan(
&i.Owners,
&i.Roots,
&i.RecoveryCodes,
&i.Changes,
&i.AuditEvents,
&i.Sessions,
&i.ActiveSessions,
)
return i, err
}
const getOwnerAuthenticationRecord = `-- name: GetOwnerAuthenticationRecord :one
SELECT
id::TEXT AS id,
username,
username_key,
display_name,
password_hash
FROM users
LIMIT 1
`
type GetOwnerAuthenticationRecordRow struct {
ID string `db:"id" json:"id"`
Username string `db:"username" json:"username"`
UsernameKey string `db:"username_key" json:"username_key"`
DisplayName string `db:"display_name" json:"display_name"`
PasswordHash string `db:"password_hash" json:"password_hash"`
}
func (q *Queries) GetOwnerAuthenticationRecord(ctx context.Context) (GetOwnerAuthenticationRecordRow, error) {
row := q.db.QueryRow(ctx, getOwnerAuthenticationRecord)
var i GetOwnerAuthenticationRecordRow
err := row.Scan(
&i.ID,
&i.Username,
&i.UsernameKey,
&i.DisplayName,
&i.PasswordHash,
)
return i, err
}
const revokeBrowserSession = `-- name: RevokeBrowserSession :execrows
UPDATE sessions
SET revoked_at = $1
WHERE id = $2::UUID
AND revoked_at IS NULL
`
type RevokeBrowserSessionParams struct {
RevokedAt pgtype.Timestamptz `db:"revoked_at" json:"revoked_at"`
SessionID pgtype.UUID `db:"session_id" json:"session_id"`
}
func (q *Queries) RevokeBrowserSession(ctx context.Context, arg RevokeBrowserSessionParams) (int64, error) {
result, err := q.db.Exec(ctx, revokeBrowserSession, arg.RevokedAt, arg.SessionID)
if err != nil {
return 0, err
}
return result.RowsAffected(), nil
}
const setOwnerRootNode = `-- name: SetOwnerRootNode :exec
UPDATE users
SET root_node_id = $1::UUID,
updated_at = $2
WHERE id = $3::UUID
`
type SetOwnerRootNodeParams struct {
RootNodeID pgtype.UUID `db:"root_node_id" json:"root_node_id"`
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
OwnerID pgtype.UUID `db:"owner_id" json:"owner_id"`
}
func (q *Queries) SetOwnerRootNode(ctx context.Context, arg SetOwnerRootNodeParams) error {
_, err := q.db.Exec(ctx, setOwnerRootNode, arg.RootNodeID, arg.UpdatedAt, arg.OwnerID)
return err
}
const touchBrowserSession = `-- name: TouchBrowserSession :exec
UPDATE sessions
SET last_seen_at = $1
WHERE id = $2::UUID
AND revoked_at IS NULL
`
type TouchBrowserSessionParams struct {
SeenAt pgtype.Timestamptz `db:"seen_at" json:"seen_at"`
SessionID pgtype.UUID `db:"session_id" json:"session_id"`
}
func (q *Queries) TouchBrowserSession(ctx context.Context, arg TouchBrowserSessionParams) error {
_, err := q.db.Exec(ctx, touchBrowserSession, arg.SeenAt, arg.SessionID)
return err
}

View file

@ -9,8 +9,20 @@ import (
)
type Querier interface {
CreateAuthenticationAuditEvent(ctx context.Context, arg CreateAuthenticationAuditEventParams) error
CreateBrowserSession(ctx context.Context, arg CreateBrowserSessionParams) (string, error)
CreateInitialRootChange(ctx context.Context, arg CreateInitialRootChangeParams) error
CreateOwner(ctx context.Context, arg CreateOwnerParams) (string, error)
CreateOwnerRootNode(ctx context.Context, arg CreateOwnerRootNodeParams) (string, error)
CreateRecoveryCode(ctx context.Context, arg CreateRecoveryCodeParams) error
DatabaseHealth(ctx context.Context) (int64, error)
GetActiveBrowserSession(ctx context.Context, arg GetActiveBrowserSessionParams) (GetActiveBrowserSessionRow, error)
GetAuthenticationInvariantCounts(ctx context.Context) (GetAuthenticationInvariantCountsRow, error)
GetOwnerAuthenticationRecord(ctx context.Context) (GetOwnerAuthenticationRecordRow, error)
OwnerExists(ctx context.Context) (bool, error)
RevokeBrowserSession(ctx context.Context, arg RevokeBrowserSessionParams) (int64, error)
SetOwnerRootNode(ctx context.Context, arg SetOwnerRootNodeParams) error
TouchBrowserSession(ctx context.Context, arg TouchBrowserSessionParams) error
}
var _ Querier = (*Queries)(nil)