Update bface UI and security work

This commit is contained in:
Amer Agovic
2026-05-31 12:30:02 -05:00
parent 6fe23fae86
commit c6f7240912
45 changed files with 4531 additions and 553 deletions
+13 -2
View File
@@ -5,6 +5,7 @@
*/
import { normalizeRightsInput } from '../security/model/rights.js';
import { evaluateAuthRequirements } from '../security/runtime/access-rules.js';
import { getProvider } from './storage.js';
// Menu root structure: Map of root directory IDs to MenuItem instances
@@ -138,6 +139,7 @@ export class MenuItem {
* @param {boolean} [config.is_active=true] - Whether menu item is active/enabled
* @param {string} [config.style='both'] - Display style: 'both', 'label_only', or 'icon_only'
* @param {string} [config.with_permits=''] - Comma-delimited permissions required (e.g., "read,write")
* @param {Object} [config.auth] - Auth visibility requirements
* @param {Object} [config.attrs={}] - Additional attributes
*/
constructor(config = {}) {
@@ -196,6 +198,7 @@ export class MenuItem {
? [...config.tags]
: (typeof config.tags === 'string' ? [config.tags] : []);
this.visible_when_permitted = config.visible_when_permitted || null;
this.auth = config.auth || null;
// Validate style
const validStyles = ['both', 'label_only', 'icon_only'];
@@ -223,7 +226,7 @@ export class MenuItem {
// Copy any other properties
Object.keys(config).forEach(key => {
if (!['id', 'label', 'tag', 'icon', 'invoke', 'invoke_type', 'invoke_target', 'handler', 'items', 'path', 'is_active', 'is_visible', 'style', 'with_permits', 'tags', 'visible_when_permitted', 'attrs'].includes(key)) {
if (!['id', 'label', 'tag', 'icon', 'invoke', 'invoke_type', 'invoke_target', 'handler', 'items', 'path', 'is_active', 'is_visible', 'style', 'with_permits', 'tags', 'visible_when_permitted', 'auth', 'attrs'].includes(key)) {
this[key] = config[key];
}
});
@@ -255,11 +258,12 @@ export class MenuItem {
with_permits: this.with_permits,
tags: [...this.tags],
visible_when_permitted: this.visible_when_permitted ? { ...this.visible_when_permitted } : null,
auth: this.auth ? { ...this.auth } : null,
...this.attrs,
// Include any additional properties
...Object.fromEntries(
Object.entries(this).filter(([key]) =>
!['id', 'label', 'tag', 'icon', 'invoke', 'invoke_type', 'invoke_target', 'items', 'path', 'is_active', 'is_visible', 'style', 'with_permits', 'tags', 'visible_when_permitted', 'attrs'].includes(key)
!['id', 'label', 'tag', 'icon', 'invoke', 'invoke_type', 'invoke_target', 'items', 'path', 'is_active', 'is_visible', 'style', 'with_permits', 'tags', 'visible_when_permitted', 'auth', 'attrs'].includes(key)
)
)
};
@@ -392,6 +396,13 @@ export class MenuItem {
* @returns {boolean}
*/
isPermitted(security = null) {
if (this.auth && typeof this.auth === 'object') {
const authResult = evaluateAuthRequirements(security, this.auth);
if (!authResult.allowed) {
return false;
}
}
const rule = this.getPermissionVisibilityRule();
if (!rule) {
return true;