mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-17 19:21:04 +01:00
feat: allow multiple room owners, closes #6503
This commit is contained in:
@@ -54,6 +54,7 @@
|
|||||||
"chat.kick": "Kick",
|
"chat.kick": "Kick",
|
||||||
"chat.show-ip": "Show IP",
|
"chat.show-ip": "Show IP",
|
||||||
"chat.owner": "Room Owner",
|
"chat.owner": "Room Owner",
|
||||||
|
"chat.grant-rescind-ownership": "Grant/Rescind Ownership",
|
||||||
|
|
||||||
"chat.system.user-join": "%1 has joined the room",
|
"chat.system.user-join": "%1 has joined the room",
|
||||||
"chat.system.user-leave": "%1 has left the room",
|
"chat.system.user-leave": "%1 has left the room",
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
RoomObject:
|
RoomObject:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
owner:
|
|
||||||
type: number
|
|
||||||
description: the uid of the chat room owner (usually the user who created the room initially)
|
|
||||||
roomId:
|
roomId:
|
||||||
type: number
|
type: number
|
||||||
description: unique identifier for the chat room
|
description: unique identifier for the chat room
|
||||||
@@ -143,6 +140,8 @@ RoomUserList:
|
|||||||
type: boolean
|
type: boolean
|
||||||
canKick:
|
canKick:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
canToggleOwner:
|
||||||
|
type: boolean
|
||||||
index:
|
index:
|
||||||
type: number
|
type: number
|
||||||
online:
|
online:
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ get:
|
|||||||
allOf:
|
allOf:
|
||||||
- type: object
|
- type: object
|
||||||
properties:
|
properties:
|
||||||
owner:
|
|
||||||
type: number
|
|
||||||
roomId:
|
roomId:
|
||||||
type: number
|
type: number
|
||||||
roomName:
|
roomName:
|
||||||
@@ -173,10 +171,6 @@ get:
|
|||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
owner:
|
|
||||||
oneOf:
|
|
||||||
- type: number
|
|
||||||
- type: string
|
|
||||||
roomId:
|
roomId:
|
||||||
type: number
|
type: number
|
||||||
roomName:
|
roomName:
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ define('forum/chats/manage', [
|
|||||||
|
|
||||||
refreshParticipantsList(roomId, modal);
|
refreshParticipantsList(roomId, modal);
|
||||||
addKickHandler(roomId, modal);
|
addKickHandler(roomId, modal);
|
||||||
|
addToggleOwnerHandler(roomId, modal);
|
||||||
|
|
||||||
const userListEl = modal.find('[component="chat/manage/user/list"]');
|
const userListEl = modal.find('[component="chat/manage/user/list"]');
|
||||||
const userListElSearch = modal.find('[component="chat/manage/user/list/search"]');
|
const userListElSearch = modal.find('[component="chat/manage/user/list/search"]');
|
||||||
@@ -89,6 +90,17 @@ define('forum/chats/manage', [
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addToggleOwnerHandler(roomId, modal) {
|
||||||
|
modal.on('click', '[data-action="toggleOwner"]', async function () {
|
||||||
|
const uid = parseInt(this.getAttribute('data-uid'), 10);
|
||||||
|
const $this = $(this);
|
||||||
|
await socket.emit('modules.chats.toggleOwner', { roomId: roomId, uid: uid });
|
||||||
|
$this.parents('[data-uid]')
|
||||||
|
.find('[component="chat/manage/user/owner/icon"]')
|
||||||
|
.toggleClass('hidden');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async function refreshParticipantsList(roomId, modal, data) {
|
async function refreshParticipantsList(roomId, modal, data) {
|
||||||
const listEl = modal.find('[component="chat/manage/user/list"]');
|
const listEl = modal.find('[component="chat/manage/user/list"]');
|
||||||
|
|
||||||
@@ -101,6 +113,7 @@ define('forum/chats/manage', [
|
|||||||
}
|
}
|
||||||
|
|
||||||
listEl.html(await app.parseAndTranslate('partials/chats/manage-room-users', data));
|
listEl.html(await app.parseAndTranslate('partials/chats/manage-room-users', data));
|
||||||
|
listEl.find('[data-bs-toggle="tooltip"]').tooltip();
|
||||||
}
|
}
|
||||||
|
|
||||||
return manage;
|
return manage;
|
||||||
|
|||||||
@@ -19,13 +19,13 @@ define('forum/chats/recent', ['alerts', 'api', 'chat'], function (alerts, api, c
|
|||||||
chat.toggleReadState(chatEl);
|
chat.toggleReadState(chatEl);
|
||||||
});
|
});
|
||||||
|
|
||||||
$('[component="chat/recent"]').on('scroll', function () {
|
$('[component="chat/recent"]').on('scroll', utils.debounce(function () {
|
||||||
const $this = $(this);
|
const $this = $(this);
|
||||||
const bottom = ($this[0].scrollHeight - $this.height()) * 0.9;
|
const bottom = ($this[0].scrollHeight - $this.height()) * 0.9;
|
||||||
if ($this.scrollTop() > bottom) {
|
if ($this.scrollTop() > bottom) {
|
||||||
loadMoreRecentChats();
|
loadMoreRecentChats();
|
||||||
}
|
}
|
||||||
});
|
}, 100));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ define('forum/chats/user-list', ['api'], function (api) {
|
|||||||
if (ajaxify.data.template.chats && app.isFocused && userListEl.scrollTop() === 0 && !userListEl.hasClass('hidden')) {
|
if (ajaxify.data.template.chats && app.isFocused && userListEl.scrollTop() === 0 && !userListEl.hasClass('hidden')) {
|
||||||
const data = await api.get(`/chats/${roomId}/users`, { start: 0 });
|
const data = await api.get(`/chats/${roomId}/users`, { start: 0 });
|
||||||
userListEl.html(await app.parseAndTranslate('partials/chats/user-list', 'users', data));
|
userListEl.html(await app.parseAndTranslate('partials/chats/user-list', 'users', data));
|
||||||
|
userListEl.find('[data-bs-toggle="tooltip"]').tooltip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -169,19 +169,22 @@ chatsAPI.users = async (caller, data) => {
|
|||||||
const start = data.hasOwnProperty('start') ? data.start : 0;
|
const start = data.hasOwnProperty('start') ? data.start : 0;
|
||||||
const stop = start + 39;
|
const stop = start + 39;
|
||||||
const io = require('../socket.io');
|
const io = require('../socket.io');
|
||||||
const [isOwner, isUserInRoom, users, onlineUids] = await Promise.all([
|
const [isOwner, isUserInRoom, users, isAdmin, onlineUids] = await Promise.all([
|
||||||
messaging.isRoomOwner(caller.uid, data.roomId),
|
messaging.isRoomOwner(caller.uid, data.roomId),
|
||||||
messaging.isUserInRoom(caller.uid, data.roomId),
|
messaging.isUserInRoom(caller.uid, data.roomId),
|
||||||
messaging.getUsersInRoomFromSet(
|
messaging.getUsersInRoomFromSet(
|
||||||
`chat:room:${data.roomId}:uids:online`, data.roomId, start, stop, true
|
`chat:room:${data.roomId}:uids:online`, data.roomId, start, stop, true
|
||||||
),
|
),
|
||||||
|
user.isAdministrator(caller.uid),
|
||||||
io.getUidsInRoom(`chat_room_${data.roomId}`),
|
io.getUidsInRoom(`chat_room_${data.roomId}`),
|
||||||
]);
|
]);
|
||||||
if (!isUserInRoom) {
|
if (!isUserInRoom) {
|
||||||
throw new Error('[[error:no-privileges]]');
|
throw new Error('[[error:no-privileges]]');
|
||||||
}
|
}
|
||||||
users.forEach((user) => {
|
users.forEach((user) => {
|
||||||
user.canKick = isOwner && (parseInt(user.uid, 10) !== parseInt(caller.uid, 10));
|
const isSelf = parseInt(user.uid, 10) === parseInt(caller.uid, 10);
|
||||||
|
user.canKick = isOwner && !isSelf;
|
||||||
|
user.canToggleOwner = (isAdmin || isOwner) && !isSelf;
|
||||||
user.online = parseInt(user.uid, 10) === parseInt(caller.uid, 10) || onlineUids.includes(String(user.uid));
|
user.online = parseInt(user.uid, 10) === parseInt(caller.uid, 10) || onlineUids.includes(String(user.uid));
|
||||||
});
|
});
|
||||||
return { users };
|
return { users };
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ module.exports = function (Messaging) {
|
|||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const roomId = await db.incrObjectField('global', 'nextChatRoomId');
|
const roomId = await db.incrObjectField('global', 'nextChatRoomId');
|
||||||
const room = {
|
const room = {
|
||||||
owner: uid,
|
|
||||||
roomId: roomId,
|
roomId: roomId,
|
||||||
timestamp: now,
|
timestamp: now,
|
||||||
};
|
};
|
||||||
@@ -93,6 +92,7 @@ module.exports = function (Messaging) {
|
|||||||
await Promise.all([
|
await Promise.all([
|
||||||
db.setObject(`chat:room:${roomId}`, room),
|
db.setObject(`chat:room:${roomId}`, room),
|
||||||
db.sortedSetAdd('chat:rooms', now, roomId),
|
db.sortedSetAdd('chat:rooms', now, roomId),
|
||||||
|
db.sortedSetAdd(`chat:room:${roomId}:owners`, now, uid),
|
||||||
db.sortedSetsAdd([
|
db.sortedSetsAdd([
|
||||||
`chat:room:${roomId}:uids`,
|
`chat:room:${roomId}:uids`,
|
||||||
`chat:room:${roomId}:uids:online`,
|
`chat:room:${roomId}:uids:online`,
|
||||||
@@ -143,6 +143,7 @@ module.exports = function (Messaging) {
|
|||||||
db.deleteAll([
|
db.deleteAll([
|
||||||
...roomIds.map(id => `chat:room:${id}`),
|
...roomIds.map(id => `chat:room:${id}`),
|
||||||
...roomIds.map(id => `chat:room:${id}:uids`),
|
...roomIds.map(id => `chat:room:${id}:uids`),
|
||||||
|
...roomIds.map(id => `chat:room:${id}:owners`),
|
||||||
...roomIds.map(id => `chat:room:${id}:uids:online`),
|
...roomIds.map(id => `chat:room:${id}:uids:online`),
|
||||||
]),
|
]),
|
||||||
db.sortedSetRemove('chat:rooms', roomIds),
|
db.sortedSetRemove('chat:rooms', roomIds),
|
||||||
@@ -207,16 +208,27 @@ module.exports = function (Messaging) {
|
|||||||
if (!isArray) {
|
if (!isArray) {
|
||||||
uids = [uids];
|
uids = [uids];
|
||||||
}
|
}
|
||||||
const owner = await db.getObjectField(`chat:room:${roomId}`, 'owner');
|
|
||||||
const isOwners = uids.map(uid => parseInt(uid, 10) === parseInt(owner, 10));
|
|
||||||
|
|
||||||
|
const isOwners = await db.isSortedSetMembers(`chat:room:${roomId}:owners`, uids);
|
||||||
const result = await Promise.all(isOwners.map(async (isOwner, index) => {
|
const result = await Promise.all(isOwners.map(async (isOwner, index) => {
|
||||||
const payload = await plugins.hooks.fire('filter:messaging.isRoomOwner', { uid: uids[index], roomId, owner, isOwner });
|
const payload = await plugins.hooks.fire('filter:messaging.isRoomOwner', { uid: uids[index], roomId, isOwner });
|
||||||
return payload.isOwner;
|
return payload.isOwner;
|
||||||
}));
|
}));
|
||||||
return isArray ? result : result[0];
|
return isArray ? result : result[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Messaging.toggleOwner = async (uid, roomId) => {
|
||||||
|
if (!(parseInt(uid, 10) > 0) || !roomId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const isOwner = await Messaging.isRoomOwner(uid, roomId);
|
||||||
|
if (isOwner) {
|
||||||
|
await db.sortedSetRemove(`chat:room:${roomId}:owners`, uid);
|
||||||
|
} else {
|
||||||
|
await db.sortedSetAdd(`chat:room:${roomId}:owners`, Date.now(), uid);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Messaging.isRoomPublic = async function (roomId) {
|
Messaging.isRoomPublic = async function (roomId) {
|
||||||
return parseInt(await db.getObjectField(`chat:room:${roomId}`, 'public'), 10) === 1;
|
return parseInt(await db.getObjectField(`chat:room:${roomId}`, 'public'), 10) === 1;
|
||||||
};
|
};
|
||||||
@@ -285,6 +297,7 @@ module.exports = function (Messaging) {
|
|||||||
await Promise.all([
|
await Promise.all([
|
||||||
db.sortedSetRemove([
|
db.sortedSetRemove([
|
||||||
`chat:room:${roomId}:uids`,
|
`chat:room:${roomId}:uids`,
|
||||||
|
`chat:room:${roomId}:owners`,
|
||||||
`chat:room:${roomId}:uids:online`,
|
`chat:room:${roomId}:uids:online`,
|
||||||
], uids),
|
], uids),
|
||||||
db.sortedSetsRemove(keys, roomId),
|
db.sortedSetsRemove(keys, roomId),
|
||||||
@@ -301,6 +314,7 @@ module.exports = function (Messaging) {
|
|||||||
|
|
||||||
const roomKeys = [
|
const roomKeys = [
|
||||||
...roomIds.map(roomId => `chat:room:${roomId}:uids`),
|
...roomIds.map(roomId => `chat:room:${roomId}:uids`),
|
||||||
|
...roomIds.map(roomId => `chat:room:${roomId}:owners`),
|
||||||
...roomIds.map(roomId => `chat:room:${roomId}:uids:online`),
|
...roomIds.map(roomId => `chat:room:${roomId}:uids:online`),
|
||||||
];
|
];
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
@@ -319,9 +333,16 @@ module.exports = function (Messaging) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
async function updateOwner(roomId) {
|
async function updateOwner(roomId) {
|
||||||
const uids = await db.getSortedSetRange(`chat:room:${roomId}:uids`, 0, 0);
|
let nextOwner = await db.getSortedSetRange(`chat:room:${roomId}:owners`, 0, 0);
|
||||||
const newOwner = uids[0] || 0;
|
if (!nextOwner[0]) {
|
||||||
await db.setObjectField(`chat:room:${roomId}`, 'owner', newOwner);
|
// no owners left grab next user
|
||||||
|
nextOwner = await db.getSortedSetRange(`chat:room:${roomId}:uids`, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const newOwner = nextOwner[0] || 0;
|
||||||
|
if (parseInt(newOwner, 10) > 0) {
|
||||||
|
await db.sortedSetAdd(`chat:room:${roomId}:owners`, Date.now(), newOwner);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Messaging.getAllUidsInRoomFromSet = async function (set) {
|
Messaging.getAllUidsInRoomFromSet = async function (set) {
|
||||||
|
|||||||
@@ -110,7 +110,13 @@ async function joinLeave(socket, roomIds, method, prefix = 'chat_room') {
|
|||||||
await Promise.all(roomIds.map(async (roomId, idx) => {
|
await Promise.all(roomIds.map(async (roomId, idx) => {
|
||||||
const isPublic = roomData[idx] && roomData[idx].public;
|
const isPublic = roomData[idx] && roomData[idx].public;
|
||||||
const roomGroups = roomData[idx] && roomData[idx].groups;
|
const roomGroups = roomData[idx] && roomData[idx].groups;
|
||||||
if (isAdmin || (inRooms[idx] && (!isPublic || await groups.isMemberOfAny(socket.uid, roomGroups)))) {
|
|
||||||
|
if (isAdmin ||
|
||||||
|
(
|
||||||
|
inRooms[idx] &&
|
||||||
|
(!isPublic || !roomGroups.length || await groups.isMemberOfAny(socket.uid, roomGroups))
|
||||||
|
)
|
||||||
|
) {
|
||||||
socket[method](`${prefix}_${roomId}`);
|
socket[method](`${prefix}_${roomId}`);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
@@ -177,4 +183,21 @@ SocketModules.chats.searchMembers = async function (socket, data) {
|
|||||||
return { users: roomUsers };
|
return { users: roomUsers };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SocketModules.chats.toggleOwner = async (socket, data) => {
|
||||||
|
if (!data || !data.uid || !data.roomId) {
|
||||||
|
throw new Error('[[error:invalid-data]]');
|
||||||
|
}
|
||||||
|
|
||||||
|
const [isAdmin, inRoom, isRoomOwner] = await Promise.all([
|
||||||
|
user.isAdministrator(socket.uid),
|
||||||
|
Messaging.isUserInRoom(socket.uid, data.roomId),
|
||||||
|
Messaging.isRoomOwner(socket.uid, data.roomId),
|
||||||
|
]);
|
||||||
|
if (!isAdmin && (!inRoom || !isRoomOwner)) {
|
||||||
|
throw new Error('[[error:no-privileges]]');
|
||||||
|
}
|
||||||
|
|
||||||
|
await Messaging.toggleOwner(data.uid, data.roomId);
|
||||||
|
};
|
||||||
|
|
||||||
require('../promisify')(SocketModules);
|
require('../promisify')(SocketModules);
|
||||||
|
|||||||
34
src/upgrades/3.3.0/chat_room_owners.js
Normal file
34
src/upgrades/3.3.0/chat_room_owners.js
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
|
const db = require('../../database');
|
||||||
|
const batch = require('../../batch');
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: 'Create chat:room:<room_id>:owners zset',
|
||||||
|
timestamp: Date.UTC(2023, 6, 17),
|
||||||
|
method: async function () {
|
||||||
|
const { progress } = this;
|
||||||
|
|
||||||
|
progress.total = await db.sortedSetCard('chat:rooms');
|
||||||
|
|
||||||
|
await batch.processSortedSet('chat:rooms', async (roomIds) => {
|
||||||
|
progress.incr(roomIds.length);
|
||||||
|
const roomData = await db.getObjects(
|
||||||
|
roomIds.map(id => `chat:room:${id}`)
|
||||||
|
);
|
||||||
|
|
||||||
|
const bulkAdd = [];
|
||||||
|
roomData.forEach((room) => {
|
||||||
|
if (room && room.roomId && room.owner) {
|
||||||
|
bulkAdd.push([`chat:room:${room.roomId}:owners`, room.timestamp, room.owner]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.sortedSetAddBulk(bulkAdd);
|
||||||
|
}, {
|
||||||
|
batch: 500,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
{{{ each selectedUsers }}}
|
{{{ each selectedUsers }}}
|
||||||
<li class="list-group-item d-flex gap-2 align-items-center justify-content-between" component="chat/user" data-uid="{./uid}">
|
<li class="list-group-item d-flex gap-2 align-items-center justify-content-between" component="chat/user" data-uid="{./uid}">
|
||||||
<a href="#" class="text-reset text-decoration-none">{buildAvatar(@value, "24px", true)} {./username}</a>
|
<a href="#" class="text-reset text-decoration-none">{buildAvatar(@value, "24px", true)} {./username}</a>
|
||||||
<button component="chat/room/users/remove" class="btn btn-sm btn-link"><i class="fa fa-times text-danger"></i></button>
|
<button component="chat/room/users/remove" class="btn btn-sm btn-light"><i class="fa fa-times text-danger"></i></button>
|
||||||
</li>
|
</li>
|
||||||
{{{ end }}}
|
{{{ end }}}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
{{{ each users }}}
|
{{{ each users }}}
|
||||||
<li class="list-group-item d-flex align-items-center justify-content-between" data-index="{./index}">
|
<li class="list-group-item d-flex align-items-center justify-content-between" data-uid="{./uid}" data-index="{./index}">
|
||||||
<div class="d-flex gap-1 align-items-center">
|
<div class="d-flex gap-1 align-items-center">
|
||||||
{buildAvatar(users, "24px", true)}
|
{buildAvatar(users, "24px", true)}
|
||||||
<span>{./username}{{{ if ./isOwner }}} <i class="fa fa-star text-warning" title="[[modules:chat.owner]]"></i>{{{ end }}}</span>
|
<span>{./username} <i component="chat/manage/user/owner/icon" class="fa fa-star text-warning {{{ if !./isOwner }}}hidden{{{ end }}}" title="[[modules:chat.owner]]" data-bs-toggle="tooltip"></i></span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="d-flex gap-1">
|
||||||
|
{{{ if ./canToggleOwner }}}
|
||||||
|
<button class="btn btn-sm btn-light" data-bs-toggle="tooltip" data-action="toggleOwner" data-uid="{./uid}" title="[[modules:chat.grant-rescind-ownership]]"><i class="fa fa-star text-warning"></i></button>
|
||||||
|
{{{ end }}}
|
||||||
|
|
||||||
{{{ if ./canKick }}}
|
{{{ if ./canKick }}}
|
||||||
<button class="btn btn-sm btn-link" data-action="kick" data-uid="{./uid}">[[modules:chat.kick]]</button>
|
<button class="btn btn-sm btn-light" data-action="kick" data-uid="{./uid}" data-bs-toggle="tooltip" title="[[modules:chat.kick]]"><i class="fa fa-ban text-danger"></i></button>
|
||||||
{{{ end }}}
|
{{{ end }}}
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{{{ end }}}
|
{{{ end }}}
|
||||||
@@ -226,8 +226,7 @@ describe('Messaging Library', () => {
|
|||||||
await callv3API('delete', `/chats/${roomId}/users/${mocks.users.baz.uid}`, {}, 'baz');
|
await callv3API('delete', `/chats/${roomId}/users/${mocks.users.baz.uid}`, {}, 'baz');
|
||||||
const isUserInRoom = await Messaging.isUserInRoom(mocks.users.baz.uid, roomId);
|
const isUserInRoom = await Messaging.isUserInRoom(mocks.users.baz.uid, roomId);
|
||||||
assert.equal(isUserInRoom, false);
|
assert.equal(isUserInRoom, false);
|
||||||
const data = await Messaging.getRoomData(roomId);
|
assert(await Messaging.isRoomOwner(mocks.users.foo.uid, roomId));
|
||||||
assert.equal(data.owner, mocks.users.foo.uid);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should send a user-leave system message when a user leaves the chat room', async () => {
|
it('should send a user-leave system message when a user leaves the chat room', async () => {
|
||||||
@@ -263,8 +262,7 @@ describe('Messaging Library', () => {
|
|||||||
|
|
||||||
await callv3API('delete', `/chats/${body.response.roomId}/users/${mocks.users.herp.uid}`, {}, 'herp');
|
await callv3API('delete', `/chats/${body.response.roomId}/users/${mocks.users.herp.uid}`, {}, 'herp');
|
||||||
|
|
||||||
const data = await Messaging.getRoomData(body.response.roomId);
|
assert(await Messaging.isRoomOwner(mocks.users.foo.uid, roomId));
|
||||||
assert.equal(data.owner, mocks.users.foo.uid);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should change owner if owner is deleted', async () => {
|
it('should change owner if owner is deleted', async () => {
|
||||||
@@ -284,8 +282,7 @@ describe('Messaging Library', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
await User.deleteAccount(sender);
|
await User.deleteAccount(sender);
|
||||||
const data = await Messaging.getRoomData(response.roomId);
|
assert(await Messaging.isRoomOwner(receiver, response.roomId));
|
||||||
assert.equal(data.owner, receiver);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fail to remove user from room', async () => {
|
it('should fail to remove user from room', async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user