Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: restore v3 API for retrieving individual admin form #2201

Merged
merged 1 commit into from
Jun 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
52 changes: 27 additions & 25 deletions src/app/routes/api/v3/admin/forms/admin-forms.form.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -19,7 +18,6 @@ AdminFormsFormRouter.route('/')

/**
* Create a new form
* @route POST /adminform
* @security session
*
* @returns 200 with newly created form
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
4 changes: 3 additions & 1 deletion src/public/services/AdminViewFormService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ export const getDashboardView = async (): Promise<FormMetaView[]> => {
export const getAdminFormView = async (
formId: string,
): Promise<FormViewDto> => {
return axios.get<FormViewDto>(`/${formId}/adminform`).then(({ data }) => data)
return axios
.get<FormViewDto>(`${ADMIN_FORM_ENDPOINT}/${formId}`)
.then(({ data }) => data)
}

/**
Expand Down
8 changes: 6 additions & 2 deletions src/public/services/__tests__/AdminViewFormService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand All @@ -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}`,
)
})
})

Expand Down