add account localization and switchable rooms
Centralize control and OBS copy in a shared TOML catalog, persist the selected locale per account, and broadcast language changes to component streams. Allow account owners to atomically switch their Bilibili room and restart the shared listener without changing component URLs.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
-- Treat an invitation room as the account's initial room rather than an
|
||||
-- immutable lifetime binding. Room IDs remain unique across accounts so two
|
||||
-- listeners cannot accidentally claim the same upstream room.
|
||||
|
||||
DROP TRIGGER IF EXISTS users_room_id_immutable ON users;
|
||||
DROP FUNCTION IF EXISTS prevent_user_room_id_change();
|
||||
|
||||
CREATE OR REPLACE FUNCTION enforce_live_source_account_room()
|
||||
RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
SET search_path = pg_catalog, public
|
||||
AS $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM public.users
|
||||
WHERE id = NEW.owner_user_id AND room_id = NEW.room_id
|
||||
) THEN
|
||||
RAISE EXCEPTION 'live source room_id must equal its owning account room_id';
|
||||
END IF;
|
||||
IF TG_OP = 'UPDATE'
|
||||
AND NEW.owner_user_id IS DISTINCT FROM OLD.owner_user_id THEN
|
||||
RAISE EXCEPTION 'live source ownership is immutable';
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
|
||||
COMMENT ON COLUMN users.room_id IS
|
||||
'Current account-level Bilibili room; initialized by invitation and user-switchable.';
|
||||
COMMENT ON COLUMN live_sources.room_id IS
|
||||
'Current room of the owning account; updated atomically with users.room_id.';
|
||||
@@ -0,0 +1,23 @@
|
||||
-- Account language preference. The browser keeps a local pre-login choice;
|
||||
-- authenticated saves become authoritative for every control session and OBS
|
||||
-- component owned by the account.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS account_preferences (
|
||||
user_id UUID PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
|
||||
-- Supported locale codes are validated against resources/i18n.toml by the
|
||||
-- repository. Keeping the column open avoids a schema migration per locale.
|
||||
language TEXT NOT NULL DEFAULT 'zh-CN',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
INSERT INTO account_preferences(user_id)
|
||||
SELECT id FROM users
|
||||
ON CONFLICT(user_id) DO NOTHING;
|
||||
|
||||
ALTER TABLE account_preferences ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE account_preferences FORCE ROW LEVEL SECURITY;
|
||||
DROP POLICY IF EXISTS account_preferences_owner ON account_preferences;
|
||||
CREATE POLICY account_preferences_owner ON account_preferences
|
||||
USING (user_id = NULLIF(current_setting('app.user_id', true), '')::UUID)
|
||||
WITH CHECK (user_id = NULLIF(current_setting('app.user_id', true), '')::UUID);
|
||||
Reference in New Issue
Block a user