qdadm 0.35.0 → 0.36.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/package.json +1 -1
- package/src/debug/AuthCollector.js +26 -0
- package/src/debug/components/panels/AuthPanel.vue +2 -0
- package/src/debug/components/panels/EntitiesPanel.vue +1 -1
- package/src/entity/EntityManager.js +22 -2
- package/src/kernel/Kernel.js +3 -4
- package/src/kernel/KernelContext.js +8 -0
package/package.json
CHANGED
|
@@ -36,6 +36,7 @@ export class AuthCollector extends Collector {
|
|
|
36
36
|
constructor(options = {}) {
|
|
37
37
|
super(options)
|
|
38
38
|
this._authAdapter = null
|
|
39
|
+
this._securityChecker = null
|
|
39
40
|
this._ctx = null
|
|
40
41
|
this._signalCleanups = []
|
|
41
42
|
// Activity tracking for login/logout events
|
|
@@ -58,6 +59,7 @@ export class AuthCollector extends Collector {
|
|
|
58
59
|
// Try alternate locations
|
|
59
60
|
this._authAdapter = ctx.authAdapter
|
|
60
61
|
}
|
|
62
|
+
this._securityChecker = ctx.security
|
|
61
63
|
this._setupSignals()
|
|
62
64
|
}
|
|
63
65
|
|
|
@@ -164,6 +166,7 @@ export class AuthCollector extends Collector {
|
|
|
164
166
|
}
|
|
165
167
|
this._signalCleanups = []
|
|
166
168
|
this._authAdapter = null
|
|
169
|
+
this._securityChecker = null
|
|
167
170
|
this._ctx = null
|
|
168
171
|
}
|
|
169
172
|
|
|
@@ -292,6 +295,29 @@ export class AuthCollector extends Collector {
|
|
|
292
295
|
// Permissions not available
|
|
293
296
|
}
|
|
294
297
|
|
|
298
|
+
// Role hierarchy & permissions (lazy fetch - securityChecker created after module connect)
|
|
299
|
+
try {
|
|
300
|
+
const securityChecker = this._securityChecker || this._ctx?.security
|
|
301
|
+
const hierarchy = securityChecker?.roleHierarchy?.map
|
|
302
|
+
if (hierarchy && Object.keys(hierarchy).length > 0) {
|
|
303
|
+
entries.push({
|
|
304
|
+
type: 'hierarchy',
|
|
305
|
+
label: 'Role Hierarchy',
|
|
306
|
+
data: hierarchy
|
|
307
|
+
})
|
|
308
|
+
}
|
|
309
|
+
const rolePermissions = securityChecker?.rolePermissions
|
|
310
|
+
if (rolePermissions && Object.keys(rolePermissions).length > 0) {
|
|
311
|
+
entries.push({
|
|
312
|
+
type: 'role-permissions',
|
|
313
|
+
label: 'Role Permissions',
|
|
314
|
+
data: rolePermissions
|
|
315
|
+
})
|
|
316
|
+
}
|
|
317
|
+
} catch (e) {
|
|
318
|
+
// Security checker not available
|
|
319
|
+
}
|
|
320
|
+
|
|
295
321
|
// Adapter info
|
|
296
322
|
entries.push({
|
|
297
323
|
type: 'adapter',
|
|
@@ -141,7 +141,7 @@ function getCapabilityLabel(cap) {
|
|
|
141
141
|
<i
|
|
142
142
|
v-if="entity.authSensitive"
|
|
143
143
|
class="pi pi-shield perm-icon-auth-sensitive"
|
|
144
|
-
title="Auth-sensitive
|
|
144
|
+
title="Auth-sensitive"
|
|
145
145
|
/>
|
|
146
146
|
</div>
|
|
147
147
|
<span class="entity-label">{{ entity.label }}</span>
|
|
@@ -59,7 +59,7 @@ export class EntityManager {
|
|
|
59
59
|
localFilterThreshold = null, // Items threshold to switch to local filtering (null = use default)
|
|
60
60
|
readOnly = false, // If true, canCreate/canUpdate/canDelete return false
|
|
61
61
|
warmup = true, // If true, cache is preloaded at boot via DeferredRegistry
|
|
62
|
-
authSensitive
|
|
62
|
+
authSensitive, // If true, auto-invalidate datalayer on auth events (auto-inferred from storage.requiresAuth if not set)
|
|
63
63
|
// Scope control
|
|
64
64
|
scopeWhitelist = null, // Array of scopes/modules that can bypass restrictions
|
|
65
65
|
// Relations
|
|
@@ -86,7 +86,8 @@ export class EntityManager {
|
|
|
86
86
|
this.localFilterThreshold = localFilterThreshold
|
|
87
87
|
this._readOnly = readOnly
|
|
88
88
|
this._warmup = warmup
|
|
89
|
-
|
|
89
|
+
// Auto-infer authSensitive from storage.requiresAuth if not explicitly set
|
|
90
|
+
this._authSensitive = authSensitive ?? this._getStorageRequiresAuth()
|
|
90
91
|
|
|
91
92
|
// Scope control
|
|
92
93
|
this._scopeWhitelist = scopeWhitelist
|
|
@@ -1034,6 +1035,25 @@ export class EntityManager {
|
|
|
1034
1035
|
return caps.supportsTotal ?? false
|
|
1035
1036
|
}
|
|
1036
1037
|
|
|
1038
|
+
/**
|
|
1039
|
+
* Check if storage requires authentication
|
|
1040
|
+
*
|
|
1041
|
+
* Used to auto-infer authSensitive when not explicitly set.
|
|
1042
|
+
* Checks both instance capabilities and static capabilities.
|
|
1043
|
+
*
|
|
1044
|
+
* @returns {boolean} - true if storage requires auth
|
|
1045
|
+
* @private
|
|
1046
|
+
*/
|
|
1047
|
+
_getStorageRequiresAuth() {
|
|
1048
|
+
// Check instance capabilities first (may have dynamic requiresAuth)
|
|
1049
|
+
if (this.storage?.capabilities?.requiresAuth !== undefined) {
|
|
1050
|
+
return this.storage.capabilities.requiresAuth
|
|
1051
|
+
}
|
|
1052
|
+
// Fallback to static capabilities
|
|
1053
|
+
const caps = this.storage?.constructor?.capabilities || {}
|
|
1054
|
+
return caps.requiresAuth ?? false
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1037
1057
|
/**
|
|
1038
1058
|
* Get searchable fields declared by storage adapter
|
|
1039
1059
|
*
|
package/src/kernel/Kernel.js
CHANGED
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
|
|
40
40
|
import { createApp, h } from 'vue'
|
|
41
41
|
import { createPinia } from 'pinia'
|
|
42
|
-
import { createRouter, createWebHistory
|
|
42
|
+
import { createRouter, createWebHistory } from 'vue-router'
|
|
43
43
|
import ToastService from 'primevue/toastservice'
|
|
44
44
|
import ConfirmationService from 'primevue/confirmationservice'
|
|
45
45
|
import Tooltip from 'primevue/tooltip'
|
|
@@ -86,7 +86,6 @@ export class Kernel {
|
|
|
86
86
|
* @param {string} options.homeRoute - Route name for home redirect (or object { name, component })
|
|
87
87
|
* @param {Array} options.coreRoutes - Additional routes as layout children (before module routes)
|
|
88
88
|
* @param {string} options.basePath - Base path for router (e.g., '/dashboard/')
|
|
89
|
-
* @param {boolean} options.hashMode - Use hash-based routing (/#/path) for static hosting
|
|
90
89
|
* @param {object} options.app - App config { name, shortName, version, logo, theme }
|
|
91
90
|
* @param {object} options.features - Feature toggles { auth, poweredBy }
|
|
92
91
|
* @param {object} options.primevue - PrimeVue config { plugin, theme, options }
|
|
@@ -520,7 +519,7 @@ export class Kernel {
|
|
|
520
519
|
* - **Layout-only mode**: Layout at root with all routes as children
|
|
521
520
|
*/
|
|
522
521
|
_createRouter() {
|
|
523
|
-
const { pages, homeRoute, coreRoutes, basePath
|
|
522
|
+
const { pages, homeRoute, coreRoutes, basePath } = this.options
|
|
524
523
|
|
|
525
524
|
// Layout is required (shell is optional)
|
|
526
525
|
if (!pages?.layout) {
|
|
@@ -598,7 +597,7 @@ export class Kernel {
|
|
|
598
597
|
}
|
|
599
598
|
|
|
600
599
|
this.router = createRouter({
|
|
601
|
-
history:
|
|
600
|
+
history: createWebHistory(basePath),
|
|
602
601
|
routes
|
|
603
602
|
})
|
|
604
603
|
}
|
|
@@ -121,6 +121,14 @@ export class KernelContext {
|
|
|
121
121
|
return this._kernel.options?.authAdapter ?? null
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Get security checker (role hierarchy, permissions)
|
|
126
|
+
* @returns {import('../entity/auth/SecurityChecker.js').SecurityChecker|null}
|
|
127
|
+
*/
|
|
128
|
+
get security() {
|
|
129
|
+
return this._kernel.securityChecker
|
|
130
|
+
}
|
|
131
|
+
|
|
124
132
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
125
133
|
// Fluent registration methods (return this for chaining)
|
|
126
134
|
// ─────────────────────────────────────────────────────────────────────────────
|