001-identity-init.xml
5.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.27.xsd">
<!--
pbc-identity initial schema.
Owns: identity__user, identity__role, identity__user_role.
Conventions enforced for every business table in vibe_erp:
• UUID primary key
• tenant_id varchar(64) NOT NULL
• Audit columns: created_at, created_by, updated_at, updated_by
• Optimistic-locking version column
• ext jsonb NOT NULL DEFAULT '{}' for key-user custom fields
• GIN index on ext for fast custom-field queries
• Composite index on (tenant_id, ...) for tenant-scoped lookups
• Postgres Row-Level Security enabled, with a simple per-tenant
policy bound to the GUC `vibeerp.current_tenant` set by the
platform on every transaction (see TODO below)
TODO(v0.2): the platform's `RlsTransactionHook` is not yet
implemented, so the RLS policy in this file uses
`current_setting('vibeerp.current_tenant', true)` and is enabled
but not yet enforced (NO FORCE). When the hook lands, change to
FORCE ROW LEVEL SECURITY in a follow-up changeset.
-->
<changeSet id="identity-init-001" author="vibe_erp">
<comment>Create identity__user table</comment>
<sql>
CREATE TABLE identity__user (
id uuid PRIMARY KEY,
tenant_id varchar(64) NOT NULL,
username varchar(128) NOT NULL,
display_name varchar(256) NOT NULL,
email varchar(320),
enabled boolean NOT NULL DEFAULT true,
ext jsonb NOT NULL DEFAULT '{}'::jsonb,
created_at timestamptz NOT NULL,
created_by varchar(128) NOT NULL,
updated_at timestamptz NOT NULL,
updated_by varchar(128) NOT NULL,
version bigint NOT NULL DEFAULT 0
);
CREATE UNIQUE INDEX identity__user_tenant_username_uk
ON identity__user (tenant_id, username);
CREATE INDEX identity__user_ext_gin
ON identity__user USING GIN (ext jsonb_path_ops);
</sql>
<rollback>
DROP TABLE identity__user;
</rollback>
</changeSet>
<changeSet id="identity-init-002" author="vibe_erp">
<comment>Enable Row-Level Security on identity__user (advisory until RlsTransactionHook lands)</comment>
<sql>
ALTER TABLE identity__user ENABLE ROW LEVEL SECURITY;
CREATE POLICY identity__user_tenant_isolation ON identity__user
USING (tenant_id = current_setting('vibeerp.current_tenant', true));
</sql>
<rollback>
DROP POLICY IF EXISTS identity__user_tenant_isolation ON identity__user;
ALTER TABLE identity__user DISABLE ROW LEVEL SECURITY;
</rollback>
</changeSet>
<changeSet id="identity-init-003" author="vibe_erp">
<comment>Create identity__role table</comment>
<sql>
CREATE TABLE identity__role (
id uuid PRIMARY KEY,
tenant_id varchar(64) NOT NULL,
code varchar(64) NOT NULL,
name varchar(256) NOT NULL,
description text,
ext jsonb NOT NULL DEFAULT '{}'::jsonb,
created_at timestamptz NOT NULL,
created_by varchar(128) NOT NULL,
updated_at timestamptz NOT NULL,
updated_by varchar(128) NOT NULL,
version bigint NOT NULL DEFAULT 0
);
CREATE UNIQUE INDEX identity__role_tenant_code_uk
ON identity__role (tenant_id, code);
CREATE INDEX identity__role_ext_gin
ON identity__role USING GIN (ext jsonb_path_ops);
ALTER TABLE identity__role ENABLE ROW LEVEL SECURITY;
CREATE POLICY identity__role_tenant_isolation ON identity__role
USING (tenant_id = current_setting('vibeerp.current_tenant', true));
</sql>
<rollback>
DROP TABLE identity__role;
</rollback>
</changeSet>
<changeSet id="identity-init-004" author="vibe_erp">
<comment>Create identity__user_role join table</comment>
<sql>
CREATE TABLE identity__user_role (
id uuid PRIMARY KEY,
tenant_id varchar(64) NOT NULL,
user_id uuid NOT NULL REFERENCES identity__user(id) ON DELETE CASCADE,
role_id uuid NOT NULL REFERENCES identity__role(id) ON DELETE CASCADE,
created_at timestamptz NOT NULL,
created_by varchar(128) NOT NULL,
updated_at timestamptz NOT NULL,
updated_by varchar(128) NOT NULL,
version bigint NOT NULL DEFAULT 0
);
CREATE UNIQUE INDEX identity__user_role_uk
ON identity__user_role (tenant_id, user_id, role_id);
ALTER TABLE identity__user_role ENABLE ROW LEVEL SECURITY;
CREATE POLICY identity__user_role_tenant_isolation ON identity__user_role
USING (tenant_id = current_setting('vibeerp.current_tenant', true));
</sql>
<rollback>
DROP TABLE identity__user_role;
</rollback>
</changeSet>
</databaseChangeLog>