berechtigungen

This commit is contained in:
Bastian Wagner
2026-08-03 10:16:42 +02:00
parent 6eeaa3a624
commit 27ab505aba
50 changed files with 1443 additions and 217 deletions

View File

@@ -0,0 +1,108 @@
import { ForbiddenException } from '@nestjs/common';
import { TeamPermissionsService } from './team-permissions.service';
describe('TeamPermissionsService', () => {
const teamRepository = { findOne: jest.fn() };
const teamSettingRepository = {
save: jest.fn((s) => Promise.resolve(s)),
create: jest.fn((s) => s),
};
const access = { assertMember: jest.fn(), assertManager: jest.fn() };
const logger = { info: jest.fn() };
let service: TeamPermissionsService;
beforeEach(() => {
jest.resetAllMocks();
teamSettingRepository.save.mockImplementation((s) => Promise.resolve(s));
teamSettingRepository.create.mockImplementation((s) => s);
service = new TeamPermissionsService(
teamRepository as any,
teamSettingRepository as any,
access as any,
logger as any,
);
});
const teamWithSettings = (overrides: Record<string, string> = {}) => ({
id: 9,
settings: [
{ key: 'transaction_create_min_role', value: overrides.transaction_create_min_role ?? '2' },
{ key: 'transaction_reverse_min_role', value: overrides.transaction_reverse_min_role ?? '2' },
{ key: 'invite_min_role', value: overrides.invite_min_role ?? '3' },
{ key: 'member_manage_min_role', value: overrides.member_manage_min_role ?? '3' },
{ key: 'penalty_manage_min_role', value: overrides.penalty_manage_min_role ?? '3' },
{ key: 'public_access_manage_min_role', value: overrides.public_access_manage_min_role ?? '3' },
],
});
it('requires at least team membership to read permissions', async () => {
access.assertMember.mockRejectedValue(new ForbiddenException());
await expect(service.getPermissions(2, 9)).rejects.toBeInstanceOf(
ForbiddenException,
);
expect(teamRepository.findOne).not.toHaveBeenCalled();
});
it('maps the stored settings to the permissions DTO', async () => {
access.assertMember.mockResolvedValue(undefined);
teamRepository.findOne.mockResolvedValue(teamWithSettings());
await expect(service.getPermissions(2, 9)).resolves.toEqual({
transactionCreateMinRole: 2,
transactionReverseMinRole: 2,
inviteMinRole: 3,
memberManageMinRole: 3,
penaltyManageMinRole: 3,
publicAccessManageMinRole: 3,
});
});
it('falls back to defaults for missing settings', async () => {
access.assertMember.mockResolvedValue(undefined);
teamRepository.findOne.mockResolvedValue({ id: 9, settings: [] });
await expect(service.getPermissions(2, 9)).resolves.toEqual({
transactionCreateMinRole: 2,
transactionReverseMinRole: 2,
inviteMinRole: 3,
memberManageMinRole: 3,
penaltyManageMinRole: 3,
publicAccessManageMinRole: 3,
});
});
it('requires manager rights to update permissions', async () => {
access.assertManager.mockRejectedValue(new ForbiddenException());
await expect(
service.updatePermissions(2, 9, { inviteMinRole: 4 }),
).rejects.toBeInstanceOf(ForbiddenException);
expect(teamSettingRepository.save).not.toHaveBeenCalled();
});
it('updates only the fields present in the DTO and leaves the rest untouched', async () => {
access.assertManager.mockResolvedValue(undefined);
const team = teamWithSettings();
teamRepository.findOne.mockResolvedValue(team);
await service.updatePermissions(2, 9, { inviteMinRole: 4 });
expect(teamSettingRepository.save).toHaveBeenCalledTimes(1);
const saved = teamSettingRepository.save.mock.calls[0][0];
expect(saved).toMatchObject({ key: 'invite_min_role', value: '4' });
expect(logger.info).toHaveBeenCalledWith(
expect.objectContaining({ event: 'team_permissions_update', userId: 2 }),
);
});
it('creates a new setting row if none exists yet for that key', async () => {
access.assertManager.mockResolvedValue(undefined);
teamRepository.findOne.mockResolvedValue({ id: 9, settings: [] });
await service.updatePermissions(2, 9, { memberManageMinRole: 4 });
expect(teamSettingRepository.create).toHaveBeenCalledWith(
expect.objectContaining({ key: 'member_manage_min_role', value: '4' }),
);
expect(teamSettingRepository.save).toHaveBeenCalledTimes(1);
});
});