mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	Feat update token seen at (#2514)
https://linear.app/unleash/issue/2-448/update-last-seen-column-for-api-tokens Co-authored-by: Ivar Conradi Østhus <ivar@getunleash.ai>
This commit is contained in:
		
							parent
							
								
									b32d3d0fee
								
							
						
					
					
						commit
						564c287025
					
				@ -203,7 +203,7 @@ export class ApiTokenStore implements IApiTokenStore {
 | 
				
			|||||||
        const now = new Date();
 | 
					        const now = new Date();
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            await this.db(TABLE)
 | 
					            await this.db(TABLE)
 | 
				
			||||||
                .whereIn('secrets', secrets)
 | 
					                .whereIn('secret', secrets)
 | 
				
			||||||
                .update({ seen_at: now });
 | 
					                .update({ seen_at: now });
 | 
				
			||||||
        } catch (err) {
 | 
					        } catch (err) {
 | 
				
			||||||
            this.logger.error('Could not update lastSeen, error: ', err);
 | 
					            this.logger.error('Could not update lastSeen, error: ', err);
 | 
				
			||||||
 | 
				
			|||||||
@ -26,6 +26,7 @@ import {
 | 
				
			|||||||
    ApiTokenUpdatedEvent,
 | 
					    ApiTokenUpdatedEvent,
 | 
				
			||||||
} from '../types';
 | 
					} from '../types';
 | 
				
			||||||
import { omitKeys } from '../util';
 | 
					import { omitKeys } from '../util';
 | 
				
			||||||
 | 
					import { IFlagResolver } from 'lib/types/experimental';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const resolveTokenPermissions = (tokenType: string) => {
 | 
					const resolveTokenPermissions = (tokenType: string) => {
 | 
				
			||||||
    if (tokenType === ApiTokenType.ADMIN) {
 | 
					    if (tokenType === ApiTokenType.ADMIN) {
 | 
				
			||||||
@ -52,10 +53,16 @@ export class ApiTokenService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private timer: NodeJS.Timeout;
 | 
					    private timer: NodeJS.Timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private seenTimer: NodeJS.Timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private activeTokens: IApiToken[] = [];
 | 
					    private activeTokens: IApiToken[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private eventStore: IEventStore;
 | 
					    private eventStore: IEventStore;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private lastSeenSecrets: Set<string> = new Set<string>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private flagResolver: IFlagResolver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(
 | 
					    constructor(
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            apiTokenStore,
 | 
					            apiTokenStore,
 | 
				
			||||||
@ -65,8 +72,12 @@ export class ApiTokenService {
 | 
				
			|||||||
            IUnleashStores,
 | 
					            IUnleashStores,
 | 
				
			||||||
            'apiTokenStore' | 'environmentStore' | 'eventStore'
 | 
					            'apiTokenStore' | 'environmentStore' | 'eventStore'
 | 
				
			||||||
        >,
 | 
					        >,
 | 
				
			||||||
        config: Pick<IUnleashConfig, 'getLogger' | 'authentication'>,
 | 
					        config: Pick<
 | 
				
			||||||
 | 
					            IUnleashConfig,
 | 
				
			||||||
 | 
					            'getLogger' | 'authentication' | 'flagResolver'
 | 
				
			||||||
 | 
					        >,
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
 | 
					        this.flagResolver = config.flagResolver;
 | 
				
			||||||
        this.store = apiTokenStore;
 | 
					        this.store = apiTokenStore;
 | 
				
			||||||
        this.eventStore = eventStore;
 | 
					        this.eventStore = eventStore;
 | 
				
			||||||
        this.environmentStore = environmentStore;
 | 
					        this.environmentStore = environmentStore;
 | 
				
			||||||
@ -76,6 +87,9 @@ export class ApiTokenService {
 | 
				
			|||||||
            () => this.fetchActiveTokens(),
 | 
					            () => this.fetchActiveTokens(),
 | 
				
			||||||
            minutesToMilliseconds(1),
 | 
					            minutesToMilliseconds(1),
 | 
				
			||||||
        ).unref();
 | 
					        ).unref();
 | 
				
			||||||
 | 
					        if (this.flagResolver.isEnabled('tokensLastSeen')) {
 | 
				
			||||||
 | 
					            this.updateLastSeen();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        if (config.authentication.initApiTokens.length > 0) {
 | 
					        if (config.authentication.initApiTokens.length > 0) {
 | 
				
			||||||
            process.nextTick(async () =>
 | 
					            process.nextTick(async () =>
 | 
				
			||||||
                this.initApiTokens(config.authentication.initApiTokens),
 | 
					                this.initApiTokens(config.authentication.initApiTokens),
 | 
				
			||||||
@ -92,6 +106,19 @@ export class ApiTokenService {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async updateLastSeen(): Promise<void> {
 | 
				
			||||||
 | 
					        if (this.lastSeenSecrets.size > 0) {
 | 
				
			||||||
 | 
					            const toStore = [...this.lastSeenSecrets];
 | 
				
			||||||
 | 
					            this.lastSeenSecrets = new Set<string>();
 | 
				
			||||||
 | 
					            await this.store.markSeenAt(toStore);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.seenTimer = setTimeout(
 | 
				
			||||||
 | 
					            async () => this.updateLastSeen(),
 | 
				
			||||||
 | 
					            minutesToMilliseconds(3),
 | 
				
			||||||
 | 
					        ).unref();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public async getAllTokens(): Promise<IApiToken[]> {
 | 
					    public async getAllTokens(): Promise<IApiToken[]> {
 | 
				
			||||||
        return this.store.getAll();
 | 
					        return this.store.getAll();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -137,6 +164,10 @@ export class ApiTokenService {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (token) {
 | 
					        if (token) {
 | 
				
			||||||
 | 
					            if (this.flagResolver.isEnabled('tokensLastSeen')) {
 | 
				
			||||||
 | 
					                this.lastSeenSecrets.add(token.secret);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return new ApiUser({
 | 
					            return new ApiUser({
 | 
				
			||||||
                username: token.username,
 | 
					                username: token.username,
 | 
				
			||||||
                permissions: resolveTokenPermissions(token.type),
 | 
					                permissions: resolveTokenPermissions(token.type),
 | 
				
			||||||
@ -269,6 +300,8 @@ export class ApiTokenService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    destroy(): void {
 | 
					    destroy(): void {
 | 
				
			||||||
        clearInterval(this.timer);
 | 
					        clearInterval(this.timer);
 | 
				
			||||||
 | 
					        clearTimeout(this.seenTimer);
 | 
				
			||||||
        this.timer = null;
 | 
					        this.timer = null;
 | 
				
			||||||
 | 
					        this.seenTimer = null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user