All files / src/lib/types/models api-token.ts

97.67% Statements 42/43
95.45% Branches 21/22
100% Functions 8/8
97.3% Lines 36/37

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 12995x     95x   95x 95x 95x                                                         95x 25x     95x         53x 49x 4x 4x 4x 1x             53x     95x     53x 53x                 95x     1x           95x         53x 3x         50x 1x         49x 2x           95x       40x 5x     35x 41x     35x 1x     34x 1x          
import BadDataError from '../../error/bad-data-error';
import { IEnvironment } from '../model';
 
export const ALL = '*';
 
export enum ApiTokenType {
    CLIENT = 'client',
    ADMIN = 'admin',
}
 
export interface ILegacyApiTokenCreate {
    secret: string;
    username: string;
    type: ApiTokenType;
    environment: string;
    project?: string;
    projects?: string[];
    expiresAt?: Date;
}
 
export interface IApiTokenCreate {
    secret: string;
    username: string;
    type: ApiTokenType;
    environment: string;
    projects: string[];
    expiresAt?: Date;
}
 
export interface IApiToken extends IApiTokenCreate {
    createdAt: Date;
    seenAt?: Date;
    environment: string;
    project: string;
}
 
export const isAllProjects = (projects: string[]): boolean => {
    return projects && projects.length === 1 && projects[0] === ALL;
};
 
export const mapLegacyProjects = (
    project?: string,
    projects?: string[],
): string[] => {
    let cleanedProjects;
    if (project) {
        cleanedProjects = [project];
    } else if (projects) {
        cleanedProjects = projects;
        if (cleanedProjects.includes('*')) {
            cleanedProjects = ['*'];
        }
    } else E{
        throw new BadDataError(
            'API tokens must either contain a project or projects field',
        );
    }
    return cleanedProjects;
};
 
export const mapLegacyToken = (
    token: Omit<ILegacyApiTokenCreate, 'secret'>,
): Omit<IApiTokenCreate, 'secret'> => {
    const cleanedProjects = mapLegacyProjects(token.project, token.projects);
    return {
        username: token.username,
        type: token.type,
        environment: token.environment,
        projects: cleanedProjects,
        expiresAt: token.expiresAt,
    };
};
 
export const mapLegacyTokenWithSecret = (
    token: ILegacyApiTokenCreate,
): IApiTokenCreate => {
    return {
        ...mapLegacyToken(token),
        secret: token.secret,
    };
};
 
export const validateApiToken = ({
    type,
    projects,
    environment,
}: Omit<IApiTokenCreate, 'secret'>): void => {
    if (type === ApiTokenType.ADMIN && !isAllProjects(projects)) {
        throw new BadDataError(
            'Admin token cannot be scoped to single project',
        );
    }
 
    if (type === ApiTokenType.ADMIN && environment !== ALL) {
        throw new BadDataError(
            'Admin token cannot be scoped to single environment',
        );
    }
 
    if (type === ApiTokenType.CLIENT && environment === ALL) {
        throw new BadDataError(
            'Client token cannot be scoped to all environments',
        );
    }
};
 
export const validateApiTokenEnvironment = (
    { environment }: Pick<IApiTokenCreate, 'environment'>,
    environments: IEnvironment[],
): void => {
    if (environment === ALL) {
        return;
    }
 
    const selectedEnvironment = environments.find(
        (env) => env.name === environment,
    );
 
    if (!selectedEnvironment) {
        throw new BadDataError(`Environment=${environment} does not exist`);
    }
 
    if (!selectedEnvironment.enabled) {
        throw new BadDataError(
            'Client token cannot be scoped to disabled environments',
        );
    }
};