Compare commits
No commits in common. "50cc87b399b55757e3d0af52513a4a779a14b70e" and "495bd71f3678f7b4930db6207fdafdff2432512c" have entirely different histories.
50cc87b399
...
495bd71f36
4 changed files with 22 additions and 44 deletions
|
@ -94,16 +94,6 @@ app.post("/post/create", [
|
||||||
app.get("/channel/:channel/messages", [
|
app.get("/channel/:channel/messages", [
|
||||||
param("channel").not().isEmpty().trim().escape().isLength({ min: 24, max: 24 })
|
param("channel").not().isEmpty().trim().escape().isLength({ min: 24, max: 24 })
|
||||||
], authenticateEndpoint(async (req, res) => {
|
], authenticateEndpoint(async (req, res) => {
|
||||||
if (!config.policies.allowSavingMessages) {
|
|
||||||
// TODO: hack
|
|
||||||
res.status(200).json({
|
|
||||||
error: false,
|
|
||||||
message: "SUCCESS_CHANNEL_MESSAGES_FETCHED",
|
|
||||||
channelMessages: []
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const errors = validationResult(req);
|
const errors = validationResult(req);
|
||||||
if (!errors.isEmpty()) {
|
if (!errors.isEmpty()) {
|
||||||
res.status(400).json({ error: true, message: "ERROR_REQUEST_INVALID_DATA", errors: errors.array() });
|
res.status(400).json({ error: true, message: "ERROR_REQUEST_INVALID_DATA", errors: errors.array() });
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
const websockets = require("ws");
|
const websockets = require("ws");
|
||||||
const { v4 } = require("uuid");
|
const uuid = require("uuid");
|
||||||
const mongoose = require("mongoose");
|
|
||||||
|
|
||||||
const { policies, gatewayPingInterval, gatewayPingCheckInterval, clientFacingPingInterval } = require("../../../config");
|
const { policies, gatewayPingInterval, gatewayPingCheckInterval, clientFacingPingInterval } = require("../../../config");
|
||||||
const { experiments } = require("../../../experiments");
|
const { experiments } = require("../../../experiments");
|
||||||
|
@ -19,21 +18,21 @@ const wsCloseCodes = {
|
||||||
NOT_AUTHORIZED: [4006, "Not authorized"],
|
NOT_AUTHORIZED: [4006, "Not authorized"],
|
||||||
FLOODING: [4007, "Flooding"],
|
FLOODING: [4007, "Flooding"],
|
||||||
NO_PING: [4008, "No ping"],
|
NO_PING: [4008, "No ping"],
|
||||||
UNSUPPORTED_ATTRIBUTE: [4009, "Unsupported attribute."],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const attributes = {
|
const attributes = {
|
||||||
PRESENCE_UPDATES: "PRESENCE_UPDATES",
|
PRESENCE_UPDATES: "PRESENCE_UPDATES",
|
||||||
|
SAVE_MESSAGES: "SAVE_MESSAGES"
|
||||||
};
|
};
|
||||||
|
|
||||||
const supportedAttributes = [attributes.PRESENCE_UPDATES];
|
const supportedAttributes = [attributes.PRESENCE_UPDATES, attributes.SAVE_MESSAGES];
|
||||||
|
|
||||||
class GatewaySession {
|
class GatewaySession {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.authenticated = false;
|
this.authenticated = false;
|
||||||
this.user = null;
|
this.user = null;
|
||||||
this.token = null;
|
this.token = null;
|
||||||
this.sessionId = v4();
|
this.sessionId = uuid.v4();
|
||||||
this.attributes = [];
|
this.attributes = [];
|
||||||
|
|
||||||
// Specific to websocket sessions
|
// Specific to websocket sessions
|
||||||
|
@ -111,7 +110,7 @@ class GatewayHandler {
|
||||||
|
|
||||||
const session = new GatewaySession();
|
const session = new GatewaySession();
|
||||||
session.setWebsocketClient(ws);
|
session.setWebsocketClient(ws);
|
||||||
session.send("HELLO", { pingInterval: clientFacingPingInterval, supportedAttributes });
|
session.send("HELLO", { pingInterval: clientFacingPingInterval });
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,9 +177,8 @@ class GatewayHandler {
|
||||||
|
|
||||||
if (data.attributes) {
|
if (data.attributes) {
|
||||||
if (!Array.isArray(data.attributes) || data.attributes.length > 8) return {error: wsCloseCodes.PAYLOAD_ERROR};
|
if (!Array.isArray(data.attributes) || data.attributes.length > 8) return {error: wsCloseCodes.PAYLOAD_ERROR};
|
||||||
for (let i = 0; i < data.attributes.length; i++) {
|
for (let i = 0; i < data.attributes; i++) {
|
||||||
if (!supportedAttributes.includes(data.attributes[i]))
|
if (!supportedAttributes.includes(data[i])) return {error: wsCloseCodes.PAYLOAD_ERROR};
|
||||||
return {error: wsCloseCodes.UNSUPPORTED_ATTRIBUTE};
|
|
||||||
}
|
}
|
||||||
session.attributes = data.attributes;
|
session.attributes = data.attributes;
|
||||||
}
|
}
|
||||||
|
@ -234,20 +232,7 @@ class GatewayHandler {
|
||||||
// Check if the user is in that channel before broadcasting the message
|
// Check if the user is in that channel before broadcasting the message
|
||||||
if (!session.channels.includes(data.channel._id)) return {error: wsCloseCodes.NOT_AUTHORIZED};
|
if (!session.channels.includes(data.channel._id)) return {error: wsCloseCodes.NOT_AUTHORIZED};
|
||||||
|
|
||||||
this.eachInChannel({channelId: data.channel._id}, async ({ session: remoteSession }) => {
|
this.eachInChannel({channelId: data.channel._id}, ({ session: remoteSession }) => {
|
||||||
let id;
|
|
||||||
if (policies.allowSavingMessages) {
|
|
||||||
const message = await Message.create({
|
|
||||||
author: session.user._id,
|
|
||||||
channel: data.channel._id,
|
|
||||||
content: messageContent,
|
|
||||||
createdAt: new Date().getTime()
|
|
||||||
});
|
|
||||||
id = message._id;
|
|
||||||
} else {
|
|
||||||
id = new mongoose.Types.ObjectId();
|
|
||||||
}
|
|
||||||
|
|
||||||
remoteSession.send("EVENT_CREATE_MESSAGE", {
|
remoteSession.send("EVENT_CREATE_MESSAGE", {
|
||||||
content: messageContent,
|
content: messageContent,
|
||||||
channel: {
|
channel: {
|
||||||
|
@ -257,9 +242,18 @@ class GatewayHandler {
|
||||||
_id: session.user._id,
|
_id: session.user._id,
|
||||||
username: session.user.username
|
username: session.user.username
|
||||||
},
|
},
|
||||||
_id: id
|
_id: uuid.v4()
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (session.hasAttribute(attributes.SAVE_MESSAGES)) {
|
||||||
|
await Message.create({
|
||||||
|
author: session.user._id,
|
||||||
|
channel: data.channel._id,
|
||||||
|
content: messageContent,
|
||||||
|
createdAt: new Date().getTime()
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,6 @@ module.exports = {
|
||||||
allowAccountCreation: true,
|
allowAccountCreation: true,
|
||||||
allowLogin: true,
|
allowLogin: true,
|
||||||
allowGatewayConnection: true,
|
allowGatewayConnection: true,
|
||||||
// The policy below will make all messages sent over the gateway to be in plain text saved to the database.
|
|
||||||
// This is experimental and dangerous, and, as such, should generally not be used.
|
|
||||||
allowSavingMessages: true,
|
|
||||||
perUserMaxGatewayConnections: 4
|
perUserMaxGatewayConnections: 4
|
||||||
},
|
},
|
||||||
/*
|
/*
|
||||||
|
@ -38,6 +35,7 @@ module.exports = {
|
||||||
gatewayPingInterval: 15000,
|
gatewayPingInterval: 15000,
|
||||||
gatewayPingCheckInterval: 4500,
|
gatewayPingCheckInterval: 4500,
|
||||||
clientFacingPingInterval: 14750,
|
clientFacingPingInterval: 14750,
|
||||||
|
unsafeStoreMessages: false,
|
||||||
bcryptRounds: 10,
|
bcryptRounds: 10,
|
||||||
roleMap: {
|
roleMap: {
|
||||||
"BANNED": 0,
|
"BANNED": 0,
|
||||||
|
|
|
@ -26,15 +26,11 @@ Packets can also have JSON as a payload:
|
||||||
|
|
||||||
Sent by the server to the client as soon as possible after they connect to the gateway.
|
Sent by the server to the client as soon as possible after they connect to the gateway.
|
||||||
|
|
||||||
JSON data format:
|
This payload contains a `pingInterval` property. Every *pingInterval*, the client must send a packet simply containing `7@1`. This is the ACTION_PING payload. If the client does not send this payload at the right time, it is disconnected.
|
||||||
| Field | Description |
|
|
||||||
| - | - |
|
|
||||||
| pingInterval | Every *pingInterval*, the client must send a packet simply containing `7@1`. This is the ACTION_PING payload. If the client does not send this payload at the right time, it is disconnected. |
|
|
||||||
| supportedAttributes | An array of attributes supported by the server. If a client requests an unsupported attribute, it is disconnected from the server. |
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```json
|
```json
|
||||||
0@{"pingInterval":14750,"supportedAttributes":["PRESENCE_UPDATES"]}
|
0@{"pingInterval":14750}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 1:YOO
|
## 1:YOO
|
||||||
|
@ -198,7 +194,7 @@ Voice server signaling is done through a websocket gateway. This gateway is spec
|
||||||
| content | The text content of the message (max 2000 characters, min 1 character, trimmed) |
|
| content | The text content of the message (max 2000 characters, min 1 character, trimmed) |
|
||||||
| channel | A [message channel object](#message-channel-object) |
|
| channel | A [message channel object](#message-channel-object) |
|
||||||
| author | A [message author object](#message-author-object) |
|
| author | A [message author object](#message-author-object) |
|
||||||
| _id | An ObjectId |
|
| _id | A UUIDv4 |
|
||||||
|
|
||||||
## Message channel object
|
## Message channel object
|
||||||
|
|
||||||
|
|
Reference in a new issue