refactor(quick-260921-bi2): maschinelle Lint-Fixe und toten Code abbauen
- Aufgabe 2: vier sichere Biome-Regeln (useImportType pfadgebunden auf apps/web+packages, noUselessEscapeInRegex, useConst, useExponentiationOperator) sowie fuenf ungesicherte Regeln (useNodejsImportProtocol, useLiteralKeys, useOptionalChain, useTemplate, useParseIntRadix) angewendet und den gesamten Diff von Hand gelesen (ldap.service.ts zeichenweise gegen Gross-/Kleinschreibung der AD-Merkmale, auth.service.ts/jwt.strategy.ts gegen Durchwinken bei fehlender Sitzung geprueft) - noUselessSwitchCase bleibt bewusst stehen (tender-normalizer.service.ts:60, die Fallmarke dokumentiert Absicht) - Toter Code (D-03): fuenf folgenlose Auffangvariablen entfernt, eine nicht benutzte Funktion (forSystemQuery, Pruefskript) entfernt, ein positionsgebundener Dekoratorparameter umbenannt (current-user.decorator.ts), fuenf Symptomfunde entfernt und als Folgeaufgaben zu melden (siehe unten) - Sechs weitere, im Plan nicht namentlich gelistete aber gleich-kategorische Dead-Code-Fundstellen in Testdateien zusaetzlich bereinigt (groups.service.spec.ts, cert-manager.test.tsx, ldap.service.spec.ts, prisma-tenant.extension.spec.ts x3) — noetig, um die vom Plan selbst verlangten Nullstaende bei noUnusedVariables/ noUnusedImports/noUnusedFunctionParameters zu erreichen Dekoratordaten aus apps/api unveraendert (593 Zeilen, sha256 6e1583f1...). Endstand 620 Befunde (541 echt, 79 Test) statt der im Plan geschaetzten 621/542 — eine Differenz von 1, weil das Streichen des Namens aus `catch (e: any)` in calendar.service.ts (Symptom-Fix) den dort ebenfalls gemeldeten noExplicitAny-Befund miteliminiert; das ist eine erwuenschte Nebenwirkung, keine Regression. Fehlerstufe 0, beide Testlaeufe punktgleich gruen (69/1124, 66/459), pnpm type-check 4/4, pnpm lint --force 5/5. Folgeaufgaben aus D-03 (nicht in diesem Vorgang behoben): - force-password-change.interceptor.ts: Freigabeliste prueft nur den Pfad, nicht die HTTP-Methode - change-password/page.tsx: nach erzwungenem Wechsel bleibt die Person auf der Seite stehen (keine Weiterleitung, keine Aktualisierung der Benutzerablage) - VehicleTable.tsx: Loeschschaltflaeche hat keinen Besetztzustand, laesst sich doppelt ausloesen - SplitTab.tsx: downloadAllAsZip erhielt eine ungenutzte Uebersetzungsfunktion, Hinweis auf fest verdrahtete Texte im Zip-Pfad Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPPB4ApQxzSU1rwV2Ffj9J
This commit is contained in:
@@ -84,7 +84,7 @@ describe('LdapConfigService — Bind-Passwort verschluesselt at rest', () => {
|
||||
|
||||
const written = prisma.ldapConfig.create.mock.calls[0][0].data;
|
||||
expect(written.encryptedBindPassword).toBe(
|
||||
'aa11:bb22:' + Buffer.from('geheim').toString('hex'),
|
||||
`aa11:bb22:${Buffer.from('geheim').toString('hex')}`,
|
||||
);
|
||||
expect(JSON.stringify(written)).not.toContain('geheim');
|
||||
// Die alte Klartext-Spalte darf nicht wieder auftauchen.
|
||||
@@ -95,7 +95,7 @@ describe('LdapConfigService — Bind-Passwort verschluesselt at rest', () => {
|
||||
await service.updateConfig('t1', { bindPassword: 'neu' } as any);
|
||||
const first = prisma.ldapConfig.update.mock.calls[0][0].data;
|
||||
expect(first.encryptedBindPassword).toBe(
|
||||
'aa11:bb22:' + Buffer.from('neu').toString('hex'),
|
||||
`aa11:bb22:${Buffer.from('neu').toString('hex')}`,
|
||||
);
|
||||
|
||||
await service.updateConfig('t1', { serverUrl: 'ldap://anders' } as any);
|
||||
@@ -113,7 +113,7 @@ describe('LdapConfigService — Bind-Passwort verschluesselt at rest', () => {
|
||||
it('gibt Aufrufern weiterhin ein entschluesseltes bindPassword', async () => {
|
||||
prisma.ldapConfig.findUnique.mockResolvedValue({
|
||||
...CONFIG_ROW,
|
||||
encryptedBindPassword: 'aa11:bb22:' + Buffer.from('geheim').toString('hex'),
|
||||
encryptedBindPassword: `aa11:bb22:${Buffer.from('geheim').toString('hex')}`,
|
||||
});
|
||||
|
||||
const config: any = await service.getConfig('t1');
|
||||
@@ -156,7 +156,7 @@ describe('LdapConfigService — Bind-Passwort verschluesselt at rest', () => {
|
||||
{
|
||||
id: 'b',
|
||||
tenantId: 't2',
|
||||
encryptedBindPassword: 'aa11:bb22:' + Buffer.from('schon').toString('hex'),
|
||||
encryptedBindPassword: `aa11:bb22:${Buffer.from('schon').toString('hex')}`,
|
||||
},
|
||||
{ id: 'c', tenantId: 't3', encryptedBindPassword: null },
|
||||
]);
|
||||
@@ -167,7 +167,7 @@ describe('LdapConfigService — Bind-Passwort verschluesselt at rest', () => {
|
||||
const call = prisma.ldapConfig.update.mock.calls[0][0];
|
||||
expect(call.where).toEqual({ id: 'a' });
|
||||
expect(call.data.encryptedBindPassword).toBe(
|
||||
'aa11:bb22:' + Buffer.from('klartext').toString('hex'),
|
||||
`aa11:bb22:${Buffer.from('klartext').toString('hex')}`,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -176,7 +176,7 @@ describe('LdapConfigService — Bind-Passwort verschluesselt at rest', () => {
|
||||
{
|
||||
id: 'a',
|
||||
tenantId: 't1',
|
||||
encryptedBindPassword: 'aa11:bb22:' + Buffer.from('x').toString('hex'),
|
||||
encryptedBindPassword: `aa11:bb22:${Buffer.from('x').toString('hex')}`,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -354,7 +354,7 @@ describe('LdapConfigService — Bindung an forTenant() (260909-ipc)', () => {
|
||||
const call = boundClient.ldapConfig.update.mock.calls[0][0];
|
||||
expect(call.where).toEqual({ id: 'alt' });
|
||||
expect(call.data.encryptedBindPassword).toBe(
|
||||
'aa11:bb22:' + Buffer.from('klartext').toString('hex'),
|
||||
`aa11:bb22:${Buffer.from('klartext').toString('hex')}`,
|
||||
);
|
||||
// Der rohe Client schreibt NICHT.
|
||||
expect(prisma.ldapConfig.update).not.toHaveBeenCalled();
|
||||
|
||||
@@ -1545,7 +1545,7 @@ describe('LdapService.syncBoundGroupsForTenant — Rekonziliation gegen das Verz
|
||||
isDefault: false,
|
||||
},
|
||||
];
|
||||
prisma.group.update = vi.fn((args: any) => {
|
||||
prisma.group.update = vi.fn((_args: any) => {
|
||||
const err: any = new Error('Unique constraint');
|
||||
err.code = 'P2002';
|
||||
// A P2002 on the OTHER unique index this update() can hit —
|
||||
@@ -1793,7 +1793,7 @@ describe('LdapService.syncBoundGroupsForTenant — Rekonziliation gegen das Verz
|
||||
];
|
||||
mockSearch.mockImplementation((_baseDn: string, opts: any) => {
|
||||
const swept = sweptGuid(opts.filter);
|
||||
if (swept && swept.equals(guidBuffer)) {
|
||||
if (swept?.equals(guidBuffer)) {
|
||||
return Promise.reject(new Error('directory unavailable'));
|
||||
}
|
||||
return Promise.resolve({
|
||||
|
||||
@@ -322,13 +322,13 @@ export class LdapService {
|
||||
const dn = entry.dn;
|
||||
const isOu = /^ou=/i.test(dn);
|
||||
const record = entry as unknown as Record<string, unknown>;
|
||||
const rawName = isOu ? record['ou'] : record['cn'];
|
||||
const rawName = isOu ? record.ou : record.cn;
|
||||
const name = Array.isArray(rawName)
|
||||
? String(rawName[0])
|
||||
: rawName
|
||||
? String(rawName)
|
||||
: dn;
|
||||
const guidValue = record['objectGUID'];
|
||||
const guidValue = record.objectGUID;
|
||||
const guidHex =
|
||||
!isOu && Buffer.isBuffer(guidValue)
|
||||
? guidValue.toString('hex')
|
||||
@@ -401,7 +401,7 @@ export class LdapService {
|
||||
mappedData[mapping.tesseraField] = String(resolved);
|
||||
}
|
||||
}
|
||||
return { username: mappedData['username']?.toLowerCase(), mappedData };
|
||||
return { username: mappedData.username?.toLowerCase(), mappedData };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -483,13 +483,13 @@ export class LdapService {
|
||||
if (existing) {
|
||||
let emailToWrite: string | undefined;
|
||||
let emailConflict: LdapEmailConflict | undefined;
|
||||
if (mappedData['email']) {
|
||||
if (mappedData.email) {
|
||||
const decision = await this.resolveEmailForWrite(
|
||||
mappedData['email'],
|
||||
mappedData.email,
|
||||
existing.id,
|
||||
);
|
||||
if (decision.collides) {
|
||||
emailConflict = { account: username, email: mappedData['email'] };
|
||||
emailConflict = { account: username, email: mappedData.email };
|
||||
} else {
|
||||
emailToWrite = decision.email;
|
||||
}
|
||||
@@ -498,11 +498,11 @@ export class LdapService {
|
||||
await tenantPrisma.user.update({
|
||||
where: { id: existing.id },
|
||||
data: {
|
||||
...(mappedData['displayName'] && {
|
||||
displayName: mappedData['displayName'],
|
||||
...(mappedData.displayName && {
|
||||
displayName: mappedData.displayName,
|
||||
}),
|
||||
...(emailToWrite && { email: emailToWrite }),
|
||||
...(mappedData['username'] && { username }),
|
||||
...(mappedData.username && { username }),
|
||||
ldapDn: dn,
|
||||
isActive: true,
|
||||
},
|
||||
@@ -511,16 +511,16 @@ export class LdapService {
|
||||
}
|
||||
|
||||
let createEmail: string | undefined =
|
||||
mappedData['email'] || `${username}@ldap.local`;
|
||||
mappedData.email || `${username}@ldap.local`;
|
||||
let emailConflict: LdapEmailConflict | undefined;
|
||||
if (mappedData['email']) {
|
||||
if (mappedData.email) {
|
||||
const decision = await this.resolveEmailForWrite(
|
||||
mappedData['email'],
|
||||
mappedData.email,
|
||||
null,
|
||||
);
|
||||
if (decision.collides) {
|
||||
createEmail = undefined;
|
||||
emailConflict = { account: username, email: mappedData['email'] };
|
||||
emailConflict = { account: username, email: mappedData.email };
|
||||
} else {
|
||||
createEmail = decision.email;
|
||||
}
|
||||
@@ -529,7 +529,7 @@ export class LdapService {
|
||||
await this.userService.create({
|
||||
username,
|
||||
...(createEmail && { email: createEmail }),
|
||||
displayName: mappedData['displayName'],
|
||||
displayName: mappedData.displayName,
|
||||
role: 'USER',
|
||||
tenantId,
|
||||
ldapDn: dn,
|
||||
@@ -592,9 +592,9 @@ export class LdapService {
|
||||
|
||||
const entries = Array.from(entriesByDn.values()).map((entry) => ({
|
||||
dn: entry.dn,
|
||||
username: first(entry['sAMAccountName']),
|
||||
displayName: first(entry['displayName']) || first(entry['cn']),
|
||||
email: first(entry['mail']),
|
||||
username: first(entry.sAMAccountName),
|
||||
displayName: first(entry.displayName) || first(entry.cn),
|
||||
email: first(entry.mail),
|
||||
}));
|
||||
|
||||
// Flag entries already present for this tenant (by ldapDn or username) in
|
||||
@@ -724,10 +724,10 @@ export class LdapService {
|
||||
// account is still created and counted, this manual-import path's
|
||||
// display stays as-is.
|
||||
let createEmail: string | undefined =
|
||||
mappedData['email'] || `${username}@ldap.local`;
|
||||
if (mappedData['email']) {
|
||||
mappedData.email || `${username}@ldap.local`;
|
||||
if (mappedData.email) {
|
||||
const decision = await this.resolveEmailForWrite(
|
||||
mappedData['email'],
|
||||
mappedData.email,
|
||||
null,
|
||||
);
|
||||
createEmail = decision.collides ? undefined : decision.email;
|
||||
@@ -736,7 +736,7 @@ export class LdapService {
|
||||
await this.userService.create({
|
||||
username,
|
||||
...(createEmail && { email: createEmail }),
|
||||
displayName: mappedData['displayName'],
|
||||
displayName: mappedData.displayName,
|
||||
role: 'USER',
|
||||
tenantId,
|
||||
ldapDn: dn,
|
||||
@@ -813,14 +813,14 @@ export class LdapService {
|
||||
|
||||
const entry = searchEntries[0];
|
||||
const record = entry as unknown as Record<string, unknown>;
|
||||
const guidValue = record['objectGUID'];
|
||||
const guidValue = record.objectGUID;
|
||||
if (!Buffer.isBuffer(guidValue)) {
|
||||
result.errors.push(`${dn}: objectGUID not readable`);
|
||||
continue;
|
||||
}
|
||||
const ldapObjectGuid = guidValue.toString('hex');
|
||||
|
||||
const rawName = record['cn'];
|
||||
const rawName = record.cn;
|
||||
const name = Array.isArray(rawName)
|
||||
? String(rawName[0])
|
||||
: rawName
|
||||
@@ -1436,7 +1436,7 @@ export class LdapService {
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
const backfillGuid = backfillRecord['objectGUID'];
|
||||
const backfillGuid = backfillRecord.objectGUID;
|
||||
if (!Buffer.isBuffer(backfillGuid)) {
|
||||
result.errors.push(
|
||||
`Gruppe ${group.name}: Alt-Bindung ${group.ldapDn} ohne lesbaren objectGUID`,
|
||||
@@ -1492,7 +1492,7 @@ export class LdapService {
|
||||
if (hit) {
|
||||
// 3. Rename/DN reconciliation (SC-3).
|
||||
const hitRecord = hit as unknown as Record<string, unknown>;
|
||||
const rawName = hitRecord['cn'];
|
||||
const rawName = hitRecord.cn;
|
||||
const name = Array.isArray(rawName)
|
||||
? String(rawName[0])
|
||||
: rawName
|
||||
|
||||
Reference in New Issue
Block a user