refactor(socket.io): deprecated SocketModules.chats.searchMembers in favour of api.search.roomUsers

This commit is contained in:
Julian Lam
2023-11-15 14:16:08 -05:00
parent 62b7dfd400
commit 6e952263d1
7 changed files with 111 additions and 48 deletions

View File

@@ -226,6 +226,8 @@ paths:
$ref: 'write/flags/flagId/notes/datetime.yaml'
/search/categories:
$ref: 'write/search/categories.yaml'
/search/chats/{roomId}/users:
$ref: 'write/search/chats/roomId/users.yaml'
/admin/settings/{setting}:
$ref: 'write/admin/settings/setting.yaml'
/admin/analytics:

View File

@@ -0,0 +1,44 @@
get:
tags:
- search
summary: find room users by keyword
description: This operation returns a set of users in a chat room matching the keyword search.
parameters:
- in: path
name: roomId
schema:
type: number
required: true
description: room ID to check
example: 1
- in: query
name: 'query'
schema:
type: string
required: false
description: The keyword used in the category search
example: 'admin'
responses:
'200':
description: matching 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:
allOf:
- $ref: ../../../../components/schemas/UserObject.yaml#/UserObjectSlim
- type: object
properties:
isOwner:
type: boolean
canKick:
type: boolean

View File

@@ -72,11 +72,8 @@ define('forum/chats/user-list', ['api'], function (api) {
userList.addSearchHandler = function (roomId, inputEl, callback) {
inputEl.on('keyup', utils.debounce(async () => {
const username = inputEl.val();
const data = await socket.emit('modules.chats.searchMembers', {
username: username,
roomId: roomId,
});
const query = inputEl.val();
const data = await api.get(`/search/chats/${roomId}/users`, { query });
callback(data);
}, 200));
};

View File

@@ -2,7 +2,9 @@
const _ = require('lodash');
const user = require('../user');
const categories = require('../categories');
const messaging = require('../messaging');
const privileges = require('../privileges');
const meta = require('../meta');
const plugins = require('../plugins');
@@ -103,3 +105,50 @@ async function loadCids(uid, parentCid) {
await getCidsRecursive(pageCids);
return resultCids;
}
searchApi.roomUsers = async (caller, { query, roomId }) => {
const [isAdmin, inRoom, isRoomOwner] = await Promise.all([
user.isAdministrator(caller.uid),
messaging.isUserInRoom(caller.uid, roomId),
messaging.isRoomOwner(caller.uid, roomId),
]);
if (!isAdmin && !inRoom) {
throw new Error('[[error:no-privileges]]');
}
const results = await user.search({
query,
paginate: false,
hardCap: -1,
uid: caller.uid,
});
const { users } = results;
const foundUids = users.map(user => user && user.uid);
const isUidInRoom = _.zipObject(
foundUids,
await messaging.isUsersInRoom(foundUids, roomId)
);
const roomUsers = users.filter(user => isUidInRoom[user.uid]);
const isOwners = await messaging.isRoomOwner(roomUsers.map(u => u.uid), roomId);
roomUsers.forEach((user, index) => {
if (user) {
user.isOwner = isOwners[index];
user.canKick = isRoomOwner && (parseInt(user.uid, 10) !== parseInt(caller.uid, 10));
}
});
roomUsers.sort((a, b) => {
if (a.isOwner && !b.isOwner) {
return -1;
} else if (!a.isOwner && b.isOwner) {
return 1;
}
return 0;
});
return { users: roomUsers };
};

View File

@@ -8,3 +8,8 @@ const Search = module.exports;
Search.categories = async (req, res) => {
helpers.formatApiResponse(200, res, await api.search.categories(req, req.query));
};
Search.roomUsers = async (req, res) => {
const { query } = req.query;
helpers.formatApiResponse(200, res, await api.search.roomUsers(req, { query, ...req.params }));
};

View File

@@ -1,19 +1,20 @@
'use strict';
const router = require('express').Router();
// const middleware = require('../../middleware');
const middleware = require('../../middleware');
const controllers = require('../../controllers');
const routeHelpers = require('../helpers');
const { setupApiRoute } = routeHelpers;
module.exports = function () {
// const middlewares = [];
const middlewares = [middleware.ensureLoggedIn];
// maybe redirect to /search/posts?
// setupApiRoute(router, 'post', '/', [...middlewares], controllers.write.search.TBD);
setupApiRoute(router, 'get', '/categories', [], controllers.write.search.categories);
setupApiRoute(router, 'get', '/chats/:roomId/users', [...middlewares, middleware.checkRequired.bind(null, ['query']), middleware.canChat, middleware.assert.room], controllers.write.search.roomUsers);
return router;
};

View File

@@ -157,51 +157,16 @@ SocketModules.chats.sortPublicRooms = async function (socket, data) {
};
SocketModules.chats.searchMembers = async function (socket, data) {
sockets.warnDeprecated(socket, 'GET /api/v3/search/chats/:roomId/users?query=');
if (!data || !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) {
throw new Error('[[error:no-privileges]]');
}
const results = await user.search({
query: data.username,
paginate: false,
hardCap: -1,
});
const { users } = results;
const foundUids = users.map(user => user && user.uid);
const isUidInRoom = _.zipObject(
foundUids,
await Messaging.isUsersInRoom(foundUids, data.roomId)
);
const roomUsers = users.filter(user => isUidInRoom[user.uid]);
const isOwners = await Messaging.isRoomOwner(roomUsers.map(u => u.uid), data.roomId);
roomUsers.forEach((user, index) => {
if (user) {
user.isOwner = isOwners[index];
user.canKick = isRoomOwner && (parseInt(user.uid, 10) !== parseInt(socket.uid, 10));
}
});
roomUsers.sort((a, b) => {
if (a.isOwner && !b.isOwner) {
return -1;
} else if (!a.isOwner && b.isOwner) {
return 1;
}
return 0;
});
return { users: roomUsers };
// parameter renamed; backwards compatibility
data.query = data.username;
delete data.username;
return await api.search.roomUsers(socket, data);
};
SocketModules.chats.toggleOwner = async (socket, data) => {