need to update specs...up next...

This commit is contained in:
Josh Burman 2019-03-22 11:06:51 -04:00
parent 072964967d
commit f4e3310a81
13 changed files with 102 additions and 59 deletions

View File

@ -3,7 +3,10 @@ import ClientBase from './clients/clientBase';
import MHSClient from './clients/sites/mhsClient';
import MHSChannel from './channels/sites/mhsChannel';
import * as Joi from 'joi';
var logger = require('./logger');
var app = require('./config/app');
class ChannelManager {
channels: any = [];
@ -66,11 +69,8 @@ class ChannelManager {
}
removeClientFromChannel(client_id: number, channel_id: string) {
var index: number = 0;
for (let channel of this.channels) {
if (channel.id == channel_id) {
this.channels.splice(index, 1);
if (channel.removeClient(client_id)) {
logger.accessLog.info(`client removed from channel - channel: ${channel_id}, client: ${client_id}`);
return true;
@ -79,23 +79,29 @@ class ChannelManager {
return false
}
}
index++;
}
return false;
}
purgeEmptyChannels() {
var index = 0
changeChannel(client: ClientBase|MHSClient, changeRequest: any) {
if (client.channel != null) {
this.removeClientFromChannel(client.id, client.channel.id)
}
var channel = this.createChannel(changeRequest);
this.addClientToChannel(client, channel.id);
this.purgeEmptyChannels();
console.log(this.channels)
}
purgeEmptyChannels() {
for (let channel of this.channels) {
if (channel.clients.length == 0 && channel.id != 'default') {
var index = this.channels.indexOf(channel)
this.channels.splice(index, 1);
logger.accessLog.info(`channel removed: ${channel.id}`);
}
index++;
}
}
};

View File

@ -34,15 +34,12 @@ class ChannelBase {
}
removeClient(id: number) {
var index: number = 0;
for (let client of this.clients) {
if (client.id == id) {
var index = this.clients.indexOf(client)
this.clients.splice(index, 1);
return true;
}
index++;
}
return false;

View File

@ -1,34 +1,19 @@
import ClientBase from '../../clients/clientBase';
import MHSClient from '../../clients/sites/mhsClient';
import ChannelBase from '../channelBase';
import * as Joi from 'joi';
var logger = require('../../logger');
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) {
const result = Joi.validate(JSON.parse(message), this.schema);
if (result.error && from != null) {
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}`);
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}});
} else {
broadcastMessage(from: ClientBase|MHSClient|null, message: any) {
for (let client of this.clients) {
if (client != from && client.data.user_type == 'teacher') {
client.ws.send(message);
client.ws.send(JSON.stringify(message));
logger.accessLog.info(`sent to ${client.id}`, { data: { message: message }});
} else {
logger.accessLog.info(`client either not a teacher or is the sender: ${client.id}`, { data: { message: message }});
}
}
}
return {'status': 'success', 'message': `message broadcast complete`};
}

View File

@ -1,6 +1,7 @@
import * as WebSocket from 'ws';
import ClientBase from './clients/clientBase';
import MHSClient from './clients/sites/mhsClient';
import ChannelManager from './channelManager';
var logger = require('./logger');
@ -11,9 +12,9 @@ class ClientManager {
//...maybe one day
}
addClient(data: any, ws: WebSocket) {
addClient(data: any, channelManager: ChannelManager, ws: WebSocket) {
if (data.client_type && !this.clientExists(data.user_id)) {
var client = this.getClientType(data, ws);
var client = this.getClientType(data, channelManager, ws);
this.clients.push(client);
logger.accessLog.info(`client added to client manager: ${data.user_id}`);
return client;
@ -65,15 +66,15 @@ class ClientManager {
}
}
getClientType(data: any, ws: WebSocket) {
getClientType(data: any, channelManager: ChannelManager, ws: WebSocket) {
try {
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}...`);
return new Client(data, ws, this);
return new Client(data, ws, channelManager, this);
} catch (e) {
logger.errorLog.info(e);
logger.accessLog.info(`creating base client: ${data.user_id}`);
return new ClientBase(data, ws, this);
return new ClientBase(data, ws, channelManager, this);
}
}
};

View File

@ -1,9 +1,10 @@
import * as WebSocket from 'ws';
import * as ChannelManager from '../channelManager';
import ClientManager from '../clientManager';
import ChannelManager from '../channelManager';
import ChannelBase from '../channels/channelBase';
import MHSChannel from '../channels/sites/mhsChannel';
var messageManager = require('../messageManager');
var logger = require('../logger');
class ClientBase {
@ -12,13 +13,15 @@ class ClientBase {
id: number;
channel: ChannelBase|MHSChannel|null;
clientManager: ClientManager;
channelManager: ChannelManager;
constructor(data: any, ws: WebSocket, clientManager: ClientManager) {
constructor(data: any, ws: WebSocket, channelManager: ChannelManager, clientManager: ClientManager) {
this.ws = ws;
this.data = data;
this.id = data.user_id;
this.channel = null;
this.clientManager = clientManager;
this.channelManager = channelManager;
}
getData() {
@ -36,11 +39,25 @@ class ClientBase {
connectToChannel(channel: ChannelBase|MHSChannel) {
this.channel = channel;
this.ws.on('message', (message: string) => {
logger.accessLog.info(`starting broadcast on channel ${channel.id}: `, {message: message});
var messageListener = (message: any) => {
logger.accessLog.info(`starting message transaction on channel ${channel.id}: `, {message: message});
this.ws.removeListener('message', messageListener);
message = messageManager.prepareMessage(message)
if (!message.error) {
if (message['message_type'] == 'broadcast') {
channel.broadcastMessage(this, message);
logger.accessLog.info(`broadcast complete on channel ${channel.id}: `, {message: message});
});
} else if (message['message_type'] == 'changeChannel') {
this.channelManager.changeChannel(this, message);
}
logger.accessLog.info(`message transaction complete on channel ${channel.id}: `, {message: message});
} else {
logger.errorLog.info(`Validation failed, please review schema: ${channel.id}`, {data: {message: message, error: message.error}});
}
}
this.ws.on('message', messageListener);
this.ws.on('close', (reasonCode: string, description: string) => {
logger.accessLog.info(`closing connection for client ${this.id}`);

View File

@ -1,12 +1,13 @@
import * as WebSocket from 'ws';
import ClientBase from '../clientBase';
import ClientManager from '../../clientManager';
import ChannelManager from '../../channelManager';
var logger = require('../../logger');
class MHSClient extends ClientBase {
constructor(data: any, ws: WebSocket, clientManager: ClientManager) {
super(data, ws, clientManager);
constructor(data: any, ws: WebSocket, channelManager: ChannelManager, clientManager: ClientManager) {
super(data, ws, channelManager, clientManager);
logger.accessLog.info('MHS Client Created', {data: data});
}
};

View File

@ -14,5 +14,6 @@ module.exports = {
subject: 'Braid JWT',
audience: 'internal',
algorithm: ["HS256"]
}
},
messageTypes : ['broadcast', 'changeChannel']
}

29
src/messageManager.ts Normal file
View File

@ -0,0 +1,29 @@
import * as Joi from 'joi';
var logger = require('./logger');
var app = require('./config/app');
let schema = {
message_type: Joi.string().valid(app.messageTypes).insensitive().required(),
current_index: Joi.number().integer(),
total_questions: Joi.number().integer(),
time_elapsed: Joi.number(),
status: Joi.string(),
channel: Joi.string(),
client: Joi.string(),
client_type: Joi.string(),
user_id: Joi.number().integer(),
};
module.exports = {
prepareMessage: (message: string) => {
var parsed = JSON.parse(message)
const result = Joi.validate(parsed, schema);
if (result.error) {
return result
} else {
return parsed
}
}
}

View File

@ -45,7 +45,7 @@ function connectionManager() {
client.replaceWebSocket(ws);
}
} else {
var client: ClientBase|MHSClient|null = clientManager.addClient(data, ws);
var client: ClientBase|MHSClient|null = clientManager.addClient(data, channelManager, ws);
}
if (client != null) {

View File

@ -1,6 +1,7 @@
import ChannelBase from '../channels/channelBase';
import ClientBase from '../clients/clientBase';
import ClientManager from '../clientManager';
import ChannelManager from '../channelManager';
var exec = require('child_process').exec;
var expect = require('chai').expect;
@ -12,8 +13,9 @@ var name: string = 'test channel';
var wsClient = new WebSocketClient();
var channel: ChannelBase;
var clientManager = new ClientManager();
var channelManager = new ChannelManager();
var data: any = { 'client': 'test', 'client_type':'site', 'user_id': 125, 'user_type': 'user', 'channel': name }
var client: ClientBase = new ClientBase(data, wsClient, clientManager);
var client: ClientBase = new ClientBase(data, wsClient, channelManager, clientManager);
describe('ChannelBase', function () {
it('should create a class of ChannelBase', function () {

View File

@ -13,9 +13,8 @@ var data: any = { 'client': 'test', 'client_type':'site', 'user_id': 125, 'user_
var WebSocketClient = require('websocket').client;
var wsClient = new WebSocketClient();
var clientManager = new ClientManager();
var client: ClientBase = new ClientBase(data, wsClient, clientManager);
let channelManager = new ChannelManager();
var channelManager = new ChannelManager();
var client: ClientBase = new ClientBase(data, wsClient, channelManager, clientManager);
describe('ChannelManager', function () {
var channel: ChannelBase;

View File

@ -1,6 +1,7 @@
import * as WebSocket from 'ws';
import ClientBase from '../clients/clientBase';
import ClientManager from '../clientManager';
import ChannelManager from '../channelManager';
var expect = require('chai').expect;
var assert = require('chai').assert;
@ -11,7 +12,8 @@ var data: any = { 'client': 'test', 'client_type':'site', 'user_id': 125, 'user_
var WebSocketClient = require('websocket').client;
var wsClient = new WebSocketClient();
var clientManager = new ClientManager();
var client: ClientBase = new ClientBase(data, wsClient, clientManager);
var channelManager = new ChannelManager();
var client: ClientBase = new ClientBase(data, wsClient, channelManager, clientManager);
describe('ClientBase', function () {
it('should get client data', function () {

View File

@ -2,6 +2,7 @@ import * as WebSocket from 'ws';
import ClientBase from '../clients/clientBase';
import MHSClient from '../clients/sites/mhsClient';
import ClientManager from '../clientManager';
import ChannelManager from '../channelManager';
var expect = require('chai').expect;
var assert = require('chai').assert;
@ -12,11 +13,13 @@ var data: any = { 'client': 'test', 'client_type':'site', 'user_id': 125, 'user_
var WebSocketClient = require('websocket').client;
var wsClient = new WebSocketClient();
var clientManager = new ClientManager();
var client: ClientBase = new ClientBase(data, wsClient, clientManager);
var channelManager = new ChannelManager();
var client: ClientBase = new ClientBase(data, wsClient, channelManager, clientManager);
describe('ClientManager', function () {
it('should add a client', function () {
var result = clientManager.addClient(data, wsClient);
var result = clientManager.addClient(data, channelManager, wsClient);
expect(result.id).to.be.equal(125);
});
@ -51,7 +54,7 @@ describe('ClientManager', function () {
it('should add client of type MHSClient', function () {
var data: any = { 'client': 'mhs', 'client_type':'site', 'user_id': 125, 'user_type': 'user', 'channel': name }
var result = clientManager.getClientType(data, wsClient);
var result = clientManager.getClientType(data, channelManager, wsClient);
expect(result.clientType()).to.be.equal('mhs');
});
});