feat(quick-260910-jab): listForUser binden, die vier Aufzeichnungen im Quelltext richtigstellen
- TenderRssFeedSourceService.listForUser() nimmt jetzt (userId, tenantId) entgegen und laeuft ueber einen gebundenen Klienten (forTenant) — die neue Leseregel schliesst plattformweite Zeilen ein, die Reparatur haette den ungebundenen Pfad sonst still auf nur die plattformweiten Zeilen reduziert (Befund F). createPlatform/remove bleiben bewusst ungebunden, Kommentare an der neuen Regel richtiggestellt. - TendersController.listRssFeeds reicht die Mandantenkennung aus dem Aufrufzusammenhang durch. - Vier Aufzeichnungen im Quelltext (module-access.service.ts, groups.service.ts, module-grants.service.ts, rls-coverage.spec.ts) sagen jetzt, dass die Datenbankregel seit 20260910120000_rls_widen_membership_ grant_and_platform_read beide Seiten prueft; die Anwendungspruefungen bleiben unveraendert bestehen (zweites Netz, wirkt vor dem Scharfschalten als einziger Schutz). - Zwei-Klienten-Nachweis in module-grants.service.spec.ts ergaenzt (Kommentar, warum die beiden Cross-Tenant-Tests nach der Regelaenderung nicht entfallen duerfen) und in tender-rss-feed.service.spec.ts umgekehrt (listForUser bindet jetzt). - Rule 1: implizites any beim Destrukturieren in listRssFeeds (feeds ist seit der Bindung `any`) mit expliziter Annotation behoben. - Falsifizierungsnachweis durchgefuehrt: Bindungsaufruf zurueckgenommen, genau ein Test wurde rot (AssertionError, 0 statt der erwarteten Aufrufe), Ruecknahme rueckgaengig gemacht. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AMASaSxv5QMY7RncqZriRR
This commit is contained in:
@@ -485,12 +485,16 @@ export class GroupsService {
|
||||
* exportiert sein.
|
||||
*
|
||||
* Prüft zusätzlich, dass der Zielbenutzer zu DIESEM Mandanten gehört
|
||||
* (Befund E, T-JTS-02, 260909-jts): die ausgelieferte Policy auf
|
||||
* GroupMembership prüft ausschließlich die Gruppenseite
|
||||
* (`groupId IN (SELECT id FROM "Group" WHERE tenantId = ...)`), gemessen
|
||||
* in Aufgabe 1 — die Benutzerseite prüft sie NICHT. Nach dem Vorbild von
|
||||
* addMembers() zwei Methoden höher: Zielbenutzer auf den Mandanten
|
||||
* filtern, bei keinem Treffer folgenlos zurückkehren statt zu werfen.
|
||||
* (T-JTS-02, 260909-jts/260910-jab): die Policy auf GroupMembership prüfte
|
||||
* bis 260910-jab ausschließlich die Gruppenseite
|
||||
* (`groupId IN (SELECT id FROM "Group" WHERE tenantId = ...)`) — die
|
||||
* Benutzerseite NICHT (Befund E, gemessen in Aufgabe 1 von 260909-jts).
|
||||
* Seit 20260910120000_rls_widen_membership_grant_and_platform_read prüft
|
||||
* die Datenbankregel selbst BEIDE Seiten — diese Anwendungsprüfung bleibt
|
||||
* trotzdem bestehen: der Schalter ist weiterhin aus (#18), die
|
||||
* Datenbankregel wirkt heute nicht. Nach dem Vorbild von addMembers() zwei
|
||||
* Methoden höher: Zielbenutzer auf den Mandanten filtern, bei keinem
|
||||
* Treffer folgenlos zurückkehren statt zu werfen.
|
||||
*/
|
||||
async addUserToDefaultGroup(tenantId: string, userId: string) {
|
||||
const tenantPrisma = forTenant(this.prisma, tenantId) as any;
|
||||
|
||||
@@ -278,6 +278,15 @@ describe('ModuleGrantsService.grant', () => {
|
||||
expect(prisma.__grantCount()).toBe(0);
|
||||
});
|
||||
|
||||
// Diese beiden Faelle (T-JTS-03, 260910-jab, Aufgabe 2) beweisen, dass
|
||||
// assertTargetBelongsToTenant() weiterhin im Anwendungscode scheitert —
|
||||
// nicht erst in der Datenbank. Seit
|
||||
// 20260910120000_rls_widen_membership_grant_and_platform_read zieht auch
|
||||
// die Datenbankregel dieselbe Grenze, aber erst NACH dem Scharfschalten
|
||||
// (#18 ist weiterhin aus). Wuerde assertTargetBelongsToTenant() im
|
||||
// Vertrauen auf "das macht jetzt die Datenbank" entfernt, werden GENAU
|
||||
// diese beiden Faelle rot: der Fake hier hat keine RLS-Policy, nur das
|
||||
// reale ModuleGrant/Group/User-Schema tut das.
|
||||
it('wirft NotFoundException für eine groupId aus einem anderen Mandanten und legt nichts an', async () => {
|
||||
const prisma = makeFakePrisma();
|
||||
seedBase(prisma);
|
||||
|
||||
@@ -91,13 +91,18 @@ export class ModuleGrantsService {
|
||||
}
|
||||
|
||||
// Die Mandanten-Gegenpruefung bleibt ausdruecklich erhalten (T-JTS-03,
|
||||
// 260909-jts, Aufgabe 1): die ausgelieferte Regel auf ModuleGrant
|
||||
// prueft ausschliesslich die Mandantenkennung der Zeile selbst
|
||||
// ("tenantId" = current_tenant_id()), NICHT die referenzierte Gruppe.
|
||||
// Eine Zeile mit korrekter eigener Mandantenkennung, die auf die
|
||||
// Gruppe eines fremden Mandanten zeigt, verletzt diese Regel
|
||||
// nachweislich nicht (gemessen gegen die echte Migration in Aufgabe 1).
|
||||
// Diese Anwendungspruefung ist damit der einzige Schutz gegen diese
|
||||
// 260909-jts/260910-jab): bis Migration
|
||||
// 20260910120000_rls_widen_membership_grant_and_platform_read pruefte
|
||||
// die Regel auf ModuleGrant ausschliesslich die Mandantenkennung der
|
||||
// Zeile selbst ("tenantId" = current_tenant_id()),
|
||||
// NICHT die referenzierte Gruppe oder den referenzierten Benutzer — eine
|
||||
// Zeile mit korrekter eigener Mandantenkennung, die auf die Gruppe/den
|
||||
// Benutzer eines fremden Mandanten zeigt, verletzte diese Regel
|
||||
// nachweislich nicht (gemessen in Aufgabe 1 von 260909-jts). Die
|
||||
// Datenbank zieht diese Grenze inzwischen ebenfalls (260910-jab, Aufgabe
|
||||
// 1) — diese zweite Ziehung wirkt aber erst NACH dem Scharfschalten
|
||||
// (#18, der Schalter ist weiterhin aus). Diese Anwendungspruefung bleibt
|
||||
// deshalb bis dahin der EINZIGE und danach der ERSTE Schutz gegen diese
|
||||
// Form der Rechteausweitung und darf nicht als "macht jetzt die
|
||||
// Datenbank" entfallen.
|
||||
await this.assertTargetBelongsToTenant(tenantId, groupId, userId);
|
||||
|
||||
Reference in New Issue
Block a user