🚧 WIP
This commit is contained in:
+35
-1
@@ -105,4 +105,38 @@ CREATE TABLE IF NOT EXISTS imei_attributes (
|
||||
COMMENT ON TABLE imei_attributes IS
|
||||
'Time-varying device attributes (e.g. offsets) as an append-only timeline; the value valid at T is the row with the greatest effective_from <= T.';
|
||||
COMMENT ON COLUMN imei_attributes.effective_from IS
|
||||
'Time from which the value applies; backdating allowed. Resolved against the device timestamp (payload_time, received_at fallback) in GET /messages.';
|
||||
'Time from which the value applies; backdating allowed. Resolved against the device timestamp (payload_time, received_at fallback) in GET /messages.';
|
||||
|
||||
-- Interactive users for the management UI: username/password login with a
|
||||
-- role. 'admin' (level 2) manages everything incl. users; 'superuser'
|
||||
-- (level 1) configures devices/configs/tokens and manages day-to-day
|
||||
-- 'user' accounts; 'user' (level 0) is a read-only viewer. Passwords are
|
||||
-- stored as scrypt hashes, never plaintext. The first admin is seeded
|
||||
-- lazily from BOOTSTRAP_ADMIN_USER/BOOTSTRAP_ADMIN_PASSWORD when the table
|
||||
-- is empty (same bootstrap pattern as app_tokens).
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
username TEXT PRIMARY KEY CHECK (username <> ''),
|
||||
password_hash TEXT NOT NULL,
|
||||
role TEXT NOT NULL DEFAULT 'user'
|
||||
CHECK (role IN ('admin', 'superuser', 'user')),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- Login sessions: the browser keeps the opaque bearer token; only its
|
||||
-- SHA-256 digest is persisted (same pattern as app_tokens). Sessions
|
||||
-- expire server-side; the role is NOT cached here (joined fresh from
|
||||
-- users on every request), so role changes apply immediately. Deleting a
|
||||
-- user cascades to their sessions.
|
||||
CREATE TABLE IF NOT EXISTS sessions (
|
||||
token_hash TEXT PRIMARY KEY CHECK (token_hash ~ '^[0-9a-f]{64}$'),
|
||||
username TEXT NOT NULL REFERENCES users (username) ON DELETE CASCADE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
expires_at TIMESTAMPTZ NOT NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_sessions_expiry ON sessions (expires_at);
|
||||
|
||||
COMMENT ON TABLE users IS
|
||||
'Interactive UI users (scrypt password hashes); admin = full access, superuser = configure + manage user accounts, user = read-only. First admin seeded from BOOTSTRAP_ADMIN_* when empty.';
|
||||
COMMENT ON TABLE sessions IS
|
||||
'Login sessions (SHA-256 digests of opaque bearer tokens); role resolved fresh from users on each request.';
|
||||
Reference in New Issue
Block a user