diff --git a/src/app/routes/api/v3/admin/forms/__tests__/admin-forms.form.routes.spec.ts b/src/app/routes/api/v3/admin/forms/__tests__/admin-forms.form.routes.spec.ts index 0a63d15b19..b75424f7c9 100644 --- a/src/app/routes/api/v3/admin/forms/__tests__/admin-forms.form.routes.spec.ts +++ b/src/app/routes/api/v3/admin/forms/__tests__/admin-forms.form.routes.spec.ts @@ -523,6 +523,172 @@ describe('admin-form.form.routes', () => { }) }) + describe('GET /admin/forms/:formId', () => { + it('should return 200 with retrieved form when user is admin', async () => { + // Arrange + const ownForm = await EmailFormModel.create({ + title: 'Own form', + emails: [defaultUser.email], + admin: defaultUser._id, + }) + + const response = await request.get(`/admin/forms/${ownForm._id}`) + // Act + + // Assert + const expected = await FormModel.findById(ownForm._id) + .populate({ + path: 'admin', + populate: { + path: 'agency', + }, + }) + .lean() + expect(response.status).toEqual(200) + expect(response.body).not.toBeNull() + expect(response.body).toEqual({ + form: jsonParseStringify(expected), + }) + }) + + it('should return 200 with retrieved form when user has read permissions', async () => { + // Arrange + // Create separate user + const collabUser = ( + await dbHandler.insertFormCollectionReqs({ + userId: new ObjectId(), + mailName: 'collab-user', + shortName: 'collabUser', + }) + ).user + + const collabForm = await EncryptFormModel.create({ + title: 'Collab form', + publicKey: 'some public key', + admin: collabUser._id, + permissionList: [{ email: defaultUser.email, write: false }], + }) + + // Act + const response = await request.get(`/admin/forms/${collabForm._id}`) + + // Assert + const expected = await FormModel.findById(collabForm._id) + .populate({ + path: 'admin', + populate: { + path: 'agency', + }, + }) + .lean() + expect(response.status).toEqual(200) + expect(response.body).not.toBeNull() + expect(response.body).toEqual({ + form: jsonParseStringify(expected), + }) + }) + + it('should return 401 when user is not logged in', async () => { + // Arrange + await logoutSession(request) + + // Act + const response = await request.get(`/admin/forms/${new ObjectId()}`) + + // Assert + expect(response.status).toEqual(401) + expect(response.body).toEqual({ message: 'User is unauthorized.' }) + }) + + it('should return 403 when user does not have read permissions to form', async () => { + // Arrange + const anotherUser = ( + await dbHandler.insertFormCollectionReqs({ + userId: new ObjectId(), + mailName: 'some-user', + shortName: 'someUser', + }) + ).user + // Form that defaultUser has no access to. + const inaccessibleForm = await EncryptFormModel.create({ + title: 'Collab form', + publicKey: 'some public key', + admin: anotherUser._id, + permissionList: [], + }) + + // Act + const response = await request.get(`/admin/forms/${inaccessibleForm._id}`) + + // Assert + expect(response.status).toEqual(403) + expect(response.body).toEqual({ + message: expect.stringContaining( + 'not authorized to perform read operation', + ), + }) + }) + + it('should return 404 when form cannot be found', async () => { + // Arrange + const invalidFormId = new ObjectId().toHexString() + + // Act + const response = await request.get(`/admin/forms/${invalidFormId}`) + + // Assert + expect(response.status).toEqual(404) + expect(response.body).toEqual({ message: 'Form not found' }) + }) + + it('should return 410 when form to retrieve is archived', async () => { + // Arrange + const archivedForm = await EncryptFormModel.create({ + title: 'archived form', + status: Status.Archived, + responseMode: ResponseMode.Encrypt, + publicKey: 'does not matter', + admin: defaultUser._id, + }) + + // Act + const response = await request.get(`/admin/forms/${archivedForm._id}`) + + // Assert + expect(response.status).toEqual(410) + expect(response.body).toEqual({ message: 'Form has been archived' }) + }) + + it('should return 422 when user in session cannot be retrieved from the database', async () => { + // Arrange + // Clear user collection + await dbHandler.clearCollection(UserModel.collection.name) + + // Act + const response = await request.get(`/admin/forms/${new ObjectId()}`) + + // Assert + expect(response.status).toEqual(422) + expect(response.body).toEqual({ message: 'User not found' }) + }) + + it('should return 500 when database error occurs whilst retrieving form', async () => { + // Arrange + jest + .spyOn(FormModel, 'getFullFormById') + .mockRejectedValueOnce(new Error('some error')) + + // Act + const response = await request.get(`/admin/forms/${new ObjectId()}`) + + // Assert + expect(response.status).toEqual(500) + expect(response.body).toEqual({ + message: 'Something went wrong. Please try again.', + }) + }) + }) + describe('DELETE /admin/forms/:formId', () => { it('should return 200 with success message when form is successfully archived', async () => { // Arrange diff --git a/src/app/routes/api/v3/admin/forms/admin-forms.form.routes.ts b/src/app/routes/api/v3/admin/forms/admin-forms.form.routes.ts index 79476bf305..16e07aa942 100644 --- a/src/app/routes/api/v3/admin/forms/admin-forms.form.routes.ts +++ b/src/app/routes/api/v3/admin/forms/admin-forms.form.routes.ts @@ -7,7 +7,6 @@ export const AdminFormsFormRouter = Router() AdminFormsFormRouter.route('/') /** * List the forms managed by the user - * @route GET /adminform * @security session * * @returns 200 with a list of forms managed by the user @@ -19,7 +18,6 @@ AdminFormsFormRouter.route('/') /** * Create a new form - * @route POST /adminform * @security session * * @returns 200 with newly created form @@ -33,27 +31,36 @@ AdminFormsFormRouter.route('/') */ .post(AdminFormController.handleCreateForm) -/** - * Archive the specified form. - * @route DELETE /:formId/adminform - * @security session - * - * @returns 200 with success message when successfully archived - * @returns 401 when user does not exist in session - * @returns 403 when user does not have permissions to archive form - * @returns 404 when form cannot be found - * @returns 410 when form is already archived - * @returns 422 when user in session cannot be retrieved from the database - * @returns 500 when database error occurs - */ -AdminFormsFormRouter.delete( - '/:formId([a-fA-F0-9]{24})', - AdminFormController.handleArchiveForm, -) +AdminFormsFormRouter.route('/:formId([a-fA-F0-9]{24})') + /** + * Return the specified form to the user. + * @security session + * + * @returns 200 with retrieved form with formId if user has read permissions + * @returns 401 when user does not exist in session + * @returns 403 when user does not have permissions to access form + * @returns 404 when form cannot be found + * @returns 410 when form is archived + * @returns 422 when user in session cannot be retrieved from the database + * @returns 500 when database error occurs + */ + .get(AdminFormController.handleGetAdminForm) + /** + * Archive the specified form. + * @security session + * + * @returns 200 with success message when successfully archived + * @returns 401 when user does not exist in session + * @returns 403 when user does not have permissions to archive form + * @returns 404 when form cannot be found + * @returns 410 when form is already archived + * @returns 422 when user in session cannot be retrieved from the database + * @returns 500 when database error occurs + */ + .delete(AdminFormController.handleArchiveForm) /** * Duplicate the specified form. - * @route POST /:formId/adminform * @security session * * @returns 200 with the duplicate form dashboard view @@ -72,7 +79,6 @@ AdminFormsFormRouter.post( /** * Transfer form ownership to another user - * @route POST /:formId/adminform/transfer-owner * @security session * * @returns 200 with updated form with transferred owners @@ -99,7 +105,6 @@ AdminFormsFormRouter.route( ) /** * Update form field according to given new body. - * @route PUT /admin/forms/:formId/fields/:fieldId * * @param body the new field to override current field * @returns 200 with updated form field @@ -117,7 +122,6 @@ AdminFormsFormRouter.route( /** * Delete form field by fieldId of form corresponding to formId. - * @route DELETE /admin/forms/:formId/fields/:fieldId * @security session * * @returns 204 when deletion is successful @@ -131,7 +135,6 @@ AdminFormsFormRouter.route( .delete(AdminFormController.handleDeleteFormField) /** * Retrives the form field using the fieldId from the specified form - * @route GET /admin/forms/:formId/fields/:fieldId * @security session * * @returns 200 with form field when retrieval is successful @@ -146,7 +149,6 @@ AdminFormsFormRouter.route( /** * Duplicates the form field with the fieldId from the specified form - * @route POST /:formId/fields/:fieldId/duplicate * @security session * * @returns 200 with duplicated field diff --git a/src/public/services/AdminViewFormService.ts b/src/public/services/AdminViewFormService.ts index 35f8abefb9..190dad63bb 100644 --- a/src/public/services/AdminViewFormService.ts +++ b/src/public/services/AdminViewFormService.ts @@ -25,7 +25,9 @@ export const getDashboardView = async (): Promise => { export const getAdminFormView = async ( formId: string, ): Promise => { - return axios.get(`/${formId}/adminform`).then(({ data }) => data) + return axios + .get(`${ADMIN_FORM_ENDPOINT}/${formId}`) + .then(({ data }) => data) } /** diff --git a/src/public/services/__tests__/AdminViewFormService.test.ts b/src/public/services/__tests__/AdminViewFormService.test.ts index 1390ee746c..75fafdb4aa 100644 --- a/src/public/services/__tests__/AdminViewFormService.test.ts +++ b/src/public/services/__tests__/AdminViewFormService.test.ts @@ -82,7 +82,9 @@ describe('AdminViewFormService', () => { // Assert expect(actual).toEqual(expected) - expect(MockAxios.get).toHaveBeenCalledWith(`/${expected._id}/adminform`) + expect(MockAxios.get).toHaveBeenCalledWith( + `${ADMIN_FORM_ENDPOINT}/${expected._id}`, + ) }) it('should reject with error message when GET request fails', async () => { @@ -96,7 +98,9 @@ describe('AdminViewFormService', () => { // Assert await expect(actualPromise).rejects.toEqual(expected) - expect(MockAxios.get).toHaveBeenCalledWith(`/${MOCK_FORM._id}/adminform`) + expect(MockAxios.get).toHaveBeenCalledWith( + `${ADMIN_FORM_ENDPOINT}/${MOCK_FORM._id}`, + ) }) })