48 lines
1.1 KiB
TypeScript
48 lines
1.1 KiB
TypeScript
|
|
import { Request, Response, NextFunction } from 'express';
|
||
|
|
|
||
|
|
export type AccessRule = { role: string; product?: string };
|
||
|
|
|
||
|
|
export const STYLES_RULES: AccessRule[] = [
|
||
|
|
{ role: 'admin' },
|
||
|
|
{ role: 'user', product: 'styles' },
|
||
|
|
{ role: 'user', product: 'premium' },
|
||
|
|
];
|
||
|
|
|
||
|
|
export function requireAccess( rules: AccessRule[] )
|
||
|
|
{
|
||
|
|
return ( req: Request, res: Response, next: NextFunction ): void =>
|
||
|
|
{
|
||
|
|
const auth = req.auth;
|
||
|
|
if ( !auth )
|
||
|
|
{
|
||
|
|
if ( req.accepts( 'html' ) )
|
||
|
|
{
|
||
|
|
res.redirect( `https://account.rokojori.com/login?redirect=${encodeURIComponent( req.originalUrl )}` );
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
res.status( 401 ).json( { error: 'Not authenticated' } );
|
||
|
|
}
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( auth.roles.includes( 'superadmin' ) ) { next(); return; }
|
||
|
|
|
||
|
|
const allowed = rules.some( rule =>
|
||
|
|
auth.roles.includes( rule.role ) &&
|
||
|
|
( !rule.product || auth.products.includes( rule.product ) )
|
||
|
|
);
|
||
|
|
|
||
|
|
if ( allowed ) { next(); return; }
|
||
|
|
|
||
|
|
if ( req.accepts( 'html' ) )
|
||
|
|
{
|
||
|
|
res.redirect( '/' );
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
res.status( 403 ).json( { error: 'Forbidden' } );
|
||
|
|
}
|
||
|
|
};
|
||
|
|
}
|