Initial commit
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
import type { Layout, LayoutItem, LayoutSubItem, Schema } from '@/types/schema';
|
||||
import { resolveObject } from '@/lib/schemaResolver';
|
||||
|
||||
function findFirstSubLink(items: LayoutSubItem[]): string | null {
|
||||
for (const item of items) {
|
||||
if (item.type === 'link') return item.viewName;
|
||||
if (item.type === 'container') {
|
||||
const found = findFirstSubLink(item.items);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function findFirstLinkInLayout(items: LayoutItem[] | Layout): string | null {
|
||||
const list = Array.isArray(items) ? items : items.items;
|
||||
for (const item of list) {
|
||||
if ('link' in item) return item.link.viewName;
|
||||
if ('container' in item) {
|
||||
const found = findFirstSubLink(item.container.items);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export type CanGet = (permissionPrefix: string) => boolean;
|
||||
export type HasPermission = (permission: string) => boolean;
|
||||
|
||||
interface SpecialLinkInfo {
|
||||
visible: boolean;
|
||||
enterprise: boolean;
|
||||
}
|
||||
|
||||
function checkSpecialLink(
|
||||
viewName: string,
|
||||
edition: string,
|
||||
hasPerm?: HasPermission,
|
||||
canGet?: CanGet,
|
||||
): SpecialLinkInfo | null {
|
||||
if (viewName.startsWith('Dashboard/') || viewName === 'CustomComponent/Dashboard') {
|
||||
if (edition === 'oss') return { visible: false, enterprise: true };
|
||||
const hasLiveMetrics = hasPerm ? hasPerm('liveMetrics') : true;
|
||||
const hasTraceGet = canGet ? canGet('sysTrace') : true;
|
||||
return { visible: hasLiveMetrics && hasTraceGet, enterprise: true };
|
||||
}
|
||||
|
||||
if (viewName === 'CustomComponent/LiveDelivery') {
|
||||
const allowed = hasPerm ? hasPerm('liveDeliveryTest') : true;
|
||||
return { visible: allowed, enterprise: false };
|
||||
}
|
||||
|
||||
if (viewName === 'CustomComponent/LiveTracing') {
|
||||
if (edition === 'oss') return { visible: false, enterprise: true };
|
||||
const allowed = hasPerm ? hasPerm('liveTracing') : true;
|
||||
return { visible: allowed, enterprise: true };
|
||||
}
|
||||
|
||||
if (viewName.startsWith('CustomComponent/')) {
|
||||
return { visible: true, enterprise: false };
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function isLinkVisible(
|
||||
schema: Schema,
|
||||
viewName: string,
|
||||
edition: string,
|
||||
canGet: CanGet,
|
||||
hasPerm?: HasPermission,
|
||||
): boolean {
|
||||
const special = checkSpecialLink(viewName, edition, hasPerm, canGet);
|
||||
if (special !== null) return special.visible;
|
||||
|
||||
const obj = schema.objects[viewName];
|
||||
if (!obj) return false;
|
||||
const resolved = resolveObject(schema, viewName);
|
||||
if (!resolved) return false;
|
||||
|
||||
if (!canGet(resolved.permissionPrefix)) return false;
|
||||
|
||||
if (resolved.enterprise && edition === 'oss') return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function isLinkEnterprise(schema: Schema, viewName: string, edition: string): boolean {
|
||||
const special = checkSpecialLink(viewName, edition);
|
||||
if (special !== null) return special.enterprise;
|
||||
|
||||
const obj = schema.objects[viewName];
|
||||
if (!obj) return false;
|
||||
if (obj.type === 'view') {
|
||||
const parent = schema.objects[obj.objectName];
|
||||
return parent?.type !== 'view' && parent?.enterprise === true;
|
||||
}
|
||||
return obj.enterprise === true;
|
||||
}
|
||||
|
||||
function findFirstVisibleSubLink(
|
||||
schema: Schema,
|
||||
items: LayoutSubItem[],
|
||||
edition: string,
|
||||
canGet: CanGet,
|
||||
hasPerm?: HasPermission,
|
||||
): string | null {
|
||||
for (const item of items) {
|
||||
if (item.type === 'link') {
|
||||
if (isLinkVisible(schema, item.viewName, edition, canGet, hasPerm)) return item.viewName;
|
||||
} else if (item.type === 'container') {
|
||||
const found = findFirstVisibleSubLink(schema, item.items, edition, canGet, hasPerm);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function findFirstVisibleLinkInLayout(
|
||||
schema: Schema,
|
||||
layout: Layout,
|
||||
edition: string,
|
||||
canGet: CanGet,
|
||||
hasPerm?: HasPermission,
|
||||
): string | null {
|
||||
for (const item of layout.items) {
|
||||
if ('link' in item) {
|
||||
if (isLinkVisible(schema, item.link.viewName, edition, canGet, hasPerm)) return item.link.viewName;
|
||||
} else if ('container' in item) {
|
||||
const found = findFirstVisibleSubLink(schema, item.container.items, edition, canGet, hasPerm);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function isLinkAccessible(
|
||||
schema: Schema,
|
||||
viewName: string,
|
||||
edition: string,
|
||||
canGet: CanGet,
|
||||
hasPerm?: HasPermission,
|
||||
): boolean {
|
||||
if (!isLinkVisible(schema, viewName, edition, canGet, hasPerm)) return false;
|
||||
if (edition === 'community' && isLinkEnterprise(schema, viewName, edition)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function findFirstAccessibleSubLink(
|
||||
schema: Schema,
|
||||
items: LayoutSubItem[],
|
||||
edition: string,
|
||||
canGet: CanGet,
|
||||
hasPerm?: HasPermission,
|
||||
): string | null {
|
||||
for (const item of items) {
|
||||
if (item.type === 'link') {
|
||||
if (isLinkAccessible(schema, item.viewName, edition, canGet, hasPerm)) return item.viewName;
|
||||
} else if (item.type === 'container') {
|
||||
const found = findFirstAccessibleSubLink(schema, item.items, edition, canGet, hasPerm);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function findFirstAccessibleLinkInLayout(
|
||||
schema: Schema,
|
||||
layout: Layout,
|
||||
edition: string,
|
||||
canGet: CanGet,
|
||||
hasPerm?: HasPermission,
|
||||
): string | null {
|
||||
for (const item of layout.items) {
|
||||
if ('link' in item) {
|
||||
if (isLinkAccessible(schema, item.link.viewName, edition, canGet, hasPerm)) return item.link.viewName;
|
||||
} else if ('container' in item) {
|
||||
const found = findFirstAccessibleSubLink(schema, item.container.items, edition, canGet, hasPerm);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function visibleLayouts(schema: Schema, edition: string, canGet: CanGet, hasPerm?: HasPermission): Layout[] {
|
||||
return schema.layouts.filter(
|
||||
(layout) => findFirstVisibleLinkInLayout(schema, layout, edition, canGet, hasPerm) !== null,
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user