mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-16 18:56:15 +01:00
feat: GET /chats/:roomId/users [breaking]
This commit is contained in:
@@ -140,6 +140,8 @@ paths:
|
||||
$ref: 'write/chats.yaml'
|
||||
/chats/{roomId}:
|
||||
$ref: 'write/chats/roomId.yaml'
|
||||
/chats/{roomId}/users:
|
||||
$ref: 'write/chats/roomId/users.yaml'
|
||||
/chats/{roomId}/{mid}:
|
||||
$ref: 'write/chats/roomId/mid.yaml'
|
||||
/flags/:
|
||||
|
||||
61
public/openapi/write/chats/roomId/users.yaml
Normal file
61
public/openapi/write/chats/roomId/users.yaml
Normal file
@@ -0,0 +1,61 @@
|
||||
get:
|
||||
tags:
|
||||
- chats
|
||||
summary: get chat room users
|
||||
description: This operation retrieves the users in a chat room message
|
||||
parameters:
|
||||
- in: path
|
||||
name: roomId
|
||||
schema:
|
||||
type: number
|
||||
required: true
|
||||
description: a valid chat room id
|
||||
example: 1
|
||||
responses:
|
||||
'200':
|
||||
description: Users successfully retrieved
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
$ref: ../../../components/schemas/Status.yaml#/Status
|
||||
response:
|
||||
type: object
|
||||
properties:
|
||||
users:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
uid:
|
||||
type: number
|
||||
description: A user identifier
|
||||
username:
|
||||
type: string
|
||||
description: A friendly name for a given user account
|
||||
picture:
|
||||
nullable: true
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
displayname:
|
||||
type: string
|
||||
description: This is either username or fullname depending on forum and user settings
|
||||
icon:text:
|
||||
type: string
|
||||
description: A single-letter representation of a username. This is used in the
|
||||
auto-generated icon given to users
|
||||
without an avatar
|
||||
icon:bgColor:
|
||||
type: string
|
||||
description: A six-character hexadecimal colour code assigned to the user. This
|
||||
value is used in conjunction with
|
||||
`icon:text` for the user's
|
||||
auto-generated icon
|
||||
example: "#f44336"
|
||||
isOwner:
|
||||
type: boolean
|
||||
canKick:
|
||||
type: boolean
|
||||
@@ -308,20 +308,15 @@ define('forum/chats', [
|
||||
};
|
||||
|
||||
Chats.refreshParticipantsList = function (roomId, modal) {
|
||||
socket.emit('modules.chats.getUsersInRoom', { roomId: roomId }, function (err, users) {
|
||||
const listEl = modal.find('.list-group');
|
||||
|
||||
if (err) {
|
||||
return translator.translate('[[error:invalid-data]]', function (translated) {
|
||||
listEl.find('li').text(translated);
|
||||
});
|
||||
}
|
||||
|
||||
app.parseAndTranslate('partials/modals/manage_room_users', {
|
||||
users: users,
|
||||
}, function (html) {
|
||||
const listEl = modal.find('.list-group');
|
||||
api.get(`/chats/${roomId}/users`, {}).then(({ users }) => {
|
||||
app.parseAndTranslate('partials/modals/manage_room_users', { users }, function (html) {
|
||||
listEl.html(html);
|
||||
});
|
||||
}).catch(() => {
|
||||
translator.translate('[[error:invalid-data]]', function (translated) {
|
||||
listEl.find('li').text(translated);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -72,3 +72,14 @@ chatsAPI.rename = async (caller, data) => {
|
||||
roomId: data.roomId,
|
||||
});
|
||||
};
|
||||
|
||||
chatsAPI.users = async (caller, data) => {
|
||||
const [isOwner, users] = await Promise.all([
|
||||
messaging.isRoomOwner(caller.uid, data.roomId),
|
||||
messaging.getUsersInRoom(data.roomId, 0, -1),
|
||||
]);
|
||||
users.forEach((user) => {
|
||||
user.canKick = (parseInt(user.uid, 10) !== parseInt(caller.uid, 10)) && isOwner;
|
||||
});
|
||||
return { users };
|
||||
};
|
||||
|
||||
@@ -54,7 +54,10 @@ Chats.rename = async (req, res) => {
|
||||
};
|
||||
|
||||
Chats.users = async (req, res) => {
|
||||
// ...
|
||||
const users = await api.chats.users(req, {
|
||||
...req.params,
|
||||
});
|
||||
helpers.formatApiResponse(200, res, users);
|
||||
};
|
||||
|
||||
Chats.invite = async (req, res) => {
|
||||
|
||||
@@ -19,7 +19,7 @@ module.exports = function () {
|
||||
setupApiRoute(router, 'put', '/:roomId', [...middlewares, middleware.assert.room, middleware.checkRequired.bind(null, ['name'])], controllers.write.chats.rename);
|
||||
// no route for room deletion, noted here just in case...
|
||||
|
||||
// setupApiRoute(router, 'get', '/:roomId/users', [...middlewares, middleware.assert.room], controllers.write.chats.users);
|
||||
setupApiRoute(router, 'get', '/:roomId/users', [...middlewares, middleware.assert.room], controllers.write.chats.users);
|
||||
// setupApiRoute(router, 'put', '/:roomId/users', [...middlewares, middleware.assert.room, middleware.checkRequired.bind(null, ['uids'])], controllers.write.chats.invite);
|
||||
// setupApiRoute(router, 'delete', '/:roomId/users', [...middlewares, middleware.assert.room, middleware.checkRequired.bind(null, ['uids'])], controllers.write.chats.kick);
|
||||
|
||||
|
||||
@@ -84,21 +84,17 @@ SocketModules.chats.loadRoom = async function (socket, data) {
|
||||
};
|
||||
|
||||
SocketModules.chats.getUsersInRoom = async function (socket, data) {
|
||||
sockets.warnDeprecated(socket, 'GET /api/v3/chats/:roomId/user');
|
||||
|
||||
if (!data || !data.roomId) {
|
||||
throw new Error('[[error:invalid-data]]');
|
||||
}
|
||||
const [isUserInRoom, isOwner, userData] = await Promise.all([
|
||||
Messaging.isUserInRoom(socket.uid, data.roomId),
|
||||
Messaging.isRoomOwner(socket.uid, data.roomId),
|
||||
Messaging.getUsersInRoom(data.roomId, 0, -1),
|
||||
]);
|
||||
const isUserInRoom = await Messaging.isUserInRoom(socket.uid, data.roomId);
|
||||
if (!isUserInRoom) {
|
||||
throw new Error('[[error:no-privileges]]');
|
||||
}
|
||||
userData.forEach((user) => {
|
||||
user.canKick = (parseInt(user.uid, 10) !== parseInt(socket.uid, 10)) && isOwner;
|
||||
});
|
||||
return userData;
|
||||
|
||||
return api.chats.users(socket, data);
|
||||
};
|
||||
|
||||
SocketModules.chats.addUserToRoom = async function (socket, data) {
|
||||
|
||||
@@ -22,6 +22,7 @@ describe('Messaging Library', () => {
|
||||
const mocks = {
|
||||
users: {
|
||||
foo: {}, // the admin
|
||||
bar: {},
|
||||
baz: {}, // the user with chat restriction enabled
|
||||
herp: {},
|
||||
},
|
||||
@@ -53,10 +54,12 @@ describe('Messaging Library', () => {
|
||||
// Create 3 users: 1 admin, 2 regular
|
||||
({
|
||||
foo: mocks.users.foo.uid,
|
||||
bar: mocks.users.bar.uid,
|
||||
baz: mocks.users.baz.uid,
|
||||
herp: mocks.users.herp.uid,
|
||||
} = await utils.promiseParallel({
|
||||
foo: User.create({ username: 'foo', password: 'barbar' }), // admin
|
||||
bar: User.create({ username: 'bar', password: 'bazbaz' }), // admin
|
||||
baz: User.create({ username: 'baz', password: 'quuxquux' }), // restricted user
|
||||
herp: User.create({ username: 'herp', password: 'derpderp' }), // a regular user
|
||||
}));
|
||||
@@ -65,6 +68,7 @@ describe('Messaging Library', () => {
|
||||
await User.setSetting(mocks.users.baz.uid, 'restrictChat', '1');
|
||||
|
||||
({ jar: mocks.users.foo.jar, csrf_token: mocks.users.foo.csrf } = await util.promisify(helpers.loginUser)('foo', 'barbar'));
|
||||
({ jar: mocks.users.bar.jar, csrf_token: mocks.users.bar.csrf } = await util.promisify(helpers.loginUser)('bar', 'bazbaz'));
|
||||
({ jar: mocks.users.baz.jar, csrf_token: mocks.users.baz.csrf } = await util.promisify(helpers.loginUser)('baz', 'quuxquux'));
|
||||
({ jar: mocks.users.herp.jar, csrf_token: mocks.users.herp.csrf } = await util.promisify(helpers.loginUser)('herp', 'derpderp'));
|
||||
|
||||
@@ -190,17 +194,16 @@ describe('Messaging Library', () => {
|
||||
});
|
||||
|
||||
it('should get users in room', async () => {
|
||||
const data = await socketModules.chats.getUsersInRoom({ uid: mocks.users.foo.uid }, { roomId: roomId });
|
||||
assert(Array.isArray(data));
|
||||
assert.strictEqual(data.length, 3);
|
||||
const { body } = await callv3API('get', `/chats/${roomId}/users`, {}, 'foo');
|
||||
assert(Array.isArray(body.response.users));
|
||||
assert.strictEqual(body.response.users.length, 3);
|
||||
console.log(body.response.users);
|
||||
});
|
||||
|
||||
it('should throw error if user is not in room', async () => {
|
||||
try {
|
||||
const data = await socketModules.chats.getUsersInRoom({ uid: 123123123 }, { roomId: roomId });
|
||||
} catch (err) {
|
||||
assert.equal(err.message, '[[error:no-privileges]]');
|
||||
}
|
||||
const { statusCode, body } = await callv3API('get', `/chats/${roomId}/users`, {}, 'bar');
|
||||
assert.strictEqual(statusCode, 403);
|
||||
assert.equal(body.status.message, await translator.translate('[[error:no-privileges]]'));
|
||||
});
|
||||
|
||||
it('should fail to add users to room if max is reached', (done) => {
|
||||
|
||||
Reference in New Issue
Block a user