72 lines
1.9 KiB
TypeScript
72 lines
1.9 KiB
TypeScript
import { Socket } from "socket.io";
|
|
import UserController from "../../../controllers/UserController";
|
|
|
|
type SecureSocket = Socket & {
|
|
data: {
|
|
user?: UserController;
|
|
[key: string]: unknown;
|
|
};
|
|
};
|
|
|
|
export const attachSocketEventPermissions = (
|
|
socket: Socket,
|
|
eventPermissions: Record<string, string[]>,
|
|
): boolean => {
|
|
const user = (socket.data?.user as UserController | undefined) ?? undefined;
|
|
if (!user) return false;
|
|
|
|
socket.use(async (packet, packetNext) => {
|
|
const eventName = packet[0];
|
|
|
|
if (typeof eventName !== "string") return packetNext();
|
|
|
|
const eventRequiredPermissions = eventPermissions[eventName] ?? [];
|
|
if (eventRequiredPermissions.length === 0) return packetNext();
|
|
|
|
const eventChecks = await Promise.all(
|
|
eventRequiredPermissions.map((permission) =>
|
|
user.hasPermission(permission),
|
|
),
|
|
);
|
|
|
|
if (eventChecks.includes(false)) {
|
|
return packetNext(new Error("Forbidden: insufficient permissions"));
|
|
}
|
|
|
|
return packetNext();
|
|
});
|
|
|
|
return true;
|
|
};
|
|
|
|
export const socketAuthMiddleware = (permParams?: {
|
|
permissions?: string[];
|
|
eventPermissions?: Record<string, string[]>;
|
|
}) => {
|
|
return async (socket: SecureSocket, next: (err?: Error) => void) => {
|
|
const user = socket.data.user;
|
|
if (!user) return next(new Error("Unauthorized"));
|
|
|
|
const requiredPermissions = permParams?.permissions ?? [];
|
|
|
|
if (requiredPermissions.length > 0) {
|
|
const permissionChecks = await Promise.all(
|
|
requiredPermissions.map((permission) => user.hasPermission(permission)),
|
|
);
|
|
|
|
if (permissionChecks.includes(false)) {
|
|
return next(new Error("Forbidden: insufficient permissions"));
|
|
}
|
|
}
|
|
|
|
const eventPermissions = permParams?.eventPermissions;
|
|
|
|
if (eventPermissions) {
|
|
const attached = attachSocketEventPermissions(socket, eventPermissions);
|
|
if (!attached) return next(new Error("Unauthorized"));
|
|
}
|
|
|
|
return next();
|
|
};
|
|
};
|