"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/*
 *  Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *  SPDX-License-Identifier: Apache-2.0
 */
const createDataSetRequestParser_1 = require("@aws/swb-app/lib/dataSets/createDataSetRequestParser");
const paabHelper_1 = require("../../support/complex/paabHelper");
const setup_1 = __importDefault(require("../../support/setup"));
const constants_1 = require("../../support/utils/constants");
const HttpError_1 = __importDefault(require("../../support/utils/HttpError"));
const randomTextGenerator_1 = __importDefault(require("../../support/utils/randomTextGenerator"));
const regExpressions_1 = require("../../support/utils/regExpressions");
const utilities_1 = require("../../support/utils/utilities");
describe('multiStep dataset integration test', () => {
    const paabHelper = new paabHelper_1.PaabHelper(2);
    const setup = setup_1.default.getSetup();
    const settings = setup.getSettings();
    let adminSession;
    let pa1Session;
    let project1Id;
    let project2Id;
    beforeAll(async () => {
        const paabResources = await paabHelper.createResources(__filename);
        adminSession = paabResources.adminSession;
        project1Id = paabResources.project1Id;
        pa1Session = paabResources.pa1Session;
        project2Id = paabResources.project2Id;
    });
    afterAll(async () => {
        await paabHelper.cleanup();
    });
    test('Environment provisioning with DataSet', async () => {
        const randomTextGenerator = new randomTextGenerator_1.default(settings.get('runId'));
        const datasetName = randomTextGenerator.getFakeText('env-DS-test');
        // Create dataset
        const dataSetBody = createDataSetRequestParser_1.CreateDataSetRequestParser.parse({
            storageName: settings.get('DataSetsBucketName'),
            awsAccountId: settings.get('mainAccountId'),
            path: datasetName,
            name: datasetName,
            region: settings.get('awsRegion'),
            type: 'internal'
        });
        console.log('CREATE');
        const { data: dataSet } = await pa1Session.resources.projects
            .project(project1Id)
            .dataSets()
            .create(dataSetBody, false);
        expect(dataSet).toMatchObject({
            id: expect.stringMatching(regExpressions_1.dsUuidRegExp)
        });
        console.log('PROVISION ENVIRONMENT WITH DATASET');
        // Provision environment with dataset
        const envBody = {
            envTypeId: settings.get('envTypeId'),
            envTypeConfigId: settings.get('envTypeConfigId'),
            envType: settings.get('envType'),
            datasetIds: [dataSet.id],
            name: randomTextGenerator.getFakeText('dataset-name'),
            description: 'Temporary DataSet for integration test'
        };
        const { data: env } = await pa1Session.resources.projects
            .project(project1Id)
            .environments()
            .create(envBody);
        // Verify environment has access point for dataset
        const { data: envDetails } = await pa1Session.resources.projects
            .project(project1Id)
            .environments()
            .environment(env.id)
            .get();
        expect(envDetails).toMatchObject({
            ENDPOINTS: expect.arrayContaining([
                expect.objectContaining({
                    dataSetId: dataSet.id
                })
            ]),
            DATASETS: expect.arrayContaining([
                expect.objectContaining({
                    id: dataSet.id
                })
            ])
        });
        console.log('GET');
        // Verify dataset has env access point listed in its external endpoints
        const { data: dataSetDetails } = await pa1Session.resources.projects
            .project(project1Id)
            .dataSets()
            .dataset(dataSet.id)
            .get();
        // Dataset was created just for this test case, so we expect only one endpoint
        expect(dataSetDetails).toMatchObject(Object.assign({}, dataSetBody));
        console.log('ASSOCIATE WITH PROJECT');
        await pa1Session.resources.projects
            .project(project1Id)
            .dataSets()
            .dataset(dataSet.id)
            .associateWithProject(project2Id, 'read-only');
        console.log('ENSURE DUPLICATE ASSOCIATION WITH PROJECT THROWS');
        try {
            await pa1Session.resources.projects
                .project(project1Id)
                .dataSets()
                .dataset(dataSet.id)
                .associateWithProject(project2Id, 'read-only');
        }
        catch (e) {
            (0, utilities_1.checkHttpError)(e, new HttpError_1.default(409, {
                error: 'Conflict',
                message: `Project ${project2Id} is already associated with Dataset ${dataSet.id}`
            }));
        }
        console.log('ASSOCIATE WITH OWNING PROJECT THROWS');
        try {
            await pa1Session.resources.projects
                .project(project1Id)
                .dataSets()
                .dataset(dataSet.id)
                .associateWithProject(project1Id, 'read-only');
        }
        catch (e) {
            (0, utilities_1.checkHttpError)(e, new HttpError_1.default(409, {
                error: 'Conflict',
                message: `${project1Id} already owns this dataset`
            }));
        }
        console.log('DELETING A DATASET STILL ASSOCIATED WITH A PROJECT FAILS');
        try {
            await pa1Session.resources.projects.project(project1Id).dataSets().dataset(dataSet.id).delete();
        }
        catch (e) {
            (0, utilities_1.checkHttpError)(e, new HttpError_1.default(409, {
                error: 'Conflict',
                message: `DataSet ${dataSet.id} cannot be removed because it is still associated with roles in the provided project(s)`
            }));
        }
        console.log('DISASSOCIATING WITH OWNING PROJECT THROWS');
        try {
            await pa1Session.resources.projects
                .project(project1Id)
                .dataSets()
                .dataset(dataSet.id)
                .disassociateFromProject(project1Id);
        }
        catch (e) {
            (0, utilities_1.checkHttpError)(e, new HttpError_1.default(409, {
                error: 'Conflict',
                message: `${project1Id} cannot remove access from ${dataSet.id} for the ProjectAdmin because it owns that dataset.`
            }));
        }
        console.log('CHECK PROJECT PERMISSIONS FOR DATASET');
        const { data: responseData } = await pa1Session.resources.projects
            .project(project1Id)
            .dataSets()
            .dataset(dataSet.id)
            .listAccessPermissions();
        const sortedActual = responseData.data.permissions.sort((p1, p2) => p1.accessLevel.localeCompare(p2.accessLevel));
        const expected = [
            {
                accessLevel: 'read-only',
                identity: `${project2Id}#ProjectAdmin`,
                identityType: 'GROUP'
            },
            {
                accessLevel: 'read-only',
                identity: `${project2Id}#Researcher`,
                identityType: 'GROUP'
            },
            {
                accessLevel: 'read-write',
                identity: `${project1Id}#ProjectAdmin`,
                identityType: 'GROUP'
            },
            {
                accessLevel: 'read-write',
                identity: `${project1Id}#Researcher`,
                identityType: 'GROUP'
            }
        ];
        expect(sortedActual).toEqual(expected);
        console.log('DISASSOCIATE FROM PROJECT');
        await pa1Session.resources.projects
            .project(project1Id)
            .dataSets()
            .dataset(dataSet.id)
            .disassociateFromProject(project2Id);
        console.log('DELETE DATASET BEFORE ENDPOINT IS DELETED FAILS');
        try {
            await pa1Session.resources.projects.project(project1Id).dataSets().dataset(dataSet.id).delete();
        }
        catch (e) {
            (0, utilities_1.checkHttpError)(e, new HttpError_1.default(409, {
                error: 'Conflict',
                message: `External endpoints found on Dataset must be removed before DataSet can be removed.`
            }));
        }
        console.log('TERMINATE ENVIRONMENT & REMOVE DATASET');
        await (0, utilities_1.poll)(async () => {
            const { data: envData } = await pa1Session.resources.projects
                .project(project1Id)
                .environments()
                .environment(env.id)
                .get();
            console.log(`env status: ${envData.status}`);
            return envData;
        }, (data) => (data === null || data === void 0 ? void 0 : data.status) === 'COMPLETED' || (data === null || data === void 0 ? void 0 : data.status) === 'FAILED', constants_1.ENVIRONMENT_START_MAX_WAITING_SECONDS);
        try {
            await pa1Session.resources.projects.project(project1Id).environments().environment(env.id).stop();
            await (0, utilities_1.poll)(async () => {
                const { data: envData } = await pa1Session.resources.projects
                    .project(project1Id)
                    .environments()
                    .environment(env.id)
                    .get();
                console.log(`env status: ${envData.status}`);
                return envData;
            }, (data) => (data === null || data === void 0 ? void 0 : data.status) === 'STOPPED' || (data === null || data === void 0 ? void 0 : data.status) === 'FAILED', constants_1.ENVIRONMENT_STOP_MAX_WAITING_SECONDS);
        }
        catch (e) {
            console.error(JSON.stringify(e));
        }
        await pa1Session.resources.projects.project(project1Id).environments().environment(env.id).terminate();
        await (0, utilities_1.poll)(async () => {
            const { data: envData } = await pa1Session.resources.projects
                .project(project1Id)
                .environments()
                .environment(env.id)
                .get();
            console.log(`env status: ${envData.status}`);
            return envData;
        }, (data) => (data === null || data === void 0 ? void 0 : data.status) === 'TERMINATED' || (data === null || data === void 0 ? void 0 : data.status) === 'FAILED', constants_1.ENVIRONMENT_TERMINATE_MAX_WAITING_SECONDS);
        console.log('CREATE ENVIRONMENT WITH UNAUTHORIZED DATASET THROWS ERROR');
        await adminSession.resources.projects
            .project(project2Id)
            .assignUserToProject(pa1Session.getUserId(), { role: 'ProjectAdmin' });
        try {
            await pa1Session.resources.projects.project(project2Id).environments().create(envBody);
        }
        catch (e) {
            await adminSession.resources.projects
                .project(project2Id)
                .removeUserFromProject(pa1Session.getUserId());
            (0, utilities_1.checkHttpError)(e, new HttpError_1.default(403, {
                error: 'Forbidden',
                message: `${project2Id} does not have access to the provided dataset(s)`
            }));
        }
        await adminSession.resources.projects.project(project2Id).removeUserFromProject(pa1Session.getUserId());
    });
});
//# sourceMappingURL=dataset.test.js.map