diff --git a/apps/meteor/app/api/server/v1/cloud.ts b/apps/meteor/app/api/server/v1/cloud.ts index c0694deef4fae..17000832897fe 100644 --- a/apps/meteor/app/api/server/v1/cloud.ts +++ b/apps/meteor/app/api/server/v1/cloud.ts @@ -1,4 +1,4 @@ -import { check } from 'meteor/check'; +import { isCloudConfirmationPollProps, isCloudCreateRegistrationIntentProps, isCloudManualRegisterProps } from '@rocket.chat/rest-typings'; import { CloudWorkspaceRegistrationError } from '../../../../lib/errors/CloudWorkspaceRegistrationError'; import { SystemLogger } from '../../../../server/lib/logger/system'; @@ -19,13 +19,9 @@ import { API } from '../api'; API.v1.addRoute( 'cloud.manualRegister', - { authRequired: true, permissionsRequired: ['register-on-cloud'] }, + { authRequired: true, permissionsRequired: ['register-on-cloud'], validateParams: isCloudManualRegisterProps }, { async post() { - check(this.bodyParams, { - cloudBlob: String, - }); - const registrationInfo = await retrieveRegistrationStatus(); if (registrationInfo.workspaceRegistered) { @@ -43,14 +39,9 @@ API.v1.addRoute( API.v1.addRoute( 'cloud.createRegistrationIntent', - { authRequired: true, permissionsRequired: ['manage-cloud'] }, + { authRequired: true, permissionsRequired: ['manage-cloud'], validateParams: isCloudCreateRegistrationIntentProps }, { async post() { - check(this.bodyParams, { - resend: Boolean, - email: String, - }); - const intentData = await startRegisterWorkspaceSetupWizard(this.bodyParams.resend, this.bodyParams.email); if (intentData) { @@ -74,17 +65,10 @@ API.v1.addRoute( API.v1.addRoute( 'cloud.confirmationPoll', - { authRequired: true, permissionsRequired: ['manage-cloud'] }, + { authRequired: true, permissionsRequired: ['manage-cloud'], validateParams: isCloudConfirmationPollProps }, { async get() { const { deviceCode } = this.queryParams; - check(this.queryParams, { - deviceCode: String, - }); - - if (!deviceCode) { - return API.v1.failure('Invalid query'); - } const pollData = await getConfirmationPoll(deviceCode); if (pollData) { diff --git a/apps/meteor/tests/end-to-end/api/cloud.ts b/apps/meteor/tests/end-to-end/api/cloud.ts new file mode 100644 index 0000000000000..dc6d08e990925 --- /dev/null +++ b/apps/meteor/tests/end-to-end/api/cloud.ts @@ -0,0 +1,181 @@ +import { expect } from 'chai'; +import { after, before, describe, it } from 'mocha'; + +import { getCredentials, api, request, credentials } from '../../data/api-data'; +import { updatePermission } from '../../data/permissions.helper'; + +describe('[Cloud]', function () { + this.retries(0); + + before((done) => getCredentials(done)); + + describe('[/cloud.manualRegister]', () => { + before(async () => { + return updatePermission('register-on-cloud', ['admin']); + }); + + after(async () => { + return updatePermission('register-on-cloud', ['admin']); + }); + + it('should fail if user is not authenticated', async () => { + return request + .post(api('cloud.manualRegister')) + .expect('Content-Type', 'application/json') + .expect(401) + .expect((res: Response) => { + expect(res.body).to.have.property('status', 'error'); + expect(res.body).to.have.property('message', 'You must be logged in to do this.'); + }); + }); + + it('should fail when cloudBlob property is not provided', async () => { + return request + .post(api('cloud.manualRegister')) + .set(credentials) + .expect('Content-Type', 'application/json') + .expect(400) + .expect((res: Response) => { + expect(res.body).to.have.property('success', false); + expect(res.body).to.have.property('errorType', 'invalid-params'); + expect(res.body).to.have.property('error', "must have required property 'cloudBlob' [invalid-params]"); + }); + }); + + it('should fail when user does not have the register-on-cloud permission', async () => { + await updatePermission('register-on-cloud', []); + return request + .post(api('cloud.manualRegister')) + .set(credentials) + .send({ + cloudBlob: 'test-blob', + }) + .expect('Content-Type', 'application/json') + .expect(403) + .expect((res: Response) => { + expect(res.body).to.have.property('success', false); + expect(res.body).to.have.property('error', 'User does not have the permissions required for this action [error-unauthorized]'); + }); + }); + }); + + describe('[/cloud.createRegistrationIntent]', () => { + before(async () => { + return updatePermission('manage-cloud', ['admin']); + }); + + after(async () => { + return updatePermission('manage-cloud', ['admin']); + }); + + it('should fail if user is not authenticated', async () => { + return request + .post(api('cloud.createRegistrationIntent')) + .expect('Content-Type', 'application/json') + .expect(401) + .expect((res: Response) => { + expect(res.body).to.have.property('status', 'error'); + expect(res.body).to.have.property('message', 'You must be logged in to do this.'); + }); + }); + + it('should fail when resend property is not provided', async () => { + return request + .post(api('cloud.createRegistrationIntent')) + .set(credentials) + .send({ + email: 'test-mail@example.com', + }) + .expect('Content-Type', 'application/json') + .expect(400) + .expect((res: Response) => { + expect(res.body).to.have.property('success', false); + expect(res.body).to.have.property('errorType', 'invalid-params'); + expect(res.body).to.have.property('error', "must have required property 'resend' [invalid-params]"); + }); + }); + + it('should fail when email property is not provided', async () => { + return request + .post(api('cloud.createRegistrationIntent')) + .set(credentials) + .send({ + resend: true, + }) + .expect('Content-Type', 'application/json') + .expect(400) + .expect((res: Response) => { + expect(res.body).to.have.property('success', false); + expect(res.body).to.have.property('errorType', 'invalid-params'); + expect(res.body).to.have.property('error', "must have required property 'email' [invalid-params]"); + }); + }); + + it('should fail when user does not have the manage-cloud permission', async () => { + await updatePermission('manage-cloud', []); + return request + .post(api('cloud.createRegistrationIntent')) + .set(credentials) + .send({ + email: 'test-mail@example.com', + resend: true, + }) + .expect('Content-Type', 'application/json') + .expect(403) + .expect((res: Response) => { + expect(res.body).to.have.property('success', false); + expect(res.body).to.have.property('error', 'User does not have the permissions required for this action [error-unauthorized]'); + }); + }); + }); + + describe('[/cloud.confirmationPoll]', () => { + before(async () => { + return updatePermission('manage-cloud', ['admin']); + }); + + after(async () => { + return updatePermission('manage-cloud', ['admin']); + }); + + it('should fail if user is not authenticated', async () => { + return request + .get(api('cloud.confirmationPoll')) + .expect('Content-Type', 'application/json') + .expect(401) + .expect((res: Response) => { + expect(res.body).to.have.property('status', 'error'); + expect(res.body).to.have.property('message', 'You must be logged in to do this.'); + }); + }); + + it('should fail when deviceCode property is not provided', async () => { + return request + .get(api('cloud.confirmationPoll')) + .set(credentials) + .expect('Content-Type', 'application/json') + .expect(400) + .expect((res: Response) => { + expect(res.body).to.have.property('success', false); + expect(res.body).to.have.property('errorType', 'invalid-params'); + expect(res.body).to.have.property('error', "must have required property 'deviceCode' [invalid-params]"); + }); + }); + + it('should fail when user does not have the manage-cloud permission', async () => { + await updatePermission('manage-cloud', []); + return request + .get(api('cloud.confirmationPoll')) + .set(credentials) + .query({ + deviceCode: 'test-code', + }) + .expect('Content-Type', 'application/json') + .expect(403) + .expect((res: Response) => { + expect(res.body).to.have.property('success', false); + expect(res.body).to.have.property('error', 'User does not have the permissions required for this action [error-unauthorized]'); + }); + }); + }); +}); diff --git a/packages/rest-typings/src/index.ts b/packages/rest-typings/src/index.ts index 94ee32f2f5bec..0b2e73a7f25b5 100644 --- a/packages/rest-typings/src/index.ts +++ b/packages/rest-typings/src/index.ts @@ -267,3 +267,4 @@ export * from './v1/rooms'; export * from './v1/groups'; export * from './v1/chat'; export * from './v1/auth'; +export * from './v1/cloud'; diff --git a/packages/rest-typings/src/v1/cloud.ts b/packages/rest-typings/src/v1/cloud.ts index 7602034b69120..8a4d040d06a4a 100644 --- a/packages/rest-typings/src/v1/cloud.ts +++ b/packages/rest-typings/src/v1/cloud.ts @@ -53,14 +53,10 @@ const CloudConfirmationPollSchema = { properties: { deviceCode: { type: 'string', - }, - resend: { - type: 'string', - nullable: true, + minLength: 1, }, }, required: ['deviceCode'], - optionalProperties: ['resend'], additionalProperties: false, };