globular-mvc
Version:
Generic template to create web-application that made use of globular as backend and materialize as css (wrap in web-component's)
413 lines (342 loc) • 14.3 kB
text/typescript
// Globular conneciton.
import * as GlobularWebClient from "globular-web-client";
import { getAllPeersInfo } from "globular-web-client/api";
import { GeneratePeerTokenRequest } from "globular-web-client/authentication/authentication_pb";
import { Peer } from "globular-web-client/resource/resource_pb";
import { formatBoolean } from "./components/utility";
import { View } from "./View";
// Keep the token in the map...
let tokens: any = {}
/**
* Return the globule url.
* @param globule
* @param callback
* @param errorCallback
*/
export function getUrl(globule: GlobularWebClient.Globular): string {
// set the url for the image.
let url = globule.config.Protocol + "://" + globule.domain
if (window.location.hostname != globule.domain) {
// if no peers has the address at windows location I will test if is an alternate domain, if so I will keep the alternate domain.
if (globule.config.Peers.filter((p) => { return p.Domain === window.location.hostname; }).length == 0) {
if (globule.config.AlternateDomains.indexOf(window.location.host) != -1) {
// keep the given url...
url = globule.config.Protocol + "://" + window.location.host
}
}
}
if (globule.config.Protocol == "https") {
if (globule.config.PortHttps != 443)
url += ":" + globule.config.PortHttps
} else {
if (globule.config.PortHttps != 80)
url += ":" + globule.config.PortHttp
}
return url
}
/**
*
* @param {*} globule The globule
* @param {*} callback The callback
* @param {*} errorCallback
*/
export function generatePeerToken(globule: GlobularWebClient.Globular, callback: (token: string) => void, errorCallback: (err: any) => void) {
if (!globule) {
errorCallback("the globule was not initialyse")
return
}
let mac = globule.config.Mac
if (Model.globular.config.Mac == mac) {
callback(localStorage.getItem("user_token"))
return
}
if (tokens[mac]) {
callback(tokens[mac])
return
}
let rqst = new GeneratePeerTokenRequest
rqst.setMac(mac)
Model.globular.authenticationService.generatePeerToken(rqst, { domain: Model.domain, application: Model.application, address: Model.address, token: localStorage.getItem("user_token") })
.then(rsp => {
let token = rsp.getToken()
tokens[mac] = token
setTimeout(() => {
delete tokens[mac]
}, (globule.config.SessionTimeout * 60 * 1000) - 15000) // remove the token before it get invalid...
callback(token)
})
.catch(errorCallback)
}
export class Model {
protected listeners: Array<any>;
// Here I will keep list of connected globules...
public static globules: Map<string, GlobularWebClient.Globular>
// That function will return a
public static getGlobule(address: string): GlobularWebClient.Globular {
if(address == "localhost"){
return Model.globular;
}
return Model.globules.get(address);
}
public static getGlobules(): Array<GlobularWebClient.Globular> {
let connections_ = Array.from(Model.globules.values())
let connections = new Array<GlobularWebClient.Globular>()
// Remove duplicat
connections_.forEach(c => {
if (connections.filter(c_ => { return c.config.Name == c_.config.Name && c_.config.Domain == c_.config.Domain; }).length == 0) {
connections.push(c)
}
})
return connections
}
// This is the globule where the application is running.
private static _globular: GlobularWebClient.Globular;
public static get globular(): GlobularWebClient.Globular {
return Model.getGlobule(Model.address);
}
// This is the event controller.
public static eventHub: GlobularWebClient.EventHub;
// The domain of the application.
public static domain: string;
// The address...
public static address: string;
// The application name.
public static application: string;
// Pulish event on all globules...
public static publish(name: string, data: any, local: boolean): void {
let globules = Model.getGlobules()
globules.forEach(g => {
g.eventHub.publish(name, data, local)
})
}
// The view.
private _view: View;
protected get view(): View {
return this._view;
}
protected set view(value: View) {
this._view = value;
}
constructor() {
// Set the application name.
// The domain will be set with the hostname.
if (window.location.protocol != "files:") {
Model.domain = window.location.hostname
Model.address = Model.domain + ":" + window.location.port
if (Model.address.endsWith(":")) {
if (window.location.protocol.toLocaleLowerCase() == "https:") {
Model.address += "443"
} else {
Model.address += "80"
}
}
}
this.listeners = new Array<any>();
}
// Append a listener.
appendListener(name: string, uuid: string) {
this.listeners.push({ name: name, uuid: uuid })
}
// Explicitly close the view.
close() {
// Close all listeners.
this.listeners.forEach((listener: any) => {
Model.eventHub.unSubscribe(listener.name, listener.uuid)
})
}
/**
* Return the json string of the class. That will be use to save user data into the database.
*/
toString(): string {
return JSON.stringify(this)
}
/**
* Set the view.
* @param view
*/
setView(view: View) {
this.view = view;
}
/**
* Initialyse model from json object.
* @param json The class data.
*/
static fromString(json: string): any {
}
/**
* Initialyse the notification from object.
* @param obj
*/
static fromObject(obj: any): any {
}
/**
* Initialyse the peer.
* @param peer The peer to initialyse
* @param callback The success callback
* @param errorCallback The error callback
*/
initPeer(peer: Peer, callback: () => void, errorCallback: (err: any) => void) {
let port = 80
if (Model._globular.config.Protocol == "https") {
port = 443
if (peer.getProtocol() == "https") {
port = peer.getPorthttps()
}
} else {
port = peer.getPorthttps()
}
let url = Model._globular.config.Protocol + "://" + peer.getDomain() + ":" + port + "/config"
let globule = new GlobularWebClient.Globular(url, () => {
// append the globule to the list.
Model.globules.set(Model._globular.config.Protocol + "://" + peer.getDomain() + ":" + port, globule)
Model.globules.set(url, globule)
Model.globules.set(peer.getDomain(), globule)
Model.globules.set(peer.getMac(), globule)
callback()
}, (err: any) => {
console.log(err)
errorCallback(err)
})
}
/**
* Remove the peer from the list of active globule.
* @param peer
*/
removePeer(peer: Peer) {
let port = 80
if (Model._globular.config.Protocol == "https") {
port = 443
if (peer.getProtocol() == "https") {
port = peer.getPorthttps()
}
} else {
port = peer.getPorthttps()
}
let url = Model._globular.config.Protocol + "://" + peer.getDomain() + ":" + port + "/config"
// append the globule to the list.
Model.globules.delete(Model._globular.config.Protocol + "://" + peer.getDomain() + ":" + port)
Model.globules.delete(url)
Model.globules.delete(peer.getDomain())
Model.globules.delete(peer.getMac())
}
/**
* Connect with the backend and get the initial configuration.
* @param initCallback On success callback
* @param errorCallback On error callback
* @param adminPort The admin service port
* @param adminProxy The admin service proxy
*/
init(url: string, initCallback: () => void, errorCallback: (err: any) => void) {
// So here I will initilyse the server connection.
Model._globular = new GlobularWebClient.Globular(url, () => {
// set the event hub.
Model.eventHub = Model._globular.eventHub;
Model.eventHub.subscribe("start_peer_evt", uuid => { }, evt => {
let obj = JSON.parse(evt)
let peer = new Peer
peer.setDomain(obj.domain)
peer.setHostname(obj.hostname)
peer.setMac(obj.mac)
peer.setPorthttp(obj.portHttp)
peer.setPorthttps(obj.portHttps)
this.initPeer(peer, () => {
// dispatch the event locally...
Model.eventHub.publish("start_peer_evt_", peer, true)
}, err => console.log(err))
}, false)
Model.eventHub.subscribe("stop_peer_evt", uuid => { }, evt => {
let obj = JSON.parse(evt)
let peer = new Peer
peer.setDomain(obj.domain)
peer.setHostname(obj.hostname)
peer.setMac(obj.mac)
peer.setPorthttp(obj.portHttp)
peer.setPorthttps(obj.portHttps)
// remove the peer from the map.
this.removePeer(peer)
Model.eventHub.publish("stop_peer_evt_", peer, true)
}, false)
// If a new peers is connected...
Model.eventHub.subscribe("update_peers_evt", uuid => { },
evt => {
let obj = JSON.parse(evt)
if (obj) {
let peer = new Peer
peer.setDomain(obj.domain)
peer.setHostname(obj.hostname)
peer.setMac(obj.mac)
peer.setPorthttp(obj.portHttp)
peer.setPorthttps(obj.portHttps)
let actions = new Array<string>()
if (obj.actions) {
obj.actions.forEach((a: string) => {
actions.push(a)
})
}
peer.setActionsList(actions)
this.initPeer(peer, () => {
// dispatch the event locally...
Model.eventHub.publish("update_peers_evt_", peer, true)
}, err => console.log(err))
} else {
console.log("fail to parse ", evt)
}
}, false)
// So here I will create connection to peers know by globular...
Model.globules = new Map<string, GlobularWebClient.Globular>();
Model.globules.set(Model.address, Model._globular)
Model.domain = Model._globular.domain;
Model.globules.set(Model.domain, Model._globular)
Model.globules.set(Model.domain + ":" + Model._globular.config.PortHttp, Model._globular)
Model.globules.set(Model.domain + ":" + Model._globular.config.PortHttps, Model._globular)
Model.globules.set(Model._globular.config.Mac, Model._globular)
// I will also set the globule to other address...
Model._globular.config.AlternateDomains.forEach(alternateDomain => {
// I will set alternate domain only if no peer has it domain.
if (Model._globular.config.Peers.filter((p) => { return p.Domain === alternateDomain; }).length == 0) {
Model.globules.set(alternateDomain, Model._globular)
let address = alternateDomain + ":" + window.location.port
if (address.endsWith(":")) {
if (Model._globular.config.Protocol == "https") {
address += "443"
} else {
address += "80"
}
}
Model.globules.set(address, Model._globular)
}
});
// Retreive peer's infos and register peers.
getAllPeersInfo(Model.globular, (peers: Peer[]) => {
let index = 0;
let connectToPeers = () => {
let peer = peers[index]
if (index < peers.length) {
index++
this.initPeer(peer, () => {
if (index < peers.length) {
connectToPeers()
} else {
initCallback();
}
},
err => {
console.log(err)
if (index < peers.length) {
connectToPeers()
} else {
initCallback();
}
})
} else {
initCallback();
}
}
// call onces
connectToPeers()
}, (err: any) => {
initCallback();
});
}, err => { console.log(err); errorCallback(err); });
}
}