Skip to content

Commit

Permalink
feat(backend): Add schema types in config.json plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
aXenDeveloper committed Jan 1, 2025
1 parent d3c9a87 commit 463d5a8
Show file tree
Hide file tree
Showing 18 changed files with 141 additions and 105 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"$schema": "https://api.vitnode.com/public/vitnode/plugin.schema.json",
"name": "Welcome",
"description": "Basic plugin with default page.",
"version": "1.0.0",
Expand All @@ -25,7 +26,7 @@
"permissions_admin": [
{
"id": "test",
"permissions": ["test123"]
"permissions": []
}
]
}
4 changes: 2 additions & 2 deletions packages/backend/scripts/update-plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ export const updatePlugins = async ({
await Promise.all(
plugins.map(async (code, index) => {
const pluginPath = join(pluginsPath, code);
const configPath = join(pluginPath, 'metadata.json');
const configPath = join(pluginPath, 'config.json');
if (!existsSync(configPath)) {
return;
}

const config = JSON.parse(
await readFile(join(pluginPath, 'metadata.json'), 'utf8'),
await readFile(join(pluginPath, 'config.json'), 'utf8'),
);

if (config.allow_default) {
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const ABSOLUTE_PATHS = {
plugin: ({ code }: { code: string }) => ({
root: join(internalPaths.plugins, code),
admin: join(internalPaths.plugins, code, 'admin'),
metadata: join(internalPaths.plugins, code, 'metadata.json'),
config: join(internalPaths.plugins, code, 'config.json'),
database: join(internalPaths.plugins, code, 'admin', 'database'),
shared: join(internalPaths.shared, code),
frontend: {
Expand Down
113 changes: 63 additions & 50 deletions packages/backend/src/core/admin/auth/services/nav/nav.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class NavAuthAdminService {

async nav({ user }: { user: User }): Promise<ShowAuthAdminObj['nav']> {
const permissions: {
groups: { id: string; permissions: string[] }[];
groups: { id: string; permissions?: string[] }[];
plugin_code: string;
}[] = await this.userHelper.getUserAdminPermission({
user,
Expand All @@ -35,7 +35,7 @@ export class NavAuthAdminService {

const navFromPlugins = await Promise.all(
adminNavPlugins.map(async ({ code }) => {
const pathConfig = ABSOLUTE_PATHS.plugin({ code }).metadata;
const pathConfig = ABSOLUTE_PATHS.plugin({ code }).config;
if (!existsSync(pathConfig)) {
return {
code,
Expand All @@ -54,9 +54,20 @@ export class NavAuthAdminService {
}),
);

const nav = [...coreNav, ...navFromPlugins].filter(
plugin => plugin.nav.length > 0,
);
const nav: ShowAuthAdminObj['nav'] = [...coreNav, ...navFromPlugins]
.filter(plugin => (plugin.nav ?? []).length > 0)
.map(plugin => ({
...plugin,
nav: (plugin.nav ?? []).map(nav => ({
...nav,
keywords: nav.keywords ?? [],
children: (nav.children ?? []).map(child => ({
...child,
keywords: child.keywords ?? [],
})),
})),
}));

if (permissions.length === 0) return nav;

// Create a map for quick lookup of permissions by plugin code
Expand All @@ -70,60 +81,62 @@ export class NavAuthAdminService {
);

// Map over the filtered plugins to process their nav items
const filterGroups = pluginsInPermissions.map(plugin => {
const pluginPermission = permissionMap.get(plugin.code);
if (!pluginPermission) return plugin;

// Create a map of group IDs to group objects with a Set of permissions
const groupMap = new Map();
pluginPermission.groups.forEach(group => {
groupMap.set(group.id, {
...group,
permissionSet: new Set(group.permissions),
const filterGroups: ShowAuthAdminObj['nav'] = pluginsInPermissions.map(
plugin => {
const pluginPermission = permissionMap.get(plugin.code);
if (!pluginPermission) return plugin;

// Create a map of group IDs to group objects with a Set of permissions
const groupMap = new Map();
pluginPermission.groups.forEach(group => {
groupMap.set(group.id, {
...group,
permissionSet: new Set(group.permissions),
});
});
});

// Filter the nav items based on the permissions
const filteredNav = plugin.nav.filter(navItem => {
return (
groupMap.has(navItem.code) ||
groupMap.has(`can_manage_${navItem.code}`) ||
navItem.code === 'dashboard'
);
});
// Filter the nav items based on the permissions
const filteredNav = (plugin.nav ?? []).filter(navItem => {
return (
groupMap.has(navItem.code) ||
groupMap.has(`can_manage_${navItem.code}`) ||
navItem.code === 'dashboard'
);
});

// Map over filteredNav to process each navItem
const processedNav = filteredNav.map(navItem => {
const group =
groupMap.get(navItem.code) ||
groupMap.get(`can_manage_${navItem.code}`);
// Map over filteredNav to process each navItem
const processedNav = filteredNav.map(navItem => {
const group =
groupMap.get(navItem.code) ||
groupMap.get(`can_manage_${navItem.code}`);

if (!group) {
return { ...navItem, permissions: [] };
}
if (!group) {
return { ...navItem, permissions: [] };
}

// If group.permissions is empty, return navItem as is
if (group.permissions.length === 0) {
return navItem;
}
// If group.permissions is empty, return navItem as is
if (group.permissions.length === 0) {
return navItem;
}

// Filter navItem's children based on group.permissions
const filteredChildren = navItem.children?.filter(child =>
group.permissionSet.has(`can_manage_${group.id}_${child.code}`),
);
// Filter navItem's children based on group.permissions
const filteredChildren = navItem.children?.filter(child =>
group.permissionSet.has(`can_manage_${group.id}_${child.code}`),
);

return {
...navItem,
children: filteredChildren,
};
});

return {
...navItem,
children: filteredChildren,
...plugin,
nav: processedNav,
};
});

return {
...plugin,
nav: processedNav,
};
});
},
);

return filterGroups.filter(plugin => plugin.nav.length > 0);
return filterGroups.filter(plugin => (plugin.nav ?? []).length > 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export class SearchAuthAdminService {
return [nav, ...mappedChildren];
});
})
.filter(nav => nav.keywords.length);
.filter(nav => (nav.keywords ?? []).length);

if (search.length === 0) {
return {
Expand All @@ -54,7 +54,7 @@ export class SearchAuthAdminService {
return {
nav: nav.filter(
nav =>
nav.keywords.some(item =>
(nav.keywords ?? []).some(item =>
search.some(search => item.toLowerCase().includes(search)),
) || search.some(search => nav.code.toLowerCase().includes(search)),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class ShowAdminStaffMembersAdminService {
plugin => {
const pathConfig = ABSOLUTE_PATHS.plugin({
code: plugin.code,
}).metadata;
}).config;
if (!existsSync(pathConfig)) {
return {
plugin_code: plugin.code,
Expand All @@ -50,7 +50,10 @@ export class ShowAdminStaffMembersAdminService {
return {
plugin_code: plugin.code,
plugin: plugin.name,
groups: config.permissions_admin ?? [],
groups: (config.permissions_admin ?? []).map(group => ({
...group,
permissions: group.permissions ?? [],
})),
};
},
);
Expand Down
24 changes: 17 additions & 7 deletions packages/backend/src/core/admin/plugins/nav/helpers.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { Injectable } from '@nestjs/common';
import {
ConfigPlugin,
NavPluginInfoJSONType,
} from 'vitnode-shared/admin/plugin.dto';
import { ItemNavAuthAdminObj } from 'vitnode-shared/admin/auth.dto';
import { ConfigPlugin } from 'vitnode-shared/admin/plugin.dto';

@Injectable()
export class HelpersAdminNavPluginsService {
Expand All @@ -12,10 +10,22 @@ export class HelpersAdminNavPluginsService {
}: {
code: string;
items: ConfigPlugin['nav'];
}): NavPluginInfoJSONType | null {
for (const item of items) {
}):
| (ItemNavAuthAdminObj & {
children?: ItemNavAuthAdminObj[];
parent_code?: string;
})
| null {
for (const item of items ?? []) {
if (item.code === code) {
return item;
return {
...item,
keywords: item.keywords ?? [],
children: (item.children ?? []).map(child => ({
...child,
keywords: child.keywords ?? [],
})),
};
}

if (item.children) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class ChangePositionNavPluginsAdminService extends HelpersAdminNavPlugins
code: string;
items: ConfigPlugin['nav'];
}): ConfigPlugin['nav'] {
return items.filter(item => {
return (items ?? []).filter(item => {
if (item.code === code) {
return false;
}
Expand All @@ -43,7 +43,7 @@ export class ChangePositionNavPluginsAdminService extends HelpersAdminNavPlugins
}): Promise<void> {
const pathConfig = ABSOLUTE_PATHS.plugin({
code: plugin_code,
}).metadata;
}).config;
if (!existsSync(pathConfig)) {
throw new NotFoundException();
}
Expand Down Expand Up @@ -74,7 +74,7 @@ export class ChangePositionNavPluginsAdminService extends HelpersAdminNavPlugins
// Move children to root if itemToMove has children
if (itemToMove.children && itemToMove.children.length > 0) {
config.nav = [
...config.nav,
...(config.nav ?? []),
...itemToMove.children.map(child => ({
...child,
children: [],
Expand All @@ -87,6 +87,7 @@ export class ChangePositionNavPluginsAdminService extends HelpersAdminNavPlugins
parentItem.children.splice(index_to_move, 0, itemToMove);
} else {
// If parent_code is not provided, add the item to the root of the nav array
config.nav = config.nav ?? [];
config.nav.splice(index_to_move, 0, itemToMove);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class CreateNavPluginsAdminService extends HelpersAdminNavPluginsService
}): Promise<ParentNavAuthAdminObj> {
const pathConfig = ABSOLUTE_PATHS.plugin({
code: plugin_code,
}).metadata;
}).config;
if (!existsSync(pathConfig)) {
throw new NotFoundException();
}
Expand All @@ -42,7 +42,7 @@ export class CreateNavPluginsAdminService extends HelpersAdminNavPluginsService

// Update config
if (parent_code) {
const parent = config.nav.find(nav => nav.code === parent_code);
const parent = (config.nav ?? []).find(nav => nav.code === parent_code);

if (!parent) {
throw new NotFoundException('PARENT_NOT_FOUND');
Expand All @@ -55,6 +55,7 @@ export class CreateNavPluginsAdminService extends HelpersAdminNavPluginsService
keywords,
});
} else {
config.nav = config.nav ?? [];
config.nav.push({
code: currentCode,
icon,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ export class DeleteNavPluginsAdminService {
}): Promise<void> {
const pathConfig = ABSOLUTE_PATHS.plugin({
code: plugin_code,
}).metadata;
}).config;
if (!existsSync(pathConfig)) {
throw new NotFoundException();
}
const config: ConfigPlugin = JSON.parse(await readFile(pathConfig, 'utf8'));

// Update config
if (parent_code) {
const parent = config.nav.find(nav => nav.code === parent_code);
const parent = (config.nav ?? []).find(nav => nav.code === parent_code);

if (!parent) {
throw new NotFoundException('PARENT_NOT_FOUND');
Expand All @@ -36,12 +36,12 @@ export class DeleteNavPluginsAdminService {
child => child.code !== code,
);
} else {
const codeExists = config.nav.find(nav => nav.code === code);
const codeExists = (config.nav ?? []).find(nav => nav.code === code);
if (!codeExists) {
throw new NotFoundException();
}

config.nav = config.nav.filter(nav => nav.code !== code);
config.nav = (config.nav ?? []).filter(nav => nav.code !== code);
}

await writeFile(pathConfig, JSON.stringify(config, null, 2));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,22 @@ export class EditNavPluginsAdminService {
}): Promise<ParentNavAuthAdminObj> {
const pathConfig = ABSOLUTE_PATHS.plugin({
code: plugin_code,
}).metadata;
}).config;
if (!existsSync(pathConfig)) {
throw new NotFoundException();
}
const config: ConfigPlugin = JSON.parse(await readFile(pathConfig, 'utf8'));

const currentCode = removeSpecialCharacters(code);
const existsNavCode = config.nav.find(nav => nav.code === currentCode);
const existsNavCode = (config.nav ?? []).find(
nav => nav.code === currentCode,
);
if (existsNavCode && code !== existsNavCode.code) {
throw new ConflictException('CODE_ALREADY_EXISTS');
}

if (parent_code) {
const parent = config.nav.find(nav => nav.code === parent_code);
const parent = (config.nav ?? []).find(nav => nav.code === parent_code);

if (!parent) {
throw new NotFoundException('PARENT_NOT_FOUND');
Expand All @@ -53,7 +55,10 @@ export class EditNavPluginsAdminService {
keywords,
};
} else {
const navIndex = config.nav.findIndex(nav => nav.code === previous_code);
const navIndex = (config.nav ?? []).findIndex(
nav => nav.code === previous_code,
);
config.nav = config.nav ?? [];
config.nav[navIndex] = {
code: currentCode,
icon,
Expand Down
Loading

0 comments on commit 463d5a8

Please sign in to comment.