additon of custom channel conditional eval, though it desperately needs sanitization and/or a framework to work upon. further optimisations and addition of direct messaging
This commit is contained in:
parent
33d1886599
commit
fb5533ce7a
@ -8,11 +8,11 @@ import CustomClient from './clients/types/customClient';
|
||||
var logger = require('./logger');
|
||||
|
||||
class ChannelManager {
|
||||
channels: any = [];
|
||||
channels: any[] = [];
|
||||
|
||||
constructor() {
|
||||
// create default channel...
|
||||
var channel: PublicChannel = new PublicChannel('default');
|
||||
let channel = new PublicChannel('default');
|
||||
this.channels.push(channel);
|
||||
}
|
||||
|
||||
@ -56,13 +56,18 @@ class ChannelManager {
|
||||
}
|
||||
|
||||
createByChannelType(data: any) {
|
||||
var channel_name = data.channel_type + 'Channel'
|
||||
|
||||
try {
|
||||
var Channel = require(`./channels/types/${channel_name}`);
|
||||
logger.accessLog.info(`attempting to create channel of type ${channel_name}, channel id: ${data.channel}...`);
|
||||
return new Channel(data.channel);
|
||||
logger.accessLog.info(`attempting to create channel of type ${data.channel_type}, channel id: ${data.channel}...`);
|
||||
|
||||
if (data.channel_type == 'public') {
|
||||
return new PublicChannel(data.channel)
|
||||
} else if (data.channel_type == 'private') {
|
||||
return new PrivateChannel(data.channel)
|
||||
} else {
|
||||
return new CustomChannel(data.channel, data.custom)
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
logger.errorLog.info(e);
|
||||
logger.accessLog.info(`creating base channel: ${data.channel}`);
|
||||
return new PublicChannel(data.channel);
|
||||
|
@ -1,23 +1,18 @@
|
||||
import PublicClient from '../clients/types/publicClient';
|
||||
import PrivateClient from '../clients/types/privateClient';
|
||||
import CustomClient from '../clients/types/customClient';
|
||||
import * as Joi from 'joi';
|
||||
|
||||
var logger = require('../logger');
|
||||
|
||||
class ChannelBase {
|
||||
id: string;
|
||||
clients: PrivateClient[]|PublicClient[]|CustomClient[] = [];
|
||||
clients: any[] = [];
|
||||
|
||||
constructor(id: string) {
|
||||
this.id = id;
|
||||
logger.accessLog.info('Channel Created', {channelId: id});
|
||||
}
|
||||
|
||||
validations() {
|
||||
return {}
|
||||
}
|
||||
|
||||
broadcastMessage(from: PublicClient|PrivateClient|CustomClient, message: object) {
|
||||
for (let to of this.clients) {
|
||||
if (this.messageTransactionPossible(from, to)) {
|
||||
|
@ -1,18 +1,18 @@
|
||||
import CustomClient from '../../clients/types/customClient';
|
||||
import ChannelBase from '../channelBase';
|
||||
import * as Joi from 'joi';
|
||||
|
||||
class CustomChannel extends ChannelBase {
|
||||
validations() {
|
||||
return {
|
||||
test: Joi.alternatives().try(Joi.string(), Joi.object())
|
||||
}
|
||||
clients: CustomClient[] = [];
|
||||
custom: any;
|
||||
|
||||
constructor(id: string, custom: any) {
|
||||
super(id);
|
||||
this.custom = custom
|
||||
}
|
||||
|
||||
messageTransactionPossible(from: CustomClient, to: CustomClient) {
|
||||
return true
|
||||
return eval(this.custom.broadcastConditions)
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = CustomChannel;
|
||||
export default CustomChannel;
|
||||
|
@ -4,6 +4,8 @@ import ChannelBase from '../channelBase';
|
||||
var logger = require('../../logger');
|
||||
|
||||
class PrivateChannel extends ChannelBase {
|
||||
clients: PrivateClient[] = [];
|
||||
|
||||
messageTransactionPossible(from: PrivateClient, to: PrivateClient) {
|
||||
return (
|
||||
to != from &&
|
||||
@ -13,5 +15,4 @@ class PrivateChannel extends ChannelBase {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = PrivateChannel;
|
||||
export default PrivateChannel;
|
||||
|
@ -4,6 +4,8 @@ import ChannelBase from '../channelBase';
|
||||
var logger = require('../../logger');
|
||||
|
||||
class PublicChannel extends ChannelBase {
|
||||
clients: PublicClient[] = [];
|
||||
|
||||
messageTransactionPossible(from: PublicClient, to: PublicClient) {
|
||||
return (
|
||||
to != from
|
||||
@ -11,5 +13,4 @@ class PublicChannel extends ChannelBase {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = PublicChannel;
|
||||
export default PublicChannel;
|
||||
|
@ -7,7 +7,7 @@ import ChannelManager from './channelManager';
|
||||
var logger = require('./logger');
|
||||
|
||||
class ClientManager {
|
||||
clients: PublicClient[]|PrivateClient[]|CustomClient[] = [];
|
||||
clients: any[] = [];
|
||||
|
||||
constructor() {
|
||||
//...maybe one day
|
||||
@ -68,12 +68,16 @@ class ClientManager {
|
||||
}
|
||||
|
||||
getClientType(data: any, channelManager: ChannelManager, ws: WebSocket) {
|
||||
var client_type = data.client_type + 'Client'
|
||||
|
||||
try {
|
||||
var Client = require(`./clients/types/${client_type}`);
|
||||
logger.accessLog.info(`attempting to create client of type ${data.client_type}, client id: ${data.user_id}...`);
|
||||
return new Client(data, ws, channelManager, this);
|
||||
|
||||
if (data.client_type == 'public') {
|
||||
return new PublicClient(data, ws, channelManager, this)
|
||||
} else if (data.channel_type == 'private') {
|
||||
return new PrivateClient(data, ws, channelManager, this)
|
||||
} else {
|
||||
return new CustomClient(data, ws, channelManager, this)
|
||||
}
|
||||
} catch (e) {
|
||||
logger.errorLog.info(e);
|
||||
logger.accessLog.info(`creating base client: ${data.user_id}`);
|
||||
|
@ -4,6 +4,9 @@ import ChannelManager from '../channelManager';
|
||||
import PublicChannel from '../channels/types/publicChannel';
|
||||
import PrivateChannel from '../channels/types/privateChannel';
|
||||
import CustomChannel from '../channels/types/customChannel';
|
||||
import PublicClient from '../clients/types/publicClient';
|
||||
import PrivateClient from '../clients/types/privateClient';
|
||||
import CustomClient from '../clients/types/customClient';
|
||||
|
||||
var messageManager = require('../messageManager');
|
||||
var logger = require('../logger');
|
||||
@ -27,10 +30,6 @@ class ClientBase {
|
||||
this.roles = ['receiver']
|
||||
}
|
||||
|
||||
validations() {
|
||||
return {}
|
||||
}
|
||||
|
||||
getData() {
|
||||
return this.data;
|
||||
}
|
||||
@ -46,21 +45,24 @@ class ClientBase {
|
||||
connectToChannel(channel: PublicChannel|PrivateChannel|CustomChannel) {
|
||||
this.channel = channel;
|
||||
|
||||
var messageListener = (message: any) => {
|
||||
logger.accessLog.info(`starting message transaction on channel ${channel.id}: `, {message: message});
|
||||
message = messageManager.prepareMessage(message, channel, this);
|
||||
var messageListener = (data: any) => {
|
||||
logger.accessLog.info(`starting message transaction on channel ${channel.id}: `, {data: data});
|
||||
data = messageManager.prepareMessage(data, channel, this);
|
||||
|
||||
if (!message.error) {
|
||||
if (message['message_type'] == 'broadcast') {
|
||||
channel.broadcastMessage(this, message);
|
||||
} else if (message['message_type'] == 'changeChannel') {
|
||||
if (!data.error) {
|
||||
if (data.message_type == 'broadcast') {
|
||||
channel.broadcastMessage(this, data);
|
||||
} else if (data.message_type == 'direct') {
|
||||
let to = this.clientManager.getClient(data.message.to)
|
||||
to.directMessage(data)
|
||||
} else if (data.message_type == 'changeChannel') {
|
||||
this.ws.removeListener('message', messageListener);
|
||||
this.channelManager.changeChannel(this, message);
|
||||
this.channelManager.changeChannel(this, data);
|
||||
}
|
||||
|
||||
logger.accessLog.info(`message transaction complete on channel ${channel.id}: `, {message: message});
|
||||
logger.accessLog.info(`message transaction complete on channel ${channel.id}: `, {message: data});
|
||||
} else {
|
||||
logger.errorLog.info(`Validation failed, please review schema: ${channel.id}`, {data: {message: message, error: message.error}});
|
||||
logger.errorLog.info(`Validation failed, please review schema: ${channel.id}`, {data: {message: data, error: data.error}});
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,6 +80,11 @@ class ClientBase {
|
||||
});
|
||||
}
|
||||
|
||||
directMessage(message: any) {
|
||||
this.ws.send(JSON.stringify(message));
|
||||
logger.accessLog.info(`sent direct message to ${this.id}`, { data: { message: message }});
|
||||
}
|
||||
|
||||
replaceWebSocket(ws: WebSocket) {
|
||||
this.ws.close();
|
||||
this.ws = ws;
|
||||
|
@ -1,14 +1,18 @@
|
||||
import ClientBase from '../clientBase';
|
||||
import ClientManager from '../../clientManager';
|
||||
import ChannelManager from '../../channelManager';
|
||||
import * as WebSocket from 'ws';
|
||||
import * as Joi from 'joi';
|
||||
|
||||
var logger = require('../../logger');
|
||||
|
||||
class CustomClient extends ClientBase {
|
||||
// validations() {
|
||||
// return {
|
||||
// test: Joi.alternatives().try(Joi.string(), Joi.object())
|
||||
// }
|
||||
// }
|
||||
constructor(data: any, ws: WebSocket, channelManager: ChannelManager, clientManager: ClientManager) {
|
||||
super(data, ws, channelManager, clientManager);
|
||||
this.roles = data.user_roles
|
||||
logger.accessLog.info('Custom Client Created', {data: data});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = CustomClient;
|
||||
export default CustomClient;
|
||||
|
||||
|
@ -13,6 +13,5 @@ class PrivateClient extends ClientBase {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = PrivateClient;
|
||||
export default PrivateClient;
|
||||
|
||||
|
@ -4,6 +4,5 @@ var logger = require('../../logger');
|
||||
|
||||
class PublicClient extends ClientBase {};
|
||||
|
||||
module.exports = PublicClient;
|
||||
export default PublicClient;
|
||||
|
||||
|
@ -15,5 +15,5 @@ module.exports = {
|
||||
audience: 'internal',
|
||||
algorithm: ["HS256"]
|
||||
},
|
||||
messageTypes : ['broadcast', 'changeChannel']
|
||||
messageTypes : ['broadcast', 'direct', 'changeChannel']
|
||||
}
|
||||
|
@ -1,31 +1,11 @@
|
||||
import * as Joi from 'joi';
|
||||
import PublicChannel from './channels/types/publicChannel';
|
||||
import PrivateChannel from './channels/types/privateChannel';
|
||||
import CustomChannel from './channels/types/customChannel';
|
||||
import PublicClient from './clients/types/publicClient';
|
||||
import PrivateClient from './clients/types/privateClient';
|
||||
import CustomClient from './clients/types/customClient';
|
||||
|
||||
var logger = require('./logger');
|
||||
var app = require('./config/app');
|
||||
|
||||
let schema = (channel: PublicChannel|PrivateChannel|CustomChannel, client: PublicClient|PrivateClient|CustomClient) => {
|
||||
let validations = {
|
||||
message_type: Joi.string().valid(app.messageTypes).insensitive().required(),
|
||||
channel: Joi.string(),
|
||||
channel_type: Joi.string(),
|
||||
client_type: Joi.string(),
|
||||
user_id: Joi.number().integer(),
|
||||
message: Joi.alternatives().try(Joi.string(), Joi.object())
|
||||
}
|
||||
|
||||
return {...validations, ...channel.validations, ...client.validations}
|
||||
};
|
||||
import Validations from './services/validations';
|
||||
|
||||
module.exports = {
|
||||
prepareMessage: (message: string, channel: PublicChannel|PrivateChannel|CustomChannel, client: PublicClient|PrivateClient|CustomClient) => {
|
||||
var parsed = JSON.parse(message)
|
||||
const result = Joi.validate(parsed, schema(channel, client));
|
||||
prepareMessage: (message: string) => {
|
||||
let validations = new Validations(message)
|
||||
let parsed = JSON.parse(message)
|
||||
const result = Joi.validate(parsed, validations.MessageConditions);
|
||||
|
||||
if (result.error) {
|
||||
return result
|
||||
|
26
src/services/validations.ts
Normal file
26
src/services/validations.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import PublicChannel from '../channels/types/publicChannel';
|
||||
import PrivateChannel from '../channels/types/privateChannel';
|
||||
import CustomChannel from '../channels/types/customChannel';
|
||||
import * as Joi from 'joi'
|
||||
|
||||
var app = require('../config/app');
|
||||
|
||||
class Validations {
|
||||
MessageConditions = {
|
||||
message_type: Joi.string().valid(app.messageTypes).insensitive().required(),
|
||||
channel: Joi.string(),
|
||||
channel_type: Joi.string(),
|
||||
client_type: Joi.string(),
|
||||
user_id: Joi.number().integer(),
|
||||
message: Joi.alternatives().try(Joi.string(), Joi.object()),
|
||||
custom: Joi.object()
|
||||
}
|
||||
|
||||
constructor(message: any) {
|
||||
if (message.channel_type == 'custom') {
|
||||
let conditions = message.conditions
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Validations;
|
@ -40,7 +40,7 @@ describe('ChannelBase', function () {
|
||||
});
|
||||
|
||||
it('should not broadcast a message to self', function () {
|
||||
var result = channel.broadcastMessage(client, 'test message');
|
||||
var result = channel.broadcastMessage(client, {message: "test message"});
|
||||
expect(result.status).to.be.equal('success');
|
||||
});
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as WebSocket from 'ws';
|
||||
import ClientBase from '../clients/clientBase';
|
||||
import PublicClient from '../clients/types/publicClient';
|
||||
import ClientManager from '../clientManager';
|
||||
import ChannelManager from '../channelManager';
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user