@topgroup/diginext
Version:
A BUILD SERVER & CLI to deploy apps to any Kubernetes clusters.
279 lines (278 loc) • 15.6 kB
JavaScript
;
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;