UNPKG

@topgroup/diginext

Version:

A BUILD SERVER & CLI to deploy apps to any Kubernetes clusters.

279 lines (278 loc) 15.6 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WorkspaceService = void 0; const app_config_1 = require("../app.config"); const Workspace_1 = require("../entities/Workspace"); const DB_1 = require("../modules/api/DB"); const dx_email_1 = require("../modules/diginext/dx-email"); const dx_user_1 = require("../modules/diginext/dx-user"); const dx_workspace_1 = require("../modules/diginext/dx-workspace"); const array_1 = require("../plugins/array"); const cloud_storage_1 = require("../plugins/cloud-storage"); const mongodb_1 = require("../plugins/mongodb"); const user_utils_1 = require("../plugins/user-utils"); const seeds_1 = __importDefault(require("../seeds")); const BaseService_1 = __importDefault(require("./BaseService")); class WorkspaceService extends BaseService_1.default { constructor(ownership) { super(Workspace_1.workspaceSchema, ownership); } async create(data, options) { const { owner = mongodb_1.MongoDB.toString(this.user._id), name } = data; if (!name) throw new Error(`Param "name" is required.`); if (!owner) throw new Error(`Param "owner" (UserID) is required.`); // find owner let ownerUser = this.user; if (!ownerUser) throw new Error("Workspace's owner not found."); // Assign some default values if it's missing if (typeof data.public === "undefined") data.public = true; // ----- VERIFY DX KEY ----- // Create a workspace in "dxup.dev" if (!(0, app_config_1.IsTest)()) { if (!ownerUser.dxUserId) { // create user on "dxup.dev" via "dxApi" try { const dxUserRes = await (0, dx_user_1.dxCreateUser)({ name: ownerUser.name, username: ownerUser.username || ownerUser.slug, email: ownerUser.email, password: ownerUser.password, isActive: true, }); if (!dxUserRes.status) throw new Error(dxUserRes.messages.join("\n")); if (dxUserRes.data.id) { const { UserService } = await Promise.resolve().then(() => __importStar(require("./UserService"))); const userSvc = new UserService(this.ownership); ownerUser = await userSvc.updateOne({ _id: ownerUser._id }, { dxUserId: dxUserRes.data.id }); } } catch (e) { console.log(`[WorkspaceService] create > dxCreateUser :>>`, e); } } // create workspace on "dxup.dev" via "dxApi" try { const dataCreateWorkSpace = { name: name, public: data.public, email: ownerUser.email, userId: ownerUser.dxUserId, }; const createWsRes = await (0, dx_workspace_1.dxCreateWorkspace)(dataCreateWorkSpace); console.log("createWsRes:", createWsRes); if (!createWsRes.status) throw new Error(createWsRes.messages.join(".")); // assign DXSITE workspace ID and key to the workspace data.dx_key = createWsRes.data.subscriptionKey; data.dx_id = createWsRes.data._id; } catch (e) { console.log(`[WorkspaceService] create > dxCreateWorkspace :>>`, e); } } // console.log("Config.SERVER_TYPE :>> ", Config.SERVER_TYPE); // ----- END VERIFYING ----- // [1] Create new workspace: if (options === null || options === void 0 ? void 0 : options.isDebugging) console.log("WorkspaceService > CREATE > data :>> ", data); const newWorkspace = await super.create(data, options); if (options === null || options === void 0 ? void 0 : options.isDebugging) console.log("WorkspaceService > CREATE > ownerUser :>> ", ownerUser); if (options === null || options === void 0 ? void 0 : options.isDebugging) console.log("WorkspaceService > CREATE > newWorkspace :>> ", newWorkspace); if (!newWorkspace) throw new Error(`Failed to create new workspace.`); /** * [2] SEED INITIAL DATA TO THIS WORKSPACE * - Default roles * - Default permissions of routes * - Default API_KEY * - Default Service Account * - Default Frameworks * - Default Clusters (if any) */ await (0, seeds_1.default)(newWorkspace, ownerUser); // [3] Ownership: add this workspace to the creator {User} if it's not existed: ownerUser = await (0, user_utils_1.addUserToWorkspace)(owner, newWorkspace, "admin"); // [4] Set this workspace as "activeWorkspace" for this creator: ownerUser = await (0, user_utils_1.makeWorkspaceActive)(owner, mongodb_1.MongoDB.toString(newWorkspace._id)); return newWorkspace; } async update(filter, data, options) { const updatedWorkspace = await super.update(filter, data, options); if (!updatedWorkspace) throw new Error(`Failed to update workspace.`); return updatedWorkspace; } async delete(filter, options) { const { ApiKeyUserService } = await Promise.resolve().then(() => __importStar(require("./ApiKeyUserService"))); const { AppService } = await Promise.resolve().then(() => __importStar(require("./AppService"))); const { CloudDatabaseService } = await Promise.resolve().then(() => __importStar(require("./CloudDatabaseService"))); const { ClusterService } = await Promise.resolve().then(() => __importStar(require("./ClusterService"))); const { ContainerRegistryService } = await Promise.resolve().then(() => __importStar(require("./ContainerRegistryService"))); const { DeployEnvironmentService } = await Promise.resolve().then(() => __importStar(require("./DeployEnvironmentService"))); const { FrameworkService } = await Promise.resolve().then(() => __importStar(require("./FrameworkService"))); const { GitProviderService } = await Promise.resolve().then(() => __importStar(require("./GitProviderService"))); const { ProjectService } = await Promise.resolve().then(() => __importStar(require("./ProjectService"))); const { ReleaseService } = await Promise.resolve().then(() => __importStar(require("./ReleaseService"))); const { RoleService } = await Promise.resolve().then(() => __importStar(require("./RoleService"))); const { RouteService } = await Promise.resolve().then(() => __importStar(require("./RouteService"))); const { ServiceAccountService } = await Promise.resolve().then(() => __importStar(require("./ServiceAccountService"))); const { TeamService } = await Promise.resolve().then(() => __importStar(require("./TeamService"))); const { UserService } = await Promise.resolve().then(() => __importStar(require("./UserService"))); const userSvc = new UserService(this.ownership); const appSvc = new AppService(this.ownership); const projectSvc = new ProjectService(this.ownership); const deployEnvSvc = new DeployEnvironmentService(this.ownership); const roleSvc = new RoleService(this.ownership); const registrySvc = new ContainerRegistryService(this.ownership); const releaseSvc = new ReleaseService(this.ownership); const teamSvc = new TeamService(this.ownership); const routeSvc = new RouteService(this.ownership); const serviceAccountSvc = new ServiceAccountService(this.ownership); const apiKeySvc = new ApiKeyUserService(this.ownership); const gitSvc = new GitProviderService(this.ownership); const frameworkSvc = new FrameworkService(this.ownership); const clusterSvc = new ClusterService(this.ownership); const databaseSvc = new CloudDatabaseService(this.ownership); // delete workspace in user: const _user = await DB_1.DB.findOne("user", { workspaces: this.workspace._id }); const workspaces = _user.workspaces.filter((wsId) => mongodb_1.MongoDB.toString(wsId) !== mongodb_1.MongoDB.toString(this.workspace._id)); const updatedUser = await DB_1.DB.updateOne("user", { _id: _user._id }, { workspaces, activeWorkspace: undefined }); console.log("[WorkspaceService] delete > updatedUser :>> ", updatedUser); // delete related data: await projectSvc.delete({ workspace: this.workspace._id }); await appSvc.delete({ workspace: this.workspace._id }); await releaseSvc.delete({ workspace: this.workspace._id }); await clusterSvc.delete({ workspace: this.workspace._id }); await frameworkSvc.delete({ workspace: this.workspace._id }); await gitSvc.delete({ workspace: this.workspace._id }); await databaseSvc.delete({ workspace: this.workspace._id }); await apiKeySvc.delete({ workspace: this.workspace._id }); await serviceAccountSvc.delete({ workspace: this.workspace._id }); await registrySvc.delete({ workspace: this.workspace._id }); await roleSvc.delete({ workspace: this.workspace._id }); await routeSvc.delete({ workspace: this.workspace._id }); await teamSvc.delete({ workspace: this.workspace._id }); const deletedWorkspace = await super.delete(filter, options); return deletedWorkspace; } async inviteMember(data, options) { if (!data.emails || data.emails.length === 0) throw new Error(`List of email is required.`); if (!this.user) throw new Error(`Unauthenticated.`); const { UserService } = await Promise.resolve().then(() => __importStar(require("./UserService"))); const userSvc = new UserService(); const WcSvc = new WorkspaceService(); const { emails, role: roleType = "member" } = data; const workspace = this.user.activeWorkspace; const wsId = workspace._id; // console.log(`[WS_Controller] Invite Member > Workspace :>>`, workspace); const userId = this.user._id; // check if this user is admin of the workspace: const activeRole = this.user.activeRole; if (activeRole.type !== "admin" && activeRole.type !== "moderator") throw new Error(`You don't have permissions to invite users, please contact administrator.`); const assignedRole = await DB_1.DB.findOne("role", { type: roleType, workspace: wsId }, { ownership: this.ownership }); // console.log("assignedRole :>> ", assignedRole); // create temporary users of invited members: const invitedMembers = await Promise.all(emails.map(async (email) => { let existingUser = await DB_1.DB.findOne("user", { email }, { ignorable: true }); if (!existingUser) { const username = email.split("@")[0] || "New User"; const invitedMember = await userSvc.create({ active: false, name: username, email: email, workspaces: [wsId], roles: [assignedRole._id], }); return invitedMember; } else { // Set user to workspace in Dx site const joinWorkspaceRes = await (0, dx_workspace_1.dxJoinWorkspace)(email, workspace.slug, workspace.dx_key); // FIXME: check API error const workspaces = existingUser.workspaces || []; workspaces.push(wsId); existingUser = await DB_1.DB.updateOne("user", { _id: existingUser._id }, { workspaces: (0, array_1.filterUniqueItems)(workspaces) }); return existingUser; } })); // send invitation emails to those users: if (!(0, app_config_1.IsTest)()) { const mailContent = `Dear,<br/><br/>You've been invited to <strong>"${workspace.name}"</strong> workspace, please <a href="${app_config_1.Config.BASE_URL}" target="_blank">click here</a> to login.<br/><br/>Cheers,<br/>Diginext System`; // send invitation email to those users: const result = await (0, dx_email_1.dxSendEmail)({ recipients: invitedMembers.map((member) => { return { email: member.email }; }), subject: `[DXUP] "${this.user.name}" has invited you to join "${workspace.name}" workspace.`, content: mailContent, }, workspace.dx_key); } return workspace; } async addUser(data) { const { userId, workspaceId, roleId } = data; const uid = userId; const wsId = workspaceId; const { UserService } = await Promise.resolve().then(() => __importStar(require("./UserService"))); const { RoleService } = await Promise.resolve().then(() => __importStar(require("./RoleService"))); const userSvc = new UserService(this.ownership); const roleSvc = new RoleService(this.ownership); const user = await userSvc.findOne({ id: uid }); const workspace = await this.findOne({ id: wsId }); let role; if (roleId) role = await roleSvc.findOne({ id: roleId }); if (!user) throw new Error(`This user is not existed.`); if (!workspace) throw new Error(`This workspace is not existed.`); if (user.workspaces.includes(wsId)) throw new Error(`This user is existed in this workspace.`); const workspaces = [...user.workspaces, wsId].filter((_wsId) => typeof _wsId !== "undefined").map((_wsId) => mongodb_1.MongoDB.toString(_wsId)); const updatedUser = await userSvc.update({ id: uid }, { workspaces }); return workspace; } async testCloudStorage() { const cloudStorage = this.workspace.settings.cloud_storage; const uploaded = await (0, cloud_storage_1.uploadFileBuffer)(Buffer.from("Hello, world!"), "test.txt", { storage: cloudStorage }); console.log("uploaded :>> ", uploaded); return uploaded; } } exports.WorkspaceService = WorkspaceService;