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' $ref: 'write/flags/flagId/notes/datetime.yaml'
/search/categories: /search/categories:
$ref: 'write/search/categories.yaml' $ref: 'write/search/categories.yaml'
/search/chats/{roomId}/users:
$ref: 'write/search/chats/roomId/users.yaml'
/admin/settings/{setting}: /admin/settings/{setting}:
$ref: 'write/admin/settings/setting.yaml' $ref: 'write/admin/settings/setting.yaml'
/admin/analytics: /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) { userList.addSearchHandler = function (roomId, inputEl, callback) {
inputEl.on('keyup', utils.debounce(async () => { inputEl.on('keyup', utils.debounce(async () => {
const username = inputEl.val(); const query = inputEl.val();
const data = await socket.emit('modules.chats.searchMembers', { const data = await api.get(`/search/chats/${roomId}/users`, { query });
username: username,
roomId: roomId,
});
callback(data); callback(data);
}, 200)); }, 200));
}; };

View File

@@ -2,7 +2,9 @@
const _ = require('lodash'); const _ = require('lodash');
const user = require('../user');
const categories = require('../categories'); const categories = require('../categories');
const messaging = require('../messaging');
const privileges = require('../privileges'); const privileges = require('../privileges');
const meta = require('../meta'); const meta = require('../meta');
const plugins = require('../plugins'); const plugins = require('../plugins');
@@ -103,3 +105,50 @@ async function loadCids(uid, parentCid) {
await getCidsRecursive(pageCids); await getCidsRecursive(pageCids);
return resultCids; 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) => { Search.categories = async (req, res) => {
helpers.formatApiResponse(200, res, await api.search.categories(req, req.query)); 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'; 'use strict';
const router = require('express').Router(); const router = require('express').Router();
// const middleware = require('../../middleware'); const middleware = require('../../middleware');
const controllers = require('../../controllers'); const controllers = require('../../controllers');
const routeHelpers = require('../helpers'); const routeHelpers = require('../helpers');
const { setupApiRoute } = routeHelpers; const { setupApiRoute } = routeHelpers;
module.exports = function () { module.exports = function () {
// const middlewares = []; const middlewares = [middleware.ensureLoggedIn];
// maybe redirect to /search/posts? // maybe redirect to /search/posts?
// setupApiRoute(router, 'post', '/', [...middlewares], controllers.write.search.TBD); // setupApiRoute(router, 'post', '/', [...middlewares], controllers.write.search.TBD);
setupApiRoute(router, 'get', '/categories', [], controllers.write.search.categories); 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; return router;
}; };

View File

@@ -157,51 +157,16 @@ SocketModules.chats.sortPublicRooms = async function (socket, data) {
}; };
SocketModules.chats.searchMembers = 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) { if (!data || !data.roomId) {
throw new Error('[[error:invalid-data]]'); 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) { // parameter renamed; backwards compatibility
throw new Error('[[error:no-privileges]]'); data.query = data.username;
} delete data.username;
return await api.search.roomUsers(socket, data);
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 };
}; };
SocketModules.chats.toggleOwner = async (socket, data) => { SocketModules.chats.toggleOwner = async (socket, data) => {