149 lines
4.5 KiB
Go
149 lines
4.5 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.31.1
|
|
// source: sessions.sql
|
|
|
|
package pgstore
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
)
|
|
|
|
const createSession = `-- name: CreateSession :exec
|
|
insert into sessions (token_sha256, user_id, created_at, last_used_at, idle_expires_at, absolute_expires_at)
|
|
values ($1, $2, $3, $3,
|
|
$4, $5)
|
|
`
|
|
|
|
type CreateSessionParams struct {
|
|
TokenSha256 []byte
|
|
UserID string
|
|
Now time.Time
|
|
IdleExpiresAt time.Time
|
|
AbsoluteExpiresAt time.Time
|
|
}
|
|
|
|
func (q *Queries) CreateSession(ctx context.Context, arg CreateSessionParams) error {
|
|
_, err := q.db.Exec(ctx, createSession,
|
|
arg.TokenSha256,
|
|
arg.UserID,
|
|
arg.Now,
|
|
arg.IdleExpiresAt,
|
|
arg.AbsoluteExpiresAt,
|
|
)
|
|
return err
|
|
}
|
|
|
|
const lookupSession = `-- name: LookupSession :one
|
|
|
|
select user_id, idle_expires_at, absolute_expires_at
|
|
from sessions
|
|
where token_sha256 = $1
|
|
and revoked_at is null
|
|
and idle_expires_at > $2
|
|
and absolute_expires_at > $2
|
|
`
|
|
|
|
type LookupSessionParams struct {
|
|
TokenSha256 []byte
|
|
Now time.Time
|
|
}
|
|
|
|
type LookupSessionRow struct {
|
|
UserID string
|
|
IdleExpiresAt time.Time
|
|
AbsoluteExpiresAt time.Time
|
|
}
|
|
|
|
// Sessions. Parameters are NAMED with sqlc.arg rather than left as $n, so that the generated params
|
|
// struct carries field names: two adjacent time.Time arguments at a call site are exactly the shape
|
|
// that transposes silently, and a named field is the cheapest defence against it.
|
|
// Expiry and revocation are clauses of THIS query, not checks a caller could forget: a row that
|
|
// comes back is live by construction.
|
|
func (q *Queries) LookupSession(ctx context.Context, arg LookupSessionParams) (LookupSessionRow, error) {
|
|
row := q.db.QueryRow(ctx, lookupSession, arg.TokenSha256, arg.Now)
|
|
var i LookupSessionRow
|
|
err := row.Scan(&i.UserID, &i.IdleExpiresAt, &i.AbsoluteExpiresAt)
|
|
return i, err
|
|
}
|
|
|
|
const revokeSession = `-- name: RevokeSession :exec
|
|
update sessions set revoked_at = $1::timestamptz
|
|
where token_sha256 = $2 and revoked_at is null
|
|
`
|
|
|
|
type RevokeSessionParams struct {
|
|
Now time.Time
|
|
TokenSha256 []byte
|
|
}
|
|
|
|
// The cast is not decoration: revoked_at is NULLABLE, so without it sqlc types the parameter from
|
|
// the column and hands the caller a *time.Time for a value that is never absent.
|
|
func (q *Queries) RevokeSession(ctx context.Context, arg RevokeSessionParams) error {
|
|
_, err := q.db.Exec(ctx, revokeSession, arg.Now, arg.TokenSha256)
|
|
return err
|
|
}
|
|
|
|
const sessionStillLive = `-- name: SessionStillLive :one
|
|
select 1
|
|
from sessions
|
|
where token_sha256 = $1
|
|
and revoked_at is null
|
|
and absolute_expires_at > $2
|
|
`
|
|
|
|
type SessionStillLiveParams struct {
|
|
TokenSha256 []byte
|
|
Now time.Time
|
|
}
|
|
|
|
// ⚠ THE IDLE CLAUSE IS DELIBERATELY ABSENT. The idle window slides on a REQUEST, and the event
|
|
// stream is ONE request that lives for hours, so a stream cannot slide its own window and asking the
|
|
// idle question here would end the stream of a user who is sitting and watching it.
|
|
func (q *Queries) SessionStillLive(ctx context.Context, arg SessionStillLiveParams) (int32, error) {
|
|
row := q.db.QueryRow(ctx, sessionStillLive, arg.TokenSha256, arg.Now)
|
|
var column_1 int32
|
|
err := row.Scan(&column_1)
|
|
return column_1, err
|
|
}
|
|
|
|
const sweepSessions = `-- name: SweepSessions :execrows
|
|
delete from sessions
|
|
where absolute_expires_at <= $1
|
|
or idle_expires_at <= $1
|
|
or revoked_at is not null
|
|
`
|
|
|
|
// Deletes rows nothing can authenticate with again: past either expiry, or revoked. A revoked row is
|
|
// the one a compromised account most wants gone. The audit lives in the login journal, not here.
|
|
func (q *Queries) SweepSessions(ctx context.Context, now time.Time) (int64, error) {
|
|
result, err := q.db.Exec(ctx, sweepSessions, now)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return result.RowsAffected(), nil
|
|
}
|
|
|
|
const touchSession = `-- name: TouchSession :exec
|
|
update sessions
|
|
set last_used_at = $1,
|
|
idle_expires_at = least($2::timestamptz, absolute_expires_at)
|
|
where token_sha256 = $3
|
|
and revoked_at is null
|
|
and idle_expires_at > $1
|
|
and absolute_expires_at > $1
|
|
`
|
|
|
|
type TouchSessionParams struct {
|
|
Now time.Time
|
|
IdleDeadline time.Time
|
|
TokenSha256 []byte
|
|
}
|
|
|
|
// Slides the idle window and never moves the absolute expiry — that is the point of having two
|
|
// clocks. Its WHERE matches LookupSession's, idle clause included (PD-4).
|
|
func (q *Queries) TouchSession(ctx context.Context, arg TouchSessionParams) error {
|
|
_, err := q.db.Exec(ctx, touchSession, arg.Now, arg.IdleDeadline, arg.TokenSha256)
|
|
return err
|
|
}
|