import type { IServerEvents, LoginServiceConfiguration } from '@rocket.chat/core-typings'; import { expect } from 'chai'; import { before, describe, it, after, afterEach } from 'mocha'; import { getCredentials, api, request, credentials } from '../../data/api-data'; import { updatePermission, updateSetting, getSettingValueById } from '../../data/permissions.helper'; import { IS_EE } from '../../e2e/config/constants'; describe('[Settings]', () => { before((done) => getCredentials(done)); describe('[/settings.public]', () => { it('should return public settings', async () => { const res = await request.get(api('settings.public')).expect('Content-Type', 'application/json').expect(200); expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('settings'); expect(res.body).to.have.property('count'); }); it('should return public settings even requested with count and offset params', async () => { const res = await request .get(api('settings.public')) .query({ count: 5, offset: 0, }) .expect('Content-Type', 'application/json') .expect(200); expect(res.body).to.have.property('success').and.to.be.true; expect(res.body).to.have.property('settings').and.to.be.an('array').and.to.have.lengthOf(5); expect(res.body).to.have.property('count').and.to.be.a('number').and.to.equal(5); }); it('should return public settings even requested with _id param', async () => { const res = await request .get(api('settings.public')) .query({ _id: 'Site_Url', }) .expect('Content-Type', 'application/json') .expect(200); expect(res.body).to.have.property('success').and.to.be.true; expect(res.body).to.have.property('settings').and.to.be.an('array').and.to.have.lengthOf(1); expect(res.body).to.have.property('count').and.to.be.a('number').and.to.equal(1); }); it('should return public settings even requested with _id param as an array', async () => { const res = await request .get(api('settings.public')) .query({ _id: 'Site_Url,LDAP_Enable', }) .expect('Content-Type', 'application/json') .expect(200); expect(res.body).to.have.property('success').and.to.be.true; expect(res.body).to.have.property('settings').and.to.be.an('array').and.to.have.lengthOf(2); expect(res.body).to.have.property('count').and.to.be.a('number').and.to.equal(2); }); it('should return an empty response when requesting public settings with a broken _id param', async () => { const res = await request .get(api('settings.public')) .query({ _id: 10, }) .expect('Content-Type', 'application/json') .expect(200); expect(res.body).to.have.property('success').and.to.be.true; expect(res.body).to.have.property('settings').and.to.be.an('array').and.to.be.empty; expect(res.body).to.have.property('count').and.to.be.a('number').and.to.equal(0); expect(res.body).to.have.property('offset').and.to.be.a('number').and.to.equal(0); expect(res.body).to.have.property('total').and.to.be.a('number').and.to.equal(0); }); }); describe('[/settings]', () => { it('should return private settings', async () => { const res = await request.get(api('settings')).set(credentials).expect('Content-Type', 'application/json').expect(200); expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('settings'); expect(res.body).to.have.property('count'); }); it('should return the default values of the settings when includeDefaults is true', async () => { return request .get(api('settings')) .query({ includeDefaults: true }) .set(credentials) .expect('Content-Type', 'application/json') .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('settings'); expect(res.body).to.have.property('count'); expect(res.body.settings[0]).to.have.property('packageValue'); }); }); describe('POST (bulk)', () => { before(async () => { await updatePermission('edit-privileged-setting', ['admin']); }); after(async () => { await updatePermission('edit-privileged-setting', ['admin']); }); it('should return unauthorized when not authenticated', async () => { await request .post(api('settings')) .send({ settings: [{ _id: 'LDAP_Enable', value: false }] }) .expect(401); }); it('should return bad request when settings is missing', async () => { await request.post(api('settings')).set(credentials).send({}).expect(400); }); it('should return bad request when settings is empty', async () => { await request.post(api('settings')).set(credentials).send({ settings: [] }).expect(400); }); it('should return bad request when an item is missing value', async () => { await request .post(api('settings')) .set(credentials) .send({ settings: [{ _id: 'LDAP_Enable' }] }) .expect(400); }); it('should reject an empty integer value without changing the setting', async () => { const settingId = 'UserData_ProcessingFrequency'; const originalValue = await getSettingValueById(settingId); await request .post(api('settings')) .set(credentials) .send({ settings: [{ _id: settingId, value: null }] }) .expect(400) .expect((res) => { expect(res.body).to.have.property('success', false); }); expect(await getSettingValueById(settingId)).to.equal(originalValue); }); it('should successfully update multiple settings in a single request', async () => { await request .post(api('settings')) .set(credentials) .send({ settings: [ { _id: 'LDAP_Enable', value: false }, { _id: 'Accounts_Default_User_Preferences_masterVolume', value: 50 }, ], }) .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); }); await request .get(api('settings/LDAP_Enable')) .set(credentials) .expect(200) .expect((res) => { expect(res.body).to.have.property('value', false); }); await request .get(api('settings/Accounts_Default_User_Preferences_masterVolume')) .set(credentials) .expect(200) .expect((res) => { expect(res.body).to.have.property('value', 50); }); }); it('should accept an optional editor for a setting', async () => { await request .post(api('settings')) .set(credentials) .send({ settings: [{ _id: 'Livechat_title_color', value: '#000000', editor: 'color' }] }) .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); }); await request .get(api('settings/Livechat_title_color')) .set(credentials) .expect(200) .expect((res) => { expect(res.body).to.have.property('value', '#000000'); }); }); it('should return bad request when editor is an empty string', async () => { await request .post(api('settings')) .set(credentials) .send({ settings: [{ _id: 'Livechat_title_color', value: '#C1272D', editor: '' }] }) .expect(400); }); it('should fail when the user does not have edit-privileged-setting permission', async () => { await updatePermission('edit-privileged-setting', []); await request .post(api('settings')) .set(credentials) .send({ settings: [{ _id: 'LDAP_Enable', value: false }] }) .expect(400) .expect((res) => { expect(res.body).to.have.property('success', false); expect(res.body.error).to.match(/error-action-not-allowed/); }); }); }); }); describe('[/settings/:_id]', () => { before(async () => { await updatePermission('view-privileged-setting', ['admin']); await updatePermission('edit-privileged-setting', ['admin']); }); after(async () => { await updatePermission('view-privileged-setting', ['admin']); await updatePermission('edit-privileged-setting', ['admin']); }); it('should successfully return one setting (GET)', async () => { return request .get(api('settings/Site_Url')) .set(credentials) .expect('Content-Type', 'application/json') .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('_id', 'Site_Url'); expect(res.body).to.have.property('value'); }); }); it('should fail returning a setting if user does NOT have the view-privileged-setting permission (GET)', async () => { await updatePermission('view-privileged-setting', []); return request .get(api('settings/Site_Url')) .set(credentials) .expect('Content-Type', 'application/json') .expect(403) .expect((res) => { 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]'); }); }); it('should successfully set the value of a setting (POST)', async () => { return request .post(api('settings/LDAP_Enable')) .set(credentials) .send({ value: false, }) .expect('Content-Type', 'application/json') .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); }); }); it('should fail updating the value of a setting less than its minValue (POST)', async () => { return request .post(api('settings/Accounts_Default_User_Preferences_masterVolume')) .set(credentials) .send({ value: '-1', }) .expect('Content-Type', 'application/json') .expect(400) .expect((res) => { expect(res.body).to.have.property('success', false); expect(res.body).to.have.property( 'error', 'Value for setting Accounts_Default_User_Preferences_masterVolume must be greater than or equal to 0 [error-invalid-setting-value]', ); }); }); it('should fail updating the value of a setting greater than its maxValue (POST)', async () => { return request .post(api('settings/Accounts_Default_User_Preferences_masterVolume')) .set(credentials) .send({ value: '101', }) .expect('Content-Type', 'application/json') .expect(400) .expect((res) => { expect(res.body).to.have.property('success', false); expect(res.body).to.have.property( 'error', 'Value for setting Accounts_Default_User_Preferences_masterVolume must be less than or equal to 100 [error-invalid-setting-value]', ); }); }); it('should fail updating the value of a setting if user does NOT have the edit-privileged-setting permission (POST)', async () => { await updatePermission('edit-privileged-setting', []); return request .post(api('settings/LDAP_Enable')) .set(credentials) .send({ value: false, }) .expect('Content-Type', 'application/json') .expect(403) .expect((res) => { 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('[Room_Toolbox_Layout]', () => { const validLayout = [ { roomType: ['c', 'p'], maxVisibleNormal: 3, items: [{ id: 'members-list', featured: true, order: 1 }] }, { roomType: ['d'], maxVisibleNormal: 1 }, ]; const saveLayout = (value: string) => request.post(api('settings/Room_Toolbox_Layout')).set(credentials).send({ value }); after(() => updateSetting('Room_Toolbox_Layout', '')); it('should reject a value that is not valid JSON', async () => { await saveLayout('not json {') .expect(400) .expect((res) => { expect(res.body).to.have.property('success', false); expect(res.body).to.have.property('error', 'Room_Toolbox_Layout_Invalid'); expect(res.body).to.have.property('errorType', 'error-setting-validation-failed'); }); }); it('should reject an entry declaring an unsupported room type', async () => { await saveLayout(JSON.stringify([{ roomType: ['l'] }])) .expect(400) .expect((res) => { expect(res.body).to.have.property('success', false); expect(res.body).to.have.property('error', 'Room_Toolbox_Layout_Invalid'); expect(res.body).to.have.property('errorType', 'error-setting-validation-failed'); }); }); it('should reject entries claiming the same room type', async () => { await saveLayout(JSON.stringify([{ roomType: ['c', 'p'] }, { roomType: ['c'] }])) .expect(400) .expect((res) => { expect(res.body).to.have.property('success', false); expect(res.body).to.have.property('error', 'Room_Toolbox_Layout_Invalid'); expect(res.body).to.have.property('errorType', 'error-setting-validation-failed'); }); }); it('should reject an entry repeating a room type', async () => { await saveLayout(JSON.stringify([{ roomType: ['c', 'c'] }])) .expect(400) .expect((res) => { expect(res.body).to.have.property('success', false); expect(res.body).to.have.property('error', 'Room_Toolbox_Layout_Invalid'); expect(res.body).to.have.property('errorType', 'error-setting-validation-failed'); }); }); it('should reject an entry carrying an unknown key', async () => { await saveLayout(JSON.stringify([{ roomType: ['c'], somethingElse: true }])) .expect(400) .expect((res) => { expect(res.body).to.have.property('success', false); expect(res.body).to.have.property('error', 'Room_Toolbox_Layout_Invalid'); expect(res.body).to.have.property('errorType', 'error-setting-validation-failed'); }); }); it('should accept a document matching the schema', async () => { await saveLayout(JSON.stringify(validLayout)) .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); }); }); it('should accept an empty value, leaving the setting unconfigured', async () => { await saveLayout('') .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); }); }); }); describe('[/service.configurations]', () => { it('should return service configurations', async () => { const res = await request.get(api('service.configurations')).set(credentials).expect('Content-Type', 'application/json').expect(200); expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('configurations'); }); describe('With OAuth enabled', () => { before(() => updateSetting('Accounts_OAuth_Google', true)); after(() => updateSetting('Accounts_OAuth_Google', false)); it('should include the OAuth service in the response', (done) => { // wait 3 seconds before getting the service list so the server has had time to update it setTimeout(() => { void request .get(api('service.configurations')) .set(credentials) .expect('Content-Type', 'application/json') .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('configurations'); expect((res.body.configurations as LoginServiceConfiguration[]).find(({ service }) => service === 'google')).to.exist; }) .end(done); }, 3000); }); }); describe('With OAuth disabled', () => { before(() => updateSetting('Accounts_OAuth_Google', false)); after(() => updateSetting('Accounts_OAuth_Google', false)); it('should not include the OAuth service in the response', (done) => { // wait 3 seconds before getting the service list so the server has had time to update it setTimeout(() => { void request .get(api('service.configurations')) .set(credentials) .expect('Content-Type', 'application/json') .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('configurations'); expect((res.body.configurations as LoginServiceConfiguration[]).find(({ service }) => service === 'google')).to.not.exist; }) .end(done); }, 3000); }); }); }); describe('/settings.oauth', () => { it('should have return list of available oauth services when user is not logged', async () => { const res = await request.get(api('settings.oauth')).expect('Content-Type', 'application/json').expect(200); expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('services').and.to.be.an('array'); }); it('should have return list of available oauth services when user is logged', async () => { const res = await request.get(api('settings.oauth')).set(credentials).expect('Content-Type', 'application/json').expect(200); expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('services').and.to.be.an('array'); }); }); (IS_EE ? describe : describe.skip)('/audit.settings', () => { const formatDate = (date: Date) => date.toISOString(); let startDate: Date; let endDate: Date; before(async () => { // Changing these settings to true and then false ensures that we have audited events // So we can test filtering reliably startDate = new Date(); await Promise.all([updateSetting('Accounts_AllowAnonymousRead', true), updateSetting('Accounts_AllowDeleteOwnAccount', true)]); await Promise.all([updateSetting('Accounts_AllowAnonymousRead', false), updateSetting('Accounts_AllowDeleteOwnAccount', false)]); endDate = new Date(); }); it('should return list of settings changed (no filters)', async () => { await request .get(api('audit.settings')) .set(credentials) .expect('Content-Type', 'application/json') .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('events').and.to.be.an('array'); expect(res.body.events.length).to.be.greaterThanOrEqual(4); }); }); it('should return list of settings between date ranges', async () => { await request .get(api('audit.settings')) .query({ start: formatDate(startDate), end: formatDate(endDate) }) .set(credentials) .expect('Content-Type', 'application/json') .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('events').and.to.be.an('array'); expect(res.body.events.length).to.be.greaterThanOrEqual(4); (res.body.events as IServerEvents['settings.changed'][]).forEach((event) => { expect(new Date(event.ts).getTime()).to.be.greaterThanOrEqual(startDate.getTime()); expect(new Date(event.ts).getTime()).to.be.lessThanOrEqual(endDate.getTime()); }); }); }); it('should throw error when sending invalid dates', async () => { const startDate = new Date(); const endDate = 'abcdef'; await request .get(api('audit.settings')) .query({ start: formatDate(startDate), end: endDate }) .set(credentials) .expect('Content-Type', 'application/json') .expect(400) .expect((res) => { expect(res.body).to.have.property('success', false); expect(res.body).to.have.property('error', 'The "end" query parameter must be a valid date.'); }); }); it('should return list of settings changed filtered by an actor', async () => { await request .get(api('audit.settings')) .query({ actor: { type: 'user' }, count: 10 }) .set(credentials) .expect('Content-Type', 'application/json') .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('events').and.to.be.an('array'); expect(res.body.events.length).to.be.greaterThanOrEqual(1); (res.body.events as IServerEvents['settings.changed'][]).forEach((sEvent) => expect(sEvent.actor.type).to.be.equal('user')); }); }); it('should return list of changes of an specific setting', async () => { await request .get(api('audit.settings')) .query({ settingId: 'Site_Url' }) .set(credentials) .expect('Content-Type', 'application/json') .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('events').and.to.be.an('array'); (res.body.events as IServerEvents['settings.changed'][]).forEach((event) => { expect(event.data[0].key).to.be.equal('id'); expect(event.data[0].value).to.be.equal('Site_Url'); }); }); }); it('should return list of changes filtered by an actor between date ranges', async () => { await request .get(api('audit.settings')) .query({ actor: { type: 'user' }, start: formatDate(startDate), end: formatDate(endDate) }) .set(credentials) .expect('Content-Type', 'application/json') .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('events').and.to.be.an('array'); expect(res.body.events.length).to.be.greaterThanOrEqual(4); (res.body.events as IServerEvents['settings.changed'][]).forEach((event) => { expect(event.actor.type).to.be.equal('user'); expect(new Date(event.ts).getTime()).to.be.greaterThanOrEqual(startDate.getTime()); expect(new Date(event.ts).getTime()).to.be.lessThanOrEqual(endDate.getTime()); }); }); }); describe('Masking sensitive settings', () => { let originalSmtpPassword: string | undefined; let originalSmtpUsername: string | undefined; let maskingStart: Date; let maskingEnd: Date; const testPassword = 'testpassword123'; const testUsername = 'testuser@example.com'; before(async () => { maskingStart = new Date(); originalSmtpPassword = (await getSettingValueById('SMTP_Password')) as string | undefined; originalSmtpUsername = (await getSettingValueById('SMTP_Username')) as string | undefined; await updateSetting('SMTP_Password', testPassword); await updateSetting('SMTP_Username', testUsername); maskingEnd = new Date(); }); after(async () => { await updateSetting('SMTP_Password', originalSmtpPassword || ''); await updateSetting('SMTP_Username', originalSmtpUsername || ''); }); it('should mask sensitive settings in audit logs', async () => { await request .get(api('audit.settings')) .query({ settingId: 'SMTP_Password', start: formatDate(maskingStart), end: formatDate(maskingEnd) }) .set(credentials) .expect('Content-Type', 'application/json') .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('events').and.to.be.an('array'); expect(res.body.events.length).to.be.greaterThanOrEqual(1); const passwordEvents = res.body.events as IServerEvents['settings.changed'][]; const passwordEvent = passwordEvents.find((event) => { const settingId = event.data.find((item) => item.key === 'id')?.value; return settingId === 'SMTP_Password'; }); expect(passwordEvent).to.exist; if (passwordEvent) { const previous = passwordEvent.data.find((item) => item.key === 'previous')?.value; const current = passwordEvent.data.find((item) => item.key === 'current')?.value; if (previous && typeof previous === 'string' && previous.length > 0) { expect(previous).to.include('*'); expect(previous).to.not.equal(testPassword); if (previous.length > 8) { expect(previous.substring(0, 3)).to.equal(originalSmtpPassword?.substring(0, 3)); expect(previous.substring(3)).to.match(/^\*+$/); } } if (current && typeof current === 'string' && current.length > 0) { expect(current).to.include('*'); expect(current).to.not.equal(testPassword); if (testPassword.length > 8) { expect(current.substring(0, 3)).to.equal(testPassword.substring(0, 3)); expect(current.substring(3)).to.match(/^\*+$/); } else { expect(current).to.match(/^\*+$/); } } } }); await request .get(api('audit.settings')) .query({ settingId: 'SMTP_Username', start: formatDate(maskingStart), end: formatDate(maskingEnd) }) .set(credentials) .expect('Content-Type', 'application/json') .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('events').and.to.be.an('array'); expect(res.body.events.length).to.be.greaterThanOrEqual(1); const usernameEvents = res.body.events as IServerEvents['settings.changed'][]; const usernameEvent = usernameEvents.find((event) => { const settingId = event.data.find((item) => item.key === 'id')?.value; return settingId === 'SMTP_Username'; }); expect(usernameEvent).to.exist; if (usernameEvent) { const previous = usernameEvent.data.find((item) => item.key === 'previous')?.value; const current = usernameEvent.data.find((item) => item.key === 'current')?.value; if (previous && typeof previous === 'string' && previous.length > 0) { expect(previous).to.include('*'); expect(previous).to.not.equal(originalSmtpUsername); } if (current && typeof current === 'string' && current.length > 0) { expect(current).to.include('*'); expect(current).to.not.equal(testUsername); if (testUsername.length > 8) { expect(current.substring(0, 3)).to.equal(testUsername.substring(0, 3)); expect(current.substring(3)).to.match(/^\*+$/); } else { expect(current).to.match(/^\*+$/); } } } }); }); }); describe('Sorting', () => { const isSortedAscending = (events: IServerEvents['settings.changed'][]) => events.every((event, i) => i === 0 || new Date(event.ts).getTime() >= new Date(events[i - 1].ts).getTime()); const isSortedDescending = (events: IServerEvents['settings.changed'][]) => events.every((event, i) => i === 0 || new Date(event.ts).getTime() <= new Date(events[i - 1].ts).getTime()); it('should sort by timestamp ascending', async () => { const response = await request .get(api('audit.settings')) .query({ sort: JSON.stringify({ ts: 1 }), start: formatDate(startDate), end: formatDate(endDate) }) .set(credentials) .expect(200); expect(response.body).to.have.property('success', true); expect(response.body.events).to.have.length.greaterThanOrEqual(2); expect(isSortedAscending(response.body.events)).to.be.true; }); it('should sort by timestamp descending', async () => { const response = await request .get(api('audit.settings')) .query({ sort: JSON.stringify({ ts: -1 }), start: formatDate(startDate), end: formatDate(endDate) }) .set(credentials) .expect(200); expect(response.body).to.have.property('success', true); expect(response.body.events).to.have.length.greaterThanOrEqual(2); expect(isSortedDescending(response.body.events)).to.be.true; }); it('should sort by timestamp descending by default', async () => { const response = await request.get(api('audit.settings')).set(credentials).expect(200); expect(response.body).to.have.property('success', true); expect(response.body.events).to.have.length.greaterThanOrEqual(2); expect(isSortedDescending(response.body.events)).to.be.true; }); }); }); describe('Custom OAuth admin endpoints', () => { const oauthName = 'apitest'; const enableSettingId = 'Accounts_OAuth_Custom-Apitest'; before(() => updatePermission('add-oauth-service', ['admin'])); // guarantee the permission is restored even if a permission-denied assertion fails mid-test, // so a failure cannot cascade into the following cases afterEach(() => updatePermission('add-oauth-service', ['admin'])); after(async () => { await updatePermission('add-oauth-service', ['admin']); // best-effort cleanup in case a test left the custom service behind await request.post(api('settings.removeCustomOAuth')).set(credentials).send({ name: oauthName }); }); describe('[/settings.addCustomOAuth]', () => { it('should fail when unauthenticated', () => request.post(api('settings.addCustomOAuth')).send({ name: oauthName }).expect(401)); it('should fail when the "name" param is not provided', () => request.post(api('settings.addCustomOAuth')).set(credentials).send({}).expect(400)); it('should fail when the user does not have the add-oauth-service permission', async () => { await updatePermission('add-oauth-service', []); await request .post(api('settings.addCustomOAuth')) .set(credentials) .send({ name: oauthName }) .expect((res) => { expect(res.status).to.equal(403); expect(res.body).to.have.property('success', false); }); }); it('should add a custom oauth service', async () => { await request .post(api('settings.addCustomOAuth')) .set(credentials) .send({ name: oauthName }) .expect('Content-Type', 'application/json') .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); }); const value = await getSettingValueById(enableSettingId); expect(value).to.be.a('boolean'); }); }); describe('[/settings.refreshOAuthServices]', () => { it('should fail when unauthenticated', () => request.post(api('settings.refreshOAuthServices')).expect(401)); it('should fail when the user does not have the add-oauth-service permission', async () => { await updatePermission('add-oauth-service', []); await request .post(api('settings.refreshOAuthServices')) .set(credentials) .expect((res) => { expect(res.status).to.equal(403); expect(res.body).to.have.property('success', false); }); }); it('should refresh the oauth services', () => request .post(api('settings.refreshOAuthServices')) .set(credentials) .expect('Content-Type', 'application/json') .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); })); }); describe('[/settings.removeCustomOAuth]', () => { it('should fail when unauthenticated', () => request.post(api('settings.removeCustomOAuth')).send({ name: oauthName }).expect(401)); it('should fail when the "name" param is not provided', () => request.post(api('settings.removeCustomOAuth')).set(credentials).send({}).expect(400)); it('should fail when the "name" normalizes to an empty string', () => request .post(api('settings.removeCustomOAuth')) .set(credentials) .send({ name: '!!!' }) .expect(400) .expect((res) => { expect(res.body).to.have.property('success', false); })); it('should fail when the user does not have the add-oauth-service permission', async () => { await updatePermission('add-oauth-service', []); await request .post(api('settings.removeCustomOAuth')) .set(credentials) .send({ name: oauthName }) .expect((res) => { expect(res.status).to.equal(403); expect(res.body).to.have.property('success', false); }); }); it('should remove a custom oauth service', async () => { await request .post(api('settings.removeCustomOAuth')) .set(credentials) .send({ name: oauthName }) .expect('Content-Type', 'application/json') .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); }); // the provider settings should be gone: settings/:_id answers 400 for an unknown id await request.get(`/api/v1/settings/${enableSettingId}`).set(credentials).expect(400); }); }); }); });