Skip to content
Open
36 changes: 36 additions & 0 deletions backend/src/v5/middleware/dataConverter/inputs/teamspaces/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@

const { createResponseCode, templates } = require('../../../../utils/responseCodes');
const { SUBSCRIPTION_TYPES } = require('../../../../models/teamspaces.constants');
const Yup = require('yup');
const YupHelper = require('../../../../utils/helper/yup');
const { getTeamspaceByAccount } = require('../../../../services/sso/frontegg/components/accounts');
const { getTeamspaceSetting } = require('../../../../models/teamspaceSettings');
const { getUserFromSession } = require('../../../../utils/sessions');
const { isTeamspaceAdmin } = require('../../../../utils/permissions');
const { isTeamspaceMember } = require('../../../../processors/teamspaces');
Expand Down Expand Up @@ -77,4 +81,36 @@ Teamspaces.validateUpdateQuota = async (req, res, next) => {
}
};

Teamspaces.validateCreateTeamspaceData = async (req, res, next) => {
const schema = Yup.object().shape({
name: YupHelper.validators.alphanumeric(Yup.string().max(128).required()
.test('check-name-is-not-used', 'Teamspace with this name already exists.', async (value) => {
if (!value) return true;
try {
await getTeamspaceSetting(value, { _id: 1 });
return false;
} catch {
return true;
}
}), false),
admin: YupHelper.types.strings.email.optional(),
accountId: Yup.string().optional()
.test('check-account-exists', 'Account with this ID does not exist.', async (value) => {
if (!value) return true;
if (await getTeamspaceByAccount(value)) {
return true;
}
return false;
}),
});

try {
req.body = await schema.validate(req.body, { stripUnknown: true });

await next();
} catch (err) {
respond(req, res, createResponseCode(templates.invalidArguments, err?.message));
}
};

module.exports = Teamspaces;
73 changes: 72 additions & 1 deletion backend/src/v5/routes/teamspaces/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

const { canRemoveTeamspaceMember, memberExists, validateUpdateQuota } = require('../../middleware/dataConverter/inputs/teamspaces');
const { canRemoveTeamspaceMember, memberExists, validateCreateTeamspaceData, validateUpdateQuota } = require('../../middleware/dataConverter/inputs/teamspaces');

const { hasAccessToTeamspace, isMemberOfTeamspace, isTeamspaceAdmin } = require('../../middleware/permissions');

const { DEFAULT_OWNER_JOB } = require('../../models/jobs.constants');
const { Router } = require('express');
const { SUBSCRIPTION_TYPES } = require('../../models/teamspaces.constants');
const Teamspaces = require('../../processors/teamspaces');
const Users = require('../../processors/users');
/* istanbul ignore file */
const { v4Path } = require('../../../interop');
// eslint-disable-next-line import/no-dynamic-require, security/detect-non-literal-require, require-sort/require-sort
const { create: createInvite } = require(`${v4Path}/models/invitations`);
const { fileExtensionFromBuffer } = require('../../utils/helper/typeCheck');
const { getUserByEmail } = require('../../models/users');
const { notUserProvisioned } = require('../../middleware/permissions/components/teamspaces');
const { respond } = require('../../utils/responder');
const { templates } = require('../../utils/responseCodes');
Expand Down Expand Up @@ -131,6 +138,34 @@ const removeQuota = async (req, res) => {
}
};

const createTeamspace = async (req, res) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this method should just call initTeamspace. The user invitation will be handled by frontegg.

In any case even if we had to send the invitation we should do this in the processor not in routes and not using a v4 method 😄

const { name, accountId, admin } = req.body;
let userName;

try {
if (admin) {
const result = await getUserByEmail(admin)
.catch((e) => {
if (e.message !== templates.userNotFound.message) throw e;
return {};
});

userName = result.user;
}

await Teamspaces.initTeamspace(name, userName, accountId);

if (!userName && admin) {
await createInvite(admin, name, DEFAULT_OWNER_JOB, undefined, { teamspace_admin: true }, false);
}

respond(req, res, templates.ok);
} catch (err) {
// istanbul ignore next
respond(req, res, err);
}
};

const establishRoutes = (isInternal) => {
const router = Router({ mergeParams: true });

Expand Down Expand Up @@ -196,6 +231,42 @@ const establishRoutes = (isInternal) => {
* description: quota has been removed
*/
router.delete('/:teamspace/quota', isMemberOfTeamspace, removeQuota);

/**
* @openapi
* /teamspaces:
* post:
* description: Create a new teamspace
* tags: [v:internal, Teamspaces]
* operationId: createTeamspace
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* name:
* type: string
* description: Name of the teamspace to be created
* example: New Teamspace
* accountId:
* type: string
* description: The account ID the teamspace will belong to
* example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
* admin:
* type: string
* description: The email of the owner of the teamspace
* example: [email protected]
* responses:
* 200:
* description: Teamspace created successfully
* 400:
* $ref: "#/components/responses/invalidArguments"
* 409:
* $ref: "#/components/responses/resourceAlreadyExists"
*/
router.post('/', validateCreateTeamspaceData, createTeamspace);
} else {
/**
* @openapi
Expand Down
Loading
Loading