[FIX] Deactivate users that are the last owner of a room using REST API (#18864)

* test: add e2e tests for REST API user deactivation

* fix(app): read confirmRelinquish from HTTP request

* chore(app): remove unnecessary console.log
pull/18945/head
Felipe Parreira 5 years ago committed by GitHub
parent 982773aeda
commit dc6bcbdba0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      app/api/server/v1/users.js
  2. 7
      tests/data/rooms.helper.js
  3. 579
      tests/end-to-end/api/01-users.js

@ -98,8 +98,10 @@ API.v1.addRoute('users.deleteOwnAccount', { authRequired: true }, {
throw new Meteor.Error('error-not-allowed', 'Not allowed');
}
const { confirmRelinquish = false } = this.requestParams();
Meteor.runAsUser(this.userId, () => {
Meteor.call('deleteUserOwnAccount', password);
Meteor.call('deleteUserOwnAccount', password, confirmRelinquish);
});
return API.v1.success();
@ -133,7 +135,8 @@ API.v1.addRoute('users.setActiveStatus', { authRequired: true }, {
}
Meteor.runAsUser(this.userId, () => {
Meteor.call('setUserActiveStatus', this.bodyParams.userId, this.bodyParams.activeStatus, this.bodyParams.confirmRelinquish);
const { userId, activeStatus, confirmRelinquish = false } = this.bodyParams;
Meteor.call('setUserActiveStatus', userId, activeStatus, confirmRelinquish);
});
return API.v1.success({ user: Users.findOneById(this.bodyParams.userId, { fields: { active: 1 } }) });
},
@ -463,8 +466,10 @@ API.v1.addRoute('users.update', { authRequired: true, twoFactorRequired: true },
}
if (typeof this.bodyParams.data.active !== 'undefined') {
const { userId, data: { active }, confirmRelinquish = false } = this.bodyParams;
Meteor.runAsUser(this.userId, () => {
Meteor.call('setUserActiveStatus', this.bodyParams.userId, this.bodyParams.data.active);
Meteor.call('setUserActiveStatus', userId, active, confirmRelinquish);
});
}
const { fields } = this.parseJsonQuery();

@ -1,6 +1,6 @@
import { api, credentials, request } from './api-data';
export const createRoom = ({ name, type, username }) => {
export const createRoom = ({ name, type, username, members = [] }) => {
if (!type) {
throw new Error('"type" is required in "createRoom" test helper');
}
@ -18,7 +18,10 @@ export const createRoom = ({ name, type, username }) => {
return request.post(api(endpoints[type]))
.set(credentials)
.send(params);
.send({
...params,
members,
});
};
export const closeRoom = ({ type, roomId }) => {

@ -18,6 +18,7 @@ import { imgURL } from '../../data/interactions.js';
import { customFieldText, clearCustomFields, setCustomFields } from '../../data/custom-fields.js';
import { updatePermission, updateSetting } from '../../data/permissions.helper';
import { createUser, login, deleteUser, getUserStatus } from '../../data/users.helper.js';
import { createRoom } from '../../data/rooms.helper';
describe('[Users]', function() {
this.retries(0);
@ -1355,6 +1356,165 @@ describe('[Users]', function() {
});
});
});
it('should return an error when trying to delete user own account if user is the last room owner', async () => {
const user = await createUser();
const createdUserCredentials = await login(user.username, password);
const room = (await createRoom({
type: 'c',
name: `channel.test.${ Date.now() }-${ Math.random() }`,
username: user.username,
members: [user.username],
})).body.channel;
await request.post(api('channels.addOwner'))
.set(credentials)
.send({
userId: user._id,
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('channels.removeOwner'))
.set(credentials)
.send({
userId: credentials['X-User-Id'],
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request
.post(api('users.deleteOwnAccount'))
.set(createdUserCredentials)
.send({
password: crypto.createHash('sha256').update(password, 'utf8').digest('hex'),
})
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body).to.have.property('error', '[user-last-owner]');
expect(res.body).to.have.property('errorType', 'user-last-owner');
});
});
it('should delete user own account if the user is the last room owner and `confirmRelinquish` is set to `true`', async () => {
const user = await createUser();
const createdUserCredentials = await login(user.username, password);
const room = (await createRoom({
type: 'c',
name: `channel.test.${ Date.now() }-${ Math.random() }`,
username: user.username,
members: [user.username],
})).body.channel;
await request.post(api('channels.addOwner'))
.set(credentials)
.send({
userId: user._id,
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('channels.removeOwner'))
.set(credentials)
.send({
userId: credentials['X-User-Id'],
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request
.post(api('users.deleteOwnAccount'))
.set(createdUserCredentials)
.send({
password: crypto.createHash('sha256').update(password, 'utf8').digest('hex'),
confirmRelinquish: true,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
});
it('should assign a new owner to the room if the last room owner is deleted', async () => {
const user = await createUser();
const createdUserCredentials = await login(user.username, password);
const room = (await createRoom({
type: 'c',
name: `channel.test.${ Date.now() }-${ Math.random() }`,
username: user.username,
members: [user.username],
})).body.channel;
await request.post(api('channels.addOwner'))
.set(credentials)
.send({
userId: user._id,
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('channels.removeOwner'))
.set(credentials)
.send({
userId: credentials['X-User-Id'],
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request
.post(api('users.deleteOwnAccount'))
.set(createdUserCredentials)
.send({
password: crypto.createHash('sha256').update(password, 'utf8').digest('hex'),
confirmRelinquish: true,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.get(api('channels.roles'))
.set(credentials)
.query({
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body.roles).to.have.lengthOf(1);
expect(res.body.roles[0].roles).to.eql(['owner']);
expect(res.body.roles[0].u).to.have.property('_id', credentials['X-User-Id']);
});
});
});
describe('[/users.delete]', () => {
@ -1371,7 +1531,7 @@ describe('[Users]', function() {
});
const testUsername = `testuserdelete${ +new Date() }`;
let targetUser;
it('register a new user...', (done) => {
beforeEach((done) => {
request.post(api('users.register'))
.set(credentials)
.send({
@ -1384,40 +1544,196 @@ describe('[Users]', function() {
.expect(200)
.expect((res) => {
targetUser = res.body.user;
}).end(done);
});
afterEach((done) => {
updatePermission('delete-user', ['admin']).then(() => {
request.post(api('users.delete'))
.set(credentials)
.send({
userId: targetUser._id,
confirmRelinquish: true,
}).end(done);
});
});
it('should return an error when trying delete user account without "delete-user" permission', async () => {
await updatePermission('delete-user', ['user']);
await request.post(api('users.delete'))
.set(credentials)
.send({
userId: targetUser._id,
})
.end(done);
.expect('Content-Type', 'application/json')
.expect(403)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body).to.have.property('error', 'unauthorized');
});
});
it('should return an error when trying delete user account without "delete-user" permission', (done) => {
updatePermission('delete-user', ['user'])
.then(() => {
request.post(api('users.delete'))
.set(credentials)
.send({
userId: targetUser._id,
})
.expect('Content-Type', 'application/json')
.expect(403)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body).to.have.property('error', 'unauthorized');
})
.end(done);
it('should return an error when trying to delete user account if the user is the last room owner', async () => {
await updatePermission('delete-user', ['admin']);
const room = (await createRoom({
type: 'c',
name: `channel.test.${ Date.now() }-${ Math.random() }`,
members: [targetUser.username],
})).body.channel;
await request.post(api('channels.addOwner'))
.set(credentials)
.send({
userId: targetUser._id,
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('channels.removeOwner'))
.set(credentials)
.send({
userId: credentials['X-User-Id'],
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('users.delete'))
.set(credentials)
.send({
userId: targetUser._id,
})
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body).to.have.property('error', '[user-last-owner]');
expect(res.body).to.have.property('errorType', 'user-last-owner');
});
});
it('should delete user account when logged user has "delete-user" permission', (done) => {
updatePermission('delete-user', ['admin'])
.then(() => {
request.post(api('users.delete'))
.set(credentials)
.send({
userId: targetUser._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
})
.end(done);
it('should delete user account if the user is the last room owner and `confirmRelinquish` is set to `true`', async () => {
await updatePermission('delete-user', ['admin']);
const room = (await createRoom({
type: 'c',
name: `channel.test.${ Date.now() }-${ Math.random() }`,
members: [targetUser.username],
})).body.channel;
await request.post(api('channels.addOwner'))
.set(credentials)
.send({
userId: targetUser._id,
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('channels.removeOwner'))
.set(credentials)
.send({
userId: credentials['X-User-Id'],
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('users.delete'))
.set(credentials)
.send({
userId: targetUser._id,
confirmRelinquish: true,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
});
it('should delete user account when logged user has "delete-user" permission', async () => {
await updatePermission('delete-user', ['admin']);
await request.post(api('users.delete'))
.set(credentials)
.send({
userId: targetUser._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
});
it('should assign a new owner to the room if the last room owner is deleted', async () => {
await updatePermission('delete-user', ['admin']);
const room = (await createRoom({
type: 'c',
name: `channel.test.${ Date.now() }-${ Math.random() }`,
members: [targetUser.username],
})).body.channel;
await request.post(api('channels.addOwner'))
.set(credentials)
.send({
userId: targetUser._id,
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('channels.removeOwner'))
.set(credentials)
.send({
userId: credentials['X-User-Id'],
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('users.delete'))
.set(credentials)
.send({
userId: targetUser._id,
confirmRelinquish: true,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.get(api('channels.roles'))
.set(credentials)
.query({
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body.roles).to.have.lengthOf(1);
expect(res.body.roles[0].roles).to.eql(['owner']);
expect(res.body.roles[0].u).to.have.property('_id', credentials['X-User-Id']);
});
});
});
@ -1681,6 +1997,207 @@ describe('[Users]', function() {
})
.end(done);
});
it('should return an error when trying to set other user status to inactive and the user is the last owner of a room', async () => {
const room = (await createRoom({
type: 'c',
name: `channel.test.${ Date.now() }-${ Math.random() }`,
username: targetUser.username,
members: [targetUser.username],
})).body.channel;
await request.post(api('channels.invite'))
.set(credentials)
.send({
userId: targetUser._id,
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('channels.addOwner'))
.set(credentials)
.send({
userId: targetUser._id,
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('channels.removeOwner'))
.set(credentials)
.send({
userId: credentials['X-User-Id'],
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('users.setActiveStatus'))
.set(userCredentials)
.send({
activeStatus: false,
userId: targetUser._id,
})
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body).to.have.property('error', '[user-last-owner]');
expect(res.body).to.have.property('errorType', 'user-last-owner');
});
});
it('should set other user status to inactive if the user is the last owner of a room and `confirmRelinquish` is set to `true`', async () => {
const room = (await createRoom({
type: 'c',
name: `channel.test.${ Date.now() }-${ Math.random() }`,
username: targetUser.username,
members: [targetUser.username],
})).body.channel;
await request.post(api('channels.invite'))
.set(credentials)
.send({
userId: targetUser._id,
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('channels.addOwner'))
.set(credentials)
.send({
userId: targetUser._id,
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('channels.removeOwner'))
.set(credentials)
.send({
userId: credentials['X-User-Id'],
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('users.setActiveStatus'))
.set(userCredentials)
.send({
activeStatus: false,
userId: targetUser._id,
confirmRelinquish: true,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
});
it('should set other user as room owner if the last owner of a room is deactivated and `confirmRelinquish` is set to `true`', async () => {
const room = (await createRoom({
type: 'c',
name: `channel.test.${ Date.now() }-${ Math.random() }`,
members: [targetUser.username],
})).body.channel;
await request.post(api('users.setActiveStatus'))
.set(userCredentials)
.send({
activeStatus: true,
userId: targetUser._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('channels.invite'))
.set(credentials)
.send({
userId: targetUser._id,
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('channels.addOwner'))
.set(credentials)
.send({
userId: targetUser._id,
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('channels.removeOwner'))
.set(credentials)
.send({
userId: credentials['X-User-Id'],
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.post(api('users.setActiveStatus'))
.set(userCredentials)
.send({
activeStatus: false,
userId: targetUser._id,
confirmRelinquish: true,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
});
await request.get(api('channels.roles'))
.set(credentials)
.query({
roomId: room._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body.roles).to.have.lengthOf(2);
expect(res.body.roles[1].roles).to.eql(['owner']);
expect(res.body.roles[1].u).to.have.property('_id', credentials['X-User-Id']);
});
});
it('should return an error when trying to set other user active status and has not the necessary permission(edit-other-user-active-status)', (done) => {
updatePermission('edit-other-user-active-status', []).then(() => {
request.post(api('users.setActiveStatus'))

Loading…
Cancel
Save