Implement owner setup and browser authentication sessions
This commit is contained in:
parent
077cf7601a
commit
715423ab8e
21 changed files with 2185 additions and 14 deletions
409
internal/adapters/postgres/generated/authentication.sql.go
Normal file
409
internal/adapters/postgres/generated/authentication.sql.go
Normal 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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue