11import {
2+ BadRequestException ,
23 Controller ,
34 Post ,
45 Body ,
@@ -26,6 +27,31 @@ import {
2627} from './key-rotation-audit.service' ;
2728import { KeyOperation } from '../generated/prisma/client' ;
2829
30+ function parsePaginationParam (
31+ value : string | undefined ,
32+ name : string ,
33+ max = 100 ,
34+ ) : number | undefined {
35+ if ( value === undefined ) return undefined ;
36+ const n = Number ( value ) ;
37+ if ( ! Number . isInteger ( n ) || n < 0 ) {
38+ throw new BadRequestException ( `${ name } must be a non-negative integer` ) ;
39+ }
40+ if ( name === 'limit' && n > max ) {
41+ throw new BadRequestException ( `limit must not exceed ${ max } ` ) ;
42+ }
43+ return n ;
44+ }
45+
46+ function parseDate ( value : string | undefined , name : string ) : Date | undefined {
47+ if ( value === undefined ) return undefined ;
48+ const d = new Date ( value ) ;
49+ if ( isNaN ( d . getTime ( ) ) ) {
50+ throw new BadRequestException ( `${ name } must be a valid ISO date string` ) ;
51+ }
52+ return d ;
53+ }
54+
2955/**
3056 * Internal controller for key management operations
3157 *
@@ -50,6 +76,15 @@ export class KeyManagementController {
5076 @Post ( 'generate' )
5177 @HttpCode ( HttpStatus . OK )
5278 async generateKey ( @Body ( ) request : GenerateKeyRequest ) {
79+ if ( ! request ?. keyType ) {
80+ throw new BadRequestException ( 'keyType is required' ) ;
81+ }
82+ if ( ! Object . values ( KeyType ) . includes ( request . keyType ) ) {
83+ throw new BadRequestException (
84+ `Invalid keyType: "${ request . keyType } ". Must be one of: ${ Object . values ( KeyType ) . join ( ', ' ) } ` ,
85+ ) ;
86+ }
87+
5388 const result = await this . keyManagementService . generateKey ( request ) ;
5489
5590 return {
@@ -133,17 +168,49 @@ export class KeyManagementController {
133168 }
134169
135170 /**
136- * Gets audit log (admin only)
171+ * Gets in-memory audit log with optional filtering and pagination
172+ *
173+ * Query parameters:
174+ * - operation: Filter by operation type (GENERATE, SIGN, ROTATE, etc.)
175+ * - publicKey: Filter by public key
176+ * - success: Filter by success status (true/false)
177+ * - startDate: Start of date range (ISO string)
178+ * - endDate: End of date range (ISO string)
179+ * - limit: Max results (default: 100, max: 100)
180+ * - offset: Pagination offset (default: 0)
137181 */
138182 @ApiOperation ( { summary : 'Retrieve in-memory audit log (internal, admin only)' } )
139183 @ApiQuery ( { name : 'limit' , required : false , description : 'Max entries to return (default: 100)' } )
140184 @ApiResponse ( { status : 200 , description : 'Array of audit log entries' } )
141185 @Get ( 'audit' )
142- async getAuditLog ( @Query ( 'limit' ) limit ?: string ) {
143- const auditLimit = limit ? parseInt ( limit , 10 ) : 100 ;
144- const logs = this . keyManagementService . getAuditLog ( auditLimit ) ;
186+ async getAuditLog (
187+ @Query ( 'operation' ) operation ?: string ,
188+ @Query ( 'publicKey' ) publicKey ?: string ,
189+ @Query ( 'success' ) success ?: string ,
190+ @Query ( 'startDate' ) startDate ?: string ,
191+ @Query ( 'endDate' ) endDate ?: string ,
192+ @Query ( 'limit' ) limit ?: string ,
193+ @Query ( 'offset' ) offset ?: string ,
194+ ) {
195+ const query : AuditLogQuery = {
196+ operation,
197+ publicKey,
198+ success : success !== undefined ? success === 'true' : undefined ,
199+ startDate : parseDate ( startDate , 'startDate' ) ,
200+ endDate : parseDate ( endDate , 'endDate' ) ,
201+ limit : parsePaginationParam ( limit , 'limit' ) ,
202+ offset : parsePaginationParam ( offset , 'offset' ) ,
203+ } ;
204+
205+ const result = this . keyManagementService . getAuditLog ( query ) ;
145206
146- return { logs } ;
207+ return {
208+ logs : result . data ,
209+ total : result . total ,
210+ limit : result . limit ,
211+ offset : result . offset ,
212+ hasMore : result . hasMore ,
213+ } ;
147214 }
148215
149216 /**
@@ -168,8 +235,8 @@ export class KeyManagementController {
168235 @Query ( 'operation' ) operation ?: string ,
169236 ) {
170237 const query : KeyStatisticsQuery = {
171- startDate : startDate ? new Date ( startDate ) : undefined ,
172- endDate : endDate ? new Date ( endDate ) : undefined ,
238+ startDate : parseDate ( startDate , ' startDate' ) ,
239+ endDate : parseDate ( endDate , ' endDate' ) ,
173240 operation,
174241 } ;
175242
@@ -203,8 +270,8 @@ export class KeyManagementController {
203270 @Query ( 'includeTimeSeries' ) includeTimeSeries ?: string ,
204271 ) {
205272 const query : KeyStatisticsQuery = {
206- startDate : startDate ? new Date ( startDate ) : undefined ,
207- endDate : endDate ? new Date ( endDate ) : undefined ,
273+ startDate : parseDate ( startDate , ' startDate' ) ,
274+ endDate : parseDate ( endDate , ' endDate' ) ,
208275 operation,
209276 includeTimeSeries : includeTimeSeries === 'true' ,
210277 } ;
0 commit comments