Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
796 lines
29 KiB
TypeScript
796 lines
29 KiB
TypeScript
import type { Credentials } from '@rocket.chat/api-client';
|
|
import type { IInstanceStatus, IRoom, ITeam, IUser } from '@rocket.chat/core-typings';
|
|
import { TeamType } from '@rocket.chat/core-typings';
|
|
import type { IInstance } from '@rocket.chat/rest-typings';
|
|
import { AssertionError, expect } from 'chai';
|
|
import { after, before, describe, it } from 'mocha';
|
|
import { MongoClient } from 'mongodb';
|
|
|
|
import { getCredentials, api, request, credentials } from '../../data/api-data';
|
|
import { updatePermission, updateSetting } from '../../data/permissions.helper';
|
|
import { createRoom, deleteRoom } from '../../data/rooms.helper';
|
|
import { createTeam, deleteTeam } from '../../data/teams.helper';
|
|
import { adminEmail, adminUsername, adminPassword, password } from '../../data/user';
|
|
import type { TestUser } from '../../data/users.helper';
|
|
import { createUser, deleteUser, login as doLogin } from '../../data/users.helper';
|
|
import { IS_EE, URL_MONGODB } from '../../e2e/config/constants';
|
|
|
|
describe('miscellaneous', () => {
|
|
before((done) => getCredentials(done));
|
|
|
|
describe('API default', () => {
|
|
// Required by mobile apps
|
|
describe('/info', () => {
|
|
let version: string;
|
|
it('should return "version", "build", "commit" and "marketplaceApiVersion" when the user is logged in', async () => {
|
|
const res = await request.get('/api/info').set(credentials).expect('Content-Type', 'application/json').expect(200);
|
|
|
|
expect(res.body).to.have.property('version').and.to.be.a('string');
|
|
expect(res.body.info).to.have.property('version').and.to.be.a('string');
|
|
expect(res.body.info).to.have.property('build').and.to.be.an('object');
|
|
expect(res.body.info).to.have.property('commit').and.to.be.an('object');
|
|
expect(res.body.info).to.have.property('marketplaceApiVersion').and.to.be.a('string');
|
|
version = res.body.info.version;
|
|
});
|
|
it('should return only "version" and the version should not have patch info when the user is not logged in', async () => {
|
|
const res = await request.get('/api/info').expect('Content-Type', 'application/json').expect(200);
|
|
|
|
expect(res.body).to.have.property('version');
|
|
expect(res.body).to.not.have.property('info');
|
|
expect(res.body.version).to.be.equal(version.replace(/(\d+\.\d+).*/, '$1'));
|
|
});
|
|
});
|
|
});
|
|
|
|
it('/login', () => {
|
|
expect(credentials).to.have.property('X-Auth-Token').with.lengthOf.at.least(1);
|
|
expect(credentials).to.have.property('X-User-Id').with.lengthOf.at.least(1);
|
|
});
|
|
|
|
it('/login (wrapper username)', async () => {
|
|
const res = await request
|
|
.post(api('login'))
|
|
.send({
|
|
user: {
|
|
username: adminUsername,
|
|
},
|
|
password: adminPassword,
|
|
})
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('status', 'success');
|
|
expect(res.body).to.have.property('data').and.to.be.an('object');
|
|
expect(res.body.data).to.have.property('userId');
|
|
expect(res.body.data).to.have.property('authToken');
|
|
expect(res.body.data).to.have.property('me');
|
|
});
|
|
|
|
it('/login (wrapper email)', async () => {
|
|
const res = await request
|
|
.post(api('login'))
|
|
.send({
|
|
user: {
|
|
email: adminEmail,
|
|
},
|
|
password: adminPassword,
|
|
})
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('status', 'success');
|
|
expect(res.body).to.have.property('data').and.to.be.an('object');
|
|
expect(res.body.data).to.have.property('userId');
|
|
expect(res.body.data).to.have.property('authToken');
|
|
expect(res.body.data).to.have.property('me');
|
|
});
|
|
|
|
it('/login by user', async () => {
|
|
const res = await request
|
|
.post(api('login'))
|
|
.send({
|
|
user: adminEmail,
|
|
password: adminPassword,
|
|
})
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('status', 'success');
|
|
expect(res.body).to.have.property('data').and.to.be.an('object');
|
|
expect(res.body.data).to.have.property('userId');
|
|
expect(res.body.data).to.have.property('authToken');
|
|
expect(res.body.data).to.have.property('me');
|
|
expect(res.body.data.me.services).to.not.have.nested.property('password.bcrypt');
|
|
expect(res.body.data.me.services).to.have.nested.property('password.exists', true);
|
|
});
|
|
|
|
it('/login by username', async () => {
|
|
const res = await request
|
|
.post(api('login'))
|
|
.send({
|
|
username: adminUsername,
|
|
password: adminPassword,
|
|
})
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('status', 'success');
|
|
expect(res.body).to.have.property('data').and.to.be.an('object');
|
|
expect(res.body.data).to.have.property('userId');
|
|
expect(res.body.data).to.have.property('authToken');
|
|
expect(res.body.data).to.have.property('me');
|
|
expect(res.body.data.me.services).to.not.have.nested.property('password.bcrypt');
|
|
expect(res.body.data.me.services).to.have.nested.property('password.exists', true);
|
|
});
|
|
|
|
it('/me', async () => {
|
|
const user = await createUser();
|
|
const userCredentials = await doLogin(user.username, password);
|
|
|
|
await request
|
|
.get(api('me'))
|
|
.set(userCredentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res) => {
|
|
const allUserPreferencesKeys = [
|
|
'alsoSendThreadToChannel',
|
|
// 'language',
|
|
'newRoomNotification',
|
|
'newMessageNotification',
|
|
'showThreadsInMainChannel',
|
|
// 'clockMode',
|
|
'useEmojis',
|
|
'convertAsciiEmoji',
|
|
'saveMobileBandwidth',
|
|
'collapseMediaByDefault',
|
|
'autoImageLoad',
|
|
'emailNotificationMode',
|
|
'unreadAlert',
|
|
'masterVolume',
|
|
'notificationsSoundVolume',
|
|
'voipRingerVolume',
|
|
'omnichannelTranscriptEmail',
|
|
IS_EE ? 'omnichannelTranscriptPDF' : false,
|
|
'desktopNotifications',
|
|
'pushNotifications',
|
|
'enableAutoAway',
|
|
// 'highlights',
|
|
'desktopNotificationRequireInteraction',
|
|
'hideUsernames',
|
|
'hideRoles',
|
|
'displayAvatars',
|
|
'hideFlexTab',
|
|
'sendOnEnter',
|
|
'idleTimeLimit',
|
|
'sidebarShowFavorites',
|
|
'sidebarShowUnread',
|
|
'themeAppearence',
|
|
'sidebarSortby',
|
|
'sidebarViewMode',
|
|
'sidebarDisplayAvatar',
|
|
'sidebarGroupByType',
|
|
'sidebarSectionsOrder',
|
|
'muteFocusedConversations',
|
|
'notifyCalendarEvents',
|
|
'enableMobileRinging',
|
|
'featuresPreview',
|
|
'desktopNotificationVoiceCalls',
|
|
].filter((p) => Boolean(p));
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('_id', user._id);
|
|
expect(res.body).to.have.property('username', user.username);
|
|
expect(res.body).to.have.property('active');
|
|
expect(res.body).to.have.property('name');
|
|
expect(res.body).to.have.property('roles').and.to.be.an('array');
|
|
expect(res.body).to.have.nested.property('emails[0].address', user.emails[0].address);
|
|
expect(res.body).to.have.nested.property('settings.preferences').and.to.be.an('object');
|
|
expect(res.body.settings.preferences).to.have.all.keys(allUserPreferencesKeys);
|
|
expect(res.body).to.have.property('isOAuthUser', false);
|
|
expect(res.body.services).to.not.have.nested.property('password.bcrypt');
|
|
expect(res.body.services).to.have.nested.property('password.exists', true);
|
|
});
|
|
|
|
await deleteUser(user);
|
|
});
|
|
|
|
describe('/directory', () => {
|
|
let user: TestUser<IUser>;
|
|
let userWithLeftoverFederationData: TestUser<IUser>;
|
|
let testChannel: IRoom;
|
|
let testGroup: IRoom;
|
|
let normalUserCredentials: Credentials;
|
|
const teamName = `new-team-name-${Date.now()}` as const;
|
|
let teamCreated: ITeam;
|
|
|
|
before(async () => {
|
|
await updatePermission('create-team', ['admin', 'user']);
|
|
user = await createUser();
|
|
userWithLeftoverFederationData = await createUser();
|
|
normalUserCredentials = await doLogin(user.username, password);
|
|
[testChannel, testGroup, teamCreated] = await Promise.all([
|
|
createRoom({ name: `channel.test.${Date.now()}`, type: 'c' }).then((res) => res.body.channel),
|
|
createRoom({ name: `group.test.${Date.now()}`, type: 'p' }).then((res) => res.body.group),
|
|
createTeam(normalUserCredentials, teamName, TeamType.PUBLIC),
|
|
]);
|
|
|
|
const connection = await MongoClient.connect(URL_MONGODB);
|
|
const updateResult = await connection
|
|
.db()
|
|
.collection('users')
|
|
.updateOne({ _id: userWithLeftoverFederationData._id as any }, { $set: { federation: { origin: 'example.com' } } });
|
|
await connection.close();
|
|
expect(updateResult.modifiedCount).to.equal(1);
|
|
});
|
|
|
|
after(async () => {
|
|
await Promise.all([
|
|
deleteTeam(normalUserCredentials, teamName),
|
|
deleteUser(user),
|
|
deleteUser(userWithLeftoverFederationData),
|
|
deleteRoom({ type: 'c', roomId: testChannel._id }),
|
|
deleteRoom({ type: 'p', roomId: testGroup._id }),
|
|
updatePermission('create-team', ['admin', 'user']),
|
|
]);
|
|
});
|
|
|
|
it('should return an array(result) when search by user and execute successfully', async () => {
|
|
const res = await request
|
|
.get(api('directory'))
|
|
.set(credentials)
|
|
.query({
|
|
text: user.username,
|
|
type: 'users',
|
|
})
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('result').and.to.be.an('array');
|
|
expect(res.body).to.have.property('offset');
|
|
expect(res.body).to.have.property('total');
|
|
expect(res.body).to.have.property('count');
|
|
expect(res.body.result[0]).to.have.property('_id');
|
|
expect(res.body.result[0]).to.have.property('createdAt');
|
|
expect(res.body.result[0]).to.have.property('username');
|
|
expect(res.body.result[0]).to.have.property('emails').and.to.be.an('array');
|
|
expect(res.body.result[0]).to.have.property('name');
|
|
});
|
|
|
|
it('should not return the emails field for non admins', async () => {
|
|
const res = await request
|
|
.get(api('directory'))
|
|
.set(normalUserCredentials)
|
|
.query({
|
|
text: user.username,
|
|
type: 'users',
|
|
})
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('result').and.to.be.an('array');
|
|
expect(res.body).to.have.property('offset');
|
|
expect(res.body).to.have.property('total');
|
|
expect(res.body).to.have.property('count');
|
|
expect(res.body.result[0]).to.have.property('_id');
|
|
expect(res.body.result[0]).to.have.property('createdAt');
|
|
expect(res.body.result[0]).to.have.property('username');
|
|
expect(res.body.result[0]).to.not.have.property('emails');
|
|
expect(res.body.result[0]).to.have.property('name');
|
|
});
|
|
it('should find local users that still have leftover federation data', async () => {
|
|
const res = await request
|
|
.get(api('directory'))
|
|
.set(credentials)
|
|
.query({
|
|
text: userWithLeftoverFederationData.username,
|
|
type: 'users',
|
|
})
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body.result).to.have.lengthOf(1);
|
|
expect(res.body.result[0]).to.have.property('_id', userWithLeftoverFederationData._id);
|
|
});
|
|
|
|
it('should return an array(result) when search by channel and execute successfully', async () => {
|
|
const res = await request
|
|
.get(api('directory'))
|
|
.set(credentials)
|
|
.query({
|
|
text: testChannel.name,
|
|
type: 'channels',
|
|
})
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('offset');
|
|
expect(res.body).to.have.property('total');
|
|
expect(res.body).to.have.property('count');
|
|
expect(res.body).to.have.property('result').and.to.be.an('array');
|
|
expect(res.body.result[0]).to.have.property('_id');
|
|
expect(res.body.result[0]).to.have.property('name');
|
|
expect(res.body.result[0]).to.have.property('usersCount').and.to.be.an('number');
|
|
expect(res.body.result[0]).to.have.property('ts');
|
|
});
|
|
|
|
it('should return private group when search by channel and execute successfully', async () => {
|
|
await request
|
|
.get(api('directory'))
|
|
.set(credentials)
|
|
.query({
|
|
text: testGroup.name,
|
|
type: 'channels',
|
|
})
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res) => {
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('offset');
|
|
expect(res.body).to.have.property('total');
|
|
expect(res.body).to.have.property('count');
|
|
expect(res.body).to.have.property('result').and.to.be.an('array');
|
|
expect(res.body.result[0]).to.have.property('_id', testGroup._id);
|
|
expect(res.body.result[0]).to.have.property('t', 'p');
|
|
expect(res.body.result[0]).to.have.property('name');
|
|
expect(res.body.result[0]).to.have.property('usersCount').and.to.be.an('number');
|
|
expect(res.body.result[0]).to.have.property('ts');
|
|
});
|
|
});
|
|
|
|
it('should return an array(result) when search by channel with sort params correctly and execute successfully', async () => {
|
|
const res = await request
|
|
.get(api('directory'))
|
|
.set(credentials)
|
|
.query({
|
|
text: testChannel.name,
|
|
type: 'channels',
|
|
sort: JSON.stringify({
|
|
name: 1,
|
|
}),
|
|
})
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('offset');
|
|
expect(res.body).to.have.property('total');
|
|
expect(res.body).to.have.property('count');
|
|
expect(res.body).to.have.property('result').and.to.be.an('array');
|
|
expect(res.body.result[0]).to.have.property('_id');
|
|
expect(res.body.result[0]).to.have.property('name');
|
|
expect(res.body.result[0]).to.have.property('usersCount').and.to.be.an('number');
|
|
expect(res.body.result[0]).to.have.property('ts');
|
|
});
|
|
it('should return an error when send invalid query', async () => {
|
|
const res = await request
|
|
.get(api('directory'))
|
|
.set(credentials)
|
|
.query({
|
|
text: 'invalid channel',
|
|
type: 'invalid',
|
|
})
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(400);
|
|
|
|
expect(res.body).to.have.property('success', false);
|
|
});
|
|
it('should return an error when have more than one sort parameter', async () => {
|
|
const res = await request
|
|
.get(api('directory'))
|
|
.set(credentials)
|
|
.query({
|
|
text: testChannel.name,
|
|
type: 'channels',
|
|
sort: JSON.stringify({
|
|
name: 1,
|
|
test: 1,
|
|
}),
|
|
})
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(400);
|
|
|
|
expect(res.body).to.have.property('success', false);
|
|
});
|
|
|
|
it('should return an object containing rooms and totalCount from teams', async () => {
|
|
const res = await request
|
|
.get(api('directory'))
|
|
.set(normalUserCredentials)
|
|
.query({
|
|
text: '',
|
|
type: 'teams',
|
|
sort: JSON.stringify({
|
|
name: 1,
|
|
}),
|
|
})
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('result');
|
|
expect(res.body.result).to.be.an(`array`);
|
|
expect(res.body).to.have.property('total');
|
|
expect(res.body.total).to.be.an('number');
|
|
expect(res.body.result[0]).to.have.property('_id', teamCreated.roomId);
|
|
expect(res.body.result[0]).to.have.property('fname');
|
|
expect(res.body.result[0]).to.have.property('teamMain');
|
|
expect(res.body.result[0]).to.have.property('name');
|
|
expect(res.body.result[0]).to.have.property('t');
|
|
expect(res.body.result[0]).to.have.property('usersCount');
|
|
expect(res.body.result[0]).to.have.property('ts');
|
|
expect(res.body.result[0]).to.have.property('teamId');
|
|
expect(res.body.result[0]).to.have.property('default');
|
|
expect(res.body.result[0]).to.have.property('roomsCount');
|
|
});
|
|
});
|
|
|
|
describe('[/spotlight]', () => {
|
|
let user: TestUser<IUser>;
|
|
let userCredentials: Credentials;
|
|
let testChannel: IRoom;
|
|
let testTeam: ITeam;
|
|
let testChannelSpecialChars: IRoom;
|
|
const fnameSpecialCharsRoom = `test ГДΕληνικά-${Date.now()}`;
|
|
const teamName = `team-test-${Date.now()}`;
|
|
|
|
before(async () => {
|
|
user = await createUser();
|
|
userCredentials = await doLogin(user.username, password);
|
|
await updateSetting('UI_Allow_room_names_with_special_chars', true);
|
|
testChannelSpecialChars = (await createRoom({ type: 'c', name: fnameSpecialCharsRoom, credentials: userCredentials })).body.channel;
|
|
testChannel = (await createRoom({ type: 'c', name: `channel.test.${Date.now()}`, credentials: userCredentials })).body.channel;
|
|
testTeam = await createTeam(userCredentials, teamName, TeamType.PUBLIC);
|
|
});
|
|
|
|
after(async () => {
|
|
await Promise.all([
|
|
deleteUser(user),
|
|
updateSetting('UI_Allow_room_names_with_special_chars', false),
|
|
deleteTeam(userCredentials, teamName),
|
|
]);
|
|
});
|
|
|
|
it('should fail when does not have query param', async () => {
|
|
const res = await request.get(api('spotlight')).set(credentials).expect('Content-Type', 'application/json').expect(400);
|
|
|
|
expect(res.body).to.have.property('success', false);
|
|
expect(res.body).to.have.property('error');
|
|
});
|
|
it('should return object inside users array when search by a valid user', async () => {
|
|
const res = await request
|
|
.get(api('spotlight'))
|
|
.query({
|
|
query: `@${adminUsername}`,
|
|
})
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('users').and.to.be.an('array');
|
|
expect(res.body.users[0]).to.have.property('_id');
|
|
expect(res.body.users[0]).to.have.property('name');
|
|
expect(res.body.users[0]).to.have.property('username');
|
|
expect(res.body.users[0]).to.have.property('status');
|
|
expect(res.body).to.have.property('rooms').and.to.be.an('array');
|
|
});
|
|
it('must return the object inside the room array when searching for a valid room and that user is not a member of it', async () => {
|
|
const res = await request
|
|
.get(api('spotlight'))
|
|
.query({
|
|
query: `#${testChannel.name}`,
|
|
})
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('users').and.to.be.an('array');
|
|
expect(res.body).to.have.property('rooms').and.to.be.an('array');
|
|
expect(res.body.rooms[0]).to.have.property('_id');
|
|
expect(res.body.rooms[0]).to.have.property('name');
|
|
expect(res.body.rooms[0]).to.have.property('t');
|
|
});
|
|
it('must return the teamMain property when searching for a valid team that the user is not a member of', async () => {
|
|
const res = await request
|
|
.get(api('spotlight'))
|
|
.query({
|
|
query: `${testTeam.name}`,
|
|
})
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('users').and.to.be.an('array');
|
|
expect(res.body).to.have.property('rooms').and.to.be.an('array');
|
|
expect(res.body.rooms[0]).to.have.property('_id');
|
|
expect(res.body.rooms[0]).to.have.property('name');
|
|
expect(res.body.rooms[0]).to.have.property('t');
|
|
expect(res.body.rooms[0]).to.have.property('teamMain');
|
|
});
|
|
it('must return rooms when searching for a valid fname', async () => {
|
|
const res = await request
|
|
.get(api('spotlight'))
|
|
.query({
|
|
query: `#${fnameSpecialCharsRoom}`,
|
|
})
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('users').and.to.be.an('array');
|
|
expect(res.body).to.have.property('rooms').and.to.be.an('array');
|
|
expect(res.body.rooms[0]).to.have.property('_id', testChannelSpecialChars._id);
|
|
expect(res.body.rooms[0]).to.have.property('name', testChannelSpecialChars.name);
|
|
expect(res.body.rooms[0]).to.have.property('t', testChannelSpecialChars.t);
|
|
});
|
|
it('should not return users when the type param disables user search', async () => {
|
|
const res = await request
|
|
.get(api('spotlight'))
|
|
.query({
|
|
query: `${adminUsername}`,
|
|
type: JSON.stringify({ users: false, rooms: true }),
|
|
})
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('users').and.to.be.an('array').that.is.empty;
|
|
expect(res.body).to.have.property('rooms').and.to.be.an('array');
|
|
});
|
|
it('should exclude usernames passed in the usernames param from the results', async () => {
|
|
const res = await request
|
|
.get(api('spotlight'))
|
|
.query({
|
|
// Use a non-exact (prefix) query so the regex search path runs; the exact-username
|
|
// match branch in Spotlight.searchUsers does not honor the usernames exclusion list.
|
|
query: adminUsername.slice(0, -2),
|
|
usernames: adminUsername,
|
|
})
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('users').and.to.be.an('array');
|
|
expect(res.body.users.map((u: { username: string }) => u.username)).to.not.include(adminUsername);
|
|
});
|
|
describe('anonymous (unauthenticated) requests', () => {
|
|
after(() => updateSetting('Accounts_AllowAnonymousRead', false));
|
|
|
|
it('should return no rooms when anonymous read is disabled', async () => {
|
|
await updateSetting('Accounts_AllowAnonymousRead', false);
|
|
|
|
const res = await request
|
|
.get(api('spotlight'))
|
|
.query({
|
|
query: `#${testChannel.name}`,
|
|
})
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('rooms').and.to.be.an('array').that.is.empty;
|
|
expect(res.body).to.have.property('users').and.to.be.an('array').that.is.empty;
|
|
});
|
|
|
|
// An unprefixed query keeps `type.users` enabled, so it also runs the user search with no
|
|
// user id - the code path that used to throw before the anonymous callers were guarded.
|
|
it('should return no rooms or users for an unprefixed query when anonymous read is disabled', async () => {
|
|
await updateSetting('Accounts_AllowAnonymousRead', false);
|
|
|
|
const res = await request
|
|
.get(api('spotlight'))
|
|
.query({
|
|
query: testChannel.name,
|
|
})
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('rooms').and.to.be.an('array').that.is.empty;
|
|
expect(res.body).to.have.property('users').and.to.be.an('array').that.is.empty;
|
|
});
|
|
|
|
it('should return public rooms but no users when anonymous read is enabled', async () => {
|
|
await updateSetting('Accounts_AllowAnonymousRead', true);
|
|
|
|
const res = await request
|
|
.get(api('spotlight'))
|
|
.query({
|
|
query: `#${testChannel.name}`,
|
|
})
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body.rooms.map((r: { _id: string }) => r._id)).to.include(testChannel._id);
|
|
expect(res.body).to.have.property('users').and.to.be.an('array').that.is.empty;
|
|
});
|
|
|
|
it('should return public rooms but no users for an unprefixed query when anonymous read is enabled', async () => {
|
|
await updateSetting('Accounts_AllowAnonymousRead', true);
|
|
|
|
const res = await request
|
|
.get(api('spotlight'))
|
|
.query({
|
|
query: testChannel.name,
|
|
})
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body.rooms.map((r: { _id: string }) => r._id)).to.include(testChannel._id);
|
|
expect(res.body).to.have.property('users').and.to.be.an('array').that.is.empty;
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('[/instances.get]', () => {
|
|
let unauthorizedUserCredentials: Credentials;
|
|
before(async () => {
|
|
const createdUser = await createUser();
|
|
unauthorizedUserCredentials = await doLogin(createdUser.username, password);
|
|
});
|
|
|
|
it('should fail if user is logged in but is unauthorized', async () => {
|
|
const res = await request
|
|
.get(api('instances.get'))
|
|
.set(unauthorizedUserCredentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(403);
|
|
|
|
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 fail if not logged in', async () => {
|
|
const res = await request.get(api('instances.get')).expect('Content-Type', 'application/json').expect(401);
|
|
|
|
expect(res.body).to.have.property('status', 'error');
|
|
expect(res.body).to.have.property('message');
|
|
});
|
|
|
|
it('should return instances if user is logged in and is authorized', async () => {
|
|
const res = await request.get(api('instances.get')).set(credentials).expect(200);
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
|
|
expect(res.body).to.have.property('instances').and.to.be.an('array').with.lengthOf(1);
|
|
|
|
const instances = res.body.instances as IInstance[];
|
|
|
|
const instanceName = IS_EE ? 'ddp-streamer' : 'rocket.chat';
|
|
|
|
const instance = instances.find((i): i is IInstance & { instanceRecord: IInstanceStatus } => i.instanceRecord?.name === instanceName);
|
|
|
|
if (!instance) throw new AssertionError(`no instance named "${instanceName}"`);
|
|
|
|
expect(instance).to.have.property('instanceRecord');
|
|
expect(instance).to.have.property('currentStatus');
|
|
|
|
expect(instance.currentStatus).to.have.property('connected');
|
|
|
|
expect(instance.instanceRecord).to.have.property('_id');
|
|
expect(instance.instanceRecord).to.have.property('extraInformation');
|
|
expect(instance.instanceRecord).to.have.property('name');
|
|
expect(instance.instanceRecord).to.have.property('pid');
|
|
|
|
if (!IS_EE) {
|
|
expect(instance).to.have.property('address');
|
|
|
|
expect(instance.currentStatus).to.have.property('lastHeartbeatTime');
|
|
expect(instance.currentStatus).to.have.property('local');
|
|
|
|
const { extraInformation } = instance.instanceRecord;
|
|
|
|
expect(extraInformation).to.have.property('host');
|
|
expect(extraInformation).to.have.property('port');
|
|
expect(extraInformation).to.have.property('os').and.to.have.property('cpus').to.be.a('number');
|
|
expect(extraInformation).to.have.property('nodeVersion');
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('[/shield.svg]', () => {
|
|
before(() => updateSetting('API_Enable_Shields', false));
|
|
|
|
after(() => updateSetting('API_Enable_Shields', true));
|
|
|
|
it('should fail if API_Enable_Shields is disabled', async () => {
|
|
const res = await request
|
|
.get(api('shield.svg'))
|
|
.query({
|
|
type: 'online',
|
|
icon: true,
|
|
channel: 'general',
|
|
name: 'Rocket.Chat',
|
|
})
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(400);
|
|
|
|
expect(res.body).to.have.property('success', false);
|
|
expect(res.body).to.have.property('errorType', 'error-endpoint-disabled');
|
|
});
|
|
|
|
it('should succeed if API_Enable_Shields is enabled', async () => {
|
|
await updateSetting('API_Enable_Shields', true);
|
|
|
|
await request
|
|
.get(api('shield.svg'))
|
|
.query({
|
|
type: 'online',
|
|
icon: true,
|
|
channel: 'general',
|
|
name: 'Rocket.Chat',
|
|
})
|
|
.expect('Content-Type', 'image/svg+xml;charset=utf-8')
|
|
.expect(200);
|
|
});
|
|
});
|
|
|
|
describe('/pw.getPolicy', () => {
|
|
it('should return policies', async () => {
|
|
const res = await request.get(api('pw.getPolicy')).set(credentials).expect('Content-Type', 'application/json').expect(200);
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('enabled');
|
|
expect(res.body).to.have.property('policy').and.to.be.an('array');
|
|
});
|
|
});
|
|
|
|
describe('/fingerprint', () => {
|
|
let unauthorizedUser: TestUser<IUser>;
|
|
let unauthorizedUserCredentials: Credentials;
|
|
|
|
before(async () => {
|
|
unauthorizedUser = await createUser();
|
|
unauthorizedUserCredentials = await doLogin(unauthorizedUser.username, password);
|
|
});
|
|
|
|
after(async () => {
|
|
await deleteUser(unauthorizedUser);
|
|
});
|
|
|
|
it('should return 401 when called without authentication', async () => {
|
|
const res = await request.post(api('fingerprint')).send({ setDeploymentAs: 'updated-configuration' });
|
|
|
|
expect(res.status).to.equal(401);
|
|
expect(res.body).to.have.property('status', 'error');
|
|
});
|
|
|
|
it('should return 403 when a user without the manage-cloud permission tries to acknowledge a deployment configuration change', async () => {
|
|
const res = await request
|
|
.post(api('fingerprint'))
|
|
.set(unauthorizedUserCredentials)
|
|
.send({ setDeploymentAs: 'updated-configuration' });
|
|
|
|
expect(res.status).to.equal(403);
|
|
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 return 403 when a user without the manage-cloud permission tries to deregister the workspace as a new workspace', async () => {
|
|
const res = await request.post(api('fingerprint')).set(unauthorizedUserCredentials).send({ setDeploymentAs: 'new-workspace' });
|
|
|
|
expect(res.status).to.equal(403);
|
|
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 return 200 when a user with the manage-cloud permission acknowledges a deployment configuration change', async () => {
|
|
const res = await request.post(api('fingerprint')).set(credentials).send({ setDeploymentAs: 'updated-configuration' });
|
|
|
|
expect(res.status).to.equal(200);
|
|
expect(res.body).to.have.property('success', true);
|
|
});
|
|
});
|
|
});
|