mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-07 04:20:12 +02:00
Add validations, req.authUser
This commit is contained in:
@@ -5,7 +5,7 @@ export const authenticateAdmin = (
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) => {
|
||||
if (!req.auth.isAdmin) {
|
||||
if (!req.authUser.isAdmin) {
|
||||
return res.status(403).json({
|
||||
error: {
|
||||
message: 'This action requires an administrator account.',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
ServerFolderPermissions,
|
||||
ServerPermissions,
|
||||
ServerCredential,
|
||||
ServerFolderPermission,
|
||||
ServerPermission,
|
||||
User,
|
||||
} from '@prisma/client';
|
||||
import { NextFunction, Request, Response } from 'express';
|
||||
@@ -9,8 +10,9 @@ import passport from 'passport';
|
||||
export type AuthUser = User & {
|
||||
flatServerFolderPermissions: string[];
|
||||
flatServerPermissions: string[];
|
||||
serverFolderPermissions: ServerFolderPermissions[];
|
||||
serverPermissions: ServerPermissions[];
|
||||
serverFolderPermissions: ServerFolderPermission[];
|
||||
serverId?: string;
|
||||
serverPermissions: ServerPermission[];
|
||||
};
|
||||
|
||||
export const authenticate = (
|
||||
@@ -46,27 +48,36 @@ export const authenticate = (
|
||||
}
|
||||
|
||||
const flatServerFolderPermissions = user.serverFolderPermissions.map(
|
||||
(permission: ServerFolderPermissions) => permission.serverFolderId
|
||||
(permission: ServerFolderPermission) => permission.serverFolderId
|
||||
);
|
||||
|
||||
const flatServerPermissions = user.serverPermissions.map(
|
||||
(permission: ServerPermissions) => permission.serverId
|
||||
(permission: ServerPermission) => permission.serverId
|
||||
);
|
||||
|
||||
const auth = {
|
||||
const serverCredentials = user.serverCredentials.map(
|
||||
(credential: ServerCredential) => ({
|
||||
id: credential.id,
|
||||
serverId: credential.serverId,
|
||||
})
|
||||
);
|
||||
|
||||
const props = {
|
||||
createdAt: user?.createdAt,
|
||||
enabled: user?.enabled,
|
||||
flatServerFolderPermissions,
|
||||
flatServerPermissions,
|
||||
id: user?.id,
|
||||
isAdmin: user?.isAdmin,
|
||||
server: req.params.serverId,
|
||||
serverCredentials,
|
||||
serverFolderPermissions: user?.serverFolderPermissions,
|
||||
serverPermissions: user?.serverPermissions,
|
||||
updatedAt: user?.updatedAt,
|
||||
username: user?.username,
|
||||
};
|
||||
|
||||
req.auth = auth;
|
||||
req.authUser = props;
|
||||
|
||||
return next();
|
||||
})(req, res, next);
|
||||
|
||||
Vendored
+1
-1
@@ -1,5 +1,5 @@
|
||||
declare namespace Express {
|
||||
export interface Request {
|
||||
auth: any;
|
||||
authUser: any;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { paginationValidation, idValidation } from './shared.validation';
|
||||
|
||||
export const list = {
|
||||
body: z.object({}),
|
||||
params: z.object({}),
|
||||
params: z.object({ ...idValidation('serverId') }),
|
||||
query: z.object({
|
||||
...paginationValidation,
|
||||
serverFolderIds: z.string().min(1),
|
||||
@@ -12,7 +12,7 @@ export const list = {
|
||||
|
||||
export const detail = {
|
||||
body: z.object({}),
|
||||
params: z.object({ ...idValidation }),
|
||||
params: z.object({ ...idValidation('id') }),
|
||||
query: z.object({}),
|
||||
};
|
||||
|
||||
|
||||
@@ -5,23 +5,27 @@ import {
|
||||
orderByValidation,
|
||||
paginationValidation,
|
||||
serverFolderIdValidation,
|
||||
serverUrlIdValidation,
|
||||
} from './shared.validation';
|
||||
|
||||
const list = {
|
||||
body: z.object({}),
|
||||
params: z.object({}),
|
||||
params: z.object({ ...idValidation('serverId') }),
|
||||
query: z.object({
|
||||
...paginationValidation,
|
||||
...serverFolderIdValidation,
|
||||
...orderByValidation,
|
||||
...serverUrlIdValidation,
|
||||
sortBy: z.nativeEnum(AlbumSort),
|
||||
}),
|
||||
};
|
||||
|
||||
const detail = {
|
||||
body: z.object({}),
|
||||
params: z.object(idValidation),
|
||||
query: z.object({}),
|
||||
params: z.object({ ...idValidation('id') }),
|
||||
query: z.object({
|
||||
...serverUrlIdValidation,
|
||||
}),
|
||||
};
|
||||
|
||||
export const albumsValidation = {
|
||||
|
||||
@@ -20,7 +20,7 @@ const list = {
|
||||
|
||||
const detail = {
|
||||
body: z.object({}),
|
||||
params: z.object(idValidation),
|
||||
params: z.object({ ...idValidation('id') }),
|
||||
query: z.object({}),
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const login = {
|
||||
body: z.object({
|
||||
password: z.string(),
|
||||
username: z.string(),
|
||||
}),
|
||||
params: z.object({}),
|
||||
query: z.object({}),
|
||||
};
|
||||
|
||||
const register = {
|
||||
body: z.object({
|
||||
password: z.string().min(6).max(255),
|
||||
username: z.string().min(4).max(26),
|
||||
}),
|
||||
params: z.object({}),
|
||||
query: z.object({}),
|
||||
};
|
||||
|
||||
const refresh = {
|
||||
body: z.object({
|
||||
refreshToken: z.string(),
|
||||
}),
|
||||
params: z.object({}),
|
||||
query: z.object({}),
|
||||
};
|
||||
|
||||
export const authValidation = {
|
||||
login,
|
||||
refresh,
|
||||
register,
|
||||
};
|
||||
@@ -1,4 +1,7 @@
|
||||
import { albumArtistsValidation } from './album-artists.validation';
|
||||
import { albumsValidation } from './albums.validation';
|
||||
import { artistsValidation } from './artists.validation';
|
||||
import { authValidation } from './auth.validation';
|
||||
import { serversValidation } from './servers.validation';
|
||||
import { songsValidation } from './songs.validation';
|
||||
import { usersValidation } from './users.validation';
|
||||
@@ -6,7 +9,10 @@ import { usersValidation } from './users.validation';
|
||||
export { validateRequest, TypedRequest } from './shared.validation';
|
||||
|
||||
export const validation = {
|
||||
albumArtists: albumArtistsValidation,
|
||||
albums: albumsValidation,
|
||||
artists: artistsValidation,
|
||||
auth: authValidation,
|
||||
servers: serversValidation,
|
||||
songs: songsValidation,
|
||||
users: usersValidation,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { idValidation } from './shared.validation';
|
||||
|
||||
const detail = {
|
||||
body: z.object({}),
|
||||
params: z.object(idValidation),
|
||||
params: z.object({ ...idValidation('id') }),
|
||||
query: z.object({}),
|
||||
};
|
||||
|
||||
@@ -27,18 +27,25 @@ const create = {
|
||||
|
||||
const scan = {
|
||||
body: z.object({ serverFolderId: z.string().array().optional() }),
|
||||
params: z.object(idValidation),
|
||||
params: z.object({ ...idValidation('id') }),
|
||||
query: z.object({}),
|
||||
};
|
||||
|
||||
const refresh = {
|
||||
body: z.object({}),
|
||||
params: z.object(idValidation),
|
||||
params: z.object({ ...idValidation('id') }),
|
||||
query: z.object({}),
|
||||
};
|
||||
|
||||
const createCredential = {
|
||||
body: z.object({ credential: z.string() }),
|
||||
params: z.object({ ...idValidation('id') }),
|
||||
query: z.object({}),
|
||||
};
|
||||
|
||||
export const serversValidation = {
|
||||
create,
|
||||
createCredential,
|
||||
detail,
|
||||
refresh,
|
||||
scan,
|
||||
|
||||
@@ -27,6 +27,16 @@ type RequestValidation<TParams, TQuery, TBody> = {
|
||||
type ErrorListItem = {
|
||||
errors: ZodError<any>;
|
||||
type: ValidationType;
|
||||
value: string;
|
||||
};
|
||||
|
||||
const getErrorValue = (object: any, error: ZodError<any>) => {
|
||||
const e = error.errors[0];
|
||||
if (e.code === z.ZodIssueCode.invalid_type) {
|
||||
return e.expected;
|
||||
}
|
||||
|
||||
return object[e.path[0]][e.path[1]];
|
||||
};
|
||||
|
||||
export const validateRequest: <TParams = any, TQuery = any, TBody = any>(
|
||||
@@ -38,29 +48,45 @@ export const validateRequest: <TParams = any, TQuery = any, TBody = any>(
|
||||
if (params) {
|
||||
const parsed = params.safeParse(req.params);
|
||||
if (!parsed.success) {
|
||||
errors.push({ errors: parsed.error, type: ValidationType.PARAMS });
|
||||
errors.push({
|
||||
errors: parsed.error,
|
||||
type: ValidationType.PARAMS,
|
||||
value: getErrorValue(req.params, parsed.error),
|
||||
});
|
||||
}
|
||||
}
|
||||
if (query) {
|
||||
const parsed = query.safeParse(req.query);
|
||||
if (!parsed.success) {
|
||||
errors.push({ errors: parsed.error, type: ValidationType.QUERY });
|
||||
const value = getErrorValue(req.query, parsed.error);
|
||||
errors.push({
|
||||
errors: parsed.error,
|
||||
type: ValidationType.QUERY,
|
||||
value,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (body) {
|
||||
const parsed = body.safeParse(req.body);
|
||||
if (!parsed.success) {
|
||||
errors.push({ errors: parsed.error, type: ValidationType.BODY });
|
||||
errors.push({
|
||||
errors: parsed.error,
|
||||
type: ValidationType.BODY,
|
||||
value: getErrorValue(req.body, parsed.error),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
const message = JSON.stringify(
|
||||
[
|
||||
`(${errors[0].type})`,
|
||||
`[${errors[0].errors.issues[0].path[0]}]`,
|
||||
// `(${errors[0].type})`,
|
||||
`(${errors[0].type}: ${errors[0].errors.issues[0].path[0]})`,
|
||||
errors[0].value && `[${errors[0].value}]`,
|
||||
errors[0].errors.issues[0].message,
|
||||
].join(' ')
|
||||
]
|
||||
.filter((x) => x)
|
||||
.join(' ')
|
||||
);
|
||||
|
||||
throw ApiError.badRequest(message);
|
||||
@@ -87,8 +113,12 @@ export const paginationValidation = {
|
||||
}),
|
||||
};
|
||||
|
||||
export const idValidation = {
|
||||
id: z.string().uuid(),
|
||||
export const serverUrlIdValidation = {
|
||||
serverUrlId: z.optional(z.string().uuid()),
|
||||
};
|
||||
|
||||
export const idValidation = (property: string) => {
|
||||
return { [property]: z.string().uuid() };
|
||||
};
|
||||
|
||||
export const serverFolderIdValidation = {
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
|
||||
const list = {
|
||||
body: z.object({}),
|
||||
params: z.object(idValidation),
|
||||
params: z.object({ ...idValidation('serverId') }),
|
||||
query: z.object({
|
||||
...paginationValidation,
|
||||
...serverFolderIdValidation,
|
||||
|
||||
@@ -3,7 +3,7 @@ import { idValidation } from './shared.validation';
|
||||
|
||||
const detail = {
|
||||
body: z.object({}),
|
||||
params: z.object(idValidation),
|
||||
params: z.object({ ...idValidation('id') }),
|
||||
query: z.object({}),
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user