mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 17:10:56 +00:00
fix: ( bookings ) require explicit tickets:generate to issue reservations
This commit is contained in:
@@ -11,4 +11,18 @@ export const PassengerStaff = (permission: string | string[]) =>
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Like {@link PassengerStaff} but the permission must be explicitly granted —
|
||||
* super admins / org admins get no automatic bypass.
|
||||
*/
|
||||
export const PassengerStaffStrict = (permission: string | string[]) =>
|
||||
applyDecorators(
|
||||
UseGuards(
|
||||
JwtGuard,
|
||||
PassengerPermissionGuard(Array.isArray(permission) ? permission : [permission], {
|
||||
strict: true,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
export const PassengerAdmin = () => PassengerStaff(PASSENGER_PERMS.admin);
|
||||
|
||||
@@ -6,9 +6,25 @@ import {
|
||||
Type,
|
||||
UnauthorizedException,
|
||||
} from '@nestjs/common';
|
||||
import { hasPassengerPermission } from './passenger-permission.util';
|
||||
import {
|
||||
hasPassengerPermission,
|
||||
hasPassengerPermissionStrict,
|
||||
} from './passenger-permission.util';
|
||||
|
||||
export type PassengerPermissionGuardOptions = {
|
||||
/**
|
||||
* When true, super admins and org admins do NOT bypass the check — the
|
||||
* permission key must be explicitly granted to them like anyone else.
|
||||
*/
|
||||
strict?: boolean;
|
||||
};
|
||||
|
||||
export function PassengerPermissionGuard(
|
||||
permissions: string[],
|
||||
options: PassengerPermissionGuardOptions = {},
|
||||
): Type<CanActivate> {
|
||||
const check = options.strict ? hasPassengerPermissionStrict : hasPassengerPermission;
|
||||
|
||||
export function PassengerPermissionGuard(permissions: string[]): Type<CanActivate> {
|
||||
@Injectable()
|
||||
class PassengerPermissionsGuard implements CanActivate {
|
||||
canActivate(context: ExecutionContext): boolean {
|
||||
@@ -18,10 +34,11 @@ export function PassengerPermissionGuard(permissions: string[]): Type<CanActivat
|
||||
if (!permissions?.length) return true;
|
||||
if (!user) throw new UnauthorizedException('Authentication required');
|
||||
|
||||
if (permissions.some((p) => hasPassengerPermission(user, p))) return true;
|
||||
if (permissions.some((p) => check(user, p))) return true;
|
||||
|
||||
throw new ForbiddenException(
|
||||
`Missing permission. Required one of: ${permissions.join(', ')}`,
|
||||
`Missing permission. Required one of: ${permissions.join(', ')}` +
|
||||
(options.strict ? ' (granted explicitly — admin role does not bypass)' : ''),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,20 @@ export function hasPassengerPermission(
|
||||
return collectPermissionKeys(user).includes(permissionKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same check as {@link hasPassengerPermission} but WITHOUT the super-admin /
|
||||
* org-admin bypass — the permission key must be explicitly granted, whether via
|
||||
* a role or an employee position. Use for actions that must stay auditable to a
|
||||
* deliberate grant (e.g. ticket generation, which can waive a fare).
|
||||
*/
|
||||
export function hasPassengerPermissionStrict(
|
||||
user: MeLikeUser | null | undefined,
|
||||
permissionKey: string,
|
||||
): boolean {
|
||||
if (!user) return false;
|
||||
return collectPermissionKeys(user).includes(permissionKey);
|
||||
}
|
||||
|
||||
export function assertPassengerPermission(
|
||||
user: MeLikeUser | null | undefined,
|
||||
permissionKey: string,
|
||||
|
||||
Reference in New Issue
Block a user