diff --git a/src/lib/db/api-token-store.ts b/src/lib/db/api-token-store.ts index 99276c842e..30ff042604 100644 --- a/src/lib/db/api-token-store.ts +++ b/src/lib/db/api-token-store.ts @@ -203,7 +203,7 @@ export class ApiTokenStore implements IApiTokenStore { const now = new Date(); try { await this.db(TABLE) - .whereIn('secrets', secrets) + .whereIn('secret', secrets) .update({ seen_at: now }); } catch (err) { this.logger.error('Could not update lastSeen, error: ', err); diff --git a/src/lib/services/api-token-service.ts b/src/lib/services/api-token-service.ts index c1831c09dd..64ed609768 100644 --- a/src/lib/services/api-token-service.ts +++ b/src/lib/services/api-token-service.ts @@ -26,6 +26,7 @@ import { ApiTokenUpdatedEvent, } from '../types'; import { omitKeys } from '../util'; +import { IFlagResolver } from 'lib/types/experimental'; const resolveTokenPermissions = (tokenType: string) => { if (tokenType === ApiTokenType.ADMIN) { @@ -52,10 +53,16 @@ export class ApiTokenService { private timer: NodeJS.Timeout; + private seenTimer: NodeJS.Timeout; + private activeTokens: IApiToken[] = []; private eventStore: IEventStore; + private lastSeenSecrets: Set = new Set(); + + private flagResolver: IFlagResolver; + constructor( { apiTokenStore, @@ -65,8 +72,12 @@ export class ApiTokenService { IUnleashStores, 'apiTokenStore' | 'environmentStore' | 'eventStore' >, - config: Pick, + config: Pick< + IUnleashConfig, + 'getLogger' | 'authentication' | 'flagResolver' + >, ) { + this.flagResolver = config.flagResolver; this.store = apiTokenStore; this.eventStore = eventStore; this.environmentStore = environmentStore; @@ -76,6 +87,9 @@ export class ApiTokenService { () => this.fetchActiveTokens(), minutesToMilliseconds(1), ).unref(); + if (this.flagResolver.isEnabled('tokensLastSeen')) { + this.updateLastSeen(); + } if (config.authentication.initApiTokens.length > 0) { process.nextTick(async () => this.initApiTokens(config.authentication.initApiTokens), @@ -92,6 +106,19 @@ export class ApiTokenService { } } + async updateLastSeen(): Promise { + if (this.lastSeenSecrets.size > 0) { + const toStore = [...this.lastSeenSecrets]; + this.lastSeenSecrets = new Set(); + await this.store.markSeenAt(toStore); + } + + this.seenTimer = setTimeout( + async () => this.updateLastSeen(), + minutesToMilliseconds(3), + ).unref(); + } + public async getAllTokens(): Promise { return this.store.getAll(); } @@ -137,6 +164,10 @@ export class ApiTokenService { } if (token) { + if (this.flagResolver.isEnabled('tokensLastSeen')) { + this.lastSeenSecrets.add(token.secret); + } + return new ApiUser({ username: token.username, permissions: resolveTokenPermissions(token.type), @@ -269,6 +300,8 @@ export class ApiTokenService { destroy(): void { clearInterval(this.timer); + clearTimeout(this.seenTimer); this.timer = null; + this.seenTimer = null; } }