fix: Access-Token wird bei deaktivierten Usern sofort ungueltig

Bisher griff der isActive-Check nur auf Routen mit @RequirePermission.
Ein deaktivierter User mit gueltigem Token konnte Routen ohne
Permission-Decorator bis zum Token-Ablauf (bis zu 15 Min) weiter
erreichen. JwtAuthGuard prueft jetzt PermissionResolverService.isUserActive
auf jedem authentifizierten Request, ueber denselben 30s-Cache wie die
Permission-Aufloesung, also ohne zusaetzliche DB-Last.
This commit is contained in:
Nick Szaunig committed 2026-08-26 14:17:49 +02:00
1 parent 5a1015c4a0
commit adfbc2ab83
4 files changed
+191 -19

No files matched your search

@@ -93,6 +93,57 @@ describe('PermissionResolverService', () => {
expect(prisma.user.findUnique).toHaveBeenCalledTimes(2);
});
describe('isUserActive', () => {
it('returns true for an active user with an active role', async () => {
prisma.user.findUnique.mockResolvedValue(
activeUserWithPermissions('colonies:read'),
);
await expect(resolver.isUserActive('user-1')).resolves.toBe(true);
});
it('returns false for a deactivated user', async () => {
prisma.user.findUnique.mockResolvedValue({
isActive: false,
role: {
status: 'ACTIVE',
permissions: [{ permission: { key: 'colonies:read' } }],
},
});
await expect(resolver.isUserActive('user-1')).resolves.toBe(false);
});
it('returns false when the role is inactive', async () => {
prisma.user.findUnique.mockResolvedValue({
isActive: true,
role: {
status: 'INACTIVE',
permissions: [{ permission: { key: 'colonies:read' } }],
},
});
await expect(resolver.isUserActive('user-1')).resolves.toBe(false);
});
it('returns false when the user does not exist', async () => {
prisma.user.findUnique.mockResolvedValue(null);
await expect(resolver.isUserActive('missing')).resolves.toBe(false);
});
it('shares the cached entry with getPermissions instead of re-querying', async () => {
prisma.user.findUnique.mockResolvedValue(
activeUserWithPermissions('colonies:read'),
);
await resolver.getPermissions('user-1');
await resolver.isUserActive('user-1');
expect(prisma.user.findUnique).toHaveBeenCalledTimes(1);
});
});
it('re-queries after invalidateAll', async () => {
prisma.user.findUnique.mockResolvedValue(
activeUserWithPermissions('colonies:read'),