diff --git a/codecov.yaml b/codecov.yaml index 58b6b2592..a1c074a06 100644 --- a/codecov.yaml +++ b/codecov.yaml @@ -11,7 +11,7 @@ coverage: default: target: auto # don't allow new commits to decrease coverage - threshold: 0% + threshold: 1% patch: # measuring the coverage of new changes default: diff --git a/src/api.v2/controllers/__mocks__/accessController.js b/src/api.v2/controllers/__mocks__/accessController.js index bbf1c265c..81a817376 100644 --- a/src/api.v2/controllers/__mocks__/accessController.js +++ b/src/api.v2/controllers/__mocks__/accessController.js @@ -1,9 +1,5 @@ -const mockGetUserAccess = jest.fn(); -const mockInviteUser = jest.fn(); -const mockRevokeAccess = jest.fn(); +const mockGetExperimentUsers = jest.fn(); module.exports = { - getUserAccess: mockGetUserAccess, - inviteUser: mockInviteUser, - revokeAccess: mockRevokeAccess, + getExperimentUsers: mockGetExperimentUsers, }; diff --git a/src/api.v2/controllers/__mocks__/cellSetsController.js b/src/api.v2/controllers/__mocks__/cellSetsController.js deleted file mode 100644 index 81147f95f..000000000 --- a/src/api.v2/controllers/__mocks__/cellSetsController.js +++ /dev/null @@ -1,7 +0,0 @@ -const mockGetCellSets = jest.fn(); -const mockPatchCellSets = jest.fn(); - -module.exports = { - getCellSets: mockGetCellSets, - patchCellSets: mockPatchCellSets, -}; diff --git a/src/api.v2/controllers/accessController.js b/src/api.v2/controllers/accessController.js index 68ba876c8..68979340d 100644 --- a/src/api.v2/controllers/accessController.js +++ b/src/api.v2/controllers/accessController.js @@ -1,51 +1,19 @@ -const getExperimentUsers = require('../helpers/access/getExperimentUsers'); -const createUserInvite = require('../helpers/access/createUserInvite'); -const removeAccess = require('../helpers/access/removeAccess'); - -const OK = require('../../utils/responses/OK'); +const getUserRoles = require('../helpers/access/getUserRoles'); const getLogger = require('../../utils/getLogger'); const logger = getLogger('[AccessController] - '); -const getUserAccess = async (req, res) => { +const getExperimentUsers = async (req, res) => { const { experimentId } = req.params; logger.log(`Fetching users for experiment ${experimentId}`); - const users = await getExperimentUsers(experimentId); + const users = await getUserRoles(experimentId); logger.log(`Users fetched for experiment ${experimentId}`); res.json(users); }; -const inviteUser = async (req, res) => { - const { experimentId } = req.params; - const { - userEmail, role, - } = req.body; - - logger.log(`Inviting users to experiment ${experimentId}`); - await createUserInvite(experimentId, userEmail, role, req.user); - - logger.log(`Users invited to experiment ${experimentId}`); - - res.json(OK()); -}; - -const revokeAccess = async (req, res) => { - const { experimentId } = req.params; - const { userEmail } = req.body; - - logger.log(`Deleting user access from experiment ${experimentId}`); - await removeAccess(experimentId, userEmail); - - logger.log(`User access deleted from experiment ${experimentId}`); - - res.json(OK()); -}; - module.exports = { - getUserAccess, - inviteUser, - revokeAccess, + getExperimentUsers, }; diff --git a/src/api.v2/controllers/cellSetsController.js b/src/api.v2/controllers/cellSetsController.js deleted file mode 100644 index e946c76e3..000000000 --- a/src/api.v2/controllers/cellSetsController.js +++ /dev/null @@ -1,45 +0,0 @@ -const getLogger = require('../../utils/getLogger'); - -const getS3Object = require('../helpers/s3/getObject'); -const bucketNames = require('../helpers/s3/bucketNames'); -const formatExperimentId = require('../../utils/v1Compatibility/formatExperimentId'); - -const { OK } = require('../../utils/responses'); - -const patchCellSetsObject = require('../helpers/s3/patchCellSetsObject'); - -const logger = getLogger('[CellSetsController] - '); - -const getCellSets = async (req, res) => { - let { experimentId } = req.params; - - experimentId = experimentId.replace(/-/g, ''); - - logger.log(`Getting cell sets for experiment ${experimentId}`); - - const cellSets = await getS3Object({ - Bucket: bucketNames.CELL_SETS, - Key: formatExperimentId(experimentId), - }); - - logger.log(`Finished getting cell sets for experiment ${experimentId}`); - - res.send(cellSets); -}; - -const patchCellSets = async (req, res) => { - const { experimentId } = req.params; - const patch = req.body; - - logger.log(`Patching cell sets for ${experimentId}`); - await patchCellSetsObject(formatExperimentId(experimentId), patch); - - logger.log(`Finished patching cell sets for experiment ${experimentId}`); - - res.json(OK()); -}; - -module.exports = { - getCellSets, - patchCellSets, -}; diff --git a/src/api.v2/helpers/access/createUserInvite.js b/src/api.v2/helpers/access/createUserInvite.js deleted file mode 100644 index 819fc4ebe..000000000 --- a/src/api.v2/helpers/access/createUserInvite.js +++ /dev/null @@ -1,43 +0,0 @@ -const UserAccess = require('../../model/UserAccess'); - -const { getAwsUserAttributesByEmail } = require('../../../utils/aws/user'); -const sendEmail = require('../../../utils/send-email'); -const buildUserInvitedEmailBody = require('../../../utils/emailTemplates/buildUserInvitedEmailBody'); -const buildUserInvitedNotRegisteredEmailBody = require('../../../utils/emailTemplates/buildUserInvitedNotRegisteredEmailBody'); - -const OK = require('../../../utils/responses/OK'); - -const getLogger = require('../../../utils/getLogger'); - -const logger = getLogger('[AccessModel] - '); - -const createUserInvite = async (experimentId, userEmail, role, inviterUser) => { - let userAttributes; - try { - userAttributes = await getAwsUserAttributesByEmail(userEmail); - } catch (e) { - if (e.code !== 'UserNotFoundException') { - throw e; - } - - logger.log('User has not yet signed up, inviting new user'); - } - - - let emailBody; - if (!userAttributes) { - new UserAccess().addToInviteAccess(userEmail, experimentId, role); - emailBody = buildUserInvitedNotRegisteredEmailBody(userEmail, inviterUser); - // User is added to experiment after they registered using post-register-lambda defined in IAC. - } else { - const userSub = userAttributes.find((attr) => attr.Name === 'sub').Value; - new UserAccess().grantAccess(userSub, experimentId, role); - emailBody = buildUserInvitedEmailBody(userEmail, experimentId, inviterUser); - } - - await sendEmail(emailBody); - - return OK(); -}; - -module.exports = createUserInvite; diff --git a/src/api.v2/helpers/access/getExperimentUsers.js b/src/api.v2/helpers/access/getUserRoles.js similarity index 68% rename from src/api.v2/helpers/access/getExperimentUsers.js rename to src/api.v2/helpers/access/getUserRoles.js index 0cf76ccf8..916e8f5db 100644 --- a/src/api.v2/helpers/access/getExperimentUsers.js +++ b/src/api.v2/helpers/access/getUserRoles.js @@ -1,10 +1,18 @@ -const { getAwsUserAttributesByEmail } = require('../../../utils/aws/user'); +const config = require('../../../config'); const UserAccess = require('../../model/UserAccess'); const AccessRole = require('../../../utils/enums/AccessRole'); -const getExperimentUsers = async (experimentId) => { +const { cognitoISP } = config; + +const getAwsUserAttributesByEmail = async (email) => { + const poolId = await config.awsUserPoolIdPromise; + const user = await cognitoISP.adminGetUser({ UserPoolId: poolId, Username: email }).promise(); + return user.UserAttributes; +}; + +const getUserRoles = async (experimentId) => { const userData = await new UserAccess().getExperimentUsers(experimentId); // Remove admin from user list @@ -31,4 +39,4 @@ const getExperimentUsers = async (experimentId) => { return experimentUsers; }; -module.exports = getExperimentUsers; +module.exports = getUserRoles; diff --git a/src/api.v2/helpers/access/removeAccess.js b/src/api.v2/helpers/access/removeAccess.js deleted file mode 100644 index 6f45281fb..000000000 --- a/src/api.v2/helpers/access/removeAccess.js +++ /dev/null @@ -1,12 +0,0 @@ -const { getAwsUserAttributesByEmail } = require('../../../utils/aws/user'); - -const UserAccess = require('../../model/UserAccess'); - -const removeAccess = async (experimentId, userEmail) => { - const userAttributes = await getAwsUserAttributesByEmail(userEmail); - const userId = userAttributes.find((attr) => attr.Name === 'sub').Value; - - new UserAccess().removeAccess(userId, experimentId); -}; - -module.exports = removeAccess; diff --git a/src/api.v2/helpers/s3/bucketNames.js b/src/api.v2/helpers/s3/bucketNames.js index 93250b727..3a0cdca5e 100644 --- a/src/api.v2/helpers/s3/bucketNames.js +++ b/src/api.v2/helpers/s3/bucketNames.js @@ -2,7 +2,6 @@ const config = require('../../../config'); const bucketNames = { SAMPLE_FILES: `biomage-originals-${config.clusterEnv}`, - CELL_SETS: `cell-sets-${config.clusterEnv}`, }; module.exports = bucketNames; diff --git a/src/api.v2/helpers/s3/getObject.js b/src/api.v2/helpers/s3/getObject.js deleted file mode 100644 index a5ded1b3e..000000000 --- a/src/api.v2/helpers/s3/getObject.js +++ /dev/null @@ -1,27 +0,0 @@ -const getS3Client = require('./getS3Client'); -const NotFoundError = require('../../../utils/responses/NotFoundError'); - -const getObject = async (params) => { - if (!params.Bucket) throw new Error('Bucket is required'); - if (!params.Key) throw new Error('Key is required'); - - const s3 = getS3Client(); - - try { - const outputObject = await s3.getObject(params).promise(); - const data = outputObject.Body.toString(); - return data; - } catch (e) { - if (e.code === 'NoSuchKey') { - throw new NotFoundError(`Couldn't find object with key: ${params.Key}`); - } - - if (e.code === 'NoSuchBucket') { - throw new NotFoundError(`Couldn't find bucket with key: ${params.Bucket}`); - } - - throw e; - } -}; - -module.exports = getObject; diff --git a/src/api.v2/helpers/s3/getS3Client.js b/src/api.v2/helpers/s3/getS3Client.js deleted file mode 100644 index 6f7f9b540..000000000 --- a/src/api.v2/helpers/s3/getS3Client.js +++ /dev/null @@ -1,18 +0,0 @@ -const AWS = require('../../../utils/requireAWS'); -const config = require('../../../config'); - -// Wanted to make this a wrapper class that extends S3, -// but it's not advisable to do so: -// https://github.com/aws/aws-sdk-js/issues/2006 -const getS3Client = (options) => { - const S3Config = { - apiVersion: '2006-03-01', - signatureVersion: 'v4', - region: config.awsRegion, - ...options, - }; - - return new AWS.S3(S3Config); -}; - -module.exports = getS3Client; diff --git a/src/api.v2/helpers/s3/patchCellSetsObject.js b/src/api.v2/helpers/s3/patchCellSetsObject.js deleted file mode 100644 index 2cadaa168..000000000 --- a/src/api.v2/helpers/s3/patchCellSetsObject.js +++ /dev/null @@ -1,39 +0,0 @@ -const jsonMerger = require('json-merger'); - -const bucketNames = require('./bucketNames'); -const getObject = require('./getObject'); -const putObject = require('./putObject'); - -const validateRequest = require('../../../utils/schema-validator'); - -const patchCellSetsObject = async (experimentId, patch) => { - const currentCellSet = await getObject({ - Bucket: bucketNames.CELL_SETS, - Key: experimentId, - }); - - const { cellSets: prePatchCellSets } = currentCellSet; - - /** - * The $remove operation will replace the element in the array with an - * undefined value. We will therefore remove this from the array. - * - * We use the $remove operation in the worker to update cell clusters, - * and we may end up using it in other places in the future. - */ - const patchedCellSetslist = jsonMerger.mergeObjects( - [prePatchCellSets, patch], - ).filter((x) => x !== undefined); - - const patchedCellSets = { cellSets: patchedCellSetslist }; - - await validateRequest(patchedCellSets, 'cell-sets-bodies/CellSets.v2.yaml'); - - await putObject({ - Bucket: bucketNames.CELL_SETS, - Key: experimentId, - Body: JSON.stringify(patchedCellSets), - }); -}; - -module.exports = patchCellSetsObject; diff --git a/src/api.v2/helpers/s3/putObject.js b/src/api.v2/helpers/s3/putObject.js deleted file mode 100644 index a87123097..000000000 --- a/src/api.v2/helpers/s3/putObject.js +++ /dev/null @@ -1,22 +0,0 @@ -const NotFoundError = require('../../../utils/responses/NotFoundError'); -const getS3Client = require('./getS3Client'); - -const putObject = async (params) => { - if (!params.Bucket) throw new Error('Bucket is required'); - if (!params.Key) throw new Error('Key is required'); - if (!params.Body) throw new Error('Body is required'); - - const s3 = getS3Client(); - - try { - await s3.putObject(params).promise(); - } catch (e) { - if (e.code === 'NoSuchBucket') { - throw new NotFoundError(`Couldn't find bucket with key: ${params.Bucket}`); - } - - throw e; - } -}; - -module.exports = putObject; diff --git a/src/api.v2/model/UserAccess.js b/src/api.v2/model/UserAccess.js index ae899d2e9..7e3f5ec3a 100644 --- a/src/api.v2/model/UserAccess.js +++ b/src/api.v2/model/UserAccess.js @@ -38,34 +38,21 @@ class UserAccess extends BasicModel { return experimentUsers; } - async addToInviteAccess(userId, experimentId, role) { - return await this.sql - .insert({ user_id: userId, experiment_id: experimentId, access_role: role }) - .into(tableNames.INVITE_ACCESS); - } - - async grantAccess(userId, experimentId, role) { - return await this.create( - { user_id: userId, experiment_id: experimentId, access_role: role }, - ); - } - - async removeAccess(userId, experimentId) { - return await this.delete({ experiment_id: experimentId, user_id: userId }); - } - async createNewExperimentPermissions(userId, experimentId) { logger.log('Setting up access permissions for experiment'); - // Create admin permissions - await this.grantAccess(config.adminSub, experimentId, AccessRole.ADMIN); + await this.create( + { user_id: config.adminSub, experiment_id: experimentId, access_role: AccessRole.ADMIN }, + ); if (userId === config.adminSub) { logger.log('User is the admin, so only creating admin access'); return; } - await this.grantAccess(userId, experimentId, AccessRole.OWNER); + await this.create( + { user_id: userId, experiment_id: experimentId, access_role: AccessRole.OWNER }, + ); } async canAccessExperiment(userId, experimentId, url, method) { diff --git a/src/api.v2/routes/access.js b/src/api.v2/routes/access.js index 99be81b0c..215cb6d67 100644 --- a/src/api.v2/routes/access.js +++ b/src/api.v2/routes/access.js @@ -1,7 +1,5 @@ const { - getUserAccess, - inviteUser, - revokeAccess, + getExperimentUsers, } = require('../controllers/accessController'); const { expressAuthorizationMiddleware } = require('../middlewares/authMiddlewares'); @@ -9,14 +7,6 @@ const { expressAuthorizationMiddleware } = require('../middlewares/authMiddlewar module.exports = { 'access#getExperimentUsers': [ expressAuthorizationMiddleware, - (req, res, next) => getUserAccess(req, res).catch(next), - ], - 'access#inviteUser': [ - expressAuthorizationMiddleware, - (req, res, next) => inviteUser(req, res).catch(next), - ], - 'access#revokeAccess': [ - expressAuthorizationMiddleware, - (req, res, next) => revokeAccess(req, res).catch(next), + (req, res, next) => getExperimentUsers(req, res).catch(next), ], }; diff --git a/src/api.v2/routes/cellSets.js b/src/api.v2/routes/cellSets.js deleted file mode 100644 index ef062e0b0..000000000 --- a/src/api.v2/routes/cellSets.js +++ /dev/null @@ -1,17 +0,0 @@ -const { - getCellSets, - patchCellSets, -} = require('../controllers/cellSetsController'); - -const { expressAuthorizationMiddleware } = require('../middlewares/authMiddlewares'); - -module.exports = { - 'cellSets#getCellSets': [ - expressAuthorizationMiddleware, - (req, res, next) => getCellSets(req, res).catch(next), - ], - 'cellSets#patchCellSets': [ - expressAuthorizationMiddleware, - (req, res, next) => patchCellSets(req, res).catch(next), - ], -}; diff --git a/src/specs/api.v2.yaml b/src/specs/api.v2.yaml index 62304fc15..a2679e795 100644 --- a/src/specs/api.v2.yaml +++ b/src/specs/api.v2.yaml @@ -58,84 +58,6 @@ paths: - env - clusterEnv description: Returns a status on the health of the API. - - '/experiments/{experimentId}/cellSets': - parameters: - - name: experimentId - in: path - description: ID of experiment to find cell sets of. - required: true - schema: - type: string - get: - tags: - - experiments - summary: Get cell sets for experiment - description: Returns a hirearchical view of cell sets in the experiment. - operationId: getExperimentCellSets - x-eov-operation-id: cellSets#getCellSets - x-eov-operation-handler: routes/cellSets - responses: - '200': - description: 'Request successful, hierarchy returned below.' - content: - application/json: - schema: - $ref: '#/components/schemas/CellSets' - '401': - description: The request lacks authentication credentials. - content: - application/json: - schema: - $ref: ./models/HTTPError.v1.yaml - '403': - description: The authenticated user is not authorized to view this resource. - content: - application/json: - schema: - $ref: ./models/HTTPError.v1.yaml - '404': - description: Experiment not found. - content: - application/json: - schema: - $ref: ./models/HTTPError.v1.yaml - patch: - summary: '' - operationId: patchExperimentCellSets - x-eov-operation-id: cellSets#patchCellSets - x-eov-operation-handler: routes/cellSets - responses: - '200': - description: Update to object in response successful. - content: - application/json: - schema: - type: object - properties: {} - '401': - description: The request lacks authentication credentials. - content: - application/json: - schema: - $ref: ./models/HTTPError.v1.yaml - '403': - description: The authenticated user is not authorized to view this resource. - content: - application/json: - schema: - $ref: ./models/HTTPError.v1.yaml - description: Performs a partial update on the experiment's cell sets. - requestBody: - content: - application/boschni-json-merger+json: - schema: - oneOf: - - type: array - items: {} - - type: object - description: The patch in the format declared by boschni/json-merger. Note the explicit naming of the content subtype (boschni-json-merger+json) which must be used to explicitly acknowledge the format. - '/experiments/{experimentId}/processingConfig': get: summary: Get processing configuration for an experiment @@ -906,11 +828,11 @@ paths: application/json: schema: $ref: '#/components/schemas/HTTPError' - + '/access/{experimentId}': get: summary: Get the users with access to an experiment - operationId: getAccess + operationId: get-access x-eov-operation-id: access#getExperimentUsers x-eov-operation-handler: routes/access description: Returns the users with access to the experiment @@ -939,75 +861,6 @@ paths: application/json: schema: $ref: ./models/HTTPError.v1.yaml - put: - summary: Add user to an experiment - operationId: inviteUser - x-eov-operation-id: access#inviteUser - x-eov-operation-handler: routes/access - description: Adds permissions for the user email for the experiment from the body - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: ./models/HTTPSuccess.v1.yaml - '404': - description: User not found - content: - application/json: - schema: - $ref: ./models/HTTPError.v1.yaml - requestBody: - content: - application/json: - schema: - type: object - properties: - userEmail: - type: string - role: - type: string - required: - - userEmail - - role - delete: - summary: Revoke access to users - operationId: deleteAccess - x-eov-operation-id: access#revokeAccess - x-eov-operation-handler: routes/access - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: ./models/HTTPSuccess.v1.yaml - '404': - description: Role not found - content: - application/json: - schema: - $ref: ./models/HTTPError.v1.yaml - '403': - description: The user does not have permissions to revoke the role. - content: - application/json: - schema: - $ref: ./models/HTTPError.v1.yaml - description: Delete a role for a user in experiment - requestBody: - content: - application/json: - schema: - type: object - properties: - userEmail: - type: string - minLength: 1 - required: - - userEmail - description: email of the user to remove from experiment /kubernetesEvents: post: summary: Monitoring of kubernetes cluster events @@ -1051,8 +904,6 @@ components: $ref: './models/samples-bodies/CreateSampleFile.v2.yaml' PatchSampleFile: $ref: './models/samples-bodies/PatchSampleFile.v2.yaml' - CellSets: - $ref: ./models/cell-sets-bodies/CellSets.v2.yaml HTTPSuccess: $ref: './models/HTTPSuccess.v1.yaml' HTTPError: diff --git a/src/specs/models/cell-sets-bodies/CellSet.v2.yaml b/src/specs/models/cell-sets-bodies/CellSet.v2.yaml deleted file mode 100644 index ca97d4b53..000000000 --- a/src/specs/models/cell-sets-bodies/CellSet.v2.yaml +++ /dev/null @@ -1,18 +0,0 @@ -title: Cell Set -description: An object representing a cell set (e.g. Cluster 1) -type: object -properties: - key: - type: string - name: - type: string - rootNode: - type: boolean - cellIds: - type: array - items: - type: integer -required: - - key - - name - - cellIds \ No newline at end of file diff --git a/src/specs/models/cell-sets-bodies/CellSetClass.v2.yaml b/src/specs/models/cell-sets-bodies/CellSetClass.v2.yaml deleted file mode 100644 index dbd03b4ab..000000000 --- a/src/specs/models/cell-sets-bodies/CellSetClass.v2.yaml +++ /dev/null @@ -1,18 +0,0 @@ -title: Cell Set -description: An object representing a cell set (e.g. Cluster 1) -type: object -properties: - key: - type: string - name: - type: string - rootNode: - type: boolean - children: - type: array - items: - $ref: ./CellSet.v2.yaml -required: - - key - - name - - children \ No newline at end of file diff --git a/src/specs/models/cell-sets-bodies/CellSets.v2.yaml b/src/specs/models/cell-sets-bodies/CellSets.v2.yaml deleted file mode 100644 index 636efb888..000000000 --- a/src/specs/models/cell-sets-bodies/CellSets.v2.yaml +++ /dev/null @@ -1,10 +0,0 @@ -title: Cell Sets object -description: Schema for CellSets object -type: object -properties: - cellSets: - type: array - items: - $ref: ./CellSetClass.v2.yaml -required: - - cellSets diff --git a/src/utils/schema-validator.js b/src/utils/schema-validator.js index 1fd4d6203..ae03bf075 100644 --- a/src/utils/schema-validator.js +++ b/src/utils/schema-validator.js @@ -6,8 +6,6 @@ const Validator = require('swagger-model-validator'); const yaml = require('js-yaml'); const _ = require('lodash'); -const BadRequestError = require('./responses/BadRequestError'); - const getLogger = require('./getLogger'); const logger = getLogger(); @@ -44,7 +42,7 @@ const validateRequest = async (request, schemaPath) => { if (!validation.valid) { logger.log(`Validation error for: ${request}`); - throw new BadRequestError(validation.errors[0]); + throw new Error(validation.errors[0]); } }; diff --git a/src/utils/v1Compatibility/formatExperimentId.js b/src/utils/v1Compatibility/formatExperimentId.js deleted file mode 100644 index a1c9a6e83..000000000 --- a/src/utils/v1Compatibility/formatExperimentId.js +++ /dev/null @@ -1,9 +0,0 @@ -// Existing experimentId in S3 (v1) are MD5 hashes not UUIDs. -// They have the same number of alhpanum characters as UUIDs but no dashes -// To maintain compatibility with v1, we remove the dashes from UUIDs. -// This function should be removed once we have migrated to v2. -// TODO: migrate existing cellsets to the dashes uuidv4 format so this function is not necessary - -const formatExperimentId = (experimentId) => experimentId.replace(/-/g, ''); - -module.exports = formatExperimentId; diff --git a/tests/api.v2/controllers/__snapshots__/accessController.test.js.snap b/tests/api.v2/controllers/__snapshots__/accessController.test.js.snap deleted file mode 100644 index f13c4114f..000000000 --- a/tests/api.v2/controllers/__snapshots__/accessController.test.js.snap +++ /dev/null @@ -1,19 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`accessController inviteUser works correctly 1`] = ` -Array [ - "mockExperimentId", - "user@example.com", - "admin", - Object { - "email": "owner@example.com", - }, -] -`; - -exports[`accessController revokeAccess works correctly 1`] = ` -Array [ - "mockExperimentId", - "user@example.com", -] -`; diff --git a/tests/api.v2/controllers/accessController.test.js b/tests/api.v2/controllers/accessController.test.js index 203c0c25a..cdf5293ae 100644 --- a/tests/api.v2/controllers/accessController.test.js +++ b/tests/api.v2/controllers/accessController.test.js @@ -1,15 +1,8 @@ // @ts-nocheck +const getUserRoles = require('../../../src/api.v2/helpers/access/getUserRoles'); const userAccessController = require('../../../src/api.v2/controllers/accessController'); -const getExperimentUsers = require('../../../src/api.v2/helpers/access/getExperimentUsers'); -const createUserInvite = require('../../../src/api.v2/helpers/access/createUserInvite'); -const removeAccess = require('../../../src/api.v2/helpers/access/removeAccess'); -const OK = require('../../../src/utils/responses/OK'); -const AccessRole = require('../../../src/utils/enums/AccessRole'); - -jest.mock('../../../src/api.v2/helpers/access/getExperimentUsers'); -jest.mock('../../../src/api.v2/helpers/access/createUserInvite'); -jest.mock('../../../src/api.v2/helpers/access/removeAccess'); +jest.mock('../../../src/api.v2/helpers/access/getUserRoles'); const mockRes = { json: jest.fn(), @@ -36,50 +29,13 @@ describe('accessController', () => { it('getExperimentUsers works correctly', async () => { const mockReq = { params: { experimentId: 'mockExperimentId' } }; - getExperimentUsers.mockImplementationOnce( + getUserRoles.mockImplementationOnce( () => Promise.resolve(mockUsersList), ); - await userAccessController.getUserAccess(mockReq, mockRes); + await userAccessController.getExperimentUsers(mockReq, mockRes); - expect(getExperimentUsers).toHaveBeenCalledWith('mockExperimentId'); + expect(getUserRoles).toHaveBeenCalledWith('mockExperimentId'); expect(mockRes.json).toHaveBeenCalledWith(mockUsersList); }); - - it('inviteUser works correctly', async () => { - const mockReq = { - user: { email: 'owner@example.com' }, - params: { experimentId: 'mockExperimentId' }, - body: { userEmail: 'user@example.com', role: AccessRole.ADMIN }, - }; - - createUserInvite.mockImplementationOnce( - () => Promise.resolve(), - ); - - await userAccessController.inviteUser(mockReq, mockRes); - - const callParams = createUserInvite.mock.calls[0]; - - expect(callParams).toMatchSnapshot(); - expect(mockRes.json).toHaveBeenCalledWith(OK()); - }); - - it('revokeAccess works correctly', async () => { - const mockReq = { - params: { experimentId: 'mockExperimentId' }, - body: { userEmail: 'user@example.com' }, - }; - - removeAccess.mockImplementationOnce( - () => Promise.resolve(), - ); - - await userAccessController.revokeAccess(mockReq, mockRes); - - const callParams = removeAccess.mock.calls[0]; - - expect(callParams).toMatchSnapshot(); - expect(mockRes.json).toHaveBeenCalledWith(OK()); - }); }); diff --git a/tests/api.v2/controllers/cellSetsController.test.js b/tests/api.v2/controllers/cellSetsController.test.js deleted file mode 100644 index 0bdeb6d6b..000000000 --- a/tests/api.v2/controllers/cellSetsController.test.js +++ /dev/null @@ -1,109 +0,0 @@ -// @ts-nocheck -const cellSetsController = require('../../../src/api.v2/controllers/cellSetsController'); -const bucketNames = require('../../../src/api.v2/helpers/s3/bucketNames'); - -const getS3Object = require('../../../src/api.v2/helpers/s3/getObject'); -const patchCellSetsObject = require('../../../src/api.v2/helpers/s3/patchCellSetsObject'); -const { OK } = require('../../../src/utils/responses'); - -const formatExperimentId = require('../../../src/utils/v1Compatibility/formatExperimentId'); - -jest.mock('../../../src/api.v2/helpers/s3/getObject'); -jest.mock('../../../src/api.v2/helpers/s3/patchCellSetsObject'); - -const mockRes = { - json: jest.fn(), - send: jest.fn(), -}; - -const mockCellSets = { - cellSets: - [ - { - key: 'louvain', - name: 'louvain clusters', - rootNode: true, - type: 'cellSets', - children: [ - { - key: 'louvain-0', - name: 'Cluster 0', - rootNode: false, - type: 'cellSets', - color: '#77aadd', - cellIds: [0, 1, 2, 3], - }, - ], - }, - ], -}; - -const mockPatch = [ - { - $match: { - query: '$[?(@.key == "scratchpad")]', - value: { - children: [ - { - $insert: - { - index: '-', - value: - { - key: 'new-cluster-1', - name: 'New Cluster 1', - color: '#3957ff', - type: 'cellSets', - cellIds: [4, 5, 6], - }, - }, - }, - ], - }, - }, - }, -]; - -const mockExperimentId = '1234-5678-9012'; - -describe('cellSetsController', () => { - beforeEach(async () => { - jest.clearAllMocks(); - }); - - it('getCellSets works correctly', async () => { - const mockReq = { params: { experimentId: mockExperimentId } }; - getS3Object.mockImplementationOnce( - () => Promise.resolve(mockCellSets), - ); - - await cellSetsController.getCellSets(mockReq, mockRes); - - expect(getS3Object).toHaveBeenCalledWith({ - Bucket: bucketNames.CELL_SETS, - Key: formatExperimentId(mockExperimentId), - }); - - expect(mockRes.send).toHaveBeenCalledWith(mockCellSets); - }); - - it('patchCellSetsObject works correctly', async () => { - const mockReq = { - params: { experimentId: mockExperimentId }, - body: mockPatch, - }; - - patchCellSetsObject.mockImplementationOnce( - () => Promise.resolve(null), - ); - - await cellSetsController.patchCellSets(mockReq, mockRes); - - expect(patchCellSetsObject).toHaveBeenCalledWith( - formatExperimentId(mockExperimentId), - mockPatch, - ); - - expect(mockRes.json).toHaveBeenCalledWith(OK()); - }); -}); diff --git a/tests/api.v2/helpers/access/__snapshots__/getExperimentUsers.test.js.snap b/tests/api.v2/helpers/access/__snapshots__/getUserRoles.test.js.snap similarity index 100% rename from tests/api.v2/helpers/access/__snapshots__/getExperimentUsers.test.js.snap rename to tests/api.v2/helpers/access/__snapshots__/getUserRoles.test.js.snap diff --git a/tests/api.v2/helpers/access/getExperimentUsers.test.js b/tests/api.v2/helpers/access/getUserRoles.test.js similarity index 90% rename from tests/api.v2/helpers/access/getExperimentUsers.test.js rename to tests/api.v2/helpers/access/getUserRoles.test.js index b49fd5055..5875b4fe4 100644 --- a/tests/api.v2/helpers/access/getExperimentUsers.test.js +++ b/tests/api.v2/helpers/access/getUserRoles.test.js @@ -6,7 +6,7 @@ const UserAccess = require('../../../../src/api.v2/model/UserAccess'); const AccessRole = require('../../../../src/utils/enums/AccessRole'); -const getExperimentUsers = require('../../../../src/api.v2/helpers/access/getExperimentUsers'); +const getUserRoles = require('../../../../src/api.v2/helpers/access/getUserRoles'); const { cognitoISP } = config; @@ -59,7 +59,7 @@ describe('getUserRoles', () => { (user) => user.accessRole === AccessRole.ADMIN, ); - const result = await getExperimentUsers(experimentId); + const result = await getUserRoles(experimentId); expect(mockUserAccess.getExperimentUsers).toHaveBeenCalledWith(experimentId); expect(mockUserAccess.getExperimentUsers).toHaveBeenCalledTimes(1); @@ -73,7 +73,7 @@ describe('getUserRoles', () => { it('getUserRoles throws a server error if there is an error fetching Cognito user data', async () => { cognitoISP.adminGetUser.mockReturnValueOnce(Promise.reject(new Error('Error fetching user data'))); - await expect(getExperimentUsers(experimentId)).rejects.toThrow(); + await expect(getUserRoles(experimentId)).rejects.toThrow(); expect(mockUserAccess.getExperimentUsers).toHaveBeenCalledWith(experimentId); expect(mockUserAccess.getExperimentUsers).toHaveBeenCalledTimes(1); diff --git a/tests/api.v2/helpers/s3/__snapshots__/getS3Client.test.js.snap b/tests/api.v2/helpers/s3/__snapshots__/getS3Client.test.js.snap deleted file mode 100644 index e84829656..000000000 --- a/tests/api.v2/helpers/s3/__snapshots__/getS3Client.test.js.snap +++ /dev/null @@ -1,18 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`getS3Client Returns an S3 client with defau lt config values if not given any params 1`] = ` -Object { - "apiVersion": "2006-03-01", - "region": "eu-west-1", - "signatureVersion": "v4", -} -`; - -exports[`getS3Client Takes in params and return S3 client with those params 1`] = ` -Object { - "apiVersion": "2006-03-01", - "endpointUrl": "https://s3.biomage-cloud.com", - "region": "us-east-1", - "signatureVersion": "v4", -} -`; diff --git a/tests/api.v2/helpers/s3/__snapshots__/patchCellSetsObject.test.js.snap b/tests/api.v2/helpers/s3/__snapshots__/patchCellSetsObject.test.js.snap deleted file mode 100644 index a9f808097..000000000 --- a/tests/api.v2/helpers/s3/__snapshots__/patchCellSetsObject.test.js.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`patchCellSetsObject Works correctly 1`] = ` -Object { - "Body": "{\\"cellSets\\":[{\\"key\\":\\"louvain\\",\\"name\\":\\"louvain clusters\\",\\"rootNode\\":true,\\"type\\":\\"cellSets\\",\\"children\\":[{\\"key\\":\\"louvain-0\\",\\"name\\":\\"Cluster 0\\",\\"rootNode\\":false,\\"type\\":\\"cellSets\\",\\"color\\":\\"#77aadd\\",\\"cellIds\\":[0,1,2,3]},{\\"key\\":\\"new-cluster-1\\",\\"name\\":\\"New Cluster 1\\",\\"rootNode\\":false,\\"color\\":\\"#3957ff\\",\\"type\\":\\"cellSets\\",\\"cellIds\\":[4,5,6]}]}]}", - "Bucket": "cell-sets-test", - "Key": "mock-experiment-id", -} -`; diff --git a/tests/api.v2/helpers/s3/getObject.test.js b/tests/api.v2/helpers/s3/getObject.test.js deleted file mode 100644 index d34cf5cae..000000000 --- a/tests/api.v2/helpers/s3/getObject.test.js +++ /dev/null @@ -1,85 +0,0 @@ -// @ts-nocheck -const getObject = require('../../../../src/api.v2/helpers/s3/getObject'); -const getS3Client = require('../../../../src/api.v2/helpers/s3/getS3Client'); - -const NotFoundError = require('../../../../src/utils/responses/NotFoundError'); - -jest.mock('../../../../src/api.v2/helpers/s3/getS3Client', () => jest.fn(() => ({ - getObject: jest.fn(() => ( - { - promise: () => Promise.resolve({ - Body: { - toString: () => 'some data', - }, - }), - } - )), -}))); - -const mockBucketName = 'mock-bucket'; -const mockKeyName = 'mock-key'; - -class MockS3Error extends Error { - constructor(message, code) { - super(message); - this.code = code; - } -} - -const mockParam = { - Bucket: mockBucketName, - Key: mockKeyName, -}; - -describe('getObject', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('Throws an error if param is in complete', async () => { - await expect(getObject()).rejects.toThrow(); - - const noBucketParam = { ...mockParam }; - delete noBucketParam.Bucket; - - await expect(getObject(noBucketParam)).rejects.toThrow(); - - const noKeyParam = { ...mockParam }; - delete noKeyParam.Key; - - await expect(getObject(noKeyParam)).rejects.toThrow(); - }); - - it('Returns data from S3', async () => { - const data = await getObject(mockParam); - expect(data).toEqual('some data'); - }); - - it('Throws NotFoundError if bucket is not found', async () => { - getS3Client.mockImplementation(() => ({ - getObject: jest.fn(() => { throw new MockS3Error('no bucket', 'NoSuchBucket'); }), - })); - - const errorText = `Couldn't find bucket with key: ${mockBucketName}`; - await expect(getObject(mockParam)).rejects.toThrow(new NotFoundError(errorText)); - }); - - it('Throws NotFoundError if key is not found', async () => { - getS3Client.mockImplementation(() => ({ - getObject: jest.fn(() => { throw new MockS3Error('no object with key', 'NoSuchKey'); }), - })); - - const errorText = `Couldn't find object with key: ${mockKeyName}`; - await expect(getObject(mockParam)).rejects.toThrow(new NotFoundError(errorText)); - }); - - it('Throws a general error if the error is not handled manually', async () => { - const errMsg = 'key too long'; - - getS3Client.mockImplementation(() => ({ - getObject: jest.fn(() => { throw new MockS3Error(errMsg, 'KeyTooLongError'); }), - })); - - await expect(getObject(mockParam)).rejects.toThrow(errMsg); - }); -}); diff --git a/tests/api.v2/helpers/s3/getS3Client.test.js b/tests/api.v2/helpers/s3/getS3Client.test.js deleted file mode 100644 index 61c9bca2a..000000000 --- a/tests/api.v2/helpers/s3/getS3Client.test.js +++ /dev/null @@ -1,39 +0,0 @@ -const getS3Client = require('../../../../src/api.v2/helpers/s3/getS3Client'); -const AWS = require('../../../../src/utils/requireAWS'); - -jest.mock('../../../../src/utils/requireAWS', () => ({ - S3: jest.fn((params) => ({ ...params })), -})); - -describe('getS3Client', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('Returns an S3 client with defau lt config values if not given any params', () => { - const s3Client = getS3Client(); - - expect(AWS.S3).toHaveBeenCalledTimes(1); - - const configParams = AWS.S3.mock.calls[0][0]; - - expect(configParams).toMatchSnapshot(); - expect(s3Client).not.toBeUndefined(); - }); - - it('Takes in params and return S3 client with those params', () => { - const additionalParams = { - region: 'us-east-1', - endpointUrl: 'https://s3.biomage-cloud.com', - }; - - const s3Client = getS3Client(additionalParams); - - expect(AWS.S3).toHaveBeenCalledTimes(1); - - const configParams = AWS.S3.mock.calls[0][0]; - - expect(configParams).toMatchSnapshot(); - expect(s3Client).not.toBeUndefined(); - }); -}); diff --git a/tests/api.v2/helpers/s3/patchCellSetsObject.test.js b/tests/api.v2/helpers/s3/patchCellSetsObject.test.js deleted file mode 100644 index d7a7bab4e..000000000 --- a/tests/api.v2/helpers/s3/patchCellSetsObject.test.js +++ /dev/null @@ -1,105 +0,0 @@ -// @ts-nocheck -const patchCellSetsObject = require('../../../../src/api.v2/helpers/s3/patchCellSetsObject'); -const getObject = require('../../../../src/api.v2/helpers/s3/getObject'); -const putObject = require('../../../../src/api.v2/helpers/s3/putObject'); - -jest.mock('../../../../src/api.v2/helpers/s3/getObject'); -jest.mock('../../../../src/api.v2/helpers/s3/putObject'); - -const mockExperimentId = 'mock-experiment-id'; - -const mockCellSets = { - cellSets: [ - { - key: 'louvain', - name: 'louvain clusters', - rootNode: true, - type: 'cellSets', - children: [ - { - key: 'louvain-0', - name: 'Cluster 0', - rootNode: false, - type: 'cellSets', - color: '#77aadd', - cellIds: [0, 1, 2, 3], - }, - ], - }, - ], -}; - -const mockPatch = [ - { - $match: { - query: '$[?(@.key == "louvain")]', - value: { - children: [ - { - $insert: - { - index: '-', - value: - { - key: 'new-cluster-1', - name: 'New Cluster 1', - rootNode: false, - color: '#3957ff', - type: 'cellSets', - cellIds: [4, 5, 6], - }, - }, - }, - ], - }, - }, - }, -]; - -getObject.mockReturnValue(mockCellSets); - -describe('patchCellSetsObject', () => { - it('Works correctly', async () => { - const result = await patchCellSetsObject(mockExperimentId, mockPatch); - - // Put a modified object - const putParams = putObject.mock.calls[0][0]; - - expect(putParams).toMatchSnapshot(); - - // Does not return anything on success - expect(result).toBeUndefined(); - }); - - it('Throws an error if the JSON merger result is not correct', async () => { - // Should fail validation because cellIds is not an array - const malformedPatch = [ - { - $match: { - query: '$[?(@.key == "louvain")]', - value: { - children: [ - { - $insert: - { - index: '-', - value: - { - key: 'singular-cluster', - name: 'Singular cluster', - rootNode: false, - color: '#3957ff', - type: 'cellSets', - cellIds: 1, - }, - }, - }, - ], - }, - }, - }, - ]; - - await expect(patchCellSetsObject(mockExperimentId, malformedPatch)).rejects.toThrow(); - }); -}); diff --git a/tests/api.v2/helpers/s3/putObject.test.js b/tests/api.v2/helpers/s3/putObject.test.js deleted file mode 100644 index f8ca6f48a..000000000 --- a/tests/api.v2/helpers/s3/putObject.test.js +++ /dev/null @@ -1,78 +0,0 @@ -// @ts-nocheck -const putObject = require('../../../../src/api.v2/helpers/s3/putObject'); -const getS3Client = require('../../../../src/api.v2/helpers/s3/getS3Client'); - -const NotFoundError = require('../../../../src/utils/responses/NotFoundError'); - -jest.mock('../../../../src/api.v2/helpers/s3/getS3Client', () => jest.fn(() => ({ - putObject: jest.fn(() => ( - { - promise: () => Promise.resolve({}), - } - )), -}))); - -class MockS3Error extends Error { - constructor(message, code) { - super(message); - this.code = code; - } -} - -const mockBucketName = 'mock-bucket'; -const mockKeyName = 'mock-key'; -const mockBody = 'mock-body'; - -const mockParam = { - Bucket: mockBucketName, - Key: mockKeyName, - Body: mockBody, -}; - -describe('putObject', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('Throws an error if param is in complete', async () => { - await expect(putObject()).rejects.toThrow(); - - const noBucketParam = { ...mockParam }; - delete noBucketParam.Bucket; - - await expect(putObject(noBucketParam)).rejects.toThrow(); - - const noKeyParam = { ...mockParam }; - delete noKeyParam.Bucket; - - await expect(putObject(noKeyParam)).rejects.toThrow(); - - const noBodyParam = { ...mockParam }; - delete noBodyParam.Bucket; - - await expect(putObject(noKeyParam)).rejects.toThrow(); - }); - - it('Does not return anything on success', async () => { - await expect(putObject(mockParam)).resolves.toBeUndefined(); - }); - - it('Throws NotFoundError if bucket is not found', async () => { - getS3Client.mockImplementation(() => ({ - putObject: jest.fn(() => { throw new MockS3Error('no bucket', 'NoSuchBucket'); }), - })); - - const errorText = `Couldn't find bucket with key: ${mockBucketName}`; - await expect(putObject(mockParam)).rejects.toThrow(new NotFoundError(errorText)); - }); - - it('Throws a general error if the error is not handled manually', async () => { - const errMsg = 'key too long'; - - getS3Client.mockImplementation(() => ({ - putObject: jest.fn(() => { throw new MockS3Error(errMsg, 'KeyTooLongError'); }), - })); - - await expect(putObject(mockParam)).rejects.toThrow(errMsg); - }); -}); diff --git a/tests/api.v2/model/UserAccess.test.js b/tests/api.v2/model/UserAccess.test.js index 52d945890..8179339ab 100644 --- a/tests/api.v2/model/UserAccess.test.js +++ b/tests/api.v2/model/UserAccess.test.js @@ -2,6 +2,7 @@ const roles = require('../../../src/api.v2/helpers/roles'); const { mockSqlClient } = require('../mocks/getMockSqlClient')(); +const { getAwsUserAttributesByEmail } = require('../../../src/utils/aws/user'); jest.mock('../../../src/api.v2/helpers/roles'); jest.mock('../../../src/sql/sqlClient', () => ({ @@ -20,37 +21,32 @@ jest.mock('../../../src/utils/aws/user', () => ({ const BasicModel = require('../../../src/api.v2/model/BasicModel'); const UserAccess = require('../../../src/api.v2/model/UserAccess'); -const AccessRole = require('../../../src/utils/enums/AccessRole'); - -const mockUserId = '1234-5678-9012-3456'; -const mockExperimentId = 'experimentId'; -const mockRole = 'mockRole'; const mockUserAccessCreateResults = [ [{ userId: 'mockAdminSub', - experimentId: mockExperimentId, - accessRole: AccessRole.OWNER, + experimentId: 'mockExperimentId', + accessRole: 'owner', updatedAt: '1910-03-23 21:06:00.573142+00', }], [{ - userId: mockUserId, - experimentId: mockExperimentId, - accessRole: AccessRole.OWNER, + userId: 'someUser', + experimentId: 'mockExperimentId', + accessRole: 'owner', updatedAt: '1910-03-23 21:06:00.573142+00', }], ]; -const mockGetUserAccessResults = [ +const mockGetExperimentUsersResults = [ { userId: 'mockAdminSub', - experimentId: mockExperimentId, - accessRole: AccessRole.ADMIN, + experimentId: 'mockExperimentId', + accessRole: 'admin', updatedAt: '1910-03-23 21:06:00.573142+00', }, { - userId: mockUserId, - experimentId: mockExperimentId, + userId: 'someUser', + experimentId: 'mockExperimentId', accessRole: 'owner', updatedAt: '1910-03-23 21:06:00.573142+00', }, @@ -61,11 +57,11 @@ describe('model/userAccess', () => { jest.clearAllMocks(); }); - it('getUserAccess work correctly', async () => { + it('getExperimentUsers work correctly', async () => { const experimentId = 'experimentId'; const mockFind = jest.spyOn(BasicModel.prototype, 'find') - .mockImplementationOnce(() => Promise.resolve(mockGetUserAccessResults)); + .mockImplementationOnce(() => Promise.resolve(mockGetExperimentUsersResults)); const result = await new UserAccess().getExperimentUsers(experimentId); @@ -75,7 +71,7 @@ describe('model/userAccess', () => { expect(result).toMatchSnapshot(); }); - it('getUserAccess throws a not found error if experiment does not exist', async () => { + it('getExperimentUsers throws a not found error if experiment does not exist', async () => { const experimentId = 'experimentId'; const mockFind = jest.spyOn(BasicModel.prototype, 'find') @@ -89,35 +85,6 @@ describe('model/userAccess', () => { expect(mockFind).toHaveBeenCalledTimes(1); }); - it('grantAccess work correctly', async () => { - const mockCreate = jest.spyOn(BasicModel.prototype, 'create') - .mockImplementationOnce(() => Promise.resolve()); - - await expect( - new UserAccess().grantAccess(mockUserId, mockExperimentId, mockRole), - ); - - expect(mockCreate).toHaveBeenCalledWith({ - user_id: mockUserId, - experiment_id: mockExperimentId, - access_role: mockRole, - }); - expect(mockCreate).toHaveBeenCalledTimes(1); - }); - - it('removeAccess work correctly', async () => { - const mockDelete = jest.spyOn(BasicModel.prototype, 'delete') - .mockImplementationOnce(() => Promise.resolve()); - - await new UserAccess().removeAccess(mockUserId, mockExperimentId); - - expect(mockDelete).toHaveBeenCalledWith({ - user_id: mockUserId, - experiment_id: mockExperimentId, - }); - expect(mockDelete).toHaveBeenCalledTimes(1); - }); - it('createNewExperimentPermissions works correctly', async () => { const userId = 'userId'; const experimentId = 'experimentId'; diff --git a/tests/api.v2/model/__snapshots__/UserAccess.test.js.snap b/tests/api.v2/model/__snapshots__/UserAccess.test.js.snap index 7bf907f34..e70120d2e 100644 --- a/tests/api.v2/model/__snapshots__/UserAccess.test.js.snap +++ b/tests/api.v2/model/__snapshots__/UserAccess.test.js.snap @@ -1,18 +1,18 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`model/userAccess getUserAccess work correctly 1`] = ` +exports[`model/userAccess getExperimentUsers work correctly 1`] = ` Array [ Object { "accessRole": "admin", - "experimentId": "experimentId", + "experimentId": "mockExperimentId", "updatedAt": "1910-03-23 21:06:00.573142+00", "userId": "mockAdminSub", }, Object { "accessRole": "owner", - "experimentId": "experimentId", + "experimentId": "mockExperimentId", "updatedAt": "1910-03-23 21:06:00.573142+00", - "userId": "1234-5678-9012-3456", + "userId": "someUser", }, ] `; diff --git a/tests/api.v2/routes/access.test.js b/tests/api.v2/routes/access.test.js index 9e77951c7..9629a9b5e 100644 --- a/tests/api.v2/routes/access.test.js +++ b/tests/api.v2/routes/access.test.js @@ -4,8 +4,7 @@ const request = require('supertest'); const expressLoader = require('../../../src/loaders/express'); const accessController = require('../../../src/api.v2/controllers/accessController'); -const { NotFoundError, OK } = require('../../../src/utils/responses'); -const AccessRole = require('../../../src/utils/enums/AccessRole'); +const { NotFoundError } = require('../../../src/utils/responses'); jest.mock('../../../src/api.v2/middlewares/authMiddlewares'); jest.mock('../../../src/api.v2/controllers/accessController'); @@ -14,12 +13,12 @@ const mockUsersList = [ { name: 'Mock Admin', email: 'admin@example.com', - role: AccessRole.ADMIN, + role: 'admin', }, { name: 'Mock User', email: 'user@example.com', - role: AccessRole.OWNER, + role: 'owner', }, ]; @@ -37,7 +36,7 @@ describe('User access endpoint', () => { }); it('Getting list of users to an existing experiment returns 200', async (done) => { - accessController.getUserAccess.mockImplementationOnce((req, res) => { + accessController.getExperimentUsers.mockImplementationOnce((req, res) => { res.json(mockUsersList); Promise.resolve(); }); @@ -54,7 +53,7 @@ describe('User access endpoint', () => { }); it('Getting list of users to an unexisting experiment returns 404', async (done) => { - accessController.getUserAccess.mockImplementationOnce(() => { + accessController.getExperimentUsers.mockImplementationOnce(() => { throw new NotFoundError('Experiment not found'); }); @@ -68,40 +67,4 @@ describe('User access endpoint', () => { return done(); }); }); - - it('Adding a new user to an experiment returns 200', async (done) => { - accessController.inviteUser.mockImplementationOnce((req, res) => { - res.json(OK()); - Promise.resolve(); - }); - - request(app) - .put('/v2/access/mockExperimentId') - .send({ userEmail: 'user@example.com', role: AccessRole.ADMIN }) - .expect(200) - .end((err) => { - if (err) { - return done(err); - } - return done(); - }); - }); - - it('Removing user access from an experiment returns a 200', async (done) => { - accessController.revokeAccess.mockImplementationOnce((req, res) => { - res.json(OK()); - Promise.resolve(); - }); - - request(app) - .delete('/v2/access/mockExperimentId') - .send({ userEmail: 'user@example.com' }) - .expect(200) - .end((err) => { - if (err) { - return done(err); - } - return done(); - }); - }); }); diff --git a/tests/api.v2/routes/cellSets.test.js b/tests/api.v2/routes/cellSets.test.js deleted file mode 100644 index 59143d41d..000000000 --- a/tests/api.v2/routes/cellSets.test.js +++ /dev/null @@ -1,136 +0,0 @@ -// @ts-nocheck -const express = require('express'); -const request = require('supertest'); -const expressLoader = require('../../../src/loaders/express'); - -const cellSetsController = require('../../../src/api.v2/controllers/cellSetsController'); -const { NotFoundError } = require('../../../src/utils/responses'); - -jest.mock('../../../src/api.v2/middlewares/authMiddlewares'); -jest.mock('../../../src/api.v2/controllers/cellSetsController'); - -const endpoint = '/v2/experiments/mockExperimentId/cellSets'; - -const mockPatch = { - key: '05e036a5-a2ae-4909-99e1-c3b927a584e3', name: 'New Cluster', color: '#3957ff', type: 'cellSets', cellIds: [438, 444, 713, 822, 192, 576, 675], -}; - -describe('Cell sets endpoint', () => { - let app; - - beforeEach(async () => { - const mockApp = await expressLoader(express()); - app = mockApp.app; - }); - - afterEach(() => { - jest.resetModules(); - jest.restoreAllMocks(); - }); - - it('Getting an existing cell set returns 200', (done) => { - cellSetsController.getCellSets.mockImplementationOnce((req, res) => { - res.json(); - Promise.resolve(); - }); - request(app) - .get(endpoint) - .expect(200) - .end((err) => { - if (err) { - return done(err); - } - return done(); - }); - }); - - it('Getting a non-existing cell set returns 404', (done) => { - cellSetsController.getCellSets.mockImplementationOnce(() => { - throw new NotFoundError('Experiment not found'); - }); - - request(app) - .get(endpoint) - .expect(404) - .end((err) => { - if (err) { - return done(err); - } - return done(); - }); - }); - - it('Patching cell sets with a valid body content type results in a successful response', (done) => { - cellSetsController.patchCellSets.mockImplementationOnce((req, res) => { - res.json(); - Promise.resolve(); - }); - - const createNewCellSetJsonMerger = [{ - $match: { - query: '$[?(@.key == "scratchpad")]', - value: { - children: [{ - $insert: { - index: '-', - value: mockPatch, - }, - }], - }, - }, - }]; - - const validContentType = 'application/boschni-json-merger+json'; - - request(app) - .patch(endpoint) - .set('Content-type', validContentType) - .send(createNewCellSetJsonMerger) - .expect(200) - .end((err) => { - if (err) { - return done(err); - } - // there is no point testing for the values of the response body - // - if something is wrong, the schema validator will catch it - return done(); - }); - }); - - it('Patching cell sets with an invalid body content type results in a 415', (done) => { - cellSetsController.patchCellSets.mockImplementationOnce((req, res) => { - res.json(); - Promise.resolve(); - }); - - const createNewCellSetJsonMerger = [{ - $match: { - query: '$[?(@.key == "scratchpad")]', - value: { - children: [{ - $insert: { - index: '-', - value: mockPatch, - }, - }], - }, - }, - }]; - - const invalidContentType = 'application/json'; - - request(app) - .patch(endpoint) - .set('Content-type', invalidContentType) - .send(createNewCellSetJsonMerger) - .expect(415) - .end((err) => { - if (err) { - return done(err); - } - // there is no point testing for the values of the response body - // - if something is wrong, the schema validator will catch it - return done(); - }); - }); -});