schema validation, yeeee
This commit is contained in:
parent
30e45f8e47
commit
02b62ed018
41
package-lock.json
generated
41
package-lock.json
generated
@ -95,6 +95,11 @@
|
|||||||
"@types/range-parser": "*"
|
"@types/range-parser": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/joi": {
|
||||||
|
"version": "14.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/joi/-/joi-14.3.2.tgz",
|
||||||
|
"integrity": "sha512-riJTpNwDOoRgRrrOjfcjwMBYJLVg8rzwMEAAcZ2JBvdmYWCLIsbzTFXHV517terbYzGmdzkwFYeXUem7eXVNoQ=="
|
||||||
|
},
|
||||||
"@types/jsonwebtoken": {
|
"@types/jsonwebtoken": {
|
||||||
"version": "8.3.0",
|
"version": "8.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.3.0.tgz",
|
||||||
@ -1247,6 +1252,11 @@
|
|||||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
|
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"hoek": {
|
||||||
|
"version": "6.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.2.tgz",
|
||||||
|
"integrity": "sha512-6qhh/wahGYZHFSFw12tBbJw5fsAhhwrrG/y3Cs0YMTv2WzMnL0oLPnQJjv1QJvEfylRSOFuP+xCu+tdx0tD16Q=="
|
||||||
|
},
|
||||||
"homedir-polyfill": {
|
"homedir-polyfill": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
|
||||||
@ -1484,6 +1494,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||||
},
|
},
|
||||||
|
"isemail": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==",
|
||||||
|
"requires": {
|
||||||
|
"punycode": "2.x.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"isexe": {
|
"isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
@ -1496,6 +1514,16 @@
|
|||||||
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
|
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"joi": {
|
||||||
|
"version": "14.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/joi/-/joi-14.3.1.tgz",
|
||||||
|
"integrity": "sha512-LQDdM+pkOrpAn4Lp+neNIFV3axv1Vna3j38bisbQhETPMANYRbFJFUyOZcOClYvM/hppMhGWuKSFEK9vjrB+bQ==",
|
||||||
|
"requires": {
|
||||||
|
"hoek": "6.x.x",
|
||||||
|
"isemail": "3.x.x",
|
||||||
|
"topo": "3.x.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"js-yaml": {
|
"js-yaml": {
|
||||||
"version": "3.12.0",
|
"version": "3.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
|
||||||
@ -2192,6 +2220,11 @@
|
|||||||
"once": "^1.3.1"
|
"once": "^1.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"punycode": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||||
|
},
|
||||||
"qs": {
|
"qs": {
|
||||||
"version": "6.5.2",
|
"version": "6.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||||
@ -2708,6 +2741,14 @@
|
|||||||
"repeat-string": "^1.6.1"
|
"repeat-string": "^1.6.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"topo": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/topo/-/topo-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==",
|
||||||
|
"requires": {
|
||||||
|
"hoek": "6.x.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"triple-beam": {
|
"triple-beam": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
|
||||||
|
@ -17,10 +17,12 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/yardstick/braid#readme",
|
"homepage": "https://github.com/yardstick/braid#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/joi": "^14.3.2",
|
||||||
"@types/mocha": "^5.2.6",
|
"@types/mocha": "^5.2.6",
|
||||||
"body-parser": "^1.18.3",
|
"body-parser": "^1.18.3",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"express": "^4.16.4",
|
"express": "^4.16.4",
|
||||||
|
"joi": "^14.3.1",
|
||||||
"jsonwebtoken": "^8.5.0",
|
"jsonwebtoken": "^8.5.0",
|
||||||
"websocket": "^1.0.28",
|
"websocket": "^1.0.28",
|
||||||
"winston": "^3.2.1",
|
"winston": "^3.2.1",
|
||||||
|
@ -6,7 +6,7 @@ import MHSChannel from './channels/sites/mhsChannel';
|
|||||||
var logger = require('./logger');
|
var logger = require('./logger');
|
||||||
|
|
||||||
class ChannelManager {
|
class ChannelManager {
|
||||||
channels: ChannelBase[]|MHSChannel[] = [];
|
channels: any = [];
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
// create default channel...
|
// create default channel...
|
||||||
@ -85,6 +85,19 @@ class ChannelManager {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
purgeEmptyChannels() {
|
||||||
|
var index = 0
|
||||||
|
|
||||||
|
for (let channel of this.channels) {
|
||||||
|
if (channel.clients.length == 0) {
|
||||||
|
this.channels.splice(index, 1);
|
||||||
|
logger.accessLog.info(`channel removed: ${channel.id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ChannelManager;
|
export default ChannelManager;
|
||||||
|
@ -1,17 +1,32 @@
|
|||||||
import ClientBase from '../../clients/clientBase';
|
import ClientBase from '../../clients/clientBase';
|
||||||
import MHSClient from '../../clients/sites/mhsClient';
|
import MHSClient from '../../clients/sites/mhsClient';
|
||||||
import ChannelBase from '../channelBase';
|
import ChannelBase from '../channelBase';
|
||||||
|
import * as Joi from 'joi';
|
||||||
|
|
||||||
var logger = require('../../logger');
|
var logger = require('../../logger');
|
||||||
|
|
||||||
class MHSChannel extends ChannelBase {
|
class MHSChannel extends ChannelBase {
|
||||||
|
private schema = {
|
||||||
|
currentIndex: Joi.number().integer().required(),
|
||||||
|
totalQuestions: Joi.number().integer().required(),
|
||||||
|
timeElapsed: Joi.number().required(),
|
||||||
|
status: Joi.string().required(),
|
||||||
|
};
|
||||||
|
|
||||||
broadcastMessage(from: ClientBase|MHSClient|null, message: string) {
|
broadcastMessage(from: ClientBase|MHSClient|null, message: string) {
|
||||||
for (let client of this.clients) {
|
const result = Joi.validate(JSON.parse(message), this.schema);
|
||||||
if (client != from && client.data.user_type == 'teacher') {
|
|
||||||
client.ws.send(message);
|
if (result.error && from != null) {
|
||||||
logger.accessLog.info(`sent to ${client.id}: `, {message: message});
|
from.ws.send(`Failed to send the message, the data provided does not conform to the schema outlined by the channel type (mhs) - ${result.error}`);
|
||||||
} else {
|
logger.errorLog.info(`Failed to send the message, the data provided does not conform to the schema outlined by the channel type (mhs)"`, {data: {clientId: from.id, message: message, error: result.error}});
|
||||||
logger.accessLog.info(`client either not a teacher or is the sender: ${client.id} - `, {message: message});
|
} else {
|
||||||
|
for (let client of this.clients) {
|
||||||
|
if (client != from && client.data.user_type == 'teacher') {
|
||||||
|
client.ws.send(message);
|
||||||
|
logger.accessLog.info(`sent to ${client.id}: `, {message: message});
|
||||||
|
} else {
|
||||||
|
logger.accessLog.info(`client either not a teacher or is the sender: ${client.id} - `, {message: message});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,11 +69,11 @@ class ClientManager {
|
|||||||
try {
|
try {
|
||||||
var Client = require(`./clients/${data.client_type}s/${data.client}client`);
|
var Client = require(`./clients/${data.client_type}s/${data.client}client`);
|
||||||
logger.accessLog.info(`attempting to create client of type ${data.client}, client id: ${data.user_id}...`);
|
logger.accessLog.info(`attempting to create client of type ${data.client}, client id: ${data.user_id}...`);
|
||||||
return new Client(data, ws);
|
return new Client(data, ws, this);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.errorLog.info(e);
|
logger.errorLog.info(e);
|
||||||
logger.accessLog.info(`creating base client: ${data.user_id}`);
|
logger.accessLog.info(`creating base client: ${data.user_id}`);
|
||||||
return new ClientBase(data, ws);
|
return new ClientBase(data, ws, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import * as WebSocket from 'ws';
|
import * as WebSocket from 'ws';
|
||||||
import * as ChannelManager from '../channelManager';
|
import * as ChannelManager from '../channelManager';
|
||||||
|
import ClientManager from '../clientManager';
|
||||||
import ChannelBase from '../channels/channelBase';
|
import ChannelBase from '../channels/channelBase';
|
||||||
import MHSChannel from '../channels/sites/mhsChannel';
|
import MHSChannel from '../channels/sites/mhsChannel';
|
||||||
|
|
||||||
@ -10,12 +11,14 @@ class ClientBase {
|
|||||||
data: any;
|
data: any;
|
||||||
id: number;
|
id: number;
|
||||||
channel: ChannelBase|MHSChannel|null;
|
channel: ChannelBase|MHSChannel|null;
|
||||||
|
clientManager: ClientManager;
|
||||||
|
|
||||||
constructor(data: any, ws: WebSocket) {
|
constructor(data: any, ws: WebSocket, clientManager: ClientManager) {
|
||||||
this.ws = ws;
|
this.ws = ws;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.id = data.user_id;
|
this.id = data.user_id;
|
||||||
this.channel = null;
|
this.channel = null;
|
||||||
|
this.clientManager = clientManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
getData() {
|
getData() {
|
||||||
@ -46,7 +49,7 @@ class ClientBase {
|
|||||||
this.channel.removeClient(this.id);
|
this.channel.removeClient(this.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// server.clientManager.removeClient(this.id);
|
this.clientManager.removeClient(this.id);
|
||||||
logger.accessLog.info(`closed connection for client ${this.id}`);
|
logger.accessLog.info(`closed connection for client ${this.id}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import * as WebSocket from 'ws';
|
import * as WebSocket from 'ws';
|
||||||
import ClientBase from '../clientBase';
|
import ClientBase from '../clientBase';
|
||||||
|
import ClientManager from '../../clientManager';
|
||||||
|
|
||||||
var logger = require('../../logger');
|
var logger = require('../../logger');
|
||||||
|
|
||||||
class MHSClient extends ClientBase {
|
class MHSClient extends ClientBase {
|
||||||
constructor(data: any, ws: WebSocket) {
|
constructor(data: any, ws: WebSocket, clientManager: ClientManager) {
|
||||||
super(data, ws);
|
super(data, ws, clientManager);
|
||||||
logger.accessLog.info('MHS Client Created', {data: data});
|
logger.accessLog.info('MHS Client Created', {data: data});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -52,6 +52,10 @@ function connectionManager() {
|
|||||||
channelManager.addClientToChannel(client, data.channel);
|
channelManager.addClientToChannel(client, data.channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//remove any channels that have no users in them
|
||||||
|
logger.accessLog.info(`Purging empty channels...`);
|
||||||
|
channelManager.purgeEmptyChannels();
|
||||||
|
|
||||||
ws.send(`Hi there, welcome to braid, Measures Web Socket server. Connecting all our services!\nYou are currently in channel: ${data.channel}`);
|
ws.send(`Hi there, welcome to braid, Measures Web Socket server. Connecting all our services!\nYou are currently in channel: ${data.channel}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import ChannelBase from '../channels/channelBase';
|
import ChannelBase from '../channels/channelBase';
|
||||||
import ClientBase from '../clients/clientBase';
|
import ClientBase from '../clients/clientBase';
|
||||||
|
import ClientManager from '../clientManager';
|
||||||
|
|
||||||
var exec = require('child_process').exec;
|
var exec = require('child_process').exec;
|
||||||
var expect = require('chai').expect;
|
var expect = require('chai').expect;
|
||||||
@ -10,8 +11,9 @@ var app = require('../config/app');
|
|||||||
var name: string = 'test channel';
|
var name: string = 'test channel';
|
||||||
var wsClient = new WebSocketClient();
|
var wsClient = new WebSocketClient();
|
||||||
var channel: ChannelBase;
|
var channel: ChannelBase;
|
||||||
|
var clientManager = new ClientManager();
|
||||||
var data: any = { 'client': 'test', 'client_type':'site', 'user_id': 125, 'user_type': 'user', 'channel': name }
|
var data: any = { 'client': 'test', 'client_type':'site', 'user_id': 125, 'user_type': 'user', 'channel': name }
|
||||||
var client: ClientBase = new ClientBase(data, wsClient);
|
var client: ClientBase = new ClientBase(data, wsClient, clientManager);
|
||||||
|
|
||||||
describe('ChannelBase', function () {
|
describe('ChannelBase', function () {
|
||||||
it('should create a class of ChannelBase', function () {
|
it('should create a class of ChannelBase', function () {
|
||||||
|
@ -3,6 +3,7 @@ import ClientBase from '../clients/clientBase';
|
|||||||
import MHSClient from '../clients/sites/mhsClient';
|
import MHSClient from '../clients/sites/mhsClient';
|
||||||
import MHSChannel from '../channels/sites/mhsChannel';
|
import MHSChannel from '../channels/sites/mhsChannel';
|
||||||
import ChannelManager from '../channelManager';
|
import ChannelManager from '../channelManager';
|
||||||
|
import ClientManager from '../clientManager';
|
||||||
|
|
||||||
var expect = require('chai').expect;
|
var expect = require('chai').expect;
|
||||||
var sinon = require('sinon');
|
var sinon = require('sinon');
|
||||||
@ -11,7 +12,8 @@ var name: string = 'test channel';
|
|||||||
var data: any = { 'client': 'test', 'client_type':'site', 'user_id': 125, 'user_type': 'user', 'channel': name }
|
var data: any = { 'client': 'test', 'client_type':'site', 'user_id': 125, 'user_type': 'user', 'channel': name }
|
||||||
var WebSocketClient = require('websocket').client;
|
var WebSocketClient = require('websocket').client;
|
||||||
var wsClient = new WebSocketClient();
|
var wsClient = new WebSocketClient();
|
||||||
var client: ClientBase = new ClientBase(data, wsClient);
|
var clientManager = new ClientManager();
|
||||||
|
var client: ClientBase = new ClientBase(data, wsClient, clientManager);
|
||||||
|
|
||||||
let channelManager = new ChannelManager();
|
let channelManager = new ChannelManager();
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import * as WebSocket from 'ws';
|
import * as WebSocket from 'ws';
|
||||||
import ClientBase from '../clients/clientBase';
|
import ClientBase from '../clients/clientBase';
|
||||||
|
import ClientManager from '../clientManager';
|
||||||
|
|
||||||
var expect = require('chai').expect;
|
var expect = require('chai').expect;
|
||||||
var assert = require('chai').assert;
|
var assert = require('chai').assert;
|
||||||
@ -9,7 +10,8 @@ var name: string = 'test channel';
|
|||||||
var data: any = { 'client': 'test', 'client_type':'site', 'user_id': 125, 'user_type': 'user', 'channel': name }
|
var data: any = { 'client': 'test', 'client_type':'site', 'user_id': 125, 'user_type': 'user', 'channel': name }
|
||||||
var WebSocketClient = require('websocket').client;
|
var WebSocketClient = require('websocket').client;
|
||||||
var wsClient = new WebSocketClient();
|
var wsClient = new WebSocketClient();
|
||||||
var client: ClientBase = new ClientBase(data, wsClient);
|
var clientManager = new ClientManager();
|
||||||
|
var client: ClientBase = new ClientBase(data, wsClient, clientManager);
|
||||||
|
|
||||||
describe('ClientBase', function () {
|
describe('ClientBase', function () {
|
||||||
it('should get client data', function () {
|
it('should get client data', function () {
|
||||||
|
@ -11,9 +11,8 @@ var name: string = 'test channel';
|
|||||||
var data: any = { 'client': 'test', 'client_type':'site', 'user_id': 125, 'user_type': 'user', 'channel': name }
|
var data: any = { 'client': 'test', 'client_type':'site', 'user_id': 125, 'user_type': 'user', 'channel': name }
|
||||||
var WebSocketClient = require('websocket').client;
|
var WebSocketClient = require('websocket').client;
|
||||||
var wsClient = new WebSocketClient();
|
var wsClient = new WebSocketClient();
|
||||||
var client: ClientBase = new ClientBase(data, wsClient);
|
var clientManager = new ClientManager();
|
||||||
|
var client: ClientBase = new ClientBase(data, wsClient, clientManager);
|
||||||
let clientManager = new ClientManager();
|
|
||||||
|
|
||||||
describe('ClientManager', function () {
|
describe('ClientManager', function () {
|
||||||
it('should add a client', function () {
|
it('should add a client', function () {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user