mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: Remove orphaned tokens flags (#7714)
Cleanup of `allowOrphanedWildcardTokens` and `cleanApiTokenWhenOrphaned`
This commit is contained in:
		
							parent
							
								
									5668bfb7d4
								
							
						
					
					
						commit
						d1e70eefbe
					
				@ -76,14 +76,12 @@ exports[`should create default config 1`] = `
 | 
			
		||||
  "flagResolver": FlagResolver {
 | 
			
		||||
    "experiments": {
 | 
			
		||||
      "adminTokenKillSwitch": false,
 | 
			
		||||
      "allowOrphanedWildcardTokens": true,
 | 
			
		||||
      "anonymiseEventLog": false,
 | 
			
		||||
      "anonymizeProjectOwners": false,
 | 
			
		||||
      "automatedActions": false,
 | 
			
		||||
      "caseInsensitiveInOperators": false,
 | 
			
		||||
      "celebrateUnleash": false,
 | 
			
		||||
      "changeRequestPlayground": false,
 | 
			
		||||
      "cleanApiTokenWhenOrphaned": false,
 | 
			
		||||
      "collectTrafficDataUsage": false,
 | 
			
		||||
      "commandBarUI": false,
 | 
			
		||||
      "demo": false,
 | 
			
		||||
 | 
			
		||||
@ -36,21 +36,9 @@ interface ITokenRow extends ITokenInsert {
 | 
			
		||||
    project: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const createTokenRowReducer =
 | 
			
		||||
    (allowOrphanedWildcardTokens: boolean) => (acc, tokenRow) => {
 | 
			
		||||
const tokenRowReducer = (acc, tokenRow) => {
 | 
			
		||||
    const { project, ...token } = tokenRow;
 | 
			
		||||
    if (!acc[tokenRow.secret]) {
 | 
			
		||||
            if (
 | 
			
		||||
                !allowOrphanedWildcardTokens &&
 | 
			
		||||
                !tokenRow.project &&
 | 
			
		||||
                tokenRow.secret.includes(':') && // Exclude v1 tokens
 | 
			
		||||
                !tokenRow.secret.startsWith('*:') && // Exclude intentionally wildcard
 | 
			
		||||
                (tokenRow.type === ApiTokenType.CLIENT ||
 | 
			
		||||
                    tokenRow.type === ApiTokenType.FRONTEND)
 | 
			
		||||
            ) {
 | 
			
		||||
                return acc;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        acc[tokenRow.secret] = {
 | 
			
		||||
            secret: token.secret,
 | 
			
		||||
            tokenName: token.token_name ? token.token_name : token.username,
 | 
			
		||||
@ -87,14 +75,8 @@ const toRow = (newToken: IApiTokenCreate) => ({
 | 
			
		||||
    alias: newToken.alias || null,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const toTokens = (
 | 
			
		||||
    rows: any[],
 | 
			
		||||
    allowOrphanedWildcardTokens: boolean,
 | 
			
		||||
): IApiToken[] => {
 | 
			
		||||
    const tokens = rows.reduce(
 | 
			
		||||
        createTokenRowReducer(allowOrphanedWildcardTokens),
 | 
			
		||||
        {},
 | 
			
		||||
    );
 | 
			
		||||
const toTokens = (rows: any[]): IApiToken[] => {
 | 
			
		||||
    const tokens = rows.reduce(tokenRowReducer, {});
 | 
			
		||||
    return Object.values(tokens);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -147,10 +129,7 @@ export class ApiTokenStore implements IApiTokenStore {
 | 
			
		||||
        const stopTimer = this.timer('getAll');
 | 
			
		||||
        const rows = await this.makeTokenProjectQuery();
 | 
			
		||||
        stopTimer();
 | 
			
		||||
        const allowOrphanedWildcardTokens = this.flagResolver.isEnabled(
 | 
			
		||||
            'allowOrphanedWildcardTokens',
 | 
			
		||||
        );
 | 
			
		||||
        return toTokens(rows, allowOrphanedWildcardTokens);
 | 
			
		||||
        return toTokens(rows);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async getAllActive(): Promise<IApiToken[]> {
 | 
			
		||||
@ -159,10 +138,7 @@ export class ApiTokenStore implements IApiTokenStore {
 | 
			
		||||
            .where('expires_at', 'IS', null)
 | 
			
		||||
            .orWhere('expires_at', '>', 'now()');
 | 
			
		||||
        stopTimer();
 | 
			
		||||
        const allowOrphanedWildcardTokens = this.flagResolver.isEnabled(
 | 
			
		||||
            'allowOrphanedWildcardTokens',
 | 
			
		||||
        );
 | 
			
		||||
        return toTokens(rows, allowOrphanedWildcardTokens);
 | 
			
		||||
        return toTokens(rows);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private makeTokenProjectQuery() {
 | 
			
		||||
@ -233,10 +209,7 @@ export class ApiTokenStore implements IApiTokenStore {
 | 
			
		||||
            key,
 | 
			
		||||
        );
 | 
			
		||||
        stopTimer();
 | 
			
		||||
        const allowOrphanedWildcardTokens = this.flagResolver.isEnabled(
 | 
			
		||||
            'allowOrphanedWildcardTokens',
 | 
			
		||||
        );
 | 
			
		||||
        return toTokens(row, allowOrphanedWildcardTokens)[0];
 | 
			
		||||
        return toTokens(row)[0];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async delete(secret: string): Promise<void> {
 | 
			
		||||
@ -253,10 +226,7 @@ export class ApiTokenStore implements IApiTokenStore {
 | 
			
		||||
            .where({ secret })
 | 
			
		||||
            .returning('*');
 | 
			
		||||
        if (rows.length > 0) {
 | 
			
		||||
            const allowOrphanedWildcardTokens = this.flagResolver.isEnabled(
 | 
			
		||||
                'allowOrphanedWildcardTokens',
 | 
			
		||||
            );
 | 
			
		||||
            return toTokens(rows, allowOrphanedWildcardTokens)[0];
 | 
			
		||||
            return toTokens(rows)[0];
 | 
			
		||||
        }
 | 
			
		||||
        throw new NotFoundError('Could not find api-token.');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -79,14 +79,7 @@ beforeAll(async () => {
 | 
			
		||||
        email: 'test@example.com',
 | 
			
		||||
    });
 | 
			
		||||
    await stores.accessStore.addUserToRole(opsUser.id, 1, '');
 | 
			
		||||
    const config = createTestConfig({
 | 
			
		||||
        getLogger,
 | 
			
		||||
        experimental: {
 | 
			
		||||
            flags: {
 | 
			
		||||
                cleanApiTokenWhenOrphaned: true,
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
    });
 | 
			
		||||
    const config = createTestConfig({ getLogger });
 | 
			
		||||
    eventService = new EventService(stores, config);
 | 
			
		||||
    accessService = createAccessService(db.rawDatabase, config);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -564,7 +564,6 @@ export default class ProjectService {
 | 
			
		||||
            auditUser,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        if (this.flagResolver.isEnabled('cleanApiTokenWhenOrphaned')) {
 | 
			
		||||
        const allTokens = await this.apiTokenService.getAllTokens();
 | 
			
		||||
        const projectTokens = allTokens.filter(
 | 
			
		||||
            (token) =>
 | 
			
		||||
@ -581,9 +580,6 @@ export default class ProjectService {
 | 
			
		||||
                this.apiTokenService.delete(token.secret, auditUser),
 | 
			
		||||
            ),
 | 
			
		||||
        );
 | 
			
		||||
        } else {
 | 
			
		||||
            await this.projectStore.delete(id);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await this.eventService.storeEvent(
 | 
			
		||||
            new ProjectDeletedEvent({
 | 
			
		||||
 | 
			
		||||
@ -64,8 +64,6 @@ export type IFlagKey =
 | 
			
		||||
    | 'anonymizeProjectOwners'
 | 
			
		||||
    | 'resourceLimits'
 | 
			
		||||
    | 'extendedMetrics'
 | 
			
		||||
    | 'cleanApiTokenWhenOrphaned'
 | 
			
		||||
    | 'allowOrphanedWildcardTokens'
 | 
			
		||||
    | 'removeUnsafeInlineStyleSrc'
 | 
			
		||||
    | 'insightsV2'
 | 
			
		||||
    | 'integrationEvents'
 | 
			
		||||
@ -310,18 +308,10 @@ const flags: IFlags = {
 | 
			
		||||
        process.env.UNLEASH_EXPERIMENTAL_RESOURCE_LIMITS,
 | 
			
		||||
        false,
 | 
			
		||||
    ),
 | 
			
		||||
    allowOrphanedWildcardTokens: parseEnvVarBoolean(
 | 
			
		||||
        process.env.UNLEASH_ORPHANED_TOKENS_KILL_SWITCH,
 | 
			
		||||
        true,
 | 
			
		||||
    ),
 | 
			
		||||
    extendedMetrics: parseEnvVarBoolean(
 | 
			
		||||
        process.env.UNLEASH_EXPERIMENTAL_EXTENDED_METRICS,
 | 
			
		||||
        false,
 | 
			
		||||
    ),
 | 
			
		||||
    cleanApiTokenWhenOrphaned: parseEnvVarBoolean(
 | 
			
		||||
        process.env.UNLEASH_EXPERIMENTAL_CLEAN_API_TOKEN_WHEN_ORPHANED,
 | 
			
		||||
        false,
 | 
			
		||||
    ),
 | 
			
		||||
    removeUnsafeInlineStyleSrc: parseEnvVarBoolean(
 | 
			
		||||
        process.env.UNLEASH_EXPERIMENTAL_REMOVE_UNSAFE_INLINE_STYLE_SRC,
 | 
			
		||||
        false,
 | 
			
		||||
 | 
			
		||||
@ -23,17 +23,7 @@ const feature3 = 'f3.p2.token.access';
 | 
			
		||||
 | 
			
		||||
beforeAll(async () => {
 | 
			
		||||
    db = await dbInit('feature_api_api_access_client_deletion', getLogger);
 | 
			
		||||
    app = await setupAppWithAuth(
 | 
			
		||||
        db.stores,
 | 
			
		||||
        {
 | 
			
		||||
            experimental: {
 | 
			
		||||
                flags: {
 | 
			
		||||
                    cleanApiTokenWhenOrphaned: true,
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
    );
 | 
			
		||||
    app = await setupAppWithAuth(db.stores, {}, db.rawDatabase);
 | 
			
		||||
    apiTokenService = app.services.apiTokenService;
 | 
			
		||||
 | 
			
		||||
    const { featureToggleServiceV2, environmentService } = app.services;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user