All files / src/lib/routes/admin-api state.ts

95.74% Statements 45/47
83.33% Branches 10/12
100% Functions 4/4
95.74% Lines 45/47

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 10659x 59x 59x 59x   59x 59x 59x             59x 59x 46x 44x   2x 2x     2x                     141x 141x 141x 141x 141x 141x       11x 11x       11x   8x   1x     7x     3x     11x           10x       4x   4x 4x 4x       4x 4x 4x   4x             4x 4x 2x     2x   2x 1x   2x       59x  
import * as mime from 'mime';
import YAML from 'js-yaml';
import multer from 'multer';
import { format as formatDate } from 'date-fns';
import { Request, Response } from 'express';
import Controller from '../controller';
import { ADMIN } from '../../types/permissions';
import { extractUsername } from '../../util/extract-user';
import { IUnleashConfig } from '../../types/option';
import { IUnleashServices } from '../../types/services';
import { Logger } from '../../logger';
import StateService from '../../services/state-service';
import { IAuthRequest } from '../unleash-types';
 
const upload = multer({ limits: { fileSize: 5242880 } });
const paramToBool = (param, def) => {
    if (param === null || param === undefined) {
        return def;
    }
    const nu = Number.parseInt(param, 10);
    Iif (Number.isNaN(nu)) {
        return param.toLowerCase() === 'true';
    }
    return Boolean(nu);
};
class StateController extends Controller {
    private logger: Logger;
 
    private stateService: StateService;
 
    constructor(
        config: IUnleashConfig,
        { stateService }: Pick<IUnleashServices, 'stateService'>,
    ) {
        super(config);
        this.logger = config.getLogger('/admin-api/state.ts');
        this.stateService = stateService;
        this.fileupload('/import', upload.single('file'), this.import, ADMIN);
        this.post('/import', this.import, ADMIN);
        this.get('/export', this.export, ADMIN);
    }
 
    async import(req: IAuthRequest, res: Response): Promise<void> {
        const userName = extractUsername(req);
        const { drop, keep } = req.query;
        // TODO: Should override request type so file is a type on request
        let data;
        // @ts-ignore
        if (req.file) {
            // @ts-ignore
            if (mime.getType(req.file.originalname) === 'text/yaml') {
                // @ts-ignore
                data = YAML.load(req.file.buffer);
            } else {
                // @ts-ignore
                data = JSON.parse(req.file.buffer);
            }
        } else {
            data = req.body;
        }
 
        await this.stateService.import({
            data,
            userName,
            dropBeforeImport: paramToBool(drop, false),
            keepExisting: paramToBool(keep, true),
        });
        res.sendStatus(202);
    }
 
    async export(req: Request, res: Response): Promise<void> {
        const { format } = req.query;
 
        const downloadFile = paramToBool(req.query.download, false);
        const includeStrategies = paramToBool(req.query.strategies, true);
        const includeFeatureToggles = paramToBool(
            req.query.featureToggles,
            true,
        );
        const includeProjects = paramToBool(req.query.projects, true);
        const includeTags = paramToBool(req.query.tags, true);
        const includeEnvironments = paramToBool(req.query.environments, true);
 
        const data = await this.stateService.export({
            includeStrategies,
            includeFeatureToggles,
            includeProjects,
            includeTags,
            includeEnvironments,
        });
        const timestamp = formatDate(Date.now(), 'yyyy-MM-dd_HH-mm-ss');
        if (format === 'yaml') {
            Iif (downloadFile) {
                res.attachment(`export-${timestamp}.yml`);
            }
            res.type('yaml').send(YAML.dump(data, { skipInvalid: true }));
        } else {
            if (downloadFile) {
                res.attachment(`export-${timestamp}.json`);
            }
            res.json(data);
        }
    }
}
export default StateController;