@@ -18,6 +18,10 @@ export interface ApiKey {
1818 status : ApiKeyStatus ;
1919 createdAt : Date ;
2020 expiresAt ?: Date ;
21+ monthlyRequestQuota : number ;
22+ rateLimitPerMinute : number ;
23+ requestsThisMonth : number ;
24+ scopedEndpoints : string [ ] ;
2125}
2226
2327@Injectable ( )
@@ -45,6 +49,9 @@ export class ApiKeyService {
4549 ownerLabel : string ,
4650 isAdmin : boolean ,
4751 expiresAt ?: Date ,
52+ monthlyRequestQuota = 1000 ,
53+ rateLimitPerMinute = 100 ,
54+ scopedEndpoints : string [ ] = [ ] ,
4855 ) : ApiKey {
4956 if ( ! isAdmin ) {
5057 throw new UnauthorizedException (
@@ -62,12 +69,42 @@ export class ApiKeyService {
6269 status : ApiKeyStatus . ACTIVE ,
6370 createdAt : new Date ( ) ,
6471 expiresAt,
72+ monthlyRequestQuota,
73+ rateLimitPerMinute,
74+ requestsThisMonth : 0 ,
75+ scopedEndpoints,
6576 } ;
6677 this . apiKeys . set ( newKey , apiKey ) ;
6778 this . logger . log ( `Generated new API key for ${ ownerLabel } : ${ newKey } ` ) ;
6879 return apiKey ;
6980 }
7081
82+ checkQuota ( key : string ) : boolean {
83+ const apiKey = this . apiKeys . get ( key ) ;
84+ if ( ! apiKey ) return false ;
85+ return apiKey . requestsThisMonth < apiKey . monthlyRequestQuota ;
86+ }
87+
88+ incrementRequestCount ( key : string ) : void {
89+ const apiKey = this . apiKeys . get ( key ) ;
90+ if ( apiKey ) {
91+ apiKey . requestsThisMonth += 1 ;
92+ this . apiKeys . set ( key , apiKey ) ;
93+ }
94+ }
95+
96+ getQuotaUsage ( key : string ) : { used : number ; limit : number ; remaining : number } {
97+ const apiKey = this . apiKeys . get ( key ) ;
98+ if ( ! apiKey ) {
99+ return { used : 0 , limit : 0 , remaining : 0 } ;
100+ }
101+ return {
102+ used : apiKey . requestsThisMonth ,
103+ limit : apiKey . monthlyRequestQuota ,
104+ remaining : Math . max ( 0 , apiKey . monthlyRequestQuota - apiKey . requestsThisMonth ) ,
105+ } ;
106+ }
107+
71108 revokeApiKey ( key : string , isAdmin : boolean ) : ApiKey {
72109 if ( ! isAdmin ) {
73110 throw new UnauthorizedException (
0 commit comments