334 lines
8.2 KiB
Go
334 lines
8.2 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.31.1
|
|
// source: identity.sql
|
|
|
|
package pgstore
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
)
|
|
|
|
const createIdentity = `-- name: CreateIdentity :execrows
|
|
insert into identities (provider, subject, user_id, email, email_verified, created_at, last_login_at)
|
|
values ($1, $2, $3, $4,
|
|
$5, $6, $6)
|
|
on conflict (provider, subject) do nothing
|
|
`
|
|
|
|
type CreateIdentityParams struct {
|
|
Provider string
|
|
Subject string
|
|
UserID string
|
|
Email *string
|
|
EmailVerified bool
|
|
Now time.Time
|
|
}
|
|
|
|
// `do nothing` rather than a bare insert: two first logins of one brand-new identity can race, and
|
|
// the loser must see the row the winner inserted rather than a unique violation.
|
|
func (q *Queries) CreateIdentity(ctx context.Context, arg CreateIdentityParams) (int64, error) {
|
|
result, err := q.db.Exec(ctx, createIdentity,
|
|
arg.Provider,
|
|
arg.Subject,
|
|
arg.UserID,
|
|
arg.Email,
|
|
arg.EmailVerified,
|
|
arg.Now,
|
|
)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return result.RowsAffected(), nil
|
|
}
|
|
|
|
const createUser = `-- name: CreateUser :exec
|
|
insert into users (id, email, created_at)
|
|
values ($1, $2, $3)
|
|
`
|
|
|
|
type CreateUserParams struct {
|
|
ID string
|
|
Email *string
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) error {
|
|
_, err := q.db.Exec(ctx, createUser, arg.ID, arg.Email, arg.CreatedAt)
|
|
return err
|
|
}
|
|
|
|
const deleteExpiredLoginStates = `-- name: DeleteExpiredLoginStates :execrows
|
|
delete from auth_states where expires_at <= $1
|
|
`
|
|
|
|
func (q *Queries) DeleteExpiredLoginStates(ctx context.Context, now time.Time) (int64, error) {
|
|
result, err := q.db.Exec(ctx, deleteExpiredLoginStates, now)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return result.RowsAffected(), nil
|
|
}
|
|
|
|
const deleteOldLoginEvents = `-- name: DeleteOldLoginEvents :execrows
|
|
delete from login_events where at < $1
|
|
`
|
|
|
|
// /auth/callback writes a row on every refusal and needs no credential to do it, so a journal that
|
|
// only grows is a liability rather than an audit.
|
|
func (q *Queries) DeleteOldLoginEvents(ctx context.Context, before time.Time) (int64, error) {
|
|
result, err := q.db.Exec(ctx, deleteOldLoginEvents, before)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return result.RowsAffected(), nil
|
|
}
|
|
|
|
const lockIdentity = `-- name: LockIdentity :one
|
|
select user_id from identities
|
|
where provider = $1 and subject = $2 for update
|
|
`
|
|
|
|
type LockIdentityParams struct {
|
|
Provider string
|
|
Subject string
|
|
}
|
|
|
|
func (q *Queries) LockIdentity(ctx context.Context, arg LockIdentityParams) (string, error) {
|
|
row := q.db.QueryRow(ctx, lockIdentity, arg.Provider, arg.Subject)
|
|
var user_id string
|
|
err := row.Scan(&user_id)
|
|
return user_id, err
|
|
}
|
|
|
|
const putLoginState = `-- name: PutLoginState :exec
|
|
|
|
insert into auth_states (state_sha256, provider, issuer, nonce, code_verifier, return_to, start_id, created_at, expires_at)
|
|
values ($1, $2, $3, $4,
|
|
$5, $6, $7, $8,
|
|
$9)
|
|
`
|
|
|
|
type PutLoginStateParams struct {
|
|
StateSha256 []byte
|
|
Provider string
|
|
Issuer string
|
|
Nonce string
|
|
CodeVerifier string
|
|
ReturnTo string
|
|
StartID string
|
|
CreatedAt time.Time
|
|
ExpiresAt time.Time
|
|
}
|
|
|
|
// Identity, login states and the login journal.
|
|
func (q *Queries) PutLoginState(ctx context.Context, arg PutLoginStateParams) error {
|
|
_, err := q.db.Exec(ctx, putLoginState,
|
|
arg.StateSha256,
|
|
arg.Provider,
|
|
arg.Issuer,
|
|
arg.Nonce,
|
|
arg.CodeVerifier,
|
|
arg.ReturnTo,
|
|
arg.StartID,
|
|
arg.CreatedAt,
|
|
arg.ExpiresAt,
|
|
)
|
|
return err
|
|
}
|
|
|
|
const recentLogins = `-- name: RecentLogins :many
|
|
select provider, outcome, reason, ip_prefix, client, at
|
|
from login_events where user_id = $1::text order by at desc limit $2::bigint
|
|
`
|
|
|
|
type RecentLoginsParams struct {
|
|
UserID string
|
|
Lim int64
|
|
}
|
|
|
|
type RecentLoginsRow struct {
|
|
Provider string
|
|
Outcome string
|
|
Reason string
|
|
IpPrefix string
|
|
Client string
|
|
At time.Time
|
|
}
|
|
|
|
func (q *Queries) RecentLogins(ctx context.Context, arg RecentLoginsParams) ([]RecentLoginsRow, error) {
|
|
rows, err := q.db.Query(ctx, recentLogins, arg.UserID, arg.Lim)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []RecentLoginsRow
|
|
for rows.Next() {
|
|
var i RecentLoginsRow
|
|
if err := rows.Scan(
|
|
&i.Provider,
|
|
&i.Outcome,
|
|
&i.Reason,
|
|
&i.IpPrefix,
|
|
&i.Client,
|
|
&i.At,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const recordLogin = `-- name: RecordLogin :exec
|
|
insert into login_events (user_id, provider, outcome, reason, ip_prefix, client, at)
|
|
values ($1, $2, $3, $4,
|
|
$5, $6, $7)
|
|
`
|
|
|
|
type RecordLoginParams struct {
|
|
UserID *string
|
|
Provider string
|
|
Outcome string
|
|
Reason string
|
|
IpPrefix string
|
|
Client string
|
|
At time.Time
|
|
}
|
|
|
|
func (q *Queries) RecordLogin(ctx context.Context, arg RecordLoginParams) error {
|
|
_, err := q.db.Exec(ctx, recordLogin,
|
|
arg.UserID,
|
|
arg.Provider,
|
|
arg.Outcome,
|
|
arg.Reason,
|
|
arg.IpPrefix,
|
|
arg.Client,
|
|
arg.At,
|
|
)
|
|
return err
|
|
}
|
|
|
|
const refreshAccountEmail = `-- name: RefreshAccountEmail :exec
|
|
update users set email = $1::text where id = $2
|
|
`
|
|
|
|
type RefreshAccountEmailParams struct {
|
|
Email string
|
|
ID string
|
|
}
|
|
|
|
// The cast keeps the parameter non-null: users.email IS nullable, but this path is reached only for
|
|
// a VERIFIED, non-empty address, and a *string here would invite a nil the branch cannot produce.
|
|
func (q *Queries) RefreshAccountEmail(ctx context.Context, arg RefreshAccountEmailParams) error {
|
|
_, err := q.db.Exec(ctx, refreshAccountEmail, arg.Email, arg.ID)
|
|
return err
|
|
}
|
|
|
|
const refreshIdentity = `-- name: RefreshIdentity :exec
|
|
update identities set email = $1, email_verified = $2,
|
|
last_login_at = $3
|
|
where provider = $4 and subject = $5
|
|
`
|
|
|
|
type RefreshIdentityParams struct {
|
|
Email *string
|
|
EmailVerified bool
|
|
Now time.Time
|
|
Provider string
|
|
Subject string
|
|
}
|
|
|
|
// The address is refreshed only when the provider says it is verified — an unverified one is kept
|
|
// on the identity and never promoted to the account.
|
|
func (q *Queries) RefreshIdentity(ctx context.Context, arg RefreshIdentityParams) error {
|
|
_, err := q.db.Exec(ctx, refreshIdentity,
|
|
arg.Email,
|
|
arg.EmailVerified,
|
|
arg.Now,
|
|
arg.Provider,
|
|
arg.Subject,
|
|
)
|
|
return err
|
|
}
|
|
|
|
const revokeUserSessions = `-- name: RevokeUserSessions :execrows
|
|
update sessions set revoked_at = $1::timestamptz
|
|
where user_id = $2 and revoked_at is null
|
|
`
|
|
|
|
type RevokeUserSessionsParams struct {
|
|
Now time.Time
|
|
UserID string
|
|
}
|
|
|
|
func (q *Queries) RevokeUserSessions(ctx context.Context, arg RevokeUserSessionsParams) (int64, error) {
|
|
result, err := q.db.Exec(ctx, revokeUserSessions, arg.Now, arg.UserID)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return result.RowsAffected(), nil
|
|
}
|
|
|
|
const takeLoginState = `-- name: TakeLoginState :one
|
|
delete from auth_states
|
|
where state_sha256 = $1 and expires_at > $2
|
|
returning provider, issuer, nonce, code_verifier, return_to, start_id, created_at, expires_at
|
|
`
|
|
|
|
type TakeLoginStateParams struct {
|
|
StateSha256 []byte
|
|
Now time.Time
|
|
}
|
|
|
|
type TakeLoginStateRow struct {
|
|
Provider string
|
|
Issuer string
|
|
Nonce string
|
|
CodeVerifier string
|
|
ReturnTo string
|
|
StartID string
|
|
CreatedAt time.Time
|
|
ExpiresAt time.Time
|
|
}
|
|
|
|
// Deleting and returning in ONE statement is what makes it single-use under concurrency: a second
|
|
// callback with the same state deletes nothing and gets nothing, with no window between the check
|
|
// and the removal.
|
|
func (q *Queries) TakeLoginState(ctx context.Context, arg TakeLoginStateParams) (TakeLoginStateRow, error) {
|
|
row := q.db.QueryRow(ctx, takeLoginState, arg.StateSha256, arg.Now)
|
|
var i TakeLoginStateRow
|
|
err := row.Scan(
|
|
&i.Provider,
|
|
&i.Issuer,
|
|
&i.Nonce,
|
|
&i.CodeVerifier,
|
|
&i.ReturnTo,
|
|
&i.StartID,
|
|
&i.CreatedAt,
|
|
&i.ExpiresAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const userByIdentity = `-- name: UserByIdentity :one
|
|
select user_id from identities
|
|
where provider = $1 and subject = $2
|
|
`
|
|
|
|
type UserByIdentityParams struct {
|
|
Provider string
|
|
Subject string
|
|
}
|
|
|
|
// Resolves a provider's subject to the account it belongs to, WITHOUT creating one.
|
|
func (q *Queries) UserByIdentity(ctx context.Context, arg UserByIdentityParams) (string, error) {
|
|
row := q.db.QueryRow(ctx, userByIdentity, arg.Provider, arg.Subject)
|
|
var user_id string
|
|
err := row.Scan(&user_id)
|
|
return user_id, err
|
|
}
|