mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-14 12:30:06 +02:00
Add per-server permissions
This commit is contained in:
@@ -9,8 +9,8 @@ const getUserDetail = async (
|
||||
req: TypedRequest<typeof validation.users.detail>,
|
||||
res: Response
|
||||
) => {
|
||||
const { id } = req.params;
|
||||
const user = await service.users.findById(req.authUser, { id });
|
||||
const { userId } = req.params;
|
||||
const user = await service.users.findById(req.authUser, { id: userId });
|
||||
const success = ApiSuccess.ok({ data: toApiModel.users([user])[0] });
|
||||
return res.status(success.statusCode).json(getSuccessResponse(success));
|
||||
};
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { ServerPermission, ServerPermissionType } from '@prisma/client';
|
||||
import { NextFunction, Request, Response } from 'express';
|
||||
|
||||
export const authenticateServerAdmin = (
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) => {
|
||||
if (!req.params.serverId) {
|
||||
return res.status(403).json({
|
||||
error: {
|
||||
message: 'Server id is required.',
|
||||
path: req.path,
|
||||
},
|
||||
response: 'Error',
|
||||
statusCode: 403,
|
||||
});
|
||||
}
|
||||
|
||||
if (req.authUser.isAdmin || req.authUser.isSuperAdmin) {
|
||||
return next();
|
||||
}
|
||||
|
||||
const permission = req.authUser.serverPermissions.find(
|
||||
(p: ServerPermission) => p.serverId === req.params.serverId
|
||||
)?.type;
|
||||
|
||||
if (permission !== ServerPermissionType.ADMIN) {
|
||||
return res.status(403).json({
|
||||
error: {
|
||||
message: 'This action requires "Admin" server permissions.',
|
||||
path: req.path,
|
||||
},
|
||||
response: 'Error',
|
||||
statusCode: 403,
|
||||
});
|
||||
}
|
||||
|
||||
return next();
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
import { ServerPermission, ServerPermissionType } from '@prisma/client';
|
||||
import { NextFunction, Request, Response } from 'express';
|
||||
|
||||
export const authenticateServerEditor = (
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) => {
|
||||
if (!req.params.serverId) {
|
||||
return res.status(403).json({
|
||||
error: {
|
||||
message: 'Server id is required.',
|
||||
path: req.path,
|
||||
},
|
||||
response: 'Error',
|
||||
statusCode: 403,
|
||||
});
|
||||
}
|
||||
|
||||
if (req.authUser.isAdmin || req.authUser.isSuperAdmin) {
|
||||
return next();
|
||||
}
|
||||
|
||||
const permission = req.authUser.serverPermissions.find(
|
||||
(p: ServerPermission) => p.serverId === req.params.serverId
|
||||
)?.type;
|
||||
|
||||
if (
|
||||
permission !== ServerPermissionType.EDITOR &&
|
||||
permission !== ServerPermissionType.ADMIN
|
||||
) {
|
||||
return res.status(403).json({
|
||||
error: {
|
||||
message: 'This action requires "Editor" server permissions.',
|
||||
path: req.path,
|
||||
},
|
||||
response: 'Error',
|
||||
statusCode: 403,
|
||||
});
|
||||
}
|
||||
|
||||
return next();
|
||||
};
|
||||
@@ -0,0 +1,40 @@
|
||||
import { ServerPermission, ServerPermissionType } from '@prisma/client';
|
||||
import { NextFunction, Request, Response } from 'express';
|
||||
|
||||
export const authenticateServerViewer = (
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) => {
|
||||
if (!req.params.serverId) {
|
||||
return res.status(403).json({
|
||||
error: {
|
||||
message: 'Server id is required.',
|
||||
path: req.path,
|
||||
},
|
||||
response: 'Error',
|
||||
statusCode: 403,
|
||||
});
|
||||
}
|
||||
|
||||
if (req.authUser.isAdmin || req.authUser.isSuperAdmin) {
|
||||
return next();
|
||||
}
|
||||
|
||||
const permission = req.authUser.serverPermissions.find(
|
||||
(p: ServerPermission) => p.serverId === req.params.serverId
|
||||
)?.type;
|
||||
|
||||
if (permission === undefined) {
|
||||
return res.status(403).json({
|
||||
error: {
|
||||
message: 'This action requires "Viewer" server permissions.',
|
||||
path: req.path,
|
||||
},
|
||||
response: 'Error',
|
||||
statusCode: 403,
|
||||
});
|
||||
}
|
||||
|
||||
return next();
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
import { NextFunction, Request, Response } from 'express';
|
||||
|
||||
export const authenticateSuperAdmin = (
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) => {
|
||||
if (!req.authUser.isSuperAdmin) {
|
||||
return res.status(403).json({
|
||||
error: {
|
||||
message: 'This action requires an administrator account.',
|
||||
path: req.path,
|
||||
},
|
||||
response: 'Error',
|
||||
statusCode: 403,
|
||||
});
|
||||
}
|
||||
|
||||
return next();
|
||||
};
|
||||
@@ -1,3 +1,7 @@
|
||||
export * from './error-handler';
|
||||
export * from './authenticate';
|
||||
export * from './authenticate-admin';
|
||||
export * from './authenticate-super-admin';
|
||||
export * from './authenticate-server-admin';
|
||||
export * from './authenticate-server-editor';
|
||||
export * from './authenticate-server-viewer';
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import express, { Router } from 'express';
|
||||
import { controller } from '@controllers/index';
|
||||
import { authenticateAdmin } from '@middleware/authenticate-admin';
|
||||
import { authenticateServerAdmin } from '@middleware/authenticate-server-admin';
|
||||
import { authenticateServerEditor } from '@middleware/authenticate-server-editor';
|
||||
import { authenticateServerViewer } from '@middleware/authenticate-server-viewer';
|
||||
import { service } from '@services/index';
|
||||
import { validateRequest, validation } from '@validations/index';
|
||||
|
||||
@@ -25,7 +28,7 @@ router
|
||||
controller.servers.getServerDetail
|
||||
)
|
||||
.patch(
|
||||
authenticateAdmin,
|
||||
authenticateServerAdmin,
|
||||
validateRequest(validation.servers.update),
|
||||
controller.servers.updateServer
|
||||
)
|
||||
@@ -38,7 +41,7 @@ router
|
||||
router
|
||||
.route('/:serverId/refresh')
|
||||
.get(
|
||||
authenticateAdmin,
|
||||
authenticateServerEditor,
|
||||
validateRequest(validation.servers.refresh),
|
||||
controller.servers.refreshServer
|
||||
);
|
||||
@@ -46,23 +49,23 @@ router
|
||||
router
|
||||
.route('/:serverId/scan')
|
||||
.post(
|
||||
authenticateServerAdmin,
|
||||
validateRequest(validation.servers.scan),
|
||||
authenticateAdmin,
|
||||
controller.servers.quickScanServer
|
||||
);
|
||||
|
||||
router
|
||||
.route('/:serverId/full-scan')
|
||||
.post(
|
||||
authenticateServerAdmin,
|
||||
validateRequest(validation.servers.scan),
|
||||
authenticateAdmin,
|
||||
controller.servers.fullScanServer
|
||||
);
|
||||
|
||||
router
|
||||
.route('/:serverId/url')
|
||||
.post(
|
||||
authenticateAdmin,
|
||||
authenticateServerEditor,
|
||||
validateRequest(validation.servers.createUrl),
|
||||
controller.servers.createServerUrl
|
||||
);
|
||||
@@ -75,7 +78,7 @@ router.param('urlId', async (_req, _res, next, urlId) => {
|
||||
router
|
||||
.route('/:serverId/url/:urlId')
|
||||
.delete(
|
||||
authenticateAdmin,
|
||||
authenticateServerEditor,
|
||||
validateRequest(validation.servers.deleteUrl),
|
||||
controller.servers.deleteServerUrl
|
||||
);
|
||||
@@ -83,6 +86,7 @@ router
|
||||
router
|
||||
.route('/:serverId/url/:urlId/enable')
|
||||
.post(
|
||||
authenticateServerViewer,
|
||||
validateRequest(validation.servers.enableUrl),
|
||||
controller.servers.enableServerUrl
|
||||
);
|
||||
@@ -90,6 +94,7 @@ router
|
||||
router
|
||||
.route('/:serverId/url/:urlId/disable')
|
||||
.post(
|
||||
authenticateServerViewer,
|
||||
validateRequest(validation.servers.disableUrl),
|
||||
controller.servers.disableServerUrl
|
||||
);
|
||||
@@ -102,7 +107,7 @@ router.param('folderId', async (_req, _res, next, folderId) => {
|
||||
router
|
||||
.route('/:serverId/folder/:folderId')
|
||||
.delete(
|
||||
authenticateAdmin,
|
||||
authenticateServerAdmin,
|
||||
validateRequest(validation.servers.deleteFolder),
|
||||
controller.servers.deleteServerFolder
|
||||
);
|
||||
@@ -110,6 +115,7 @@ router
|
||||
router
|
||||
.route('/:serverId/folder/:folderId/enable')
|
||||
.post(
|
||||
authenticateServerAdmin,
|
||||
validateRequest(validation.servers.enableFolder),
|
||||
controller.servers.enableServerFolder
|
||||
);
|
||||
@@ -117,6 +123,7 @@ router
|
||||
router
|
||||
.route('/:serverId/folder/:folderId/disable')
|
||||
.post(
|
||||
authenticateServerAdmin,
|
||||
validateRequest(validation.servers.disableFolder),
|
||||
controller.servers.disableServerFolder
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ const findById = async (user: AuthUser, options: { id: string }) => {
|
||||
}
|
||||
|
||||
const uniqueUser = await prisma.user.findUnique({
|
||||
include: { serverFolderPermissions: true },
|
||||
include: { serverFolderPermissions: true, serverPermissions: true },
|
||||
where: { id },
|
||||
});
|
||||
|
||||
@@ -61,7 +61,7 @@ const createUser = async (
|
||||
const createdUser = await prisma.user.create({
|
||||
data: {
|
||||
deviceId: `${username}_${randomString(10)}`,
|
||||
enabled: false,
|
||||
enabled: true,
|
||||
isAdmin,
|
||||
password: hashedPassword,
|
||||
username,
|
||||
|
||||
Reference in New Issue
Block a user