"use strict";
/*
 *  Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *  SPDX-License-Identifier: Apache-2.0
 */
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProjectEnvTypeConfigService = void 0;
const swb_app_1 = require("@aws/swb-app");
const workbench_core_accounts_1 = require("@aws/workbench-core-accounts");
const workbench_core_authorization_1 = require("@aws/workbench-core-authorization");
const workbench_core_base_1 = require("@aws/workbench-core-base");
const roleUtils_1 = require("../utils/roleUtils");
class ProjectEnvTypeConfigService {
    constructor(metadataService, projectService, envTypeConfigService, envTypeService, environmentService, dynamicAuthService) {
        this._identityPermissionTemplate = {
            action: 'READ',
            effect: 'ALLOW',
            identityId: '',
            identityType: 'GROUP',
            subjectId: '',
            subjectType: "SWB_ETC" /* SwbAuthZSubject.SWB_ETC */
        };
        this._metadataService = metadataService;
        this._projectService = projectService;
        this._envTypeConfigService = envTypeConfigService;
        this._envTypeService = envTypeService;
        this._environmentService = environmentService;
        this._dynamicAuthService = dynamicAuthService;
    }
    async associateProjectWithEnvTypeConfig(request) {
        const { projectId, envTypeId, envTypeConfigId, user } = request;
        const project = await this._projectService.getProject({ projectId });
        if (project.status === workbench_core_accounts_1.ProjectStatus.DELETED) {
            throw new swb_app_1.ProjectDeletedError(`Project ${projectId} was deleted`);
        }
        await this._envTypeConfigService.getEnvironmentTypeConfig(envTypeId, envTypeConfigId);
        const composedId = `${envTypeId}${workbench_core_base_1.resourceTypeToKey.envTypeConfig}#${envTypeConfigId}`;
        await this._metadataService.updateRelationship(workbench_core_base_1.resourceTypeToKey.project, { id: projectId }, workbench_core_base_1.resourceTypeToKey.envType, [{ id: composedId, data: { id: envTypeConfigId } }]);
        await this._addAuthZPermissionsForETC(user, projectId, envTypeConfigId);
    }
    async disassociateProjectAndEnvTypeConfig(request) {
        const { projectId, envTypeId, envTypeConfigId, user } = request;
        await this._projectService.getProject({ projectId });
        await this._envTypeConfigService.getEnvironmentTypeConfig(envTypeId, envTypeConfigId);
        const composedId = `${envTypeId}${workbench_core_base_1.resourceTypeToKey.envTypeConfig}#${envTypeConfigId}`;
        await this._validateActiveEnvironments(projectId, envTypeId, envTypeConfigId, user);
        await this._removeAuthZPermissionsForETC(user, projectId, envTypeConfigId);
        await this._metadataService.deleteRelationships(workbench_core_base_1.resourceTypeToKey.project, projectId, workbench_core_base_1.resourceTypeToKey.envType, [composedId]);
    }
    async listProjectEnvTypeConfigs(request) {
        var _a;
        const { projectId, envTypeId } = request, pagionationParams = __rest(request, ["projectId", "envTypeId"]);
        await this._projectService.getProject({ projectId });
        await this._envTypeService.getEnvironmentType(envTypeId);
        const composedType = `${workbench_core_base_1.resourceTypeToKey.envType}#${envTypeId}${workbench_core_base_1.resourceTypeToKey.envTypeConfig}`;
        const relationshipIds = await this._metadataService.listDependentMetadata(workbench_core_base_1.resourceTypeToKey.project, projectId, composedType, workbench_core_base_1.RelationshipDDBItemParser, pagionationParams);
        const envTypeConfigs = ((_a = relationshipIds === null || relationshipIds === void 0 ? void 0 : relationshipIds.data) === null || _a === void 0 ? void 0 : _a.length) > 0
            ? await this._envTypeConfigService.getEnvironmentTypeConfigs(relationshipIds.data.map((r) => r.id))
            : [];
        return {
            data: envTypeConfigs,
            paginationToken: relationshipIds.paginationToken
        };
    }
    async listEnvTypeConfigProjects(request) {
        var _a;
        const { envTypeId, envTypeConfigId } = request, pagionationParams = __rest(request, ["envTypeId", "envTypeConfigId"]);
        await this._envTypeConfigService.getEnvironmentTypeConfig(envTypeId, envTypeConfigId);
        const composedType = `${workbench_core_base_1.resourceTypeToKey.envType}#${envTypeId}${workbench_core_base_1.resourceTypeToKey.envTypeConfig}`;
        const relationshipIds = await this._metadataService.listDependentMetadata(composedType, envTypeConfigId, workbench_core_base_1.resourceTypeToKey.project, workbench_core_base_1.RelationshipDDBItemParser, pagionationParams);
        const projects = ((_a = relationshipIds === null || relationshipIds === void 0 ? void 0 : relationshipIds.data) === null || _a === void 0 ? void 0 : _a.length) > 0
            ? await this._projectService.getProjects({ projectIds: relationshipIds.data.map((r) => r.id) })
            : [];
        return {
            data: projects,
            paginationToken: relationshipIds.paginationToken
        };
    }
    async getEnvTypeConfig(request) {
        const { projectId, envTypeId, envTypeConfigId } = request;
        const composedType = `${workbench_core_base_1.resourceTypeToKey.envType}#${envTypeId}${workbench_core_base_1.resourceTypeToKey.envTypeConfig}`;
        const relationshipItem = await this._metadataService.getMetadataItem(workbench_core_base_1.resourceTypeToKey.project, projectId, composedType, envTypeConfigId, workbench_core_base_1.RelationshipDDBItemParser);
        if (!relationshipItem) {
            return undefined;
        }
        return await this._envTypeConfigService.getEnvironmentTypeConfig(envTypeId, envTypeConfigId);
    }
    async _addAuthZPermissionsForETC(authenticatedUser, projectId, envTypeConfigId) {
        var _a, _b;
        const identityPermissions = [];
        const adminIdentity = Object.assign(Object.assign({}, this._identityPermissionTemplate), { identityId: (0, roleUtils_1.getProjectAdminRole)(projectId), subjectId: envTypeConfigId });
        const researcherIdentity = Object.assign(Object.assign({}, this._identityPermissionTemplate), { identityId: (0, roleUtils_1.getResearcherRole)(projectId), subjectId: envTypeConfigId });
        identityPermissions.push(adminIdentity);
        identityPermissions.push(researcherIdentity);
        const existingIdentities = await this._dynamicAuthService.getIdentityPermissionsBySubject({
            action: 'READ',
            identities: [
                { identityType: adminIdentity.identityType, identityId: adminIdentity.identityId },
                { identityType: researcherIdentity.identityType, identityId: researcherIdentity.identityId }
            ],
            subjectType: adminIdentity.subjectType,
            subjectId: adminIdentity.subjectId
        });
        if (((_b = (_a = existingIdentities === null || existingIdentities === void 0 ? void 0 : existingIdentities.data) === null || _a === void 0 ? void 0 : _a.identityPermissions) === null || _b === void 0 ? void 0 : _b.length) > 0)
            //identity already exists
            return Promise.resolve();
        const createRequest = workbench_core_authorization_1.CreateIdentityPermissionsRequestParser.parse({
            authenticatedUser,
            identityPermissions
        });
        await this._dynamicAuthService.createIdentityPermissions(createRequest);
    }
    async _removeAuthZPermissionsForETC(authenticatedUser, projectId, envTypeConfigId) {
        const identityPermissions = [];
        identityPermissions.push(Object.assign(Object.assign({}, this._identityPermissionTemplate), { identityId: (0, roleUtils_1.getProjectAdminRole)(projectId), subjectId: envTypeConfigId }));
        identityPermissions.push(Object.assign(Object.assign({}, this._identityPermissionTemplate), { identityId: (0, roleUtils_1.getResearcherRole)(projectId), subjectId: envTypeConfigId }));
        const deleteRequest = workbench_core_authorization_1.DeleteIdentityPermissionsRequestParser.parse({
            authenticatedUser,
            identityPermissions
        });
        await this._dynamicAuthService.deleteIdentityPermissions(deleteRequest);
    }
    async _validateActiveEnvironments(projectId, envTypeId, envTypeConfigId, user) {
        const typeId = `${workbench_core_base_1.resourceTypeToKey.envType}#${envTypeId}${workbench_core_base_1.resourceTypeToKey.envTypeConfig}#${envTypeConfigId}`;
        let paginationToken = undefined;
        do {
            const dependencies = await this._environmentService.listEnvironments({
                filter: { type: { eq: typeId } },
                pageSize: 200,
                paginationToken
            });
            if (dependencies === null || dependencies === void 0 ? void 0 : dependencies.data) {
                const activeEnvironments = dependencies.data.filter((e) => e.status !== 'FAILED' && e.projectId === projectId);
                if (activeEnvironments.length > 0) {
                    const activeEnvironmentsSummary = activeEnvironments
                        .map((e) => `Environment:'${e.id}' Status:'${e.status}'`)
                        .join('\n');
                    throw new swb_app_1.ConflictError(`There are active environments using this configuration: ${activeEnvironmentsSummary}. Please Terminate environments or wait until environments are in 'TERMINATED' status before trying to disassociate configuration.`);
                }
                paginationToken = dependencies.paginationToken;
            }
        } while (paginationToken !== undefined);
    }
}
exports.ProjectEnvTypeConfigService = ProjectEnvTypeConfigService;
//# sourceMappingURL=projectEnvTypeConfigService.js.map