diff --git a/server/controllers/servers.controller.ts b/server/controllers/servers.controller.ts index e74c0df1f..bd7e6ed9a 100644 --- a/server/controllers/servers.controller.ts +++ b/server/controllers/servers.controller.ts @@ -259,11 +259,90 @@ const disableServerFolder = async ( return res.status(success.statusCode).json(getSuccessResponse(success)); }; +const addServerPermission = async ( + req: TypedRequest, + res: Response +) => { + const { serverId } = req.params; + const { userId, type } = req.body; + + const data = await service.servers.addPermission({ + serverId, + type, + userId, + }); + + const success = ApiSuccess.ok({ data }); + return res.status(success.statusCode).json(getSuccessResponse(success)); +}; + +const deleteServerPermission = async ( + req: TypedRequest, + res: Response +) => { + const { permissionId } = req.params; + + await service.servers.deletePermission({ + id: permissionId, + }); + + const success = ApiSuccess.noContent({ data: null }); + return res.status(success.statusCode).json(getSuccessResponse(success)); +}; + +const updateServerPermission = async ( + req: TypedRequest, + res: Response +) => { + const { permissionId } = req.params; + const { type } = req.body; + + await service.servers.updateServerPermission({ + id: permissionId, + type, + }); + + const success = ApiSuccess.noContent({ data: null }); + return res.status(success.statusCode).json(getSuccessResponse(success)); +}; + +const addServerFolderPermission = async ( + req: TypedRequest, + res: Response +) => { + const { folderId } = req.params; + const { userId } = req.body; + + const data = await service.servers.addFolderPermission({ + serverFolderId: folderId, + userId, + }); + + const success = ApiSuccess.ok({ data }); + return res.status(success.statusCode).json(getSuccessResponse(success)); +}; + +const deleteServerFolderPermission = async ( + req: TypedRequest, + res: Response +) => { + const { permissionId } = req.params; + + await service.servers.deleteFolderPermission({ id: permissionId }); + + const success = ApiSuccess.noContent({ data: null }); + return res.status(success.statusCode).json(getSuccessResponse(success)); +}; + export const serversController = { + addServerFolderPermission, + addServerPermission, createServer, createServerUrl, deleteServer, deleteServerFolder, + deleteServerFolderPermission, + deleteServerPermission, deleteServerUrl, disableServerFolder, disableServerUrl, @@ -275,4 +354,5 @@ export const serversController = { quickScanServer, refreshServer, updateServer, + updateServerPermission, }; diff --git a/server/routes/servers.route.ts b/server/routes/servers.route.ts index 186d8e172..b59110455 100644 --- a/server/routes/servers.route.ts +++ b/server/routes/servers.route.ts @@ -99,6 +99,25 @@ router controller.servers.disableServerUrl ); +router + .route('/:serverId/permissions') + .post( + authenticateServerAdmin, + validateRequest(validation.servers.addServerPermission), + controller.servers.addServerPermission + ); + +router + .route('/:serverId/permissions/:permissionId') + .patch( + authenticateServerAdmin, + validateRequest(validation.servers.updateServerPermission) + ) + .delete( + authenticateServerAdmin, + validateRequest(validation.servers.deleteServerPermission) + ); + router.param('folderId', async (_req, _res, next, folderId) => { await service.servers.findFolderById({ id: folderId }); next(); @@ -127,3 +146,12 @@ router validateRequest(validation.servers.disableFolder), controller.servers.disableServerFolder ); + +router + .route('/:serverId/folder/:folderId/permissions') + .post(authenticateServerAdmin); + +router + .route('/:serverId/folder/:folderId/permissions/:folderPermissionId') + .patch(authenticateServerAdmin) + .delete(authenticateServerAdmin); diff --git a/server/services/servers.service.ts b/server/services/servers.service.ts index 4441744e6..b82613874 100644 --- a/server/services/servers.service.ts +++ b/server/services/servers.service.ts @@ -530,11 +530,87 @@ const disableFolderById = async (options: { id: string }) => { return null; }; +const addPermission = async (options: { + serverId: string; + type: ServerPermissionType; + userId: string; +}) => { + const { serverId, userId, type } = options; + + const user = await prisma.user.findUnique({ + where: { id: userId }, + }); + + if (!user) { + throw ApiError.notFound('User not found.'); + } + + const permission = await prisma.serverPermission.create({ + data: { + serverId, + type, + userId, + }, + }); + + return permission; +}; + +const deletePermission = async (options: { id: string }) => { + await prisma.serverPermission.delete({ + where: { id: options.id }, + }); + + return null; +}; + +const updateServerPermission = async (options: { + id: string; + type: ServerPermissionType; +}) => { + const { type, id } = options; + + const permission = await prisma.serverPermission.update({ + data: { type }, + where: { id }, + }); + + return permission; +}; + +const addFolderPermission = async (options: { + serverFolderId: string; + userId: string; +}) => { + const { serverFolderId, userId } = options; + + const permission = await prisma.serverFolderPermission.create({ + data: { + serverFolderId, + userId, + }, + }); + + return permission; +}; + +const deleteFolderPermission = async (options: { id: string }) => { + await prisma.serverFolderPermission.delete({ + where: { id: options.id }, + }); + + return null; +}; + export const serversService = { + addFolderPermission, + addPermission, create, createUrl, deleteById, deleteFolderById, + deleteFolderPermission, + deletePermission, deleteUrlById, disableFolderById, disableUrlById, @@ -550,4 +626,5 @@ export const serversService = { refresh, remoteServerLogin, update, + updateServerPermission, }; diff --git a/server/validations/servers.validation.ts b/server/validations/servers.validation.ts index 344c65afd..7778cf840 100644 --- a/server/validations/servers.validation.ts +++ b/server/validations/servers.validation.ts @@ -1,4 +1,4 @@ -import { ServerType } from '@prisma/client'; +import { ServerPermissionType, ServerType } from '@prisma/client'; import { z } from 'zod'; import { idValidation } from './shared.validation'; @@ -163,13 +163,76 @@ const disableFolder = { query: z.object({}), }; +const addServerPermission = { + body: z.object({ + type: z.enum([ + ServerPermissionType.ADMIN, + ServerPermissionType.VIEWER, + ServerPermissionType.EDITOR, + ]), + userId: z.string().uuid(), + }), + params: z.object({ + ...idValidation('serverId'), + }), + query: z.object({}), +}; + +const updateServerPermission = { + body: z.object({ + type: z.enum([ + ServerPermissionType.ADMIN, + ServerPermissionType.VIEWER, + ServerPermissionType.EDITOR, + ]), + }), + params: z.object({ + ...idValidation('serverId'), + ...idValidation('permissionId'), + }), + query: z.object({}), +}; + +const deleteServerPermission = { + body: z.object({}), + params: z.object({ + ...idValidation('serverId'), + }), + query: z.object({}), +}; + +const addServerFolderPermission = { + body: z.object({ + userId: z.string().uuid(), + }), + params: z.object({ + ...idValidation('serverId'), + ...idValidation('folderId'), + }), + query: z.object({}), +}; + +const deleteServerFolderPermission = { + body: z.object({}), + params: z.object({ + ...idValidation('serverId'), + ...idValidation('folderId'), + ...idValidation('folderPermissionId'), + }), + query: z.object({}), +}; + export const serversValidation = { + addServerFolderPermission, + addServerPermission, create, createCredential, createUrl, deleteCredential, deleteFolder, deleteServer, + deleteServerFolderPermission, + deleteServerPermission, deleteUrl, detail, disableCredential, @@ -183,4 +246,5 @@ export const serversValidation = { refresh, scan, update, + updateServerPermission, };