@jmruthers/pace-core 0.5.39 → 0.5.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/rbac/cli/policy-manager.js +278 -0
- package/dist/rbac/cli/policy-manager.js.map +1 -0
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +1 -1
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventContextType.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +1 -1
- package/docs/api/interfaces/EventProviderProps.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
- package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
- package/docs/api/interfaces/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACContextType.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACProviderProps.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +1 -1
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +2 -2
- package/docs/implementation-guides/data-tables.md +189 -0
- package/docs/rbac/README-rbac-rls-integration.md +358 -0
- package/docs/rbac/examples/rbac-rls-integration-example.md +332 -0
- package/docs/rbac/rbac-rls-integration.md +377 -0
- package/package.json +19 -3
- package/src/rbac/cli/policy-manager.ts +443 -0
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "../../chunk-PLDDJCW6.js";
|
|
3
|
+
|
|
4
|
+
// src/rbac/cli/policy-manager.ts
|
|
5
|
+
import { createClient } from "@supabase/supabase-js";
|
|
6
|
+
import { Command } from "commander";
|
|
7
|
+
import chalk from "chalk";
|
|
8
|
+
import ora from "ora";
|
|
9
|
+
import Table from "cli-table3";
|
|
10
|
+
var PolicyManager = class {
|
|
11
|
+
constructor(url, key) {
|
|
12
|
+
this.supabase = createClient(url, key);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* List all registered tables
|
|
16
|
+
*/
|
|
17
|
+
async listTables() {
|
|
18
|
+
const spinner = ora("Fetching registered tables...").start();
|
|
19
|
+
try {
|
|
20
|
+
const { data, error } = await this.supabase.from("rbac_policy_configs").select("*").eq("is_active", true).order("table_name");
|
|
21
|
+
if (error) throw error;
|
|
22
|
+
spinner.succeed("Fetched registered tables");
|
|
23
|
+
if (data.length === 0) {
|
|
24
|
+
console.log(chalk.yellow("No tables registered for RBAC policy management."));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const table = new Table({
|
|
28
|
+
head: ["Table", "Page", "App", "Org Column", "Event Column", "Operations"],
|
|
29
|
+
colWidths: [20, 15, 10, 15, 15, 30]
|
|
30
|
+
});
|
|
31
|
+
data.forEach((config) => {
|
|
32
|
+
table.push([
|
|
33
|
+
config.table_name,
|
|
34
|
+
config.page_name,
|
|
35
|
+
config.app_name,
|
|
36
|
+
config.organisation_column,
|
|
37
|
+
config.event_column || "N/A",
|
|
38
|
+
config.operations.join(", ")
|
|
39
|
+
]);
|
|
40
|
+
});
|
|
41
|
+
console.log(table.toString());
|
|
42
|
+
} catch (error) {
|
|
43
|
+
spinner.fail("Failed to fetch tables");
|
|
44
|
+
console.error(chalk.red("Error:"), error instanceof Error ? error.message : String(error));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Register a new table for RBAC policy management
|
|
49
|
+
*/
|
|
50
|
+
async registerTable(tableName, pageName, appName = "CAKE", orgColumn = "organisation_id", eventColumn, operations = ["read", "create", "update", "delete"]) {
|
|
51
|
+
const spinner = ora(`Registering table ${tableName}...`).start();
|
|
52
|
+
try {
|
|
53
|
+
const { data, error } = await this.supabase.rpc("register_rbac_table", {
|
|
54
|
+
p_table_name: tableName,
|
|
55
|
+
p_page_name: pageName,
|
|
56
|
+
p_app_name: appName,
|
|
57
|
+
p_organisation_column: orgColumn,
|
|
58
|
+
p_event_column: eventColumn,
|
|
59
|
+
p_operations: operations
|
|
60
|
+
});
|
|
61
|
+
if (error) throw error;
|
|
62
|
+
if (data) {
|
|
63
|
+
spinner.succeed(`Successfully registered table ${tableName}`);
|
|
64
|
+
} else {
|
|
65
|
+
spinner.fail(`Failed to register table ${tableName}`);
|
|
66
|
+
}
|
|
67
|
+
} catch (error) {
|
|
68
|
+
spinner.fail(`Failed to register table ${tableName}`);
|
|
69
|
+
console.error(chalk.red("Error:"), error instanceof Error ? error.message : String(error));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Update policies for a specific table
|
|
74
|
+
*/
|
|
75
|
+
async updateTable(tableName, pageName, appName = "CAKE") {
|
|
76
|
+
const spinner = ora(`Updating policies for ${tableName}...`).start();
|
|
77
|
+
try {
|
|
78
|
+
const { data, error } = await this.supabase.rpc("update_rbac_policies_for_table", {
|
|
79
|
+
p_table_name: tableName,
|
|
80
|
+
p_page_name: pageName,
|
|
81
|
+
p_app_name: appName
|
|
82
|
+
});
|
|
83
|
+
if (error) throw error;
|
|
84
|
+
if (data) {
|
|
85
|
+
spinner.succeed(`Successfully updated policies for ${tableName}`);
|
|
86
|
+
} else {
|
|
87
|
+
spinner.fail(`Failed to update policies for ${tableName}`);
|
|
88
|
+
}
|
|
89
|
+
} catch (error) {
|
|
90
|
+
spinner.fail(`Failed to update policies for ${tableName}`);
|
|
91
|
+
console.error(chalk.red("Error:"), error instanceof Error ? error.message : String(error));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Update all RBAC policies
|
|
96
|
+
*/
|
|
97
|
+
async updateAll() {
|
|
98
|
+
const spinner = ora("Updating all RBAC policies...").start();
|
|
99
|
+
try {
|
|
100
|
+
const { data, error } = await this.supabase.rpc("update_all_rbac_policies");
|
|
101
|
+
if (error) throw error;
|
|
102
|
+
spinner.succeed("Updated all RBAC policies");
|
|
103
|
+
const table = new Table({
|
|
104
|
+
head: ["Table", "Page", "App", "Success", "Error"],
|
|
105
|
+
colWidths: [20, 15, 10, 10, 30]
|
|
106
|
+
});
|
|
107
|
+
data.forEach((result) => {
|
|
108
|
+
table.push([
|
|
109
|
+
result.table_name,
|
|
110
|
+
result.page_name,
|
|
111
|
+
result.app_name,
|
|
112
|
+
result.success ? chalk.green("\u2713") : chalk.red("\u2717"),
|
|
113
|
+
result.error_message || ""
|
|
114
|
+
]);
|
|
115
|
+
});
|
|
116
|
+
console.log(table.toString());
|
|
117
|
+
} catch (error) {
|
|
118
|
+
spinner.fail("Failed to update all policies");
|
|
119
|
+
console.error(chalk.red("Error:"), error instanceof Error ? error.message : String(error));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Check policy health
|
|
124
|
+
*/
|
|
125
|
+
async checkHealth() {
|
|
126
|
+
const spinner = ora("Checking policy health...").start();
|
|
127
|
+
try {
|
|
128
|
+
const { data, error } = await this.supabase.rpc("check_rbac_policy_health");
|
|
129
|
+
if (error) throw error;
|
|
130
|
+
spinner.succeed("Policy health check complete");
|
|
131
|
+
if (data.length === 0) {
|
|
132
|
+
console.log(chalk.yellow("No policies found."));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const healthyPolicies = data.filter((h) => h.is_healthy);
|
|
136
|
+
const unhealthyPolicies = data.filter((h) => !h.is_healthy);
|
|
137
|
+
console.log(chalk.green(`\u2713 ${healthyPolicies.length} healthy policies`));
|
|
138
|
+
console.log(chalk.red(`\u2717 ${unhealthyPolicies.length} unhealthy policies`));
|
|
139
|
+
if (unhealthyPolicies.length > 0) {
|
|
140
|
+
console.log("\n" + chalk.red("Unhealthy Policies:"));
|
|
141
|
+
const table = new Table({
|
|
142
|
+
head: ["Table", "Policy", "Operation", "Issues"],
|
|
143
|
+
colWidths: [20, 25, 10, 40]
|
|
144
|
+
});
|
|
145
|
+
unhealthyPolicies.forEach((policy) => {
|
|
146
|
+
table.push([
|
|
147
|
+
policy.table_name,
|
|
148
|
+
policy.policy_name,
|
|
149
|
+
policy.operation,
|
|
150
|
+
policy.issues.join(", ")
|
|
151
|
+
]);
|
|
152
|
+
});
|
|
153
|
+
console.log(table.toString());
|
|
154
|
+
}
|
|
155
|
+
} catch (error) {
|
|
156
|
+
spinner.fail("Failed to check policy health");
|
|
157
|
+
console.error(chalk.red("Error:"), error instanceof Error ? error.message : String(error));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Show policy audit log
|
|
162
|
+
*/
|
|
163
|
+
async showAudit(limit = 20) {
|
|
164
|
+
const spinner = ora("Fetching audit log...").start();
|
|
165
|
+
try {
|
|
166
|
+
const { data, error } = await this.supabase.from("rbac_policy_audit").select("*").order("changed_at", { ascending: false }).limit(limit);
|
|
167
|
+
if (error) throw error;
|
|
168
|
+
spinner.succeed("Fetched audit log");
|
|
169
|
+
if (data.length === 0) {
|
|
170
|
+
console.log(chalk.yellow("No audit entries found."));
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const table = new Table({
|
|
174
|
+
head: ["Table", "Policy", "Operation", "Action", "Success", "Changed At"],
|
|
175
|
+
colWidths: [15, 20, 10, 10, 8, 20]
|
|
176
|
+
});
|
|
177
|
+
data.forEach((audit) => {
|
|
178
|
+
table.push([
|
|
179
|
+
audit.table_name,
|
|
180
|
+
audit.policy_name,
|
|
181
|
+
audit.operation,
|
|
182
|
+
audit.action,
|
|
183
|
+
audit.success ? chalk.green("\u2713") : chalk.red("\u2717"),
|
|
184
|
+
new Date(audit.changed_at).toLocaleString()
|
|
185
|
+
]);
|
|
186
|
+
});
|
|
187
|
+
console.log(table.toString());
|
|
188
|
+
} catch (error) {
|
|
189
|
+
spinner.fail("Failed to fetch audit log");
|
|
190
|
+
console.error(chalk.red("Error:"), error instanceof Error ? error.message : String(error));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Test permission check
|
|
195
|
+
*/
|
|
196
|
+
async testPermission(operation, pageName, orgId, eventId, appName = "CAKE") {
|
|
197
|
+
const spinner = ora("Testing permission check...").start();
|
|
198
|
+
try {
|
|
199
|
+
const { data, error } = await this.supabase.rpc("check_rbac_permission_with_context", {
|
|
200
|
+
p_operation: operation,
|
|
201
|
+
p_page_name: pageName,
|
|
202
|
+
p_resource_organisation_id: orgId,
|
|
203
|
+
p_resource_event_id: eventId,
|
|
204
|
+
p_app_name: appName
|
|
205
|
+
});
|
|
206
|
+
if (error) throw error;
|
|
207
|
+
spinner.succeed("Permission check complete");
|
|
208
|
+
const result = data ? chalk.green("ALLOWED") : chalk.red("DENIED");
|
|
209
|
+
console.log(`Permission: ${operation} on ${pageName} = ${result}`);
|
|
210
|
+
} catch (error) {
|
|
211
|
+
spinner.fail("Failed to test permission");
|
|
212
|
+
console.error(chalk.red("Error:"), error instanceof Error ? error.message : String(error));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
var program = new Command();
|
|
217
|
+
program.name("rbac-policy-manager").description("CLI tool for managing RBAC-RLS integration policies").version("1.0.0");
|
|
218
|
+
program.option("-u, --url <url>", "Supabase URL", process.env.SUPABASE_URL).option("-k, --key <key>", "Supabase service key", process.env.SUPABASE_SERVICE_ROLE_KEY).option("--verbose", "Enable verbose output");
|
|
219
|
+
program.command("list").description("List all registered tables").action(async (options) => {
|
|
220
|
+
const url = options.parent?.url || process.env.SUPABASE_URL;
|
|
221
|
+
const key = options.parent?.key || process.env.SUPABASE_SERVICE_ROLE_KEY;
|
|
222
|
+
const manager = new PolicyManager(url, key);
|
|
223
|
+
await manager.listTables();
|
|
224
|
+
});
|
|
225
|
+
program.command("register <tableName> <pageName>").description("Register a table for RBAC policy management").option("-a, --app <appName>", "App name", "CAKE").option("-o, --org-column <column>", "Organisation column name", "organisation_id").option("-e, --event-column <column>", "Event column name").option("--operations <operations>", "Comma-separated operations", "read,create,update,delete").action(async (tableName, pageName, options) => {
|
|
226
|
+
const operations = options.operations.split(",").map((op) => op.trim());
|
|
227
|
+
const url = options.parent?.url || process.env.SUPABASE_URL;
|
|
228
|
+
const key = options.parent?.key || process.env.SUPABASE_SERVICE_ROLE_KEY;
|
|
229
|
+
const manager = new PolicyManager(url, key);
|
|
230
|
+
await manager.registerTable(
|
|
231
|
+
tableName,
|
|
232
|
+
pageName,
|
|
233
|
+
options.app,
|
|
234
|
+
options.orgColumn,
|
|
235
|
+
options.eventColumn,
|
|
236
|
+
operations
|
|
237
|
+
);
|
|
238
|
+
});
|
|
239
|
+
program.command("update <tableName> <pageName>").description("Update policies for a specific table").option("-a, --app <appName>", "App name", "CAKE").action(async (tableName, pageName, options) => {
|
|
240
|
+
const url = options.parent?.url || process.env.SUPABASE_URL;
|
|
241
|
+
const key = options.parent?.key || process.env.SUPABASE_SERVICE_ROLE_KEY;
|
|
242
|
+
const manager = new PolicyManager(url, key);
|
|
243
|
+
await manager.updateTable(tableName, pageName, options.app);
|
|
244
|
+
});
|
|
245
|
+
program.command("update-all").description("Update all RBAC policies").action(async (options) => {
|
|
246
|
+
const url = options.url || process.env.SUPABASE_URL;
|
|
247
|
+
const key = options.key || process.env.SUPABASE_SERVICE_ROLE_KEY;
|
|
248
|
+
const manager = new PolicyManager(url, key);
|
|
249
|
+
await manager.updateAll();
|
|
250
|
+
});
|
|
251
|
+
program.command("health").description("Check policy health").action(async (options) => {
|
|
252
|
+
const url = options.url || process.env.SUPABASE_URL;
|
|
253
|
+
const key = options.key || process.env.SUPABASE_SERVICE_ROLE_KEY;
|
|
254
|
+
const manager = new PolicyManager(url, key);
|
|
255
|
+
await manager.checkHealth();
|
|
256
|
+
});
|
|
257
|
+
program.command("audit").description("Show policy audit log").option("-l, --limit <number>", "Number of entries to show", "20").action(async (options) => {
|
|
258
|
+
const url = options.parent?.url || process.env.SUPABASE_URL;
|
|
259
|
+
const key = options.parent?.key || process.env.SUPABASE_SERVICE_ROLE_KEY;
|
|
260
|
+
const manager = new PolicyManager(url, key);
|
|
261
|
+
await manager.showAudit(parseInt(options.limit));
|
|
262
|
+
});
|
|
263
|
+
program.command("test <operation> <pageName> <orgId>").description("Test a permission check").option("-e, --event-id <eventId>", "Event ID").option("-a, --app <appName>", "App name", "CAKE").action(async (operation, pageName, orgId, options) => {
|
|
264
|
+
const url = options.parent?.url || process.env.SUPABASE_URL;
|
|
265
|
+
const key = options.parent?.key || process.env.SUPABASE_SERVICE_ROLE_KEY;
|
|
266
|
+
const manager = new PolicyManager(url, key);
|
|
267
|
+
await manager.testPermission(operation, pageName, orgId, options.eventId, options.app);
|
|
268
|
+
});
|
|
269
|
+
program.parse(process.argv);
|
|
270
|
+
if (!process.env.SUPABASE_URL || !process.env.SUPABASE_SERVICE_ROLE_KEY) {
|
|
271
|
+
console.error(chalk.red("Error: Missing required environment variables"));
|
|
272
|
+
console.error("Please set SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY");
|
|
273
|
+
process.exit(1);
|
|
274
|
+
}
|
|
275
|
+
export {
|
|
276
|
+
PolicyManager
|
|
277
|
+
};
|
|
278
|
+
//# sourceMappingURL=policy-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/rbac/cli/policy-manager.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * RBAC Policy Manager CLI Tool\n * \n * This tool provides command-line interface for managing RBAC-RLS integration policies.\n * It allows developers and administrators to easily manage dynamic permission policies.\n */\n\nimport { createClient } from '@supabase/supabase-js';\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport Table from 'cli-table3';\n\ninterface PolicyConfig {\n table_name: string;\n page_name: string;\n app_name: string;\n organisation_column: string;\n event_column?: string;\n operations: string[];\n is_active: boolean;\n}\n\ninterface PolicyAudit {\n table_name: string;\n policy_name: string;\n operation: string;\n action: string;\n changed_at: string;\n success: boolean;\n error_message?: string;\n}\n\ninterface HealthCheck {\n table_name: string;\n policy_name: string;\n operation: string;\n is_healthy: boolean;\n issues: string[];\n}\n\nclass PolicyManager {\n private supabase: any;\n\n constructor(url: string, key: string) {\n this.supabase = createClient(url, key);\n }\n\n /**\n * List all registered tables\n */\n async listTables(): Promise<void> {\n const spinner = ora('Fetching registered tables...').start();\n \n try {\n const { data, error } = await this.supabase\n .from('rbac_policy_configs')\n .select('*')\n .eq('is_active', true)\n .order('table_name');\n\n if (error) throw error;\n\n spinner.succeed('Fetched registered tables');\n\n if (data.length === 0) {\n console.log(chalk.yellow('No tables registered for RBAC policy management.'));\n return;\n }\n\n const table = new Table({\n head: ['Table', 'Page', 'App', 'Org Column', 'Event Column', 'Operations'],\n colWidths: [20, 15, 10, 15, 15, 30]\n });\n\n data.forEach((config: PolicyConfig) => {\n table.push([\n config.table_name,\n config.page_name,\n config.app_name,\n config.organisation_column,\n config.event_column || 'N/A',\n config.operations.join(', ')\n ]);\n });\n\n console.log(table.toString());\n } catch (error) {\n spinner.fail('Failed to fetch tables');\n console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));\n }\n }\n\n /**\n * Register a new table for RBAC policy management\n */\n async registerTable(\n tableName: string,\n pageName: string,\n appName: string = 'CAKE',\n orgColumn: string = 'organisation_id',\n eventColumn?: string,\n operations: string[] = ['read', 'create', 'update', 'delete']\n ): Promise<void> {\n const spinner = ora(`Registering table ${tableName}...`).start();\n\n try {\n const { data, error } = await this.supabase\n .rpc('register_rbac_table', {\n p_table_name: tableName,\n p_page_name: pageName,\n p_app_name: appName,\n p_organisation_column: orgColumn,\n p_event_column: eventColumn,\n p_operations: operations\n });\n\n if (error) throw error;\n\n if (data) {\n spinner.succeed(`Successfully registered table ${tableName}`);\n } else {\n spinner.fail(`Failed to register table ${tableName}`);\n }\n } catch (error) {\n spinner.fail(`Failed to register table ${tableName}`);\n console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));\n }\n }\n\n /**\n * Update policies for a specific table\n */\n async updateTable(tableName: string, pageName: string, appName: string = 'CAKE'): Promise<void> {\n const spinner = ora(`Updating policies for ${tableName}...`).start();\n\n try {\n const { data, error } = await this.supabase\n .rpc('update_rbac_policies_for_table', {\n p_table_name: tableName,\n p_page_name: pageName,\n p_app_name: appName\n });\n\n if (error) throw error;\n\n if (data) {\n spinner.succeed(`Successfully updated policies for ${tableName}`);\n } else {\n spinner.fail(`Failed to update policies for ${tableName}`);\n }\n } catch (error) {\n spinner.fail(`Failed to update policies for ${tableName}`);\n console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));\n }\n }\n\n /**\n * Update all RBAC policies\n */\n async updateAll(): Promise<void> {\n const spinner = ora('Updating all RBAC policies...').start();\n\n try {\n const { data, error } = await this.supabase\n .rpc('update_all_rbac_policies');\n\n if (error) throw error;\n\n spinner.succeed('Updated all RBAC policies');\n\n // Display results\n const table = new Table({\n head: ['Table', 'Page', 'App', 'Success', 'Error'],\n colWidths: [20, 15, 10, 10, 30]\n });\n\n data.forEach((result: any) => {\n table.push([\n result.table_name,\n result.page_name,\n result.app_name,\n result.success ? chalk.green('✓') : chalk.red('✗'),\n result.error_message || ''\n ]);\n });\n\n console.log(table.toString());\n } catch (error) {\n spinner.fail('Failed to update all policies');\n console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));\n }\n }\n\n /**\n * Check policy health\n */\n async checkHealth(): Promise<void> {\n const spinner = ora('Checking policy health...').start();\n\n try {\n const { data, error } = await this.supabase\n .rpc('check_rbac_policy_health');\n\n if (error) throw error;\n\n spinner.succeed('Policy health check complete');\n\n if (data.length === 0) {\n console.log(chalk.yellow('No policies found.'));\n return;\n }\n\n const healthyPolicies = data.filter((h: HealthCheck) => h.is_healthy);\n const unhealthyPolicies = data.filter((h: HealthCheck) => !h.is_healthy);\n\n console.log(chalk.green(`✓ ${healthyPolicies.length} healthy policies`));\n console.log(chalk.red(`✗ ${unhealthyPolicies.length} unhealthy policies`));\n\n if (unhealthyPolicies.length > 0) {\n console.log('\\n' + chalk.red('Unhealthy Policies:'));\n const table = new Table({\n head: ['Table', 'Policy', 'Operation', 'Issues'],\n colWidths: [20, 25, 10, 40]\n });\n\n unhealthyPolicies.forEach((policy: HealthCheck) => {\n table.push([\n policy.table_name,\n policy.policy_name,\n policy.operation,\n policy.issues.join(', ')\n ]);\n });\n\n console.log(table.toString());\n }\n } catch (error) {\n spinner.fail('Failed to check policy health');\n console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));\n }\n }\n\n /**\n * Show policy audit log\n */\n async showAudit(limit: number = 20): Promise<void> {\n const spinner = ora('Fetching audit log...').start();\n\n try {\n const { data, error } = await this.supabase\n .from('rbac_policy_audit')\n .select('*')\n .order('changed_at', { ascending: false })\n .limit(limit);\n\n if (error) throw error;\n\n spinner.succeed('Fetched audit log');\n\n if (data.length === 0) {\n console.log(chalk.yellow('No audit entries found.'));\n return;\n }\n\n const table = new Table({\n head: ['Table', 'Policy', 'Operation', 'Action', 'Success', 'Changed At'],\n colWidths: [15, 20, 10, 10, 8, 20]\n });\n\n data.forEach((audit: PolicyAudit) => {\n table.push([\n audit.table_name,\n audit.policy_name,\n audit.operation,\n audit.action,\n audit.success ? chalk.green('✓') : chalk.red('✗'),\n new Date(audit.changed_at).toLocaleString()\n ]);\n });\n\n console.log(table.toString());\n } catch (error) {\n spinner.fail('Failed to fetch audit log');\n console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));\n }\n }\n\n /**\n * Test permission check\n */\n async testPermission(\n operation: string,\n pageName: string,\n orgId: string,\n eventId?: string,\n appName: string = 'CAKE'\n ): Promise<void> {\n const spinner = ora('Testing permission check...').start();\n\n try {\n const { data, error } = await this.supabase\n .rpc('check_rbac_permission_with_context', {\n p_operation: operation,\n p_page_name: pageName,\n p_resource_organisation_id: orgId,\n p_resource_event_id: eventId,\n p_app_name: appName\n });\n\n if (error) throw error;\n\n spinner.succeed('Permission check complete');\n\n const result = data ? chalk.green('ALLOWED') : chalk.red('DENIED');\n console.log(`Permission: ${operation} on ${pageName} = ${result}`);\n } catch (error) {\n spinner.fail('Failed to test permission');\n console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));\n }\n }\n}\n\n// CLI Setup\nconst program = new Command();\n\nprogram\n .name('rbac-policy-manager')\n .description('CLI tool for managing RBAC-RLS integration policies')\n .version('1.0.0');\n\n// Global options\nprogram\n .option('-u, --url <url>', 'Supabase URL', process.env.SUPABASE_URL)\n .option('-k, --key <key>', 'Supabase service key', process.env.SUPABASE_SERVICE_ROLE_KEY)\n .option('--verbose', 'Enable verbose output');\n\n// List tables command\nprogram\n .command('list')\n .description('List all registered tables')\n .action(async (options) => {\n const url = options.parent?.url || process.env.SUPABASE_URL;\n const key = options.parent?.key || process.env.SUPABASE_SERVICE_ROLE_KEY;\n const manager = new PolicyManager(url, key);\n await manager.listTables();\n });\n\n// Register table command\nprogram\n .command('register <tableName> <pageName>')\n .description('Register a table for RBAC policy management')\n .option('-a, --app <appName>', 'App name', 'CAKE')\n .option('-o, --org-column <column>', 'Organisation column name', 'organisation_id')\n .option('-e, --event-column <column>', 'Event column name')\n .option('--operations <operations>', 'Comma-separated operations', 'read,create,update,delete')\n .action(async (tableName, pageName, options) => {\n const operations = options.operations.split(',').map((op: string) => op.trim());\n const url = options.parent?.url || process.env.SUPABASE_URL;\n const key = options.parent?.key || process.env.SUPABASE_SERVICE_ROLE_KEY;\n const manager = new PolicyManager(url, key);\n await manager.registerTable(\n tableName,\n pageName,\n options.app,\n options.orgColumn,\n options.eventColumn,\n operations\n );\n });\n\n// Update table command\nprogram\n .command('update <tableName> <pageName>')\n .description('Update policies for a specific table')\n .option('-a, --app <appName>', 'App name', 'CAKE')\n .action(async (tableName, pageName, options) => {\n const url = options.parent?.url || process.env.SUPABASE_URL;\n const key = options.parent?.key || process.env.SUPABASE_SERVICE_ROLE_KEY;\n const manager = new PolicyManager(url, key);\n await manager.updateTable(tableName, pageName, options.app);\n });\n\n// Update all command\nprogram\n .command('update-all')\n .description('Update all RBAC policies')\n .action(async (options) => {\n const url = options.url || process.env.SUPABASE_URL;\n const key = options.key || process.env.SUPABASE_SERVICE_ROLE_KEY;\n const manager = new PolicyManager(url, key);\n await manager.updateAll();\n });\n\n// Health check command\nprogram\n .command('health')\n .description('Check policy health')\n .action(async (options) => {\n const url = options.url || process.env.SUPABASE_URL;\n const key = options.key || process.env.SUPABASE_SERVICE_ROLE_KEY;\n const manager = new PolicyManager(url, key);\n await manager.checkHealth();\n });\n\n// Audit command\nprogram\n .command('audit')\n .description('Show policy audit log')\n .option('-l, --limit <number>', 'Number of entries to show', '20')\n .action(async (options) => {\n const url = options.parent?.url || process.env.SUPABASE_URL;\n const key = options.parent?.key || process.env.SUPABASE_SERVICE_ROLE_KEY;\n const manager = new PolicyManager(url, key);\n await manager.showAudit(parseInt(options.limit));\n });\n\n// Test permission command\nprogram\n .command('test <operation> <pageName> <orgId>')\n .description('Test a permission check')\n .option('-e, --event-id <eventId>', 'Event ID')\n .option('-a, --app <appName>', 'App name', 'CAKE')\n .action(async (operation, pageName, orgId, options) => {\n const url = options.parent?.url || process.env.SUPABASE_URL;\n const key = options.parent?.key || process.env.SUPABASE_SERVICE_ROLE_KEY;\n const manager = new PolicyManager(url, key);\n await manager.testPermission(operation, pageName, orgId, options.eventId, options.app);\n });\n\n// Parse command line arguments\nprogram.parse(process.argv);\n\n// Handle missing required options\nif (!process.env.SUPABASE_URL || !process.env.SUPABASE_SERVICE_ROLE_KEY) {\n console.error(chalk.red('Error: Missing required environment variables'));\n console.error('Please set SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY');\n process.exit(1);\n}\n\nexport { PolicyManager };\n"],"mappings":"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","names":[]}
|