fix(core): update

This commit is contained in:
Philipp Kunz 2019-08-13 15:48:20 +02:00
parent c4261765ec
commit 89feeca735
10 changed files with 116 additions and 47 deletions

View File

@ -15,7 +15,7 @@ const testServerData = {
const testChannelData = { const testChannelData = {
channelName: 'awesomeTestChannel', channelName: 'awesomeTestChannel',
channelPass: 'awesomeChannelPAss' channelPass: 'awesomeChannelPass'
}; };
tap.test('first test', async () => { tap.test('first test', async () => {
@ -44,6 +44,10 @@ tap.test('should add the same channel to the client universe in the same way', a
await testClientUniverse.addChannel(testChannelData.channelName, testChannelData.channelPass); await testClientUniverse.addChannel(testChannelData.channelName, testChannelData.channelPass);
}); });
tap.test('should start the ClientUniverse', async () => {
await testClientUniverse.start();
})
tap.test('should get a observable correctly', async () => { tap.test('should get a observable correctly', async () => {
testClientChannel = await testClientUniverse.getChannel(testChannelData.channelName); testClientChannel = await testClientUniverse.getChannel(testChannelData.channelName);
expect(testClientChannel).to.be.instanceof(smartuniverse.ClientUniverseChannel); expect(testClientChannel).to.be.instanceof(smartuniverse.ClientUniverseChannel);
@ -70,7 +74,7 @@ tap.test('a second client should be able to subscibe', async () => {
tap.test('should receive a message correctly', async () => {}); tap.test('should receive a message correctly', async () => {});
tap.test('should disconnect the client correctly', async () => { tap.test('should disconnect the client correctly', async () => {
testClientUniverse.close(); testClientUniverse.stop();
}); });
tap.test('should end the server correctly', async tools => { tap.test('should end the server correctly', async tools => {

View File

@ -1,4 +0,0 @@
export interface IAuthenticationRequest {
channelName: string;
password: string;
}

View File

@ -22,8 +22,6 @@ export class ClientUniverse {
public options; public options;
public smartsocketClient: plugins.smartsocket.SmartsocketClient; public smartsocketClient: plugins.smartsocket.SmartsocketClient;
public observableIntake: plugins.smartrx.ObservableIntake<UniverseMessage>; public observableIntake: plugins.smartrx.ObservableIntake<UniverseMessage>;
public channelStore = new Objectmap<ClientUniverseChannel>();
public clientUniverseCache = new ClientUniverseCache(); public clientUniverseCache = new ClientUniverseCache();
constructor(optionsArg: IClientOptions) { constructor(optionsArg: IClientOptions) {
@ -51,8 +49,7 @@ export class ClientUniverse {
* @param passphraseArg * @param passphraseArg
*/ */
public async getChannel(channelName: string): Promise<ClientUniverseChannel> { public async getChannel(channelName: string): Promise<ClientUniverseChannel> {
await this.checkConnection(); const clientUniverseChannel = this.clientUniverseCache.channelMap.find(channel => {
const clientUniverseChannel = this.channelStore.find(channel => {
return channel.name === channelName; return channel.name === channelName;
}); });
return clientUniverseChannel; return clientUniverseChannel;
@ -63,12 +60,16 @@ export class ClientUniverse {
* @param messageArg * @param messageArg
*/ */
public removeChannel(channelNameArg, notifyServer = true) { public removeChannel(channelNameArg, notifyServer = true) {
const clientUniverseChannel = this.channelStore.findOneAndRemove(channelItemArg => { const clientUniverseChannel = this.clientUniverseCache.channelMap.findOneAndRemove(channelItemArg => {
return channelItemArg.name === channelNameArg; return channelItemArg.name === channelNameArg;
}); });
} }
public close() { public async start() {
await this.checkConnection();
}
public stop() {
this.smartsocketClient.disconnect(); this.smartsocketClient.disconnect();
} }
@ -95,7 +96,7 @@ export class ClientUniverse {
/** /**
* should handle a forced unsubscription by the server * should handle a forced unsubscription by the server
*/ */
const unsubscribe = new plugins.smartsocket.SocketFunction({ const socketFunctionUnsubscribe = new plugins.smartsocket.SocketFunction({
funcName: 'unsubscribe', funcName: 'unsubscribe',
allowedRoles: [], allowedRoles: [],
funcDef: async (data: interfaces.IServerUnsubscribeActionPayload) => { funcDef: async (data: interfaces.IServerUnsubscribeActionPayload) => {
@ -104,17 +105,25 @@ export class ClientUniverse {
}); });
/** /**
* should handle a message reception * handles message reception
*/ */
const processMessageSocketFunction = new plugins.smartsocket.SocketFunction({ const socketFunctionProcessMessage = new plugins.smartsocket.SocketFunction({
funcName: 'processMessage', funcName: 'processMessage',
allowedRoles: [], allowedRoles: [],
funcDef: async (data: interfaces.IServerUnsubscribeActionPayload) => { funcDef: async (data: interfaces.IServerUnsubscribeActionPayload) => {
throw new Error('TODO'); console.log('Got message from server');
} }
}); });
// add functions
this.smartsocketClient.addSocketFunction(socketFunctionUnsubscribe);
this.smartsocketClient.addSocketFunction(socketFunctionProcessMessage);
await this.smartsocketClient.connect(); await this.smartsocketClient.connect();
console.log('universe client connected successfully');
await this.clientUniverseCache.channelMap.forEach(async clientUniverseChannelArg => {
await clientUniverseChannelArg.subscribe();
});
} }
} }
} }

View File

@ -1,8 +1,11 @@
import * as plugins from './smartuniverse.plugins'; import * as plugins from './smartuniverse.plugins';
import { ClientUniverseChannel } from './smartuniverse.classes.clientuniversechannel';
/** /**
* a cache for clients * a cache for clients
* keeps track of which messages have already been received * keeps track of which messages have already been received
* good for deduplication in mesh environments * good for deduplication in mesh environments
*/ */
export class ClientUniverseCache {} export class ClientUniverseCache {
public channelMap = new plugins.lik.Objectmap<ClientUniverseChannel>();
}

View File

@ -23,8 +23,7 @@ export class ClientUniverseChannel implements interfaces.IUniverseChannel {
channelNameArg, channelNameArg,
passphraseArg passphraseArg
); );
clientUniverseArg.channelStore.add(clientChannel); clientUniverseArg.clientUniverseCache.channelMap.add(clientChannel);
await clientChannel.subscribe();
return clientChannel; return clientChannel;
} }

View File

@ -34,7 +34,7 @@ export class Universe {
constructor(optionsArg: ISmartUniverseConstructorOptions) { constructor(optionsArg: ISmartUniverseConstructorOptions) {
this.options = optionsArg; this.options = optionsArg;
this.universeCache = new UniverseCache(this.options.messageExpiryInMilliseconds); this.universeCache = new UniverseCache(this, this.options.messageExpiryInMilliseconds);
} }
/** /**
@ -60,7 +60,7 @@ export class Universe {
* adds a channel to the Universe * adds a channel to the Universe
*/ */
public async addChannel(nameArg: string, passphraseArg: string) { public async addChannel(nameArg: string, passphraseArg: string) {
const newChannel = UniverseChannel.createChannel(this.universeCache, nameArg, passphraseArg); const newChannel = UniverseChannel.createChannel(this, nameArg, passphraseArg);
} }
/** /**
@ -98,12 +98,11 @@ export class Universe {
) => { ) => {
// run in "this context" of this class // run in "this context" of this class
await (async () => { await (async () => {
// TODO: properly add the connection
const universeConnection = new UniverseConnection({ const universeConnection = new UniverseConnection({
socketConnection: socketConnectionArg, socketConnection: socketConnectionArg,
authenticationRequests: [] authenticationRequests: [dataArg]
}); });
await UniverseConnection.addConnectionToCache(this.universeCache, universeConnection); await UniverseConnection.addConnectionToCache(this, universeConnection);
return { return {
'subscription status': 'success' 'subscription status': 'success'
}; };
@ -128,7 +127,7 @@ export class Universe {
error: 'You need to authenticate for a channel' error: 'You need to authenticate for a channel'
}; };
} }
const unauthenticatedMessage = UniverseMessage.createMessageFromPayload(dataArg); const unauthenticatedMessage = UniverseMessage.createMessageFromPayload(socketConnectionArg, dataArg);
const foundChannel = await UniverseChannel.authorizeAMessageForAChannel( const foundChannel = await UniverseChannel.authorizeAMessageForAChannel(
this.universeCache, this.universeCache,
unauthenticatedMessage unauthenticatedMessage

View File

@ -9,6 +9,7 @@ import { Observable, from } from 'rxjs';
import { filter } from 'rxjs/operators'; import { filter } from 'rxjs/operators';
import { rxjs } from '@pushrocks/smartrx'; import { rxjs } from '@pushrocks/smartrx';
import { UniverseConnection } from './smartuniverse.classes.universeconnection'; import { UniverseConnection } from './smartuniverse.classes.universeconnection';
import { Universe } from './smartuniverse.classes.universe';
/** /**
* universe store handles the creation, storage and retrieval of messages. * universe store handles the creation, storage and retrieval of messages.
@ -30,15 +31,22 @@ export class UniverseCache {
*/ */
public channelMap = new Objectmap<UniverseChannel>(); public channelMap = new Objectmap<UniverseChannel>();
/**
* stores all connections
*/
public connectionMap = new plugins.lik.Objectmap<UniverseConnection>(); public connectionMap = new plugins.lik.Objectmap<UniverseConnection>();
/** /**
* allows messages to be processed in a blacklist mode for further analysis * allows messages to be processed in a blacklist mode for further analysis
*/ */
public blackListChannel = new UniverseChannel(this, 'blacklist', 'nada'); public blackListChannel: UniverseChannel;
constructor(standardMessageExpiryArg: number) { public universeRef: Universe;
constructor(universeArg: Universe, standardMessageExpiryArg: number) {
this.universeRef = universeArg;
this.standardMessageExpiry = standardMessageExpiryArg; this.standardMessageExpiry = standardMessageExpiryArg;
this.blackListChannel = new UniverseChannel(this.universeRef, 'blacklist', 'nada');
} }
/** /**
@ -50,6 +58,9 @@ export class UniverseCache {
messageArg.setUniverseCache(this); messageArg.setUniverseCache(this);
UniverseChannel.authorizeAMessageForAChannel(this, messageArg); UniverseChannel.authorizeAMessageForAChannel(this, messageArg);
this.messageMap.add(messageArg); this.messageMap.add(messageArg);
messageArg.universeChannelList.forEach(universeChannel => {
universeChannel.pushToClients(messageArg);
});
} }
/** /**

View File

@ -1,7 +1,10 @@
import * as plugins from './smartuniverse.plugins'; import * as plugins from './smartuniverse.plugins';
import * as interfaces from './interfaces';
import { UniverseCache } from './smartuniverse.classes.universecache'; import { UniverseCache } from './smartuniverse.classes.universecache';
import { UniverseMessage } from './smartuniverse.classes.universemessage'; import { UniverseMessage } from './smartuniverse.classes.universemessage';
import { UniverseConnection } from './smartuniverse.classes.universeconnection';
import { Universe } from './smartuniverse.classes.universe';
/** /**
* enables messages to stay within a certain scope. * enables messages to stay within a certain scope.
@ -17,12 +20,12 @@ export class UniverseChannel {
* @param passphraseArg the secret thats used for a certain topic. * @param passphraseArg the secret thats used for a certain topic.
*/ */
public static createChannel( public static createChannel(
universeCacheArg: UniverseCache, universeArg: Universe,
channelNameArg: string, channelNameArg: string,
passphraseArg: string passphraseArg: string
) { ) {
const newChannel = new UniverseChannel(universeCacheArg, channelNameArg, passphraseArg); const newChannel = new UniverseChannel(universeArg, channelNameArg, passphraseArg);
universeCacheArg.channelMap.add(newChannel); universeArg.universeCache.channelMap.add(newChannel);
return newChannel; return newChannel;
} }
@ -68,6 +71,12 @@ export class UniverseChannel {
} }
} }
public static getUniverseChannelByName(universeRef: Universe, universeChannelName: string) {
return universeRef.universeCache.channelMap.find(channelArg => {
return channelArg.name === universeChannelName;
});
}
// ======== // ========
// INSTANCE // INSTANCE
// ======== // ========
@ -75,14 +84,15 @@ export class UniverseChannel {
* the name of the channel * the name of the channel
*/ */
public name: string; public name: string;
public universeCacheInstance: UniverseCache; public universeRef: Universe;
/** /**
* the passphrase for the channel * the passphrase for the channel
*/ */
public passphrase: string; public passphrase: string;
constructor(universeCacheArg: UniverseCache, channelNameArg: string, passphraseArg: string) { constructor(universeArg: Universe, channelNameArg: string, passphraseArg: string) {
this.universeRef = universeArg;
this.name = channelNameArg; this.name = channelNameArg;
this.passphrase = passphraseArg; this.passphrase = passphraseArg;
} }
@ -99,5 +109,29 @@ export class UniverseChannel {
); );
} }
public pushToClients(messageArg: UniverseMessage) {} /**
* pushes a message to clients
* @param messageArg
*/
public async pushToClients(messageArg: UniverseMessage) {
const universeConnectionsWithChannelAccess: UniverseConnection[] = [];
this.universeRef.universeCache.connectionMap.forEach(async socketConnection => {
if (socketConnection.authenticatedChannels.includes(this)) {
universeConnectionsWithChannelAccess.push(socketConnection);
}
});
for (const universeConnection of universeConnectionsWithChannelAccess) {
const smartsocket = universeConnection.socketConnection.smartsocketRef as plugins.smartsocket.Smartsocket;
const universeMessageToSend: interfaces.IUniverseMessage = {
id: messageArg.id,
timestamp: messageArg.timestamp,
passphrase: messageArg.passphrase,
targetChannelName: this.name,
messageText: messageArg.messageText,
payload: messageArg.payload,
payloadStringType: messageArg.payloadStringType
};
smartsocket.clientCall('processMessage', universeMessageToSend, universeConnection.socketConnection);
}
}
} }

View File

@ -2,6 +2,7 @@ import * as plugins from './smartuniverse.plugins';
import * as interfaces from './interfaces'; import * as interfaces from './interfaces';
import { UniverseChannel } from './smartuniverse.classes.universechannel'; import { UniverseChannel } from './smartuniverse.classes.universechannel';
import { UniverseCache } from './smartuniverse.classes.universecache'; import { UniverseCache } from './smartuniverse.classes.universecache';
import { Universe } from './smartuniverse.classes.universe';
/** /**
* represents a connection to the universe * represents a connection to the universe
@ -12,18 +13,19 @@ export class UniverseConnection {
* @param universeConnectionArg * @param universeConnectionArg
*/ */
public static async addConnectionToCache( public static async addConnectionToCache(
universeCache: UniverseCache, universeRef: Universe,
universeConnectionArg: UniverseConnection universeConnectionArg: UniverseConnection
) { ) {
let universeConnection = universeConnectionArg; let universeConnection = universeConnectionArg;
universeConnection = await UniverseConnection.deduplicateUniverseConnection( universeConnection = await UniverseConnection.deduplicateUniverseConnection(
universeCache, universeRef.universeCache,
universeConnection universeConnection
); );
universeConnection = await UniverseConnection.authenticateAuthenticationRequests( universeConnection = await UniverseConnection.authenticateAuthenticationRequests(
universeRef,
universeConnection universeConnection
); );
universeCache.connectionMap.add(universeConnection); universeRef.universeCache.connectionMap.add(universeConnection);
} }
/** /**
@ -51,10 +53,17 @@ export class UniverseConnection {
/** /**
* authenticate AuthenticationRequests * authenticate AuthenticationRequests
*/ */
public static authenticateAuthenticationRequests( public static async authenticateAuthenticationRequests(
universeConnectionArg universeRef: Universe,
universeConnectionArg: UniverseConnection
): Promise<UniverseConnection> { ): Promise<UniverseConnection> {
// TODO: authenticate connections for (const authenticationRequest of universeConnectionArg.authenticationRequests) {
// TODO: authenticate channel subscriptions
const universeChannelToAuthenticateAgainst = UniverseChannel.getUniverseChannelByName(universeRef, authenticationRequest.name);
if (universeChannelToAuthenticateAgainst.passphrase === authenticationRequest.passphrase) {
universeConnectionArg.authenticatedChannels.push(universeChannelToAuthenticateAgainst);
}
}
return universeConnectionArg; return universeConnectionArg;
} }
@ -88,7 +97,7 @@ export class UniverseConnection {
* the socketClient to ping * the socketClient to ping
*/ */
public socketConnection: plugins.smartsocket.SocketConnection; public socketConnection: plugins.smartsocket.SocketConnection;
public authenticationRequests = []; public authenticationRequests: interfaces.IServerCallSubscribeActionPayload[] = [];
public subscribedChannels: UniverseChannel[] = []; public subscribedChannels: UniverseChannel[] = [];
public authenticatedChannels: UniverseChannel[] = []; public authenticatedChannels: UniverseChannel[] = [];
public failedToJoinChannels: UniverseChannel[] = []; public failedToJoinChannels: UniverseChannel[] = [];
@ -105,7 +114,7 @@ export class UniverseConnection {
socketConnection: plugins.smartsocket.SocketConnection; socketConnection: plugins.smartsocket.SocketConnection;
authenticationRequests: interfaces.IServerCallSubscribeActionPayload[]; authenticationRequests: interfaces.IServerCallSubscribeActionPayload[];
}) { }) {
// TODO: check if this is correct this.authenticationRequests = optionsArg.authenticationRequests;
this.socketConnection = optionsArg.socketConnection; this.socketConnection = optionsArg.socketConnection;
} }
} }

View File

@ -7,27 +7,28 @@ import { Timer, TimeStamp } from '@pushrocks/smarttime';
import { Universe } from './smartuniverse.classes.universe'; import { Universe } from './smartuniverse.classes.universe';
import { UniverseChannel } from './smartuniverse.classes.universechannel'; import { UniverseChannel } from './smartuniverse.classes.universechannel';
import { UniverseCache } from './smartuniverse.classes.universecache'; import { UniverseCache } from './smartuniverse.classes.universecache';
import { IUniverseMessage } from './interfaces'; import { SocketConnection } from '@pushrocks/smartsocket';
/** /**
* represents a message within a universe * represents a message within a universe
* acts as a container to save message states like authentication status * acts as a container to save message states like authentication status
*/ */
export class UniverseMessage implements interfaces.IUniverseMessage { export class UniverseMessage implements interfaces.IUniverseMessage {
public static createMessageFromPayload(dataArg: interfaces.IUniverseMessage) { public static createMessageFromPayload(socketConnectionArg: SocketConnection, dataArg: interfaces.IUniverseMessage) {
return new UniverseMessage(dataArg); const universeMessageInstance = new UniverseMessage(dataArg);
universeMessageInstance.socketConnection = socketConnectionArg;
return universeMessageInstance;
} }
public id: string; public id: string;
public timestamp: number; public timestamp: number;
public smartTimestamp: TimeStamp; public smartTimestamp: TimeStamp;
public messageText: string; public messageText: string;
public passphrase: string; public passphrase: string;
public payload: any; public payload: any;
public payloadStringType; public payloadStringType;
public targetChannelName: string; public targetChannelName: string;
public socketConnection: SocketConnection;
/** /**
* the UniverseCache the message is attached to * the UniverseCache the message is attached to
@ -54,7 +55,7 @@ export class UniverseMessage implements interfaces.IUniverseMessage {
* @param messageArg * @param messageArg
* @param attachedPayloadArg * @param attachedPayloadArg
*/ */
constructor(messageDescriptor: IUniverseMessage) { constructor(messageDescriptor: interfaces.IUniverseMessage) {
this.smartTimestamp = new TimeStamp(this.timestamp); this.smartTimestamp = new TimeStamp(this.timestamp);
this.messageText = messageDescriptor.messageText; this.messageText = messageDescriptor.messageText;
this.targetChannelName = messageDescriptor.targetChannelName; this.targetChannelName = messageDescriptor.targetChannelName;
@ -68,6 +69,10 @@ export class UniverseMessage implements interfaces.IUniverseMessage {
this.universeCache = universeCacheArg; this.universeCache = universeCacheArg;
} }
public setTargetChannel() {
}
public setDestructionTimer(selfdestructAfterArg: number) { public setDestructionTimer(selfdestructAfterArg: number) {
if (selfdestructAfterArg) { if (selfdestructAfterArg) {
this.destructionTimer = new Timer(selfdestructAfterArg); this.destructionTimer = new Timer(selfdestructAfterArg);