@qwickapps/server 1.2.0 → 1.3.0
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/README.md +238 -0
- package/dist/core/control-panel.d.ts +7 -2
- package/dist/core/control-panel.d.ts.map +1 -1
- package/dist/core/control-panel.js +92 -54
- package/dist/core/control-panel.js.map +1 -1
- package/dist/core/gateway.d.ts +159 -79
- package/dist/core/gateway.d.ts.map +1 -1
- package/dist/core/gateway.js +679 -319
- package/dist/core/gateway.js.map +1 -1
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/plugin-registry.d.ts +271 -0
- package/dist/core/plugin-registry.d.ts.map +1 -0
- package/dist/core/plugin-registry.js +326 -0
- package/dist/core/plugin-registry.js.map +1 -0
- package/dist/core/types.d.ts +16 -33
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.d.ts +8 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -7
- package/dist/index.js.map +1 -1
- package/dist/plugins/auth/adapters/auth0-adapter.d.ts +14 -0
- package/dist/plugins/auth/adapters/auth0-adapter.d.ts.map +1 -0
- package/dist/plugins/auth/adapters/auth0-adapter.js +179 -0
- package/dist/plugins/auth/adapters/auth0-adapter.js.map +1 -0
- package/dist/plugins/auth/adapters/basic-adapter.d.ts +13 -0
- package/dist/plugins/auth/adapters/basic-adapter.d.ts.map +1 -0
- package/dist/plugins/auth/adapters/basic-adapter.js +51 -0
- package/dist/plugins/auth/adapters/basic-adapter.js.map +1 -0
- package/dist/plugins/auth/adapters/index.d.ts +9 -0
- package/dist/plugins/auth/adapters/index.d.ts.map +1 -0
- package/dist/plugins/auth/adapters/index.js +9 -0
- package/dist/plugins/auth/adapters/index.js.map +1 -0
- package/dist/plugins/auth/adapters/supabase-adapter.d.ts +13 -0
- package/dist/plugins/auth/adapters/supabase-adapter.d.ts.map +1 -0
- package/dist/plugins/auth/adapters/supabase-adapter.js +109 -0
- package/dist/plugins/auth/adapters/supabase-adapter.js.map +1 -0
- package/dist/plugins/auth/auth-plugin.d.ts +40 -0
- package/dist/plugins/auth/auth-plugin.d.ts.map +1 -0
- package/dist/plugins/auth/auth-plugin.js +255 -0
- package/dist/plugins/auth/auth-plugin.js.map +1 -0
- package/dist/plugins/auth/auth-plugin.test.d.ts +9 -0
- package/dist/plugins/auth/auth-plugin.test.d.ts.map +1 -0
- package/dist/plugins/auth/auth-plugin.test.js +147 -0
- package/dist/plugins/auth/auth-plugin.test.js.map +1 -0
- package/dist/plugins/auth/index.d.ts +12 -0
- package/dist/plugins/auth/index.d.ts.map +1 -0
- package/dist/plugins/auth/index.js +13 -0
- package/dist/plugins/auth/index.js.map +1 -0
- package/dist/plugins/auth/types.d.ts +148 -0
- package/dist/plugins/auth/types.d.ts.map +1 -0
- package/dist/plugins/auth/types.js +14 -0
- package/dist/plugins/auth/types.js.map +1 -0
- package/dist/plugins/bans/bans-plugin.d.ts +59 -0
- package/dist/plugins/bans/bans-plugin.d.ts.map +1 -0
- package/dist/plugins/bans/bans-plugin.js +428 -0
- package/dist/plugins/bans/bans-plugin.js.map +1 -0
- package/dist/plugins/bans/index.d.ts +9 -0
- package/dist/plugins/bans/index.d.ts.map +1 -0
- package/dist/plugins/bans/index.js +10 -0
- package/dist/plugins/bans/index.js.map +1 -0
- package/dist/plugins/bans/stores/index.d.ts +7 -0
- package/dist/plugins/bans/stores/index.d.ts.map +1 -0
- package/dist/plugins/bans/stores/index.js +7 -0
- package/dist/plugins/bans/stores/index.js.map +1 -0
- package/dist/plugins/bans/stores/postgres-store.d.ts +29 -0
- package/dist/plugins/bans/stores/postgres-store.d.ts.map +1 -0
- package/dist/plugins/bans/stores/postgres-store.js +132 -0
- package/dist/plugins/bans/stores/postgres-store.js.map +1 -0
- package/dist/plugins/bans/types.d.ts +128 -0
- package/dist/plugins/bans/types.d.ts.map +1 -0
- package/dist/plugins/bans/types.js +11 -0
- package/dist/plugins/bans/types.js.map +1 -0
- package/dist/plugins/cache-plugin.d.ts +14 -3
- package/dist/plugins/cache-plugin.d.ts.map +1 -1
- package/dist/plugins/cache-plugin.js +27 -7
- package/dist/plugins/cache-plugin.js.map +1 -1
- package/dist/plugins/cache-plugin.test.js +96 -32
- package/dist/plugins/cache-plugin.test.js.map +1 -1
- package/dist/plugins/config-plugin.d.ts +3 -2
- package/dist/plugins/config-plugin.d.ts.map +1 -1
- package/dist/plugins/config-plugin.js +17 -10
- package/dist/plugins/config-plugin.js.map +1 -1
- package/dist/plugins/diagnostics-plugin.d.ts +2 -2
- package/dist/plugins/diagnostics-plugin.d.ts.map +1 -1
- package/dist/plugins/diagnostics-plugin.js +17 -10
- package/dist/plugins/diagnostics-plugin.js.map +1 -1
- package/dist/plugins/entitlements/entitlements-plugin.d.ts +95 -0
- package/dist/plugins/entitlements/entitlements-plugin.d.ts.map +1 -0
- package/dist/plugins/entitlements/entitlements-plugin.js +707 -0
- package/dist/plugins/entitlements/entitlements-plugin.js.map +1 -0
- package/dist/plugins/entitlements/index.d.ts +12 -0
- package/dist/plugins/entitlements/index.d.ts.map +1 -0
- package/dist/plugins/entitlements/index.js +16 -0
- package/dist/plugins/entitlements/index.js.map +1 -0
- package/dist/plugins/entitlements/sources/index.d.ts +9 -0
- package/dist/plugins/entitlements/sources/index.d.ts.map +1 -0
- package/dist/plugins/entitlements/sources/index.js +9 -0
- package/dist/plugins/entitlements/sources/index.js.map +1 -0
- package/dist/plugins/entitlements/sources/postgres-source.d.ts +29 -0
- package/dist/plugins/entitlements/sources/postgres-source.d.ts.map +1 -0
- package/dist/plugins/entitlements/sources/postgres-source.js +169 -0
- package/dist/plugins/entitlements/sources/postgres-source.js.map +1 -0
- package/dist/plugins/entitlements/types.d.ts +232 -0
- package/dist/plugins/entitlements/types.d.ts.map +1 -0
- package/dist/plugins/entitlements/types.js +11 -0
- package/dist/plugins/entitlements/types.js.map +1 -0
- package/dist/plugins/frontend-app-plugin.d.ts +9 -3
- package/dist/plugins/frontend-app-plugin.d.ts.map +1 -1
- package/dist/plugins/frontend-app-plugin.js +14 -9
- package/dist/plugins/frontend-app-plugin.js.map +1 -1
- package/dist/plugins/health-plugin.d.ts +5 -2
- package/dist/plugins/health-plugin.d.ts.map +1 -1
- package/dist/plugins/health-plugin.js +20 -5
- package/dist/plugins/health-plugin.js.map +1 -1
- package/dist/plugins/index.d.ts +8 -2
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +8 -2
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/logs-plugin.d.ts +3 -2
- package/dist/plugins/logs-plugin.d.ts.map +1 -1
- package/dist/plugins/logs-plugin.js +21 -12
- package/dist/plugins/logs-plugin.js.map +1 -1
- package/dist/plugins/postgres-plugin.d.ts +3 -3
- package/dist/plugins/postgres-plugin.d.ts.map +1 -1
- package/dist/plugins/postgres-plugin.js +9 -7
- package/dist/plugins/postgres-plugin.js.map +1 -1
- package/dist/plugins/postgres-plugin.test.js +47 -29
- package/dist/plugins/postgres-plugin.test.js.map +1 -1
- package/dist/plugins/users/index.d.ts +12 -0
- package/dist/plugins/users/index.d.ts.map +1 -0
- package/dist/plugins/users/index.js +13 -0
- package/dist/plugins/users/index.js.map +1 -0
- package/dist/plugins/users/stores/index.d.ts +7 -0
- package/dist/plugins/users/stores/index.d.ts.map +1 -0
- package/dist/plugins/users/stores/index.js +7 -0
- package/dist/plugins/users/stores/index.js.map +1 -0
- package/dist/plugins/users/stores/postgres-store.d.ts +28 -0
- package/dist/plugins/users/stores/postgres-store.d.ts.map +1 -0
- package/dist/plugins/users/stores/postgres-store.js +157 -0
- package/dist/plugins/users/stores/postgres-store.js.map +1 -0
- package/dist/plugins/users/types.d.ts +189 -0
- package/dist/plugins/users/types.d.ts.map +1 -0
- package/dist/plugins/users/types.js +12 -0
- package/dist/plugins/users/types.js.map +1 -0
- package/dist/plugins/users/users-plugin.d.ts +39 -0
- package/dist/plugins/users/users-plugin.d.ts.map +1 -0
- package/dist/plugins/users/users-plugin.js +242 -0
- package/dist/plugins/users/users-plugin.js.map +1 -0
- package/dist-ui/assets/index-Bsp2ntcw.js +465 -0
- package/dist-ui/assets/index-Bsp2ntcw.js.map +1 -0
- package/dist-ui/index.html +1 -1
- package/dist-ui-lib/api/controlPanelApi.d.ts +232 -0
- package/dist-ui-lib/components/ControlPanelApp.d.ts +61 -0
- package/dist-ui-lib/components/index.d.ts +18 -0
- package/dist-ui-lib/config/AppConfig.d.ts +7 -0
- package/dist-ui-lib/dashboard/DashboardWidgetRegistry.d.ts +62 -0
- package/dist-ui-lib/dashboard/DashboardWidgetRenderer.d.ts +8 -0
- package/dist-ui-lib/dashboard/PluginWidgetRenderer.d.ts +19 -0
- package/dist-ui-lib/dashboard/WidgetComponentRegistry.d.ts +44 -0
- package/dist-ui-lib/dashboard/builtInWidgets.d.ts +19 -0
- package/dist-ui-lib/dashboard/index.d.ts +13 -0
- package/dist-ui-lib/dashboard/widgets/ServiceHealthWidget.d.ts +12 -0
- package/dist-ui-lib/dashboard/widgets/index.d.ts +6 -0
- package/dist-ui-lib/index.js +6441 -0
- package/dist-ui-lib/index.js.map +1 -0
- package/dist-ui-lib/pages/ConfigPage.d.ts +1 -0
- package/dist-ui-lib/pages/DashboardPage.d.ts +1 -0
- package/dist-ui-lib/pages/DiagnosticsPage.d.ts +1 -0
- package/dist-ui-lib/pages/EntitlementsPage.d.ts +17 -0
- package/dist-ui-lib/pages/LogsPage.d.ts +1 -0
- package/dist-ui-lib/pages/NotFoundPage.d.ts +1 -0
- package/dist-ui-lib/pages/PluginPage.d.ts +15 -0
- package/dist-ui-lib/pages/SystemPage.d.ts +1 -0
- package/dist-ui-lib/pages/UsersPage.d.ts +22 -0
- package/package.json +18 -6
- package/src/core/control-panel.ts +114 -61
- package/src/core/gateway.ts +863 -403
- package/src/core/index.ts +21 -2
- package/src/core/plugin-registry.ts +653 -0
- package/src/core/types.ts +31 -37
- package/src/index.ts +118 -19
- package/src/plugins/auth/adapters/auth0-adapter.ts +214 -0
- package/src/plugins/auth/adapters/basic-adapter.ts +61 -0
- package/src/plugins/auth/adapters/index.ts +9 -0
- package/src/plugins/auth/adapters/supabase-adapter.ts +141 -0
- package/src/plugins/auth/auth-plugin.test.ts +176 -0
- package/src/plugins/auth/auth-plugin.ts +303 -0
- package/src/plugins/auth/index.ts +33 -0
- package/src/plugins/auth/types.ts +165 -0
- package/src/plugins/bans/bans-plugin.ts +485 -0
- package/src/plugins/bans/index.ts +31 -0
- package/src/plugins/bans/stores/index.ts +7 -0
- package/src/plugins/bans/stores/postgres-store.ts +195 -0
- package/src/plugins/bans/types.ts +141 -0
- package/src/plugins/cache-plugin.test.ts +105 -32
- package/src/plugins/cache-plugin.ts +40 -9
- package/src/plugins/config-plugin.ts +23 -12
- package/src/plugins/diagnostics-plugin.ts +22 -12
- package/src/plugins/entitlements/entitlements-plugin.ts +820 -0
- package/src/plugins/entitlements/index.ts +51 -0
- package/src/plugins/entitlements/sources/index.ts +9 -0
- package/src/plugins/entitlements/sources/postgres-source.ts +253 -0
- package/src/plugins/entitlements/types.ts +256 -0
- package/src/plugins/frontend-app-plugin.ts +24 -12
- package/src/plugins/health-plugin.ts +27 -7
- package/src/plugins/index.ts +106 -4
- package/src/plugins/logs-plugin.ts +28 -14
- package/src/plugins/postgres-plugin.test.ts +49 -29
- package/src/plugins/postgres-plugin.ts +11 -9
- package/src/plugins/users/index.ts +35 -0
- package/src/plugins/users/stores/index.ts +7 -0
- package/src/plugins/users/stores/postgres-store.ts +225 -0
- package/src/plugins/users/types.ts +209 -0
- package/src/plugins/users/users-plugin.ts +281 -0
- package/ui/src/App.tsx +185 -31
- package/ui/src/api/controlPanelApi.ts +354 -1
- package/ui/src/components/ControlPanelApp.tsx +209 -0
- package/ui/src/components/index.ts +62 -0
- package/ui/src/dashboard/DashboardWidgetRegistry.tsx +129 -0
- package/ui/src/dashboard/DashboardWidgetRenderer.tsx +34 -0
- package/ui/src/dashboard/PluginWidgetRenderer.tsx +115 -0
- package/ui/src/dashboard/WidgetComponentRegistry.tsx +116 -0
- package/ui/src/dashboard/builtInWidgets.tsx +29 -0
- package/ui/src/dashboard/index.ts +35 -0
- package/ui/src/dashboard/widgets/ServiceHealthWidget.tsx +140 -0
- package/ui/src/dashboard/widgets/index.ts +7 -0
- package/ui/src/pages/DashboardPage.tsx +28 -149
- package/ui/src/pages/EntitlementsPage.tsx +557 -0
- package/ui/src/pages/LogsPage.tsx +174 -8
- package/ui/src/pages/PluginPage.tsx +148 -0
- package/ui/src/pages/SystemPage.tsx +445 -0
- package/ui/src/pages/UsersPage.tsx +837 -0
- package/ui/tsconfig.lib.json +11 -0
- package/ui/vite.lib.config.ts +51 -0
- package/dist-ui/assets/index-CW1BviRn.js +0 -465
- package/dist-ui/assets/index-CW1BviRn.js.map +0 -1
- package/ui/src/pages/HealthPage.tsx +0 -204
package/src/core/types.ts
CHANGED
|
@@ -116,6 +116,16 @@ export interface ControlPanelConfig {
|
|
|
116
116
|
/** Product name displayed in the control panel */
|
|
117
117
|
productName: string;
|
|
118
118
|
|
|
119
|
+
/** Optional: Logo name for ProductLogo component (defaults to productName) */
|
|
120
|
+
logoName?: string;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Optional: URL path to the product logo icon (SVG, PNG, etc.).
|
|
124
|
+
* Used by the React UI to display a custom logo instead of the default QwickIcon.
|
|
125
|
+
* Example: '/cpanel/logo.svg'
|
|
126
|
+
*/
|
|
127
|
+
logoIconUrl?: string;
|
|
128
|
+
|
|
119
129
|
/** Port to run the control panel on */
|
|
120
130
|
port: number;
|
|
121
131
|
|
|
@@ -124,7 +134,6 @@ export interface ControlPanelConfig {
|
|
|
124
134
|
|
|
125
135
|
/** Optional: Branding configuration */
|
|
126
136
|
branding?: {
|
|
127
|
-
logo?: string;
|
|
128
137
|
primaryColor?: string;
|
|
129
138
|
favicon?: string;
|
|
130
139
|
};
|
|
@@ -168,40 +177,20 @@ export interface ControlPanelConfig {
|
|
|
168
177
|
customUiPath?: string;
|
|
169
178
|
}
|
|
170
179
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
export interface ControlPanelPlugin {
|
|
186
|
-
/** Unique plugin name */
|
|
187
|
-
name: string;
|
|
188
|
-
|
|
189
|
-
/** Order for tab display (lower = first) */
|
|
190
|
-
order?: number;
|
|
191
|
-
|
|
192
|
-
/** API routes provided by this plugin */
|
|
193
|
-
routes?: Array<{
|
|
194
|
-
method: 'get' | 'post' | 'put' | 'delete';
|
|
195
|
-
path: string;
|
|
196
|
-
handler: RequestHandler;
|
|
197
|
-
}>;
|
|
198
|
-
|
|
199
|
-
/** Lifecycle: Initialize plugin */
|
|
200
|
-
onInit?: (context: PluginContext) => Promise<void>;
|
|
201
|
-
|
|
202
|
-
/** Lifecycle: Shutdown plugin */
|
|
203
|
-
onShutdown?: () => Promise<void>;
|
|
204
|
-
}
|
|
180
|
+
// Plugin types are now in plugin-registry.ts
|
|
181
|
+
// Re-export for convenience
|
|
182
|
+
export type {
|
|
183
|
+
Plugin,
|
|
184
|
+
PluginConfig,
|
|
185
|
+
PluginInfo,
|
|
186
|
+
PluginEvent,
|
|
187
|
+
PluginEventHandler,
|
|
188
|
+
PluginRegistry,
|
|
189
|
+
MenuContribution,
|
|
190
|
+
PageContribution,
|
|
191
|
+
WidgetContribution,
|
|
192
|
+
RouteDefinition,
|
|
193
|
+
} from './plugin-registry.js';
|
|
205
194
|
|
|
206
195
|
/**
|
|
207
196
|
* Health Check types
|
|
@@ -283,14 +272,17 @@ export interface ControlPanelInstance {
|
|
|
283
272
|
/** Stop the control panel server */
|
|
284
273
|
stop: () => Promise<void>;
|
|
285
274
|
|
|
286
|
-
/**
|
|
287
|
-
|
|
275
|
+
/** Start a plugin with optional configuration */
|
|
276
|
+
startPlugin: (plugin: import('./plugin-registry.js').Plugin, config?: import('./plugin-registry.js').PluginConfig) => Promise<boolean>;
|
|
288
277
|
|
|
289
278
|
/** Get health check results */
|
|
290
279
|
getHealthStatus: () => Record<string, HealthCheckResult>;
|
|
291
280
|
|
|
292
281
|
/** Get diagnostics for AI agents */
|
|
293
282
|
getDiagnostics: () => DiagnosticsReport;
|
|
283
|
+
|
|
284
|
+
/** Get the plugin registry for direct access */
|
|
285
|
+
getPluginRegistry: () => import('./plugin-registry.js').PluginRegistry;
|
|
294
286
|
}
|
|
295
287
|
|
|
296
288
|
/**
|
|
@@ -300,6 +292,8 @@ export interface DiagnosticsReport {
|
|
|
300
292
|
timestamp: string;
|
|
301
293
|
product: string;
|
|
302
294
|
version?: string;
|
|
295
|
+
/** @qwickapps/server framework version */
|
|
296
|
+
frameworkVersion?: string;
|
|
303
297
|
uptime: number;
|
|
304
298
|
health: Record<string, HealthCheckResult>;
|
|
305
299
|
system: {
|
package/src/index.ts
CHANGED
|
@@ -9,15 +9,33 @@
|
|
|
9
9
|
|
|
10
10
|
// Core exports
|
|
11
11
|
export { createControlPanel } from './core/control-panel.js';
|
|
12
|
+
export type { CreateControlPanelOptions } from './core/control-panel.js';
|
|
12
13
|
export { createGateway } from './core/gateway.js';
|
|
13
14
|
export { HealthManager } from './core/health-manager.js';
|
|
14
15
|
|
|
15
|
-
//
|
|
16
|
+
// Plugin Registry exports (event-driven architecture v2.0)
|
|
16
17
|
export {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
createPluginRegistry,
|
|
19
|
+
getPluginRegistry,
|
|
20
|
+
hasPluginRegistry,
|
|
21
|
+
resetPluginRegistry,
|
|
22
|
+
PluginRegistryImpl,
|
|
23
|
+
} from './core/plugin-registry.js';
|
|
24
|
+
export type {
|
|
25
|
+
Plugin,
|
|
26
|
+
PluginConfig,
|
|
27
|
+
PluginEvent,
|
|
28
|
+
PluginEventHandler,
|
|
29
|
+
PluginRegistry,
|
|
30
|
+
PluginInfo,
|
|
31
|
+
MenuContribution,
|
|
32
|
+
PageContribution,
|
|
33
|
+
WidgetContribution,
|
|
34
|
+
RouteDefinition,
|
|
35
|
+
} from './core/plugin-registry.js';
|
|
36
|
+
|
|
37
|
+
// Route guards (for control panel protection)
|
|
38
|
+
export { createRouteGuard } from './core/guards.js';
|
|
21
39
|
|
|
22
40
|
// Logging exports
|
|
23
41
|
export {
|
|
@@ -29,9 +47,7 @@ export type { LoggingConfig } from './core/logging.js';
|
|
|
29
47
|
|
|
30
48
|
export type {
|
|
31
49
|
ControlPanelConfig,
|
|
32
|
-
ControlPanelPlugin,
|
|
33
50
|
ControlPanelInstance,
|
|
34
|
-
PluginContext,
|
|
35
51
|
HealthCheck,
|
|
36
52
|
HealthCheckType,
|
|
37
53
|
HealthCheckResult,
|
|
@@ -40,7 +56,7 @@ export type {
|
|
|
40
56
|
ConfigDisplayOptions,
|
|
41
57
|
Logger,
|
|
42
58
|
DiagnosticsReport,
|
|
43
|
-
//
|
|
59
|
+
// Route guard types
|
|
44
60
|
RouteGuardType,
|
|
45
61
|
RouteGuardConfig,
|
|
46
62
|
BasicAuthGuardConfig,
|
|
@@ -53,7 +69,7 @@ export type {
|
|
|
53
69
|
export type {
|
|
54
70
|
GatewayConfig,
|
|
55
71
|
GatewayInstance,
|
|
56
|
-
|
|
72
|
+
MountedAppConfig,
|
|
57
73
|
} from './core/gateway.js';
|
|
58
74
|
|
|
59
75
|
// Built-in plugins
|
|
@@ -63,18 +79,64 @@ export {
|
|
|
63
79
|
createConfigPlugin,
|
|
64
80
|
createDiagnosticsPlugin,
|
|
65
81
|
createFrontendAppPlugin,
|
|
66
|
-
//
|
|
82
|
+
// Postgres plugin
|
|
67
83
|
createPostgresPlugin,
|
|
68
84
|
getPostgres,
|
|
69
85
|
hasPostgres,
|
|
70
|
-
//
|
|
71
|
-
createPostgresPlugin as createDatabasePlugin,
|
|
72
|
-
getPostgres as getDatabase,
|
|
73
|
-
hasPostgres as hasDatabase,
|
|
74
|
-
// Cache plugins
|
|
86
|
+
// Cache plugin
|
|
75
87
|
createCachePlugin,
|
|
76
88
|
getCache,
|
|
77
89
|
hasCache,
|
|
90
|
+
// Auth plugin
|
|
91
|
+
createAuthPlugin,
|
|
92
|
+
isAuthenticated,
|
|
93
|
+
getAuthenticatedUser,
|
|
94
|
+
getAccessToken,
|
|
95
|
+
requireAuth,
|
|
96
|
+
requireRoles,
|
|
97
|
+
requireAnyRole,
|
|
98
|
+
auth0Adapter,
|
|
99
|
+
basicAdapter,
|
|
100
|
+
supabaseAdapter,
|
|
101
|
+
isAuthenticatedRequest,
|
|
102
|
+
// Users plugin
|
|
103
|
+
createUsersPlugin,
|
|
104
|
+
getUserStore,
|
|
105
|
+
getUserById,
|
|
106
|
+
getUserByEmail,
|
|
107
|
+
findOrCreateUser,
|
|
108
|
+
postgresUserStore,
|
|
109
|
+
// Bans plugin (separate from Users, depends on Users)
|
|
110
|
+
createBansPlugin,
|
|
111
|
+
getBanStore,
|
|
112
|
+
isUserBanned,
|
|
113
|
+
isEmailBanned,
|
|
114
|
+
getActiveBan,
|
|
115
|
+
banUser,
|
|
116
|
+
unbanUser,
|
|
117
|
+
listActiveBans,
|
|
118
|
+
postgresBanStore,
|
|
119
|
+
// Entitlements plugin
|
|
120
|
+
createEntitlementsPlugin,
|
|
121
|
+
getEntitlementSource,
|
|
122
|
+
isSourceReadonly,
|
|
123
|
+
getEntitlements,
|
|
124
|
+
refreshEntitlements,
|
|
125
|
+
hasEntitlement,
|
|
126
|
+
hasAnyEntitlement,
|
|
127
|
+
hasAllEntitlements,
|
|
128
|
+
grantEntitlement,
|
|
129
|
+
revokeEntitlement,
|
|
130
|
+
setEntitlements,
|
|
131
|
+
getAvailableEntitlements,
|
|
132
|
+
getEntitlementStats,
|
|
133
|
+
invalidateEntitlementCache,
|
|
134
|
+
storeExternalIdMapping,
|
|
135
|
+
invalidateByExternalId,
|
|
136
|
+
requireEntitlement,
|
|
137
|
+
requireAnyEntitlement,
|
|
138
|
+
requireAllEntitlements,
|
|
139
|
+
postgresEntitlementSource,
|
|
78
140
|
} from './plugins/index.js';
|
|
79
141
|
export type {
|
|
80
142
|
HealthPluginConfig,
|
|
@@ -82,14 +144,51 @@ export type {
|
|
|
82
144
|
ConfigPluginConfig,
|
|
83
145
|
DiagnosticsPluginConfig,
|
|
84
146
|
FrontendAppPluginConfig,
|
|
85
|
-
//
|
|
147
|
+
// Postgres plugin types
|
|
86
148
|
PostgresPluginConfig,
|
|
87
149
|
PostgresInstance,
|
|
88
150
|
TransactionCallback,
|
|
89
|
-
// Backward compatibility aliases (deprecated)
|
|
90
|
-
PostgresPluginConfig as DatabasePluginConfig,
|
|
91
|
-
PostgresInstance as DatabaseInstance,
|
|
92
151
|
// Cache plugin types
|
|
93
152
|
CachePluginConfig,
|
|
94
153
|
CacheInstance,
|
|
154
|
+
// Auth plugin types
|
|
155
|
+
AuthPluginConfig,
|
|
156
|
+
AuthAdapter,
|
|
157
|
+
AuthenticatedUser,
|
|
158
|
+
AuthenticatedRequest,
|
|
159
|
+
Auth0AdapterConfig,
|
|
160
|
+
SupabaseAdapterConfig,
|
|
161
|
+
BasicAdapterConfig,
|
|
162
|
+
// Users plugin types
|
|
163
|
+
UsersPluginConfig,
|
|
164
|
+
UserStore,
|
|
165
|
+
User,
|
|
166
|
+
CreateUserInput,
|
|
167
|
+
UpdateUserInput,
|
|
168
|
+
UserSearchParams,
|
|
169
|
+
UserListResponse,
|
|
170
|
+
PostgresUserStoreConfig,
|
|
171
|
+
UserSyncConfig,
|
|
172
|
+
UsersApiConfig,
|
|
173
|
+
UsersUiConfig,
|
|
174
|
+
// Bans plugin types
|
|
175
|
+
BansPluginConfig,
|
|
176
|
+
BanStore,
|
|
177
|
+
Ban,
|
|
178
|
+
CreateBanInput,
|
|
179
|
+
RemoveBanInput,
|
|
180
|
+
BanCallbacks,
|
|
181
|
+
PostgresBanStoreConfig,
|
|
182
|
+
// Entitlements plugin types
|
|
183
|
+
EntitlementsPluginConfig,
|
|
184
|
+
EntitlementSource,
|
|
185
|
+
EntitlementResult,
|
|
186
|
+
EntitlementDefinition,
|
|
187
|
+
EntitlementCallbacks,
|
|
188
|
+
EntitlementsCacheConfig,
|
|
189
|
+
EntitlementsApiConfig,
|
|
190
|
+
PostgresEntitlementSourceConfig,
|
|
191
|
+
UserEntitlement,
|
|
192
|
+
CachedEntitlements,
|
|
193
|
+
EntitlementStats,
|
|
95
194
|
} from './plugins/index.js';
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth0 Adapter
|
|
3
|
+
*
|
|
4
|
+
* Provides Auth0 authentication using express-openid-connect.
|
|
5
|
+
* Enhanced with RBAC support, domain whitelisting, and token exposure.
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { Request, Response, RequestHandler } from 'express';
|
|
11
|
+
import type { AuthAdapter, AuthenticatedUser, Auth0AdapterConfig } from '../types.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Extract user roles from Auth0 claims
|
|
15
|
+
*/
|
|
16
|
+
function extractUserRoles(req: Request, domain: string): string[] {
|
|
17
|
+
const oidc = (req as any).oidc;
|
|
18
|
+
const user = oidc?.user;
|
|
19
|
+
|
|
20
|
+
if (!user) return [];
|
|
21
|
+
|
|
22
|
+
// Check various common locations for roles
|
|
23
|
+
const roles: string[] = [];
|
|
24
|
+
|
|
25
|
+
// Standard RBAC claim
|
|
26
|
+
if (Array.isArray(user['https://roles'])) {
|
|
27
|
+
roles.push(...user['https://roles']);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Namespaced roles (common pattern)
|
|
31
|
+
const namespace = domain ? `https://${domain}/` : '';
|
|
32
|
+
if (namespace && Array.isArray(user[`${namespace}roles`])) {
|
|
33
|
+
roles.push(...user[`${namespace}roles`]);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Auth0 authorization extension
|
|
37
|
+
if (Array.isArray(user.roles)) {
|
|
38
|
+
roles.push(...user.roles);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Custom claims
|
|
42
|
+
if (Array.isArray(user['custom:roles'])) {
|
|
43
|
+
roles.push(...user['custom:roles']);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return [...new Set(roles)]; // Deduplicate
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Create an Auth0 authentication adapter
|
|
51
|
+
*/
|
|
52
|
+
export function auth0Adapter(config: Auth0AdapterConfig): AuthAdapter {
|
|
53
|
+
let authMiddleware: RequestHandler | null = null;
|
|
54
|
+
let initializationError: Error | null = null;
|
|
55
|
+
|
|
56
|
+
const adapter: AuthAdapter = {
|
|
57
|
+
name: 'auth0',
|
|
58
|
+
|
|
59
|
+
initialize(): RequestHandler {
|
|
60
|
+
// Return a middleware that lazily initializes Auth0
|
|
61
|
+
return async (req: Request, res: Response, next) => {
|
|
62
|
+
// Skip if already initialized with error
|
|
63
|
+
if (initializationError) {
|
|
64
|
+
return res.status(500).json({
|
|
65
|
+
error: 'Auth Configuration Error',
|
|
66
|
+
message: 'Auth0 is not properly configured.',
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Lazy initialize the Auth0 middleware
|
|
71
|
+
if (!authMiddleware) {
|
|
72
|
+
try {
|
|
73
|
+
const { auth } = await import('express-openid-connect');
|
|
74
|
+
|
|
75
|
+
const authConfig: Record<string, unknown> = {
|
|
76
|
+
authRequired: false, // We handle auth requirement ourselves
|
|
77
|
+
auth0Logout: true,
|
|
78
|
+
secret: config.secret,
|
|
79
|
+
baseURL: config.baseUrl,
|
|
80
|
+
clientID: config.clientId,
|
|
81
|
+
issuerBaseURL: `https://${config.domain}`,
|
|
82
|
+
clientSecret: config.clientSecret,
|
|
83
|
+
idpLogout: true,
|
|
84
|
+
routes: {
|
|
85
|
+
login: config.routes?.login || '/login',
|
|
86
|
+
logout: config.routes?.logout || '/logout',
|
|
87
|
+
callback: config.routes?.callback || '/callback',
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// Add audience if specified (for API access tokens)
|
|
92
|
+
if (config.audience) {
|
|
93
|
+
authConfig.authorizationParams = {
|
|
94
|
+
audience: config.audience,
|
|
95
|
+
scope: (config.scopes || ['openid', 'profile', 'email']).join(' '),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Enable access token fetching if needed
|
|
100
|
+
if (config.exposeAccessToken && config.audience) {
|
|
101
|
+
authConfig.afterCallback = (
|
|
102
|
+
_req: Request,
|
|
103
|
+
_res: Response,
|
|
104
|
+
session: Record<string, unknown>
|
|
105
|
+
) => {
|
|
106
|
+
// Access token is automatically stored in session
|
|
107
|
+
return session;
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
authMiddleware = auth(authConfig);
|
|
112
|
+
} catch (error) {
|
|
113
|
+
initializationError =
|
|
114
|
+
error instanceof Error ? error : new Error('Failed to initialize Auth0');
|
|
115
|
+
console.error('[Auth0Adapter] Initialization error:', error);
|
|
116
|
+
return res.status(500).json({
|
|
117
|
+
error: 'Auth Configuration Error',
|
|
118
|
+
message:
|
|
119
|
+
'Auth0 is not properly configured. Install express-openid-connect package.',
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Apply the Auth0 middleware
|
|
125
|
+
authMiddleware!(req, res, next);
|
|
126
|
+
};
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
isAuthenticated(req: Request): boolean {
|
|
130
|
+
const oidc = (req as any).oidc;
|
|
131
|
+
if (!oidc?.isAuthenticated()) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Check domain whitelist if configured
|
|
136
|
+
if (config.allowedDomains && config.allowedDomains.length > 0) {
|
|
137
|
+
const email = oidc.user?.email;
|
|
138
|
+
if (!email) return false;
|
|
139
|
+
|
|
140
|
+
const domain = email.split('@')[1];
|
|
141
|
+
if (!config.allowedDomains.includes(domain) && !config.allowedDomains.includes(`@${domain}`)) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Check role whitelist if configured
|
|
147
|
+
if (config.allowedRoles && config.allowedRoles.length > 0) {
|
|
148
|
+
const userRoles = extractUserRoles(req, config.domain);
|
|
149
|
+
const hasRole = config.allowedRoles.some((role) => userRoles.includes(role));
|
|
150
|
+
if (!hasRole) {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return true;
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
getUser(req: Request): AuthenticatedUser | null {
|
|
159
|
+
const oidc = (req as any).oidc;
|
|
160
|
+
|
|
161
|
+
if (!adapter.isAuthenticated(req)) {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const user = oidc.user;
|
|
166
|
+
if (!user) return null;
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
id: user.sub,
|
|
170
|
+
email: user.email,
|
|
171
|
+
name: user.name || user.nickname,
|
|
172
|
+
picture: user.picture,
|
|
173
|
+
emailVerified: user.email_verified,
|
|
174
|
+
roles: extractUserRoles(req, config.domain),
|
|
175
|
+
raw: user,
|
|
176
|
+
};
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
hasRoles(req: Request, roles: string[]): boolean {
|
|
180
|
+
const userRoles = extractUserRoles(req, config.domain);
|
|
181
|
+
return roles.every((role) => userRoles.includes(role));
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
getAccessToken(req: Request): string | null {
|
|
185
|
+
if (!config.exposeAccessToken) {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const oidc = (req as any).oidc;
|
|
190
|
+
return oidc?.accessToken?.access_token || null;
|
|
191
|
+
},
|
|
192
|
+
|
|
193
|
+
onUnauthorized(req: Request, res: Response): void {
|
|
194
|
+
// Check if it's an API request
|
|
195
|
+
const isApiRequest =
|
|
196
|
+
req.headers.accept?.includes('application/json') || req.path.startsWith('/api/');
|
|
197
|
+
|
|
198
|
+
if (isApiRequest) {
|
|
199
|
+
res.status(401).json({
|
|
200
|
+
error: 'Unauthorized',
|
|
201
|
+
message: 'Authentication required',
|
|
202
|
+
loginUrl: config.routes?.login || '/login',
|
|
203
|
+
});
|
|
204
|
+
} else {
|
|
205
|
+
// Redirect to login for browser requests
|
|
206
|
+
const loginPath = config.routes?.login || '/login';
|
|
207
|
+
const returnTo = encodeURIComponent(req.originalUrl);
|
|
208
|
+
res.redirect(`${loginPath}?returnTo=${returnTo}`);
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
return adapter;
|
|
214
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basic Auth Adapter
|
|
3
|
+
*
|
|
4
|
+
* Provides HTTP Basic authentication for simple use cases.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { Request, Response, RequestHandler } from 'express';
|
|
10
|
+
import type { AuthAdapter, AuthenticatedUser, BasicAdapterConfig } from '../types.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Create a Basic authentication adapter
|
|
14
|
+
*/
|
|
15
|
+
export function basicAdapter(config: BasicAdapterConfig): AuthAdapter {
|
|
16
|
+
const expectedAuth = `Basic ${Buffer.from(`${config.username}:${config.password}`).toString('base64')}`;
|
|
17
|
+
const realm = config.realm || 'Protected';
|
|
18
|
+
|
|
19
|
+
// Create a static user for basic auth
|
|
20
|
+
const staticUser: AuthenticatedUser = {
|
|
21
|
+
id: 'basic-auth-user',
|
|
22
|
+
email: `${config.username}@localhost`,
|
|
23
|
+
name: config.username,
|
|
24
|
+
roles: ['admin'], // Basic auth users typically have full access
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
name: 'basic',
|
|
29
|
+
|
|
30
|
+
initialize(): RequestHandler {
|
|
31
|
+
// Basic auth doesn't need initialization middleware
|
|
32
|
+
// Just return a pass-through middleware
|
|
33
|
+
return (_req, _res, next) => next();
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
isAuthenticated(req: Request): boolean {
|
|
37
|
+
const authHeader = req.headers.authorization;
|
|
38
|
+
return authHeader === expectedAuth;
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
getUser(req: Request): AuthenticatedUser | null {
|
|
42
|
+
if (!this.isAuthenticated(req)) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
return staticUser;
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
hasRoles(_req: Request, roles: string[]): boolean {
|
|
49
|
+
// Basic auth user has 'admin' role
|
|
50
|
+
return roles.every((role) => staticUser.roles?.includes(role));
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
onUnauthorized(_req: Request, res: Response): void {
|
|
54
|
+
res.setHeader('WWW-Authenticate', `Basic realm="${realm}"`);
|
|
55
|
+
res.status(401).json({
|
|
56
|
+
error: 'Unauthorized',
|
|
57
|
+
message: 'Authentication required.',
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|