feat(15-02): automatische Standardgruppen-Mitgliedschaft an genau einem Ort
- UserService.create ruft nach der Anlage GroupsService.addUserToDefaultGroup auf (D-11/D-12) — einziger Erzeugungspunkt für Benutzer, erbt LdapService ohne eigene Kopie der Regel - try/catch mit Logger: gescheiterte Gruppenzuordnung bricht weder die Benutzeranlage noch einen LDAP-Sync-Lauf ab (T-15-14) - UserModule importiert GroupsModule, keine Zirkularität - 4 Tests in user.service.spec.ts; ldap.service.ts unverändert
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { UserService } from './user.service';
|
||||
|
||||
/**
|
||||
* UserService.create — Standardgruppen-Mitgliedschaft (D-11/D-12, PERM-06).
|
||||
*
|
||||
* UserService.create ist der einzige Erzeugungspunkt für Benutzer im
|
||||
* Backend (auch LdapService.upsertMappedUser/importUsersByDn rufen
|
||||
* ausschließlich hierüber auf, unverändert in diesem Plan). Diese Tests
|
||||
* decken ausschließlich die neue Standardgruppen-Anbindung ab, mit
|
||||
* gemocktem PrismaService und gemocktem GroupsService.
|
||||
*/
|
||||
describe('UserService.create — Standardgruppen-Mitgliedschaft (D-11/D-12)', () => {
|
||||
let prisma: any;
|
||||
let groupsService: any;
|
||||
let service: UserService;
|
||||
|
||||
const createdUser = { id: 'u1', tenantId: 't1', username: 'alice' };
|
||||
const baseData = {
|
||||
username: 'Alice',
|
||||
email: 'alice@example.com',
|
||||
tenantId: 't1',
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
prisma = {
|
||||
user: {
|
||||
create: vi.fn().mockResolvedValue(createdUser),
|
||||
},
|
||||
};
|
||||
groupsService = {
|
||||
addUserToDefaultGroup: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
service = new UserService(prisma, groupsService);
|
||||
});
|
||||
|
||||
it('ruft nach der Benutzeranlage genau einmal GroupsService.addUserToDefaultGroup mit derselben tenantId und der frisch erzeugten userId auf', async () => {
|
||||
const result = await service.create(baseData);
|
||||
|
||||
expect(result).toEqual(createdUser);
|
||||
expect(groupsService.addUserToDefaultGroup).toHaveBeenCalledTimes(1);
|
||||
expect(groupsService.addUserToDefaultGroup).toHaveBeenCalledWith('t1', 'u1');
|
||||
});
|
||||
|
||||
it('legt den Benutzer bei einem Mandanten ohne markierte Standardgruppe trotzdem an — addUserToDefaultGroup bleibt folgenlos, die Anlage schlägt nicht fehl', async () => {
|
||||
groupsService.addUserToDefaultGroup.mockResolvedValue(undefined);
|
||||
|
||||
const result = await service.create(baseData);
|
||||
|
||||
expect(result).toEqual(createdUser);
|
||||
expect(prisma.user.create).toHaveBeenCalledTimes(1);
|
||||
expect(groupsService.addUserToDefaultGroup).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('gibt den Benutzer trotz werfendem addUserToDefaultGroup zurück — der Fehler wird protokolliert, nicht propagiert', async () => {
|
||||
groupsService.addUserToDefaultGroup.mockRejectedValue(new Error('boom'));
|
||||
|
||||
await expect(service.create(baseData)).resolves.toEqual(createdUser);
|
||||
});
|
||||
|
||||
it('gibt weiterhin den erzeugten Benutzerdatensatz zurück; die Signatur bleibt unverändert', async () => {
|
||||
const result = await service.create(baseData);
|
||||
|
||||
expect(prisma.user.create).toHaveBeenCalledWith({
|
||||
data: expect.objectContaining({
|
||||
username: 'alice',
|
||||
email: 'alice@example.com',
|
||||
tenantId: 't1',
|
||||
}),
|
||||
});
|
||||
expect(result).toHaveProperty('id', 'u1');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user