Files
story/migrations/000017_resource_sharing.up.sql
T

57 lines
3.4 KiB
PL/PgSQL
Raw Normal View History

2026-08-26 06:41:07 +08:00
BEGIN;
CREATE TABLE sharing_grant (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
public_id uuid NOT NULL UNIQUE DEFAULT gen_random_uuid(),
tenant_id uuid NOT NULL REFERENCES tenant(id),
household_id uuid NOT NULL,
subject_id uuid NOT NULL,
resource_type varchar(32) NOT NULL CHECK (resource_type IN ('STORY','TRANSCRIPT','RECORDING')),
resource_public_id uuid NOT NULL,
grantee_user_id uuid NOT NULL,
permission varchar(24) NOT NULL CHECK (permission IN ('VIEW_TEXT','LISTEN','DOWNLOAD','EDIT')),
purpose varchar(500) NOT NULL CHECK (length(trim(purpose))>0),
login_required boolean NOT NULL DEFAULT true,
granted_by uuid NOT NULL,
granted_at timestamptz NOT NULL DEFAULT now(),
expires_at timestamptz NOT NULL,
revoked_at timestamptz,
revoked_by uuid,
version bigint NOT NULL DEFAULT 1 CHECK (version>0),
updated_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT sharing_grant_household_tenant_fk FOREIGN KEY (household_id,tenant_id) REFERENCES household(id,tenant_id),
CONSTRAINT sharing_grant_subject_tenant_fk FOREIGN KEY (subject_id,tenant_id) REFERENCES subject_profile(id,tenant_id) ON DELETE CASCADE,
CONSTRAINT sharing_grant_grantee_tenant_fk FOREIGN KEY (grantee_user_id,tenant_id) REFERENCES user_account(id,tenant_id),
CONSTRAINT sharing_grant_grantor_tenant_fk FOREIGN KEY (granted_by,tenant_id) REFERENCES user_account(id,tenant_id),
CONSTRAINT sharing_grant_revoker_tenant_fk FOREIGN KEY (revoked_by,tenant_id) REFERENCES user_account(id,tenant_id),
CONSTRAINT sharing_grant_permission_resource_check CHECK (
(resource_type='STORY' AND permission IN ('VIEW_TEXT','EDIT')) OR
(resource_type='TRANSCRIPT' AND permission='VIEW_TEXT') OR
(resource_type='RECORDING' AND permission IN ('LISTEN','DOWNLOAD'))
),
CONSTRAINT sharing_grant_expiry_check CHECK (expires_at>granted_at)
);
CREATE INDEX sharing_grant_subject_idx ON sharing_grant(tenant_id,subject_id,granted_at DESC);
CREATE INDEX sharing_grant_recipient_idx ON sharing_grant(tenant_id,grantee_user_id,expires_at DESC) WHERE revoked_at IS NULL;
CREATE INDEX sharing_grant_resource_idx ON sharing_grant(tenant_id,resource_type,resource_public_id);
CREATE TABLE sharing_access_log (
id bigserial PRIMARY KEY,
tenant_id uuid NOT NULL REFERENCES tenant(id),
sharing_grant_id uuid NOT NULL REFERENCES sharing_grant(id) ON DELETE CASCADE,
actor_user_id uuid,
actor_identifier_digest char(64) NOT NULL,
resource_type varchar(32) NOT NULL,
resource_public_id uuid NOT NULL,
permission varchar(24) NOT NULL,
result varchar(16) NOT NULL CHECK (result IN ('SUCCESS','DENIED')),
reason_code varchar(80),
request_id varchar(128),
accessed_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT sharing_access_actor_tenant_fk FOREIGN KEY (actor_user_id,tenant_id) REFERENCES user_account(id,tenant_id)
);
CREATE INDEX sharing_access_grant_time_idx ON sharing_access_log(sharing_grant_id,accessed_at DESC);
CREATE INDEX sharing_access_tenant_time_idx ON sharing_access_log(tenant_id,accessed_at DESC);
COMMIT;