🚧 WIP
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
-- Access control for the API and web UI: users, groups, and glob-based
|
||||
-- topic access rules (allow/deny; see shared/access.py for semantics).
|
||||
|
||||
-- NOTE: user/group administration happens in the web UI (or SQL). Rule
|
||||
-- patterns are globs matched against the full topic/tag name, where
|
||||
-- '*' matches any character sequence (including '.') and everything
|
||||
-- else is literal. Example: '11001.*_Value' grants everything under
|
||||
-- '11001.' ending in '_Value'; user rules can override group rules via
|
||||
-- deny, which always wins over allow.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
username TEXT NOT NULL UNIQUE,
|
||||
password_hash TEXT NOT NULL,
|
||||
role TEXT NOT NULL DEFAULT 'user'
|
||||
CHECK (role IN ('user', 'admin')),
|
||||
disabled_at TIMESTAMPTZ,
|
||||
must_change_password BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS groups (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_groups (
|
||||
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
group_id BIGINT NOT NULL REFERENCES groups(id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (user_id, group_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS access_rules (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id BIGINT REFERENCES users(id) ON DELETE CASCADE,
|
||||
group_id BIGINT REFERENCES groups(id) ON DELETE CASCADE,
|
||||
kind TEXT NOT NULL CHECK (kind IN ('allow', 'deny')),
|
||||
pattern TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
CHECK ((user_id IS NULL) <> (group_id IS NULL)) -- exactly one owner
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_access_rules_user ON access_rules (user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_access_rules_group ON access_rules (group_id);
|
||||
|
||||
-- Sessions issued by the web UI; the API validates the same table, so a
|
||||
-- web login is also an API login. Only a SHA-256 of the token is stored.
|
||||
CREATE TABLE IF NOT EXISTS sessions (
|
||||
token_hash TEXT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
csrf_token TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
expires_at TIMESTAMPTZ NOT NULL,
|
||||
seen_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_sessions_user ON sessions (user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_sessions_expiry ON sessions (expires_at);
|
||||
|
||||
-- Login attempt throttling for the web UI.
|
||||
CREATE TABLE IF NOT EXISTS login_attempts (
|
||||
ip TEXT PRIMARY KEY,
|
||||
attempts INTEGER NOT NULL DEFAULT 0,
|
||||
last_seen TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
Reference in New Issue
Block a user