Compare commits

..

2 Commits

Author SHA1 Message Date
b4699e987c feat: service and user session queries 2025-06-08 22:59:33 +02:00
be9d4f2a1b feat: user and service sessions 2025-06-08 22:59:24 +02:00
4 changed files with 154 additions and 0 deletions

View File

@ -0,0 +1,33 @@
-- +goose Up
-- +goose StatementBegin
CREATE TABLE user_sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
user_id UUID REFERENCES users (id) NOT NULL,
session_type VARCHAR(32) NOT NULL DEFAULT 'user', -- e.g. 'user', 'admin'
issued_at TIMESTAMP
WITH
TIME ZONE NOT NULL DEFAULT NOW (),
expires_at TIMESTAMP
WITH
TIME ZONE,
last_active TIMESTAMP
WITH
TIME ZONE,
ip_address VARCHAR(45), -- supports IPv4/IPv6
user_agent TEXT,
refresh_token TEXT,
device_info JSONB, -- optional: structured info (browser, OS, etc.)
is_active BOOLEAN NOT NULL DEFAULT TRUE,
revoked_at TIMESTAMP
WITH
TIME ZONE
);
CREATE INDEX IF NOT EXISTS idx_user_sessions_user_id ON user_sessions (user_id);
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
DROP TABLE IF EXISTS user_sessions;
-- +goose StatementEnd

View File

@ -0,0 +1,37 @@
-- +goose Up
-- +goose StatementBegin
CREATE TABLE service_sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid (),
service_id UUID REFERENCES api_services (id) NOT NULL,
client_id TEXT NOT NULL,
user_id UUID REFERENCES users (id), -- user on behalf of whom the service is acting, nullable for direct use with client creds
issued_at TIMESTAMP
WITH
TIME ZONE NOT NULL DEFAULT NOW (),
expires_at TIMESTAMP
WITH
TIME ZONE,
last_active TIMESTAMP
WITH
TIME ZONE,
ip_address VARCHAR(45),
user_agent TEXT,
refresh_token TEXT,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
revoked_at TIMESTAMP
WITH
TIME ZONE,
scope TEXT, -- what scopes/permissions this session was issued for
claims JSONB -- snapshot of claims at session start, optional
);
CREATE INDEX IF NOT EXISTS idx_service_sessions_client_id ON service_sessions (client_id);
CREATE INDEX IF NOT EXISTS idx_service_sessions_user_id ON service_sessions (user_id);
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
DROP TABLE IF EXISTS service_sessions;
-- +goose StatementEnd

View File

@ -0,0 +1,44 @@
-- name: CreateServiceSession :one
INSERT INTO service_sessions (
client_id, user_id, issued_at, expires_at, last_active,
ip_address, user_agent, is_active, scope, claims
) VALUES (
$1, $2, NOW(), $3, $4,
$5, $6, $6, TRUE, $7, $8
)
RETURNING *;
-- name: ListActiveServiceSessionsByClient :many
SELECT * FROM service_sessions
WHERE client_id = $1
AND is_active = TRUE
ORDER BY issued_at DESC;
-- name: ListActiveServiceSessionsByUser :many
SELECT * FROM service_sessions
WHERE user_id = $1
AND is_active = TRUE
ORDER BY issued_at DESC;
-- name: GetServiceSessionByToken :one
SELECT * FROM service_sessions
WHERE refresh_token = $1
AND is_active = TRUE;
-- name: RevokeServiceSession :exec
UPDATE service_sessions
SET is_active = FALSE,
revoked_at = NOW()
WHERE id = $1
AND is_active = TRUE;
-- name: UpdateServiceSessionLastActive :exec
UPDATE service_sessions
SET last_active = NOW()
WHERE id = $1
AND is_active = TRUE;
-- name: ListAllServiceSessions :many
SELECT * FROM service_sessions
ORDER BY issued_at DESC
LIMIT $1 OFFSET $2;

40
queries/user_sessions.sql Normal file
View File

@ -0,0 +1,40 @@
-- name: CreateUserSession :one
INSERT INTO user_sessions (
user_id, session_type, issued_at, expires_at, last_active,
ip_address, user_agent,
device_info, is_active
) VALUES (
$1, $2, NOW(), $3, $4,
$5, $6,
$7, TRUE
)
RETURNING *;
-- name: ListActiveUserSessions :many
SELECT * FROM user_sessions
WHERE user_id = $1
AND is_active = TRUE
ORDER BY issued_at DESC;
-- name: GetUserSessionByToken :one
SELECT * FROM user_sessions
WHERE refresh_token = $1
AND is_active = TRUE;
-- name: RevokeUserSession :exec
UPDATE user_sessions
SET is_active = FALSE,
revoked_at = NOW()
WHERE id = $1
AND is_active = TRUE;
-- name: UpdateSessionLastActive :exec
UPDATE user_sessions
SET last_active = NOW()
WHERE id = $1
AND is_active = TRUE;
-- name: ListAllSessions :many
SELECT * FROM user_sessions
ORDER BY issued_at DESC
LIMIT $1 OFFSET $2;