refactor(quick-260921-m34): Aufgabe 2a - gemeinsamer Aufrufer-Typ, aus den Signierstellen abgeleitet
apps/api/src/auth/types/auth-user.ts angelegt: AuthUser, AuthenticatedRequest, LocalAuthenticatedRequest, LoginUser, JwtPayload, UploadedFileLike. Jedes Feld traegt seine Herkunft als Kommentar. tenantId ist string, hergeleitet und nicht gewaehlt: die Spalte User.tenantId ist in schema.prisma Pflicht, beide Signierstellen schreiben genau sie, und der Bestand beschreibt dasselbe Objekt in SessionUser schon so. Der SUPER_ADMIN-Zweig in TenantGuard spricht nicht dagegen - der Waechter liest AuthUser gar nicht, und dass es den Zweig gibt, steht als null in AuthenticatedRequest.tenantId weiter im Typsystem. tenant.guard.ts bleibt unberuehrt. role ist die Aufzaehlung Role: schema.prisma deklariert die Spalte so, die SQL-Funktion auth_lookup_user_by_username gibt sie als "Role" zurueck. Die Handannotation role: string in AuthLookupUserByUsernameRow war eine zweite Fassung desselben Wertes und faellt damit weg. SessionUser und UploadedPng in bug-reports.service.ts sind jetzt Pick<> der neuen Typen statt eigener Beschreibungen. Fixtures in auth.controller.spec.ts ergaenzt: sie uebergaben einen Aufrufer ohne username und ohne mustChangePassword - eine Form, die JwtStrategy nie erzeugt. Testzahlen unveraendert. noExplicitAny in apps/api/src: 149 -> 137. type-check 4/4, lint 5/5, apps/api 72/1143, apps/web 73/531. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPPB4ApQxzSU1rwV2Ffj9J
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { Body, Controller, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
import { CurrentUser } from '../auth/decorators/current-user.decorator';
|
||||
import type { AuthUser, UploadedFileLike } from '../auth/types/auth-user';
|
||||
import { BugReportsService } from './bug-reports.service';
|
||||
import { BugReportDto } from './dto/bug-report.dto';
|
||||
|
||||
@@ -30,9 +31,9 @@ export class BugReportsController {
|
||||
FileInterceptor('screenshot', { limits: { fileSize: 4 * 1024 * 1024, files: 1 } }),
|
||||
)
|
||||
async submit(
|
||||
@CurrentUser() user: any,
|
||||
@CurrentUser() user: AuthUser,
|
||||
@Body() dto: BugReportDto,
|
||||
@UploadedFile() file?: any,
|
||||
@UploadedFile() file?: UploadedFileLike,
|
||||
) {
|
||||
return this.service.submit(user, dto, file);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
ConflictException,
|
||||
HttpException,
|
||||
} from '@nestjs/common';
|
||||
import { Role } from '@prisma/client';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { forTenant } from '../prisma/prisma-tenant.extension';
|
||||
import { BugReportsService } from './bug-reports.service';
|
||||
@@ -37,7 +38,7 @@ const PNG_1x1 = Buffer.from(
|
||||
'base64',
|
||||
);
|
||||
|
||||
const sessionUser = { id: 'u1', username: 'anna', role: 'USER', tenantId: 't1' };
|
||||
const sessionUser = { id: 'u1', username: 'anna', role: Role.USER, tenantId: 't1' };
|
||||
|
||||
const baseDto = {
|
||||
page: '/admin/users?tab=x',
|
||||
|
||||
@@ -14,6 +14,7 @@ import { forTenant } from '../prisma/prisma-tenant.extension';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { SettingsService } from '../settings/settings.service';
|
||||
import { BugReportDto } from './dto/bug-report.dto';
|
||||
import type { AuthUser, UploadedFileLike } from '../auth/types/auth-user';
|
||||
import { describeOrigin } from './origin';
|
||||
|
||||
/**
|
||||
@@ -58,18 +59,22 @@ const WINDOW_MS = 10 * 60 * 1000;
|
||||
const MAX_PER_WINDOW = 5;
|
||||
const PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
||||
|
||||
interface SessionUser {
|
||||
id: string;
|
||||
username: string;
|
||||
role: string;
|
||||
tenantId: string;
|
||||
}
|
||||
/**
|
||||
* Der Aufrufer, so weit dieser Dienst ihn liest. Seit quick-260921-m34 aus
|
||||
* `AuthUser` abgeleitet statt danebengestellt: es soll nicht zwei
|
||||
* Beschreibungen desselben Sitzungsobjekts geben, die auseinanderlaufen
|
||||
* koennen. Ausgelassen wird `mustChangePassword` — dieser Dienst liest es
|
||||
* nicht.
|
||||
*/
|
||||
type SessionUser = Pick<AuthUser, 'id' | 'username' | 'role' | 'tenantId'>;
|
||||
|
||||
interface UploadedPng {
|
||||
buffer: Buffer;
|
||||
size: number;
|
||||
mimetype?: string;
|
||||
}
|
||||
/**
|
||||
* Das Bildschirmfoto, so weit dieser Dienst es liest — abgeleitet aus
|
||||
* `UploadedFileLike`, damit die Hochladewege eine gemeinsame Beschreibung
|
||||
* haben. `originalname` fehlt bewusst: der Anhangname ist hier fest
|
||||
* vorgegeben (T-M97-04), der eingereichte Name wird nie benutzt.
|
||||
*/
|
||||
type UploadedPng = Pick<UploadedFileLike, 'buffer' | 'size' | 'mimetype'>;
|
||||
|
||||
@Injectable()
|
||||
export class BugReportsService {
|
||||
|
||||
Reference in New Issue
Block a user