diff --git a/api/v1/gateway/index.js b/api/v1/gateway/index.js index 0f24933..8cb17d6 100644 --- a/api/v1/gateway/index.js +++ b/api/v1/gateway/index.js @@ -116,11 +116,57 @@ GatewayServer.prototype.eventSetup = function() { if (socket.joinedCategories[v]) continue; socket.joinedCategories[v] = category.title; await socket.join(v); + + console.log(`[*] [gateway] User ${socket.user.username} subscribed to room ${v} (${category.title}), sending updated user list to all members of that room...`); + + this._gateway.in(v).emit('clientListUpdate', await this._generateClientListUpdateObject(v, category.title)); } } }); + + socket.on('disconnecting', async () => { + console.log(`[*] [gateway] User ${socket.user.username} is disconnecting, broadcasting updated user list to all of the rooms they have been in...`); + const rooms = socket.rooms; + rooms.forEach(async (room) => { + // Socket io automatically adds a user to a room with their own id + if (room === socket.id) return; + + const categoryTitle = socket.joinedCategories[room] || 'UNKNOWN'; + await socket.leave(room); + + socket.in(room).emit('clientListUpdate', await this._generateClientListUpdateObject(room, categoryTitle)); + }); + }); }); }); }; +GatewayServer.prototype._getSocketsInRoom = async function(room) { + const clients = this._gateway.in(room).sockets; + const updatedClientList = []; + + clients.forEach((client) => { + if (!client.isConnected || !client.user) return; + updatedClientList.push({ + user: { + username: client.user.username, + _id: client.user._id + } + }); + }); + return updatedClientList; +}; + +GatewayServer.prototype._generateClientListUpdateObject = async function(room, categoryTitle='UNKNOWN') { + const clientList = await this._getSocketsInRoom(room); + return { + category: { + title: categoryTitle, + _id: room + }, + clientList + }; +}; + + module.exports = GatewayServer; \ No newline at end of file diff --git a/api/v1/users.js b/api/v1/users.js index 488b5db..b0d4adb 100755 --- a/api/v1/users.js +++ b/api/v1/users.js @@ -56,17 +56,21 @@ app.post('/account/create', [ password: hashedPassword, role: startingRole }); + + const responseUserObject = { + _id: user._id, + username: user.username, + email: user.email, + role: user.role, + permissionLevel: config.roleMap[user.role] + }; + + console.log('[*] [logger] [users] [create] User created', responseUserObject); res.status(200).json({ error: false, message: 'SUCCESS_USER_CREATED', - user: { - _id: user._id, - username: user.username, - email: user.email, - role: user.role, - permissionLevel: config.roleMap[user.role] - } + user: responseUserObject }); } catch (e) { console.error('Internal server error', e); @@ -123,17 +127,21 @@ app.post('/token/create', [ maxAge: 3 * 60 * 60 * 1000, httpOnly: true, domain: config.address, }); } + + const responseUserObject = { + _id: existingUser._id, + username: existingUser.username, + email: existingUser.email, + role: existingUser.role, + permissionLevel: config.roleMap[existingUser.role] + }; + + console.log('[*] [logger] [users] [token create] Token created', responseUserObject); res.status(200).json({ error: false, message: 'SUCCESS_TOKEN_CREATED', - user: { - _id: existingUser._id, - username: existingUser.username, - email: existingUser.email, - role: existingUser.role, - permissionLevel: config.roleMap[existingUser.role] - }, + user: responseUserObject, token }); }); diff --git a/app/app.html b/app/app.html index 567a47b..c4b1ac8 100755 --- a/app/app.html +++ b/app/app.html @@ -131,8 +131,12 @@ -

Browsing category: {{ selection.category.title }}

-

Browsing {{ selection.category.title }}

+

Browsing category: {{ selection.category.title }}

+

Browsing {{ selection.category.title }}

+

+ Browsing {{ selection.category.title }} with + {{ user.user.username }} +

Back Refresh
diff --git a/app/resources/js/app.js b/app/resources/js/app.js index 1b81427..0347977 100755 --- a/app/resources/js/app.js +++ b/app/resources/js/app.js @@ -88,7 +88,7 @@ GatewayConnection.prototype.connect = function(token) { this.onConnect('CONNECT_RECEIVED_HELLO'); console.log('[*] [gateway] [handshake] Assuming that server received yoo and that connection is completed.'); }); - }); + }) this.socket.on('error', (e) => { console.log('[E] [gateway] Gateway error', e); @@ -124,7 +124,11 @@ GatewayConnection.prototype.sendMessage = function(categoryId, content) { GatewayConnection.prototype.subscribeToCategoryChat = function(categoryId) { if (!this.isConnected) return; - this.socket.emit('subscribe', [categoryId]); + const request = [categoryId]; + + console.log('[*] [gateway] Subscribing to channel(s)', request); + + this.socket.emit('subscribe', request); }; @@ -175,6 +179,9 @@ const app = new Vue({ messages: { 'X': [ { username: 'NONEXISTENT_TEST_ACCOUNT', content: 'TEST MSG' } ] }, + userLists: { + 'X': [ { username: 'NONEXISTENT_TEST_ACCOUNT', _id: 'INVALID_ID' } ] + }, message: { typed: '' } @@ -226,6 +233,10 @@ const app = new Vue({ this.gateway.socket.on('message', (e) => { this.processMessage(e); }); + this.gateway.socket.on('clientListUpdate', (e) => { + console.log('[*] [gateway] Client list update', e); + this.processUserListUpdate(e); + }); }, processMessage: async function(messageObject) { if (!this.messages[messageObject.category._id]) this.$set(this.messages, messageObject.category._id, []); @@ -256,6 +267,11 @@ const app = new Vue({ } } }, + processUserListUpdate: async function(e) { + const { category, clientList } = e; + if (!this.userLists[category._id]) this.$set(this.userLists, category._id, []); + this.userLists[category._id] = clientList; + }, openChatForCategory: async function(categoryId) { this.gateway.subscribeToCategoryChat(categoryId);