Skip to content

Commit 2c7fa49

Browse files
committed
feat: filter returned fields based on column showIn visibility
1 parent c39ed72 commit 2c7fa49

File tree

1 file changed

+40
-6
lines changed

1 file changed

+40
-6
lines changed

adminforth/modules/restApi.ts

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@ export async function interpretResource(
2929
meta: any,
3030
source: ActionCheckSource,
3131
adminforth: IAdminForth
32-
): Promise<{allowedActions: AllowedActionsResolved}> {
32+
): Promise<{ allowedActions: AllowedActionsResolved; visibleColumns: Record<string, boolean> }> {
3333
if (process.env.HEAVY_DEBUG) {
3434
console.log('🪲Interpreting resource', resource.resourceId, source, 'adminUser', adminUser);
3535
}
36+
3637
const allowedActions = {} as AllowedActionsResolved;
3738

3839
// we need to compute only allowed actions for this source:
@@ -61,8 +62,6 @@ export async function interpretResource(
6162
allowedActions[key] = false;
6263
return;
6364
}
64-
65-
// if callable then call
6665
if (typeof value === 'function') {
6766
allowedActions[key] = await value({ adminUser, resource, meta, source, adminforth });
6867
} else {
@@ -71,7 +70,41 @@ export async function interpretResource(
7170
})
7271
);
7372

74-
return { allowedActions };
73+
const resolveAllowed = async (val: any): Promise<boolean> => {
74+
if (typeof val === 'boolean') return val;
75+
if (typeof val === 'function') {
76+
const r = val({ adminUser, resource, meta, source, adminforth });
77+
return r instanceof Promise ? await r : !!r;
78+
}
79+
return true;
80+
};
81+
82+
const page: 'list' | 'show' | 'edit' = ({
83+
[ActionCheckSource.ListRequest]: 'list',
84+
[ActionCheckSource.ShowRequest]: 'show',
85+
[ActionCheckSource.EditLoadRequest]: 'edit',
86+
} as const)[source] ?? 'show';
87+
88+
const isColumnVisible = async (col: any): Promise<boolean> => {
89+
const si = col.showIn;
90+
if (!si) return true;
91+
92+
if (Array.isArray(si)) {
93+
return si.includes('all') || si.includes(page);
94+
}
95+
96+
if (si[page] !== undefined) return await resolveAllowed(si[page]);
97+
if (si.all !== undefined) return await resolveAllowed(si.all);
98+
return true;
99+
};
100+
101+
const visibleColumnsEntries = await Promise.all(
102+
resource.columns.map(async (col) => [col.name, await isColumnVisible(col)] as const)
103+
);
104+
105+
const visibleColumns = Object.fromEntries(visibleColumnsEntries) as Record<string, boolean>;
106+
107+
return { allowedActions, visibleColumns };
75108
}
76109

77110
export default class AdminForthRestAPI implements IAdminForthRestAPI {
@@ -602,7 +635,7 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI {
602635
meta.pk = body.filters.find((f) => f.field === resource.columns.find((col) => col.primaryKey).name)?.value;
603636
}
604637

605-
const { allowedActions } = await interpretResource(
638+
const { allowedActions, visibleColumns } = await interpretResource(
606639
adminUser,
607640
resource,
608641
meta,
@@ -804,7 +837,8 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI {
804837
// remove all columns which are not defined in resources, or defined but backendOnly
805838
data.data.forEach((item) => {
806839
Object.keys(item).forEach((key) => {
807-
if (!resource.columns.find((col) => col.name === key) || resource.columns.find((col) => col.name === key && col.backendOnly)) {
840+
console.log(visibleColumns?.[key], key);
841+
if (!resource.columns.find((col) => col.name === key) || resource.columns.find((col) => col.name === key && col.backendOnly) || visibleColumns?.[key] === false ) {
808842
delete item[key];
809843
}
810844
})

0 commit comments

Comments
 (0)