diff --git a/package-lock.json b/package-lock.json index 93caa57..ca3b76e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1382,6 +1382,14 @@ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } + }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", @@ -1571,6 +1579,33 @@ "prr": "~1.0.1" } }, + "es-abstract": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz", + "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==", + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.0", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.6.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -2764,6 +2799,11 @@ } } }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", @@ -2982,12 +3022,25 @@ "har-schema": "^2.0.0" } }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -3235,6 +3288,11 @@ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" + }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -3253,6 +3311,11 @@ } } }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + }, "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", @@ -3340,6 +3403,14 @@ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "requires": { + "has": "^1.0.1" + } + }, "is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", @@ -3354,6 +3425,14 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "requires": { + "has-symbols": "^1.0.0" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -4182,6 +4261,16 @@ } } }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", @@ -4201,6 +4290,15 @@ "isobject": "^3.0.0" } }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, "object.map": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", @@ -4863,9 +4961,9 @@ } }, "rpclibrary": { - "version": "1.3.17", - "resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.3.17.tgz", - "integrity": "sha512-ZdhZ1TSDO+bcz5kCJ7Ol+YAAyYpwg7YI/hETS4vv3RYerUEQVZSZjcm22J5a91RnQVN2SRiXzdoXbbFb/Renog==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.4.0.tgz", + "integrity": "sha512-JUU7+HymV2ZTI+NrIVOiIr5LGFoRsPq4k/ffdUonqIpd9fjOHBQ2/PFLVXx9z94+dKxdqN8/D9ZXPwU03ovZrg==", "requires": { "bsock": "^0.1.9", "http": "0.0.0", @@ -5403,6 +5501,24 @@ "strip-ansi": "^5.1.0" } }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -5842,6 +5958,15 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -6080,6 +6205,21 @@ } } }, + "xml2js": { + "version": "0.4.22", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.22.tgz", + "integrity": "sha512-MWTbxAQqclRSTnehWWe5nMKzI3VmJ8ltiJEco8akcC6j3miOhjjfzKum5sId+CWhfxdOs/1xauYr8/ZDBtQiRw==", + "requires": { + "sax": ">=0.6.0", + "util.promisify": "~1.0.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index 249805f..9c57807 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "build-backend": "tsc; npm run webpack", "build-frontend": "npm run build-dashboard; cp node_modules/rpclibrary/js/browser/rpclibrary.browser.js ./dist/static/FrontblockLib.js", "build-dashboard": "cd src/frontend; npm i && npm run build; mkdir ../../dist/static; cp -r dist/* ../../dist/static", - "clean": "rm -rf lib static plugins conf dist widget .rpt2_cache *.js *.ts src/frontend/dist data", + "clean": "rm -rf lib static plugins conf dist/static widget .rpt2_cache *.js *.ts src/frontend/dist data", "update-frontblock": "npm remove frontblock frontblock-generic; npm install frontblock-generic@latest frontblock@latest", "webpack": "webpack --config src/backend/webpack.prod.js --progress --colors" }, @@ -37,13 +37,14 @@ "node-fetch": "^2.6.0", "path": "^0.12.7", "rimraf": "^3.0.0", - "rpclibrary": "^1.3.17", + "rpclibrary": "^1.4.0", "simple-git": "^1.124.0", "spawn-sync": "^2.0.0", "sqlite3": "^4.1.0", "trash": "^6.0.0", "upgiter": "^1.0.4", - "uuid": "^3.3.3" + "uuid": "^3.3.3", + "xml2js": "^0.4.22" }, "devDependencies": { "@types/express": "^4.17.0", diff --git a/src/backend/Admin.ts b/src/backend/Admin/Admin.ts similarity index 85% rename from src/backend/Admin.ts rename to src/backend/Admin/Admin.ts index 14008c7..61b4548 100644 --- a/src/backend/Admin.ts +++ b/src/backend/Admin/Admin.ts @@ -3,52 +3,26 @@ import { getLogger } from 'frontblock-generic/Types'; import { promises as fs, mkdirSync } from "fs" import { RPCServer } from 'rpclibrary' -import { AdminConf, TableDefiniton } from './Types'; -import { RPCConfigLoader } from './RPCConfigLoader'; -import { RPCPluginLoader } from './PluginLoader'; +import { AdminConf, TableDefiniton } from '../Types/Types'; +import { RPCConfigLoader } from '../Components/RPCConfigLoader'; import * as Path from 'path' -import Knex = require('knex'); -import http = require('http'); -import express = require('express'); -import { TableDefinitionExporter } from './Interfaces'; -import { FrontworkEventBus } from './Eventbus'; +import * as Knex from 'knex'; +import * as http from 'http'; +import * as express from 'express'; +import { TableDefinitionExporter } from '../Types/Interfaces'; +import { FrontworkComponent } from '../Types/FrontworkComponent'; const logger = getLogger("admin", 'debug') export class FrontworkAdmin implements TableDefinitionExporter { + knex:Knex + config: RPCConfigLoader private express private httpServer - private pluginLoader:RPCPluginLoader = new RPCPluginLoader(this) - private eventBus:FrontworkEventBus = new FrontworkEventBus(this) - config: RPCConfigLoader - knex:Knex - constructor(){} - - async start(){ - this.initConfig() - await this.makeKnex() - this.startWebsocket() - this.startWebserver() - } - - protected configChangeHandler = (conf:AdminConf, key?:string) => { - if(key === 'dbConf'){ - this.makeKnex() - } - } - - getConfigKey(key:string){ - return this.config.getConfigKey(key) - } - - setConfigKey(key:string, value:any){ - return this.config.setConfigKey(key, value) - } - - private initConfig(){ + constructor(private components: FrontworkComponent[]){ this.config = new RPCConfigLoader({ name: "FrontworkAdminConf", getDefaultConfig: () => { @@ -65,20 +39,44 @@ implements TableDefinitionExporter { } } }, './config', this.configChangeHandler) + + components.forEach(c => { + c.admin = this + if(c.onSetAdmin) c.onSetAdmin(this) + }) + } + + async start(){ + await this.makeKnex() + this.startWebsocket() + await Promise.all( this.components.map(c => c.initialize?c.initialize():undefined )) + this.startWebserver() + + } + + protected configChangeHandler = (conf:AdminConf, key?:string) => { + if(key === 'dbConf'){ + this.makeKnex() + } + } + + getConfigKey(key:string){ + return this.config.getConfigKey(key) + } + + setConfigKey(key:string, value:any){ + return this.config.setConfigKey(key, value) } getTableDefinitions(): TableDefiniton[]{ return [ - this.eventBus, - ...this.pluginLoader.getPlugins() + ...this.components ].flatMap(exporter => exporter.getTableDefinitions()) } private startWebsocket(){ new RPCServer(20000, [ - this.config, - this.pluginLoader, - this.eventBus + ...this.components, ]) } diff --git a/src/backend/Components/Debugger/Debugger.ts b/src/backend/Components/Debugger/Debugger.ts new file mode 100644 index 0000000..61de241 --- /dev/null +++ b/src/backend/Components/Debugger/Debugger.ts @@ -0,0 +1,34 @@ +import { RPCExporter } from "rpclibrary" +import { FrontworkAdmin } from "../../Admin/Admin" +import { TableDefiniton } from "../../Types/Types" +import { PrivilegedRPCExporter } from "../../Types/PrivilegedRPCExporter" +import { FrontworkComponent } from "../../Types/FrontworkComponent" + +export class Debugger +implements FrontworkComponent{ + public admin: FrontworkAdmin + name = "Debugger" + + + constructor(private exporters: PrivilegedRPCExporter[]){ + } + + exportRPCs(){ + + return [{ + name: 'getTable', + call: async(table:string) => this.admin.knex.select('*').from(table) + }, + ...this.exporters.flatMap(e => e.exportRPCs()), + ...this.exporters.flatMap(e => e.exportRPCFeatures().flatMap(e => e.exportRPCs()))] + } + + exportRPCFeatures(): RPCExporter[] { + return [] + } + + getTableDefinitions(): TableDefiniton[] { + return [] + } + +} \ No newline at end of file diff --git a/src/backend/Eventbus.ts b/src/backend/Components/Eventbus.ts similarity index 92% rename from src/backend/Eventbus.ts rename to src/backend/Components/Eventbus.ts index f615841..d5d55d6 100644 --- a/src/backend/Eventbus.ts +++ b/src/backend/Components/Eventbus.ts @@ -1,9 +1,10 @@ import { RPCExporter, SubscriptionResponse, ErrorResponse, SuccessResponse } from "rpclibrary"; -import { FrontworkAdmin } from "./Admin"; -import { TableDefinitionExporter } from "./Interfaces"; +import { FrontworkAdmin } from "../Admin/Admin"; +import { TableDefinitionExporter } from "../Types/Interfaces"; import { getLogger } from 'frontblock-generic/Types'; import * as uuid from 'uuid/v4' +import { TableDefiniton } from "../Types/Types"; export type NotificationSeverity = 'Info' | 'Important' | 'Error' @@ -84,11 +85,11 @@ implements RPCExporter, TableDefinitionExporter { }] } - getTableDefinitions(){ + getTableDefinitions(): TableDefiniton[]{ return [{ name: 'notifications', tableBuilder: (table) => { - table.increments('ID'); + table.increments('ID').primary(); table.string('severity'); table.string('topic'); table.string('message'); diff --git a/src/backend/Components/Item/ItemManager.ts b/src/backend/Components/Item/ItemManager.ts new file mode 100644 index 0000000..933489b --- /dev/null +++ b/src/backend/Components/Item/ItemManager.ts @@ -0,0 +1,107 @@ +import { TableDefinitionExporter } from "../../Types/Interfaces"; +import { TableDefiniton, _Rank } from "../../Types/Types"; +import { FrontworkAdmin } from "../../Admin/Admin"; +import { T1 } from "../../Types/Items"; +import { FrontworkComponent } from "../../Types/FrontworkComponent"; +import { RPC } from "rpclibrary"; +const fetch = require('node-fetch') +const xml2js = require('xml2js'); +const parser = new xml2js.Parser(/* options */); + + +export type ItemManagerFeatureIfc = any + +export type Item = { + id?:number + name:string + iconname:string + url:string + quality:string + hidden:boolean +} + +export class ItemManager +implements FrontworkComponent, TableDefinitionExporter{ + + admin:FrontworkAdmin + name = "ItemManager"; + + exportRPCs(): RPC[]{ + return [{ + name: 'getItems', + call: async () => await this.getItems() + },{ + name: 'getItem', + call: async (name:string) => await this.getItem(name) + }] + } + + exportRPCFeatures() { + return [] + } + + getItems = async () :Promise => await this.admin.knex.select('*').from('items') + + getItem = async (name:string):Promise => { + const res = await fetch('https://classic.wowhead.com/item='+name+'&xml'); + const txt = await res.text(); + const r = await parser.parseStringPromise(txt); + + try{ + return { + name: r.wowhead.item[0].name[0], + iconname: r.wowhead.item[0].icon[0]._, + url: r.wowhead.item[0].link[0], + quality: r.wowhead.item[0].quality[0]._, + } + }catch (e){ + console.log(name) + throw e + } + } + + getTableDefinitions(): TableDefiniton[] { + return [ + { + name: 'reservations', + tableBuilder: (table) => { + table.integer("user_id").primary() + table.foreign("user_id").references("id").inTable('users') + table.integer("item_id").primary() + table.foreign("item_id").references("id").inTable('items') + table.integer("raid_id").primary() + table.foreign("raid_id").references("id").inTable('raids') + } + },{ + name: 'items', + tableBuilder: (table) => { + table.increments("id").primary() + table.string('name').unique().notNullable() + table.string('iconname').notNullable() + table.string('url').notNullable() + table.string('quality').defaultTo('Epic').notNullable() + table.boolean('hidden').defaultTo(false).notNullable() + } + }] + } + + countItems = async() :Promise => { + const count = await this.admin.knex('items').count('*'); + return count[0]['count(*)'] + } + + initialize = async() => { + const allItems = [...T1] + const countCache = await this.countItems() + if(countCache != allItems.length){ + const items:Item[] = await Promise.all(allItems.map(async (i) => this.getItem(i))) + try{ + await this.admin + .knex('items') + .insert(items) + }catch(e){ + console.error(e) + } + } + } +} \ No newline at end of file diff --git a/src/backend/Components/Login/LoginManager.ts b/src/backend/Components/Login/LoginManager.ts new file mode 100644 index 0000000..d21d0f1 --- /dev/null +++ b/src/backend/Components/Login/LoginManager.ts @@ -0,0 +1,196 @@ +import { RPCServer } from "rpclibrary"; +import { TableDefiniton, AnyRPCExporter, User, RPCPermission, _Rank, Token, Auth } from "../../Types/Types"; +import { FrontworkAdmin } from "../../Admin/Admin"; +import { PrivilegedRPCExporter } from "../../Types/PrivilegedRPCExporter"; +import { FrontworkComponent } from "../../Types/FrontworkComponent"; +const uuid = require('uuid/v4') + + +export class LoginManager +implements FrontworkComponent{ + name = "Authenticator" as "Authenticator"; + admin:FrontworkAdmin + + constructor(private exporters: PrivilegedRPCExporter[]){} + + exportRPCs() { + return [ + { + name: 'login' as 'login', + call: async (username:string, pwHash:string) => await this.login(username, pwHash) + },{ + name: 'authenticate' as 'authenticate', + call: async (tokenValue:string | Token) => await this.authenticate(tokenValue) + } + ] + } + + onSetAdmin(admin:FrontworkAdmin){ + this.exporters.forEach(e => e['admin'] = admin) + } + + exportRPCFeatures() { + return [{ + name: 'createUser' as 'createUser', + exportRPCs: () => [{ + name: 'createUser' as 'createUser', + call: async (user:User) => { + return await this.createUser(user) + } + }] + },{ + name: 'modifyPermissions' as 'modifyPermissions', + exportRPCs: () => [{ + name: 'getPermissions' as 'getPermissions', + call: async () => await this.getPermissions() + },{ + name: 'setPermission' as 'setPermission', + call: async (perm: RPCPermission) => await this.setPermission(perm) + }] + }] + } + + getTableDefinitions(): TableDefiniton[] { + return [ + { + name: 'users', + tableBuilder: (table) => { + table.increments("id").primary() + table.string("name").notNullable().unique() + table.string("pwhash").notNullable() + table.string("rank").notNullable() + table.string("class").notNullable() + table.string("email").nullable().unique() + } + },{ + name: 'rpcpermissions', + tableBuilder: (table) => { + table.string("rpcName").primary().notNullable() + table.boolean("ADMIN").defaultTo(true).notNullable() + _Rank.forEach(r => table.boolean(r).defaultTo(false).notNullable()) + } + },{ + name: 'tokens', + tableBuilder: (table) => { + table.string('value').primary() + table.integer('user_id').notNullable() + table.foreign('user_id').references('users') + table.dateTime('created').defaultTo(this.admin.knex.fn.now()) + } + } + ,...this.exporters.flatMap(exp => exp['getTableDefinitions']?exp['getTableDefinitions']():undefined)] + } + + async initialize(){ + await Promise.all( + [this, ...this.exporters].flatMap(exp => exp.exportRPCFeatures().map(async (rpc) => { + try{ + await this.admin.knex.insert({ rpcname: rpc.name }).into('rpcpermissions') + }catch(e){} + }))) + + await Promise.all(this.exporters.map(ex => ex['initialize']?ex['initialize']():undefined)) + } + + async setPermission(permission: RPCPermission){ + await this.admin.knex('rpcpermissions') + .where('rpcname', '=', permission.name) + .update(permission) + } + + getPermissions = async () : Promise => { + return await this.admin.knex.select('*').from('rpcpermissions') + } + + getRPCForUser = async (user:User): Promise => { + return [...this.exportRPCFeatures(), ...this.exporters.flatMap((exp) => exp.exportRPCFeatures())] + } + + createUser = async(user:User): Promise => { + await this.admin.knex('users') + .insert(user) + + const users = await this.admin.knex + .select("*") + .from('users') + .where(user) + return users[0] + } + + login = async(username:string, pwHash:string) : Promise => { + const res:User[] = await this.admin.knex + .select("*") + .from('users') + .where({ name: username }) + + if(res.length > 0 && pwHash === res[0].pwhash){ + return await this.createToken(res[0]) + } + + throw new Error('login failed') + } + + authenticate = async(tokenValue: string | Token) : Promise => { + if(typeof tokenValue !== 'string') tokenValue = tokenValue.value + + const res : User[] = await this.admin.knex + .select('users.id', 'name', 'class', 'rank', 'email') + .from('tokens') + .join('users', function(){ + this.on('users.id', '=', 'tokens.user_id') + }) + .where({ value: tokenValue}) + + if(res.length === 0) + throw new Error('authentication failed') + + const allowedRPCs = await this.getRPCForUser(res[0]) + const randomPort = 20000 + Math.floor(Math.random() * 10000) + while(true){ + try{ + let commSock = new RPCServer(randomPort, allowedRPCs, { + closeHandler: () => { + console.log(res[0].name, 'disconnected') + commSock.destroy() + }, + connectionHandler: () => { + console.log(res[0].name, 'connected') + cancelTimeout() + }, + sesame: tokenValue + }) + const timeout = setTimeout(() => { + console.log(res[0].name, 'timeout') + commSock.destroy() + }, 10000) + const cancelTimeout = () => { clearTimeout(timeout) } + break; + }catch(e){ + //retry + } + } + + return { + port: randomPort, + user: res[0], + token: { + value: tokenValue, + user_id: res[0].id! + } + } + } + + createToken = async(user:User): Promise => { + const old = await this.admin.knex.select('*').from('tokens').where({user_id: user.id}) + if(old.length === 0){ + const token:Token = { + value: uuid(), + user_id: user.id! + } + await this.admin.knex('tokens').insert(token) + return token + }else{ + return old[0] + } + } +} \ No newline at end of file diff --git a/src/backend/PluginLoader.ts b/src/backend/Components/PluginLoader.ts similarity index 98% rename from src/backend/PluginLoader.ts rename to src/backend/Components/PluginLoader.ts index c767ce1..81ee23f 100644 --- a/src/backend/PluginLoader.ts +++ b/src/backend/Components/PluginLoader.ts @@ -1,8 +1,8 @@ import { RPCExporter } from "rpclibrary"; import { Git } from "upgiter" import { FolderStatus } from "upgiter/js/src/Types"; -import { Plugin } from "./Plugin"; -import { FrontworkAdmin } from "./Admin"; +import { Plugin } from "../Types/Plugin"; +import { FrontworkAdmin } from "../Admin/Admin"; class PluginLoader { private runningPlugins: Plugin[] = [] diff --git a/src/backend/RPCConfigLoader.ts b/src/backend/Components/RPCConfigLoader.ts similarity index 100% rename from src/backend/RPCConfigLoader.ts rename to src/backend/Components/RPCConfigLoader.ts diff --git a/src/backend/Components/Raid/RaidManager.ts b/src/backend/Components/Raid/RaidManager.ts new file mode 100644 index 0000000..75a1a1d --- /dev/null +++ b/src/backend/Components/Raid/RaidManager.ts @@ -0,0 +1,95 @@ +import { TableDefiniton, User, _Rank, Raid, Signup, RaidManagerFeatureIfc } from "../../Types/Types"; +import { FrontworkAdmin } from "../../Admin/Admin"; +import { FrontworkComponent } from "../../Types/FrontworkComponent"; + + +export class RaidManager +implements FrontworkComponent{ + name = "RaidManager"; + admin: FrontworkAdmin + + exportRPCs = () => [] + + exportRPCFeatures() { + return [{ + name: 'manageRaid' as 'manageRaid', + exportRPCs: () => [{ + name: 'createRaid' as 'createRaid', + call: async (raid:Raid) => await this.createRaid(raid) + },{ + name: 'addSignup' as 'addSignup', + call: async(signup: Signup) => await this.addSignup(signup) + },{ + name: 'removeSignup' as 'removeSignup', + call: async(signup: Signup) => await this.removeSignup(signup) + }] + },{ + name: 'signup' as 'signup', + exportRPCs: () => [{ + name: 'getRaids' as 'getRaids', + call: async () => await this.getRaids() + },{ + name: 'getSingups' as 'getSingups', + call: async(raid: Raid) => await this.getSignups(raid) + },{ + name: 'sign' as 'sign', + call: async(user:User, raid:Raid) => await this.sign(user, raid) + }] + },] + } + + getTableDefinitions(): TableDefiniton[] { + return [ + { + name: 'raids', + tableBuilder: (table) => { + table.increments('id').primary() + table.dateTime('start').notNullable() + table.string('description').notNullable() + table.string('title').notNullable() + table.integer('minrank').notNullable() + } + },{ + name: 'signups', + tableBuilder: (table) => { + table.integer('raid_id').primary() + table.foreign('raid_id').references('id').inTable('raids') + table.integer('user_id').primary() + table.foreign('user_id').references('id').inTable('users') + } + } + ] + } + + createRaid = async (raid:Raid) => await this.admin + .knex('raids') + .insert(raid) + + addSignup = async (signup: Signup) => await this.admin + .knex('signups') + .insert(signup) + + removeSignup = async (signup: Signup) => await this.admin + .knex('signups') + .where({ + raid_id: signup.raid_id, + user_id: signup.user_id + }) + .delete() + + getRaids = async () => await this.admin.knex + .select('*') + .from('raids') + + getSignups = async (raid:Raid) => await this.admin.knex + .select('*') + .from('signups') + .where('raid_id', '=', raid.id!) + + sign = async (user:User, raid:Raid) => await this.admin + .knex('signups') + .insert({ + raid_id: raid.id!, + user_id: user.id! + }) +} \ No newline at end of file diff --git a/src/backend/Installer.ts b/src/backend/Installer.ts deleted file mode 100644 index a712d53..0000000 --- a/src/backend/Installer.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Plugin } from "./Plugin" -import { getLogger } from "frontblock-generic/Types" -import { FrontworkAdmin } from "./Admin"; -var exec = require('child-process-promise').exec; - -const logger = getLogger("installer", 'info') - -export type NPMPkgName = string -export type NPMVersion = string - -export const installAdmin = (plugins: Plugin[] = []) => { - - const npmPkgs:[NPMPkgName, NPMVersion][] = [['sqlite3', '4.1.0'], ['knex', '0.19.2']] - const deps = npmPkgs.map(tuple => tuple.join('@') ).join(" ") - logger.info("Installing plaform dependencies: "+deps) - - exec("npm i " + deps).then(async process => { - logger.debug(process.stdout) - const Admin = require("./Admin").FrontworkAdmin - const fbAdmin:FrontworkAdmin = new Admin(plugins) - fbAdmin.start() - }) - -} \ No newline at end of file diff --git a/src/backend/Launcher.ts b/src/backend/Launcher.ts index 0cb2b16..6cf6f88 100644 --- a/src/backend/Launcher.ts +++ b/src/backend/Launcher.ts @@ -1,2 +1,20 @@ -import { installAdmin } from "./Installer"; -installAdmin() +import { FrontworkAdmin } from './Admin/Admin' +import { RaidManager } from "./Components/Raid/RaidManager"; +import { ItemManager } from "./Components/Item/ItemManager"; +import { LoginManager } from "./Components/Login/LoginManager"; +import { Debugger } from './Components/Debugger/Debugger'; +import { FrontworkComponent } from './Types/FrontworkComponent'; +require('events').EventEmitter.defaultMaxListeners = 0; + +let raidManager = new RaidManager() +let itemManager = new ItemManager() +let loginManager = new LoginManager([ + raidManager, + itemManager +]) + +let components:FrontworkComponent[] = [ raidManager, itemManager, loginManager ] +let dbg = new Debugger(components) + + +new FrontworkAdmin([dbg, ...components]).start() diff --git a/src/backend/Types.ts b/src/backend/Types.ts deleted file mode 100644 index dad1c03..0000000 --- a/src/backend/Types.ts +++ /dev/null @@ -1,14 +0,0 @@ -import Knex = require("knex") - -export declare type NotificationSeverity = 'Info' | 'Important' | 'Error'; - -export type AdminConf = { - httpPort: number, - dbConf:Knex.Config, - eventBusConf: { [topic in string]: NotificationSeverity} -} - -export type TableDefiniton = { - name: string, - tableBuilder: (table: Knex.CreateTableBuilder) => void -} \ No newline at end of file diff --git a/src/backend/Types/FrontworkComponent.ts b/src/backend/Types/FrontworkComponent.ts new file mode 100644 index 0000000..d76649a --- /dev/null +++ b/src/backend/Types/FrontworkComponent.ts @@ -0,0 +1,24 @@ +import { PrivilegedRPCExporter } from "./PrivilegedRPCExporter"; +import { RPCInterface, RPC, AnyFunction, RPCExporter } from "rpclibrary"; +import { TableDefinitionExporter } from "./Interfaces"; +import { FrontworkAdmin } from "../Admin/Admin"; +import { TableDefiniton } from "./Types"; + +export interface FrontworkComponent< + Ifc extends RPCInterface = RPCInterface, + Name extends keyof Ifc = keyof Ifc, + SubresT = {} +> extends + PrivilegedRPCExporter, + TableDefinitionExporter +{ + admin:FrontworkAdmin + name: string; + + exportRPCFeatures(): RPCExporter[] + exportRPCs(): RPC[] + getTableDefinitions(): TableDefiniton[] + + initialize?(): Promise + onSetAdmin?(admin:FrontworkAdmin): void +} \ No newline at end of file diff --git a/src/backend/Interfaces.ts b/src/backend/Types/Interfaces.ts similarity index 98% rename from src/backend/Interfaces.ts rename to src/backend/Types/Interfaces.ts index 890f95f..f36ecfb 100644 --- a/src/backend/Interfaces.ts +++ b/src/backend/Types/Interfaces.ts @@ -2,4 +2,4 @@ import { TableDefiniton } from "./Types"; export interface TableDefinitionExporter{ getTableDefinitions(): TableDefiniton[] -} \ No newline at end of file +} diff --git a/src/backend/Types/Items.ts b/src/backend/Types/Items.ts new file mode 100644 index 0000000..b67b29d --- /dev/null +++ b/src/backend/Types/Items.ts @@ -0,0 +1,64 @@ +export const T1 = [ +"Robe of Volatile Power", +"Salamander Scale Pants", +"Heavy Dark Iron Ring", +"Ring of Spell Power", +"Sorcerous Dagger", +"Wristguards of Stability", +"Helm of the Lifegiver", +"Fire Runed Grimoire", +"Crimson Shocker", +"Mana Igniting Cord", +"Quick Strike Ring", +"Seal of the Archmagus", +"Talisman of Ephemeral Power", +"Flameguard Gauntlets", +"Magma Tempered Boots", +"Obsidian Edged Blade", +"Aged Core Leather Gloves", +"Sabatons of the Flamewalker", +"Striker's Mark", +"Medallion of Steadfast Might", +"Earthshaker", +"Brutality Blade", +"Aurastone Hammer", +"Gutgore Ripper", +"Drillborer Disk", +"Azuresong Mageblade", +"Staff of Dominance", +"Blastershot Launcher", +"The Eye of Divinity", +"Ancient Petrified Leaf", +"Finkle's Lava Dredger", +"Core Hound Tooth", +"Core Forged Greaves", +"Gloves of the Hypnotic Flame", +"Sash of Whispered Secrets", +"Wild Growth Spaulders", +"Fireproof Cloak", +"Wristguards of True Flight", +"Fireguard Shoulders", +"Cauterizing Band", +"Onslaught Girdle", +"Perdition's Blade", +"Cloak of the Shrouded Mists", +"Band of Accuria", +"Crown of Destruction", +"Choker of the Fire Lord", +"Band of Sulfuras", +"Dragon's Blood Cape", +"Malistar's Defender", +"Spinal Reaper", +"Bonereaver's Edge", +"Shard of the Flame", +"Essence of the Pure Flame", +"Eye of Sulfuras", +"Deathbringer", +"Vis'kag the Bloodletter", +"Sapphiron Drape", +"Ancient Cornerstone Grimoire", +"Eskhandar's Collar", +"Ring of Binding", +"Shard of the Scale", +"Head of Onyxia", +"Bindings of the Windseeker"] \ No newline at end of file diff --git a/src/backend/Plugin.ts b/src/backend/Types/Plugin.ts similarity index 94% rename from src/backend/Plugin.ts rename to src/backend/Types/Plugin.ts index 44effdb..f13854f 100644 --- a/src/backend/Plugin.ts +++ b/src/backend/Types/Plugin.ts @@ -1,4 +1,4 @@ -import { FrontworkAdmin } from "./Admin" +import { FrontworkAdmin } from "../Admin/Admin" import { RPC, RPCExporter } from "rpclibrary" import { TableDefiniton } from "./Types" import { TableDefinitionExporter } from "./Interfaces" diff --git a/src/backend/Types/PrivilegedRPCExporter.ts b/src/backend/Types/PrivilegedRPCExporter.ts new file mode 100644 index 0000000..0242267 --- /dev/null +++ b/src/backend/Types/PrivilegedRPCExporter.ts @@ -0,0 +1,7 @@ +import { RPCExporter, RPCInterface, RPC, RPCInterfaceArray } from "rpclibrary"; + +export interface PrivilegedRPCExporter +extends RPCExporter{ + + exportRPCFeatures() : RPCExporter[] +} \ No newline at end of file diff --git a/src/backend/Types/Types.ts b/src/backend/Types/Types.ts new file mode 100644 index 0000000..6e1a521 --- /dev/null +++ b/src/backend/Types/Types.ts @@ -0,0 +1,91 @@ +import * as Knex from "knex" +import { RPCExporter } from "rpclibrary"; + +export declare type NotificationSeverity = 'Info' | 'Important' | 'Error'; + +export type AdminConf = { + httpPort: number, + dbConf:Knex.Config, + eventBusConf: { [topic in string]: NotificationSeverity} +} + +export type TableDefiniton = { + name: string, + tableBuilder: (table: Knex.CreateTableBuilder) => void +} + +export type Rank = "ADMIN" | "Guildmaster" | "Officer" | "Classleader" | "Raider" | "Trial" | "Social" | "Guest" +export const _Rank : Rank[] = ["Guildmaster" , "Officer" , "Classleader" , "Raider" , "Trial" , "Social" , "Guest"] +export type Class = "Warrior" | "Rogue" | "Hunter" | "Mage" | "Warlock" | "Priest" | "Shaman" | "Paladin" | "Druid" +export const _Class : Class[] = ["Warrior" , "Rogue" , "Hunter" , "Mage" , "Warlock" , "Priest" , "Shaman" , "Paladin" , "Druid"] + +export type AnyRPCExporter = RPCExporter + +export type RPCPermission = { + name: string +} & { + [rank in Rank] : boolean +} + +export type User = { + id?: number + name: string + pwhash: string + class: Class + rank: Rank + email?: string +} + +export type Raid = { + id?: number + title: string + description: string + start: string + minrank: Rank +} + +export type Signup = { + raid_id: number + user_id: number +} + +export type Token = { + value: string + user_id: number + created?: number +} + +export type Auth = {port: number, user: User, token: Token} + +export type FrontcraftFeatureIfc = RaidManagerFeatureIfc & LoginManagerFeatureIfc + + +export type LoginManagerIfc = { + Authenticator: { + login: (username:string, pwHash:string) => Promise + authenticate: (token:string | Token) => Promise + } +} + +export type LoginManagerFeatureIfc = { + createUser: { + createUser: (user:User) => Promise + } + modifyPermissions: { + setPermission: (perm: RPCPermission) => Promise + getPermissions: () => Promise + } +} + +export type RaidManagerFeatureIfc = { + manageRaid: { + createRaid: (raid:Raid) => Promise + addSignup: (signup: Signup) => Promise + removeSignup: (signup: Signup) => Promise + } + signup: { + getRaids: () => Promise + getSingups: (raid:Raid) => Promise + sign: (user:User, raid:Raid, attending:boolean) => Promise + } +} \ No newline at end of file diff --git a/src/frontend/angular.json b/src/frontend/angular.json index 9ae6d21..ae28591 100644 --- a/src/frontend/angular.json +++ b/src/frontend/angular.json @@ -9,8 +9,12 @@ "projectType": "application", "architect": { "build": { - "builder": "@angular-devkit/build-angular:browser", + "builder": "@angular-builders/custom-webpack:browser", "options": { + "customWebpackConfig": { + "path": "./custom-webpack.config.js", + "replaceDuplicatePlugins": true + }, "preserveSymlinks": true, "rebaseRootRelativeCssUrls": true, "outputPath": "dist", @@ -75,7 +79,7 @@ } }, "serve": { - "builder": "@angular-devkit/build-angular:dev-server", + "builder": "@angular-builders/custom-webpack:dev-server", "options": { "browserTarget": "ngx-admin-demo:build" }, diff --git a/src/frontend/custom-webpack.config.js b/src/frontend/custom-webpack.config.js new file mode 100644 index 0000000..c44fbd2 --- /dev/null +++ b/src/frontend/custom-webpack.config.js @@ -0,0 +1,4 @@ +module.exports = { + externals: ['http'], + node: {global: true, fs: 'empty'} +} \ No newline at end of file diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json index 4ec69b2..3644f4f 100644 --- a/src/frontend/package-lock.json +++ b/src/frontend/package-lock.json @@ -9,6 +9,22 @@ "resolved": "https://registry.npmjs.org/@agm/core/-/core-1.0.0-beta.5.tgz", "integrity": "sha512-LVENJqtBZEWpX+uJkGI0zgg+Xkm2KkktQm4ojZozArbeNvQkVL6pqVc04Mme6vvOzwJpD1cET5w4byC8Xaq1QQ==" }, + "@angular-builders/custom-webpack": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@angular-builders/custom-webpack/-/custom-webpack-8.2.0.tgz", + "integrity": "sha512-6654RfyqhTGhCI0edC9YU/iMn1UJnzX01bxYJbDWFgvReCqXdlgy+Fe9tp1MeqKweX6BQ1d0gRroR/WjY1aX0A==", + "requires": { + "lodash": "^4.17.10", + "webpack-merge": "^4.2.1" + }, + "dependencies": { + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + } + } + }, "@angular-devkit/architect": { "version": "0.800.2", "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.800.2.tgz", @@ -11695,6 +11711,11 @@ } } }, + "ngx-cookie-service": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ngx-cookie-service/-/ngx-cookie-service-2.2.0.tgz", + "integrity": "sha512-2kaC1itlEMxiMAPJ320hOpcwU9vhvjbKQCZ1Go6bGhYjJtqG7eYvhNP7mM9IhFz1/afG2tBryJPySWmFUGhRpA==" + }, "ngx-echarts": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/ngx-echarts/-/ngx-echarts-4.0.1.tgz", @@ -14314,9 +14335,9 @@ "integrity": "sha512-ZYzRkETgBrdEGzL5JSKimvjI2CX7ioyZCkX2BpcfyjqI+079W0wHAyj5W4rIZMcDSOHgLZtgz1IdDi/vU77KEQ==" }, "rpclibrary": { - "version": "1.3.17", - "resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.3.17.tgz", - "integrity": "sha512-ZdhZ1TSDO+bcz5kCJ7Ol+YAAyYpwg7YI/hETS4vv3RYerUEQVZSZjcm22J5a91RnQVN2SRiXzdoXbbFb/Renog==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.4.0.tgz", + "integrity": "sha512-JUU7+HymV2ZTI+NrIVOiIr5LGFoRsPq4k/ffdUonqIpd9fjOHBQ2/PFLVXx9z94+dKxdqN8/D9ZXPwU03ovZrg==", "requires": { "bsock": "^0.1.9", "http": "0.0.0", @@ -20446,7 +20467,6 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz", "integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==", - "dev": true, "requires": { "lodash": "^4.17.5" } diff --git a/src/frontend/package.json b/src/frontend/package.json index a70bb44..f57eb37 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -30,6 +30,7 @@ }, "dependencies": { "@agm/core": "^1.0.0-beta.5", + "@angular-builders/custom-webpack": "^8.2.0", "@angular/animations": "^8.0.0", "@angular/cdk": "^8.0.0", "@angular/common": "^8.0.0", @@ -62,12 +63,13 @@ "ng2-ckeditor": "^1.2.2", "ng2-completer": "2.0.8", "ng2-smart-table": "1.3.5", + "ngx-cookie-service": "^2.2.0", "ngx-echarts": "^4.0.1", "node-sass": "^4.12.0", "normalize.css": "6.0.0", "pace-js": "1.0.2", "roboto-fontface": "0.8.0", - "rpclibrary": "^1.3.17", + "rpclibrary": "^1.4.0", "rxjs": "6.5.2", "rxjs-compat": "6.3.0", "socicon": "3.0.5", diff --git a/src/frontend/src/app/@core/core.module.ts b/src/frontend/src/app/@core/core.module.ts index 786d895..6cb5861 100644 --- a/src/frontend/src/app/@core/core.module.ts +++ b/src/frontend/src/app/@core/core.module.ts @@ -1,146 +1,35 @@ -import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core'; +import { ModuleWithProviders, NgModule, Optional, SkipSelf, APP_INITIALIZER } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { NbAuthModule, NbDummyAuthStrategy } from '@nebular/auth'; -import { NbSecurityModule, NbRoleProvider } from '@nebular/security'; -import { of as observableOf } from 'rxjs'; - import { throwIfAlreadyLoaded } from './module-import-guard'; +import { CookieService } from 'ngx-cookie-service'; + import { AnalyticsService, LayoutService, PlayerService, StateService, } from './utils'; -import { UserData } from './data/users'; -import { ElectricityData } from './data/electricity'; -import { SmartTableData } from './data/smart-table'; -import { UserActivityData } from './data/user-activity'; -import { OrdersChartData } from './data/orders-chart'; -import { ProfitChartData } from './data/profit-chart'; -import { TrafficListData } from './data/traffic-list'; -import { EarningData } from './data/earning'; -import { OrdersProfitChartData } from './data/orders-profit-chart'; -import { TrafficBarData } from './data/traffic-bar'; -import { ProfitBarAnimationChartData } from './data/profit-bar-animation-chart'; -import { TemperatureHumidityData } from './data/temperature-humidity'; -import { SolarData } from './data/solar'; -import { TrafficChartData } from './data/traffic-chart'; -import { StatsBarData } from './data/stats-bar'; -import { CountryOrderData } from './data/country-order'; -import { StatsProgressBarData } from './data/stats-progress-bar'; -import { VisitorsAnalyticsData } from './data/visitors-analytics'; -import { SecurityCamerasData } from './data/security-cameras'; +import { LoginApiService, initializeLoginSvc } from '../frontcraft/login-api'; -import { UserService } from './mock/users.service'; -import { ElectricityService } from './mock/electricity.service'; -import { SmartTableService } from './mock/smart-table.service'; -import { UserActivityService } from './mock/user-activity.service'; -import { OrdersChartService } from './mock/orders-chart.service'; -import { ProfitChartService } from './mock/profit-chart.service'; -import { TrafficListService } from './mock/traffic-list.service'; -import { EarningService } from './mock/earning.service'; -import { OrdersProfitChartService } from './mock/orders-profit-chart.service'; -import { TrafficBarService } from './mock/traffic-bar.service'; -import { ProfitBarAnimationChartService } from './mock/profit-bar-animation-chart.service'; -import { TemperatureHumidityService } from './mock/temperature-humidity.service'; -import { SolarService } from './mock/solar.service'; -import { TrafficChartService } from './mock/traffic-chart.service'; -import { StatsBarService } from './mock/stats-bar.service'; -import { CountryOrderService } from './mock/country-order.service'; -import { StatsProgressBarService } from './mock/stats-progress-bar.service'; -import { VisitorsAnalyticsService } from './mock/visitors-analytics.service'; -import { SecurityCamerasService } from './mock/security-cameras.service'; -import { MockDataModule } from './mock/mock-data.module'; - -const socialLinks = [ +const DATA_SERVICES = [ + {provide: LoginApiService, useClass: LoginApiService}, + {provide: CookieService, useClass: CookieService}, { - url: 'https://github.com/akveo/nebular', - target: '_blank', - icon: 'github', - }, - { - url: 'https://www.facebook.com/akveo/', - target: '_blank', - icon: 'facebook', - }, - { - url: 'https://twitter.com/akveo_inc', - target: '_blank', - icon: 'twitter', - }, -]; - -const DATA_SERVICES = [ - { provide: UserData, useClass: UserService }, - { provide: ElectricityData, useClass: ElectricityService }, - { provide: SmartTableData, useClass: SmartTableService }, - { provide: UserActivityData, useClass: UserActivityService }, - { provide: OrdersChartData, useClass: OrdersChartService }, - { provide: ProfitChartData, useClass: ProfitChartService }, - { provide: TrafficListData, useClass: TrafficListService }, - { provide: EarningData, useClass: EarningService }, - { provide: OrdersProfitChartData, useClass: OrdersProfitChartService }, - { provide: TrafficBarData, useClass: TrafficBarService }, - { provide: ProfitBarAnimationChartData, useClass: ProfitBarAnimationChartService }, - { provide: TemperatureHumidityData, useClass: TemperatureHumidityService }, - { provide: SolarData, useClass: SolarService }, - { provide: TrafficChartData, useClass: TrafficChartService }, - { provide: StatsBarData, useClass: StatsBarService }, - { provide: CountryOrderData, useClass: CountryOrderService }, - { provide: StatsProgressBarData, useClass: StatsProgressBarService }, - { provide: VisitorsAnalyticsData, useClass: VisitorsAnalyticsService }, - { provide: SecurityCamerasData, useClass: SecurityCamerasService }, -]; - -export class NbSimpleRoleProvider extends NbRoleProvider { - getRole() { - // here you could provide any role based on any auth flow - return observableOf('guest'); + provide: APP_INITIALIZER, + useFactory: initializeLoginSvc, + deps: [LoginApiService, CookieService], + multi: true } -} +]; export const NB_CORE_PROVIDERS = [ - ...MockDataModule.forRoot().providers, ...DATA_SERVICES, - ...NbAuthModule.forRoot({ - strategies: [ - NbDummyAuthStrategy.setup({ - name: 'email', - delay: 3000, - }), - ], - forms: { - login: { - socialLinks: socialLinks, - }, - register: { - socialLinks: socialLinks, - }, - }, - }).providers, - - NbSecurityModule.forRoot({ - accessControl: { - guest: { - view: '*', - }, - user: { - parent: 'guest', - create: '*', - edit: '*', - remove: '*', - }, - }, - }).providers, - - { - provide: NbRoleProvider, useClass: NbSimpleRoleProvider, - }, AnalyticsService, LayoutService, PlayerService, StateService, + CookieService, ]; @NgModule({ @@ -148,7 +37,6 @@ export const NB_CORE_PROVIDERS = [ CommonModule, ], exports: [ - NbAuthModule, ], declarations: [], }) diff --git a/src/frontend/src/app/@core/mock/README.md b/src/frontend/src/app/@core/mock/README.md deleted file mode 100644 index af96780..0000000 --- a/src/frontend/src/app/@core/mock/README.md +++ /dev/null @@ -1 +0,0 @@ -Application-wise data providers. diff --git a/src/frontend/src/app/@core/mock/country-order.service.ts b/src/frontend/src/app/@core/mock/country-order.service.ts deleted file mode 100644 index ea28589..0000000 --- a/src/frontend/src/app/@core/mock/country-order.service.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Injectable } from '@angular/core'; -import { of as observableOf, Observable } from 'rxjs'; -import { CountryOrderData } from '../data/country-order'; - -@Injectable() -export class CountryOrderService extends CountryOrderData { - - private countriesCategories = [ - 'Sofas', - 'Furniture', - 'Lighting', - 'Tables', - 'Textiles', - ]; - private countriesCategoriesLength = this.countriesCategories.length; - private generateRandomData(nPoints: number): number[] { - return Array.from(Array(nPoints)).map(() => { - return Math.round(Math.random() * 20); - }); - } - - getCountriesCategories(): Observable { - return observableOf(this.countriesCategories); - } - - getCountriesCategoriesData(country: string): Observable { - return observableOf(this.generateRandomData(this.countriesCategoriesLength)); - } -} diff --git a/src/frontend/src/app/@core/mock/earning.service.ts b/src/frontend/src/app/@core/mock/earning.service.ts deleted file mode 100644 index 1a4c76f..0000000 --- a/src/frontend/src/app/@core/mock/earning.service.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { Injectable } from '@angular/core'; -import { of as observableOf, Observable } from 'rxjs'; -import { LiveUpdateChart, PieChart, EarningData } from '../data/earning'; - -@Injectable() -export class EarningService extends EarningData { - - private currentDate: Date = new Date(); - private currentValue = Math.random() * 1000; - private ONE_DAY = 24 * 3600 * 1000; - - private pieChartData = [ - { - value: 50, - name: 'Bitcoin', - }, - { - value: 25, - name: 'Tether', - }, - { - value: 25, - name: 'Ethereum', - }, - ]; - - private liveUpdateChartData = { - bitcoin: { - liveChart: [], - delta: { - up: true, - value: 4, - }, - dailyIncome: 45895, - }, - tether: { - liveChart: [], - delta: { - up: false, - value: 9, - }, - dailyIncome: 5862, - }, - ethereum: { - liveChart: [], - delta: { - up: false, - value: 21, - }, - dailyIncome: 584, - }, - }; - - getDefaultLiveChartData(elementsNumber: number) { - this.currentDate = new Date(); - this.currentValue = Math.random() * 1000; - - return Array.from(Array(elementsNumber)) - .map(item => this.generateRandomLiveChartData()); - } - - generateRandomLiveChartData() { - this.currentDate = new Date(+this.currentDate + this.ONE_DAY); - this.currentValue = this.currentValue + Math.random() * 20 - 11; - - if (this.currentValue < 0) { - this.currentValue = Math.random() * 100; - } - - return { - value: [ - [ - this.currentDate.getFullYear(), - this.currentDate.getMonth(), - this.currentDate.getDate(), - ].join('/'), - Math.round(this.currentValue), - ], - }; - } - - getEarningLiveUpdateCardData(currency): Observable { - const data = this.liveUpdateChartData[currency.toLowerCase()]; - const newValue = this.generateRandomLiveChartData(); - - data.liveChart.shift(); - data.liveChart.push(newValue); - - return observableOf(data.liveChart); - } - - getEarningCardData(currency: string): Observable { - const data = this.liveUpdateChartData[currency.toLowerCase()]; - - data.liveChart = this.getDefaultLiveChartData(150); - - return observableOf(data); - } - - getEarningPieChartData(): Observable { - return observableOf(this.pieChartData); - } -} diff --git a/src/frontend/src/app/@core/mock/electricity.service.ts b/src/frontend/src/app/@core/mock/electricity.service.ts deleted file mode 100644 index 4f8fb2f..0000000 --- a/src/frontend/src/app/@core/mock/electricity.service.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { Injectable } from '@angular/core'; -import { of as observableOf, Observable } from 'rxjs'; -import { Electricity, ElectricityChart, ElectricityData } from '../data/electricity'; - -@Injectable() -export class ElectricityService extends ElectricityData { - - private listData: Electricity[] = [ - { - title: '2015', - months: [ - { month: 'Jan', delta: '0.97', down: true, kWatts: '816', cost: '97' }, - { month: 'Feb', delta: '1.83', down: true, kWatts: '806', cost: '95' }, - { month: 'Mar', delta: '0.64', down: true, kWatts: '803', cost: '94' }, - { month: 'Apr', delta: '2.17', down: false, kWatts: '818', cost: '98' }, - { month: 'May', delta: '1.32', down: true, kWatts: '809', cost: '96' }, - { month: 'Jun', delta: '0.05', down: true, kWatts: '808', cost: '96' }, - { month: 'Jul', delta: '1.39', down: false, kWatts: '815', cost: '97' }, - { month: 'Aug', delta: '0.73', down: true, kWatts: '807', cost: '95' }, - { month: 'Sept', delta: '2.61', down: true, kWatts: '792', cost: '92' }, - { month: 'Oct', delta: '0.16', down: true, kWatts: '791', cost: '92' }, - { month: 'Nov', delta: '1.71', down: true, kWatts: '786', cost: '89' }, - { month: 'Dec', delta: '0.37', down: false, kWatts: '789', cost: '91' }, - ], - }, - { - title: '2016', - active: true, - months: [ - { month: 'Jan', delta: '1.56', down: true, kWatts: '789', cost: '91' }, - { month: 'Feb', delta: '0.33', down: false, kWatts: '791', cost: '92' }, - { month: 'Mar', delta: '0.62', down: true, kWatts: '790', cost: '92' }, - { month: 'Apr', delta: '1.93', down: true, kWatts: '783', cost: '87' }, - { month: 'May', delta: '2.52', down: true, kWatts: '771', cost: '83' }, - { month: 'Jun', delta: '0.39', down: false, kWatts: '774', cost: '85' }, - { month: 'Jul', delta: '1.61', down: true, kWatts: '767', cost: '81' }, - { month: 'Aug', delta: '1.41', down: true, kWatts: '759', cost: '76' }, - { month: 'Sept', delta: '1.03', down: true, kWatts: '752', cost: '74' }, - { month: 'Oct', delta: '2.94', down: false, kWatts: '769', cost: '82' }, - { month: 'Nov', delta: '0.26', down: true, kWatts: '767', cost: '81' }, - { month: 'Dec', delta: '1.62', down: true, kWatts: '760', cost: '76' }, - ], - }, - { - title: '2017', - months: [ - { month: 'Jan', delta: '1.34', down: false, kWatts: '789', cost: '91' }, - { month: 'Feb', delta: '0.95', down: false, kWatts: '793', cost: '93' }, - { month: 'Mar', delta: '0.25', down: true, kWatts: '791', cost: '92' }, - { month: 'Apr', delta: '1.72', down: false, kWatts: '797', cost: '95' }, - { month: 'May', delta: '2.62', down: true, kWatts: '786', cost: '90' }, - { month: 'Jun', delta: '0.72', down: false, kWatts: '789', cost: '91' }, - { month: 'Jul', delta: '0.78', down: true, kWatts: '784', cost: '89' }, - { month: 'Aug', delta: '0.36', down: true, kWatts: '782', cost: '88' }, - { month: 'Sept', delta: '0.55', down: false, kWatts: '787', cost: '90' }, - { month: 'Oct', delta: '1.81', down: true, kWatts: '779', cost: '86' }, - { month: 'Nov', delta: '1.12', down: true, kWatts: '774', cost: '84' }, - { month: 'Dec', delta: '0.52', down: false, kWatts: '776', cost: '95' }, - ], - }, - ]; - - private chartPoints = [ - 490, 490, 495, 500, - 505, 510, 520, 530, - 550, 580, 630, 720, - 800, 840, 860, 870, - 870, 860, 840, 800, - 720, 200, 145, 130, - 130, 145, 200, 570, - 635, 660, 670, 670, - 660, 630, 580, 460, - 380, 350, 340, 340, - 340, 340, 340, 340, - 340, 340, 340, - ]; - - chartData: ElectricityChart[]; - - constructor() { - super(); - this.chartData = this.chartPoints.map((p, index) => ({ - label: (index % 5 === 3) ? `${Math.round(index / 5)}` : '', - value: p, - })); - } - - getListData(): Observable { - return observableOf(this.listData); - } - - getChartData(): Observable { - return observableOf(this.chartData); - } -} diff --git a/src/frontend/src/app/@core/mock/mock-data.module.ts b/src/frontend/src/app/@core/mock/mock-data.module.ts deleted file mode 100644 index a21c4d3..0000000 --- a/src/frontend/src/app/@core/mock/mock-data.module.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { NgModule, ModuleWithProviders } from '@angular/core'; -import { CommonModule } from '@angular/common'; - -import { UserService } from './users.service'; -import { ElectricityService } from './electricity.service'; -import { SmartTableService } from './smart-table.service'; -import { UserActivityService } from './user-activity.service'; -import { OrdersChartService } from './orders-chart.service'; -import { ProfitChartService } from './profit-chart.service'; -import { TrafficListService } from './traffic-list.service'; -import { PeriodsService } from './periods.service'; -import { EarningService } from './earning.service'; -import { OrdersProfitChartService } from './orders-profit-chart.service'; -import { TrafficBarService } from './traffic-bar.service'; -import { ProfitBarAnimationChartService } from './profit-bar-animation-chart.service'; -import { TemperatureHumidityService } from './temperature-humidity.service'; -import { SolarService } from './solar.service'; -import { TrafficChartService } from './traffic-chart.service'; -import { StatsBarService } from './stats-bar.service'; -import { CountryOrderService } from './country-order.service'; -import { StatsProgressBarService } from './stats-progress-bar.service'; -import { VisitorsAnalyticsService } from './visitors-analytics.service'; -import { SecurityCamerasService } from './security-cameras.service'; - -const SERVICES = [ - UserService, - ElectricityService, - SmartTableService, - UserActivityService, - OrdersChartService, - ProfitChartService, - TrafficListService, - PeriodsService, - EarningService, - OrdersProfitChartService, - TrafficBarService, - ProfitBarAnimationChartService, - TemperatureHumidityService, - SolarService, - TrafficChartService, - StatsBarService, - CountryOrderService, - StatsProgressBarService, - VisitorsAnalyticsService, - SecurityCamerasService, -]; - -@NgModule({ - imports: [ - CommonModule, - ], - providers: [ - ...SERVICES, - ], -}) -export class MockDataModule { - static forRoot(): ModuleWithProviders { - return { - ngModule: MockDataModule, - providers: [ - ...SERVICES, - ], - }; - } -} diff --git a/src/frontend/src/app/@core/mock/orders-chart.service.ts b/src/frontend/src/app/@core/mock/orders-chart.service.ts deleted file mode 100644 index 7b4c8e0..0000000 --- a/src/frontend/src/app/@core/mock/orders-chart.service.ts +++ /dev/null @@ -1,155 +0,0 @@ -import { Injectable } from '@angular/core'; -import { PeriodsService } from './periods.service'; -import { OrdersChart, OrdersChartData } from '../data/orders-chart'; - -@Injectable() -export class OrdersChartService extends OrdersChartData { - - private year = [ - '2012', - '2013', - '2014', - '2015', - '2016', - '2017', - '2018', - ]; - - private data = { }; - - constructor(private period: PeriodsService) { - super(); - this.data = { - week: this.getDataForWeekPeriod(), - month: this.getDataForMonthPeriod(), - year: this.getDataForYearPeriod(), - }; - } - - private getDataForWeekPeriod(): OrdersChart { - return { - chartLabel: this.getDataLabels(42, this.period.getWeeks()), - linesData: [ - [ - 184, 267, 326, 366, 389, 399, - 392, 371, 340, 304, 265, 227, - 191, 158, 130, 108, 95, 91, 97, - 109, 125, 144, 166, 189, 212, - 236, 259, 280, 300, 316, 329, - 338, 342, 339, 329, 312, 288, - 258, 221, 178, 128, 71, - ], - [ - 158, 178, 193, 205, 212, 213, - 204, 190, 180, 173, 168, 164, - 162, 160, 159, 158, 159, 166, - 179, 195, 215, 236, 257, 276, - 292, 301, 304, 303, 300, 293, - 284, 273, 262, 251, 241, 234, - 232, 232, 232, 232, 232, 232, - ], - [ - 58, 137, 202, 251, 288, 312, - 323, 324, 311, 288, 257, 222, - 187, 154, 124, 100, 81, 68, 61, - 58, 61, 69, 80, 96, 115, 137, - 161, 186, 210, 233, 254, 271, - 284, 293, 297, 297, 297, 297, - 297, 297, 297, 297, 297, - ], - ], - }; - } - - private getDataForMonthPeriod(): OrdersChart { - return { - chartLabel: this.getDataLabels(47, this.period.getMonths()), - linesData: [ - [ - 5, 63, 113, 156, 194, 225, - 250, 270, 283, 289, 290, - 286, 277, 264, 244, 220, - 194, 171, 157, 151, 150, - 152, 155, 160, 166, 170, - 167, 153, 135, 115, 97, - 82, 71, 64, 63, 62, 61, - 62, 65, 73, 84, 102, - 127, 159, 203, 259, 333, - ], - [ - 6, 83, 148, 200, 240, - 265, 273, 259, 211, - 122, 55, 30, 28, 36, - 50, 68, 88, 109, 129, - 146, 158, 163, 165, - 173, 187, 208, 236, - 271, 310, 346, 375, - 393, 400, 398, 387, - 368, 341, 309, 275, - 243, 220, 206, 202, - 207, 222, 247, 286, 348, - ], - [ - 398, 348, 315, 292, 274, - 261, 251, 243, 237, 231, - 222, 209, 192, 172, 152, - 132, 116, 102, 90, 80, 71, - 64, 58, 53, 49, 48, 54, 66, - 84, 104, 125, 142, 156, 166, - 172, 174, 172, 167, 159, 149, - 136, 121, 105, 86, 67, 45, 22, - ], - ], - }; - } - - private getDataForYearPeriod(): OrdersChart { - return { - chartLabel: this.getDataLabels(42, this.year), - linesData: [ - [ - 190, 269, 327, 366, 389, 398, - 396, 387, 375, 359, 343, 327, - 312, 298, 286, 276, 270, 268, - 265, 258, 247, 234, 220, 204, - 188, 172, 157, 142, 128, 116, - 106, 99, 95, 94, 92, 89, 84, - 77, 69, 60, 49, 36, 22, - ], - [ - 265, 307, 337, 359, 375, 386, - 393, 397, 399, 397, 390, 379, - 365, 347, 326, 305, 282, 261, - 241, 223, 208, 197, 190, 187, - 185, 181, 172, 160, 145, 126, - 105, 82, 60, 40, 26, 19, 22, - 43, 82, 141, 220, 321, - ], - [ - 9, 165, 236, 258, 244, 206, - 186, 189, 209, 239, 273, 307, - 339, 365, 385, 396, 398, 385, - 351, 300, 255, 221, 197, 181, - 170, 164, 162, 161, 159, 154, - 146, 135, 122, 108, 96, 87, - 83, 82, 82, 82, 82, 82, 82, - ], - ], - }; - } - - getDataLabels(nPoints: number, labelsArray: string[]): string[] { - const labelsArrayLength = labelsArray.length; - const step = Math.round(nPoints / labelsArrayLength); - - return Array.from(Array(nPoints)).map((item, index) => { - const dataIndex = Math.round(index / step); - - return index % step === 0 ? labelsArray[dataIndex] : ''; - }); - } - - getOrdersChartData(period: string): OrdersChart { - return this.data[period]; - } -} diff --git a/src/frontend/src/app/@core/mock/orders-profit-chart.service.ts b/src/frontend/src/app/@core/mock/orders-profit-chart.service.ts deleted file mode 100644 index 88bf996..0000000 --- a/src/frontend/src/app/@core/mock/orders-profit-chart.service.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { of as observableOf, Observable } from 'rxjs'; -import { Injectable } from '@angular/core'; -import { OrdersChart, OrdersChartData } from '../data/orders-chart'; -import { OrderProfitChartSummary, OrdersProfitChartData } from '../data/orders-profit-chart'; -import { ProfitChart, ProfitChartData } from '../data/profit-chart'; - -@Injectable() -export class OrdersProfitChartService extends OrdersProfitChartData { - - private summary = [ - { - title: 'Marketplace', - value: 3654, - }, - { - title: 'Last Month', - value: 946, - }, - { - title: 'Last Week', - value: 654, - }, - { - title: 'Today', - value: 230, - }, - ]; - - constructor(private ordersChartService: OrdersChartData, - private profitChartService: ProfitChartData) { - super(); - } - - getOrderProfitChartSummary(): Observable { - return observableOf(this.summary); - } - - getOrdersChartData(period: string): Observable { - return observableOf(this.ordersChartService.getOrdersChartData(period)); - } - - getProfitChartData(period: string): Observable { - return observableOf(this.profitChartService.getProfitChartData(period)); - } -} diff --git a/src/frontend/src/app/@core/mock/periods.service.ts b/src/frontend/src/app/@core/mock/periods.service.ts deleted file mode 100644 index a097842..0000000 --- a/src/frontend/src/app/@core/mock/periods.service.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Injectable } from '@angular/core'; - -@Injectable() -export class PeriodsService { - getYears() { - return [ - '2010', '2011', '2012', - '2013', '2014', '2015', - '2016', '2017', '2018', - ]; - } - - getMonths() { - return [ - 'Jan', 'Feb', 'Mar', - 'Apr', 'May', 'Jun', - 'Jul', 'Aug', 'Sep', - 'Oct', 'Nov', 'Dec', - ]; - } - - getWeeks() { - return [ - 'Mon', - 'Tue', - 'Wed', - 'Thu', - 'Fri', - 'Sat', - 'Sun', - ]; - } -} diff --git a/src/frontend/src/app/@core/mock/profit-bar-animation-chart.service.ts b/src/frontend/src/app/@core/mock/profit-bar-animation-chart.service.ts deleted file mode 100644 index e632261..0000000 --- a/src/frontend/src/app/@core/mock/profit-bar-animation-chart.service.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Injectable } from '@angular/core'; -import { of as observableOf, Observable } from 'rxjs'; -import { ProfitBarAnimationChartData } from '../data/profit-bar-animation-chart'; - -@Injectable() -export class ProfitBarAnimationChartService extends ProfitBarAnimationChartData { - - private data: any; - - constructor() { - super(); - this.data = { - firstLine: this.getDataForFirstLine(), - secondLine: this.getDataForSecondLine(), - }; - } - - getDataForFirstLine(): number[] { - return this.createEmptyArray(100) - .map((_, index) => { - const oneFifth = index / 5; - - return (Math.sin(oneFifth) * (oneFifth - 10) + index / 6) * 5; - }); - } - - getDataForSecondLine(): number[] { - return this.createEmptyArray(100) - .map((_, index) => { - const oneFifth = index / 5; - - return (Math.cos(oneFifth) * (oneFifth - 10) + index / 6) * 5; - }); - } - - createEmptyArray(nPoints: number) { - return Array.from(Array(nPoints)); - } - - getChartData(): Observable<{ firstLine: number[]; secondLine: number[]; }> { - return observableOf(this.data); - } -} diff --git a/src/frontend/src/app/@core/mock/profit-chart.service.ts b/src/frontend/src/app/@core/mock/profit-chart.service.ts deleted file mode 100644 index 5d99545..0000000 --- a/src/frontend/src/app/@core/mock/profit-chart.service.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { Injectable } from '@angular/core'; -import { PeriodsService } from './periods.service'; -import { ProfitChart, ProfitChartData } from '../data/profit-chart'; - -@Injectable() -export class ProfitChartService extends ProfitChartData { - - private year = [ - '2012', - '2013', - '2014', - '2015', - '2016', - '2017', - '2018', - ]; - - private data = { }; - - constructor(private period: PeriodsService) { - super(); - this.data = { - week: this.getDataForWeekPeriod(), - month: this.getDataForMonthPeriod(), - year: this.getDataForYearPeriod(), - }; - } - - private getDataForWeekPeriod(): ProfitChart { - const nPoint = this.period.getWeeks().length; - - return { - chartLabel: this.period.getWeeks(), - data: [ - this.getRandomData(nPoint), - this.getRandomData(nPoint), - this.getRandomData(nPoint), - ], - }; - } - - private getDataForMonthPeriod(): ProfitChart { - const nPoint = this.period.getMonths().length; - - return { - chartLabel: this.period.getMonths(), - data: [ - this.getRandomData(nPoint), - this.getRandomData(nPoint), - this.getRandomData(nPoint), - ], - }; - } - - private getDataForYearPeriod(): ProfitChart { - const nPoint = this.year.length; - - return { - chartLabel: this.year, - data: [ - this.getRandomData(nPoint), - this.getRandomData(nPoint), - this.getRandomData(nPoint), - ], - }; - } - - private getRandomData(nPoints: number): number[] { - return Array.from(Array(nPoints)).map(() => { - return Math.round(Math.random() * 500); - }); - } - - getProfitChartData(period: string): ProfitChart { - return this.data[period]; - } -} diff --git a/src/frontend/src/app/@core/mock/security-cameras.service.ts b/src/frontend/src/app/@core/mock/security-cameras.service.ts deleted file mode 100644 index b96b250..0000000 --- a/src/frontend/src/app/@core/mock/security-cameras.service.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Injectable } from '@angular/core'; -import { of as observableOf, Observable } from 'rxjs'; -import { Camera, SecurityCamerasData } from '../data/security-cameras'; - -@Injectable() -export class SecurityCamerasService extends SecurityCamerasData { - - private cameras: Camera[] = [ - { - title: 'Camera #1', - source: 'assets/images/camera1.jpg', - }, - { - title: 'Camera #2', - source: 'assets/images/camera2.jpg', - }, - { - title: 'Camera #3', - source: 'assets/images/camera3.jpg', - }, - { - title: 'Camera #4', - source: 'assets/images/camera4.jpg', - }, - ]; - - getCamerasData(): Observable { - return observableOf(this.cameras); - } -} diff --git a/src/frontend/src/app/@core/mock/smart-table.service.ts b/src/frontend/src/app/@core/mock/smart-table.service.ts deleted file mode 100644 index 3227f0f..0000000 --- a/src/frontend/src/app/@core/mock/smart-table.service.ts +++ /dev/null @@ -1,432 +0,0 @@ -import { Injectable } from '@angular/core'; -import { SmartTableData } from '../data/smart-table'; - -@Injectable() -export class SmartTableService extends SmartTableData { - - data = [{ - id: 1, - firstName: 'Mark', - lastName: 'Otto', - username: '@mdo', - email: 'mdo@gmail.com', - age: '28', - }, { - id: 2, - firstName: 'Jacob', - lastName: 'Thornton', - username: '@fat', - email: 'fat@yandex.ru', - age: '45', - }, { - id: 3, - firstName: 'Larry', - lastName: 'Bird', - username: '@twitter', - email: 'twitter@outlook.com', - age: '18', - }, { - id: 4, - firstName: 'John', - lastName: 'Snow', - username: '@snow', - email: 'snow@gmail.com', - age: '20', - }, { - id: 5, - firstName: 'Jack', - lastName: 'Sparrow', - username: '@jack', - email: 'jack@yandex.ru', - age: '30', - }, { - id: 6, - firstName: 'Ann', - lastName: 'Smith', - username: '@ann', - email: 'ann@gmail.com', - age: '21', - }, { - id: 7, - firstName: 'Barbara', - lastName: 'Black', - username: '@barbara', - email: 'barbara@yandex.ru', - age: '43', - }, { - id: 8, - firstName: 'Sevan', - lastName: 'Bagrat', - username: '@sevan', - email: 'sevan@outlook.com', - age: '13', - }, { - id: 9, - firstName: 'Ruben', - lastName: 'Vardan', - username: '@ruben', - email: 'ruben@gmail.com', - age: '22', - }, { - id: 10, - firstName: 'Karen', - lastName: 'Sevan', - username: '@karen', - email: 'karen@yandex.ru', - age: '33', - }, { - id: 11, - firstName: 'Mark', - lastName: 'Otto', - username: '@mark', - email: 'mark@gmail.com', - age: '38', - }, { - id: 12, - firstName: 'Jacob', - lastName: 'Thornton', - username: '@jacob', - email: 'jacob@yandex.ru', - age: '48', - }, { - id: 13, - firstName: 'Haik', - lastName: 'Hakob', - username: '@haik', - email: 'haik@outlook.com', - age: '48', - }, { - id: 14, - firstName: 'Garegin', - lastName: 'Jirair', - username: '@garegin', - email: 'garegin@gmail.com', - age: '40', - }, { - id: 15, - firstName: 'Krikor', - lastName: 'Bedros', - username: '@krikor', - email: 'krikor@yandex.ru', - age: '32', - }, { - 'id': 16, - 'firstName': 'Francisca', - 'lastName': 'Brady', - 'username': '@Gibson', - 'email': 'franciscagibson@comtours.com', - 'age': 11, - }, { - 'id': 17, - 'firstName': 'Tillman', - 'lastName': 'Figueroa', - 'username': '@Snow', - 'email': 'tillmansnow@comtours.com', - 'age': 34, - }, { - 'id': 18, - 'firstName': 'Jimenez', - 'lastName': 'Morris', - 'username': '@Bryant', - 'email': 'jimenezbryant@comtours.com', - 'age': 45, - }, { - 'id': 19, - 'firstName': 'Sandoval', - 'lastName': 'Jacobson', - 'username': '@Mcbride', - 'email': 'sandovalmcbride@comtours.com', - 'age': 32, - }, { - 'id': 20, - 'firstName': 'Griffin', - 'lastName': 'Torres', - 'username': '@Charles', - 'email': 'griffincharles@comtours.com', - 'age': 19, - }, { - 'id': 21, - 'firstName': 'Cora', - 'lastName': 'Parker', - 'username': '@Caldwell', - 'email': 'coracaldwell@comtours.com', - 'age': 27, - }, { - 'id': 22, - 'firstName': 'Cindy', - 'lastName': 'Bond', - 'username': '@Velez', - 'email': 'cindyvelez@comtours.com', - 'age': 24, - }, { - 'id': 23, - 'firstName': 'Frieda', - 'lastName': 'Tyson', - 'username': '@Craig', - 'email': 'friedacraig@comtours.com', - 'age': 45, - }, { - 'id': 24, - 'firstName': 'Cote', - 'lastName': 'Holcomb', - 'username': '@Rowe', - 'email': 'coterowe@comtours.com', - 'age': 20, - }, { - 'id': 25, - 'firstName': 'Trujillo', - 'lastName': 'Mejia', - 'username': '@Valenzuela', - 'email': 'trujillovalenzuela@comtours.com', - 'age': 16, - }, { - 'id': 26, - 'firstName': 'Pruitt', - 'lastName': 'Shepard', - 'username': '@Sloan', - 'email': 'pruittsloan@comtours.com', - 'age': 44, - }, { - 'id': 27, - 'firstName': 'Sutton', - 'lastName': 'Ortega', - 'username': '@Black', - 'email': 'suttonblack@comtours.com', - 'age': 42, - }, { - 'id': 28, - 'firstName': 'Marion', - 'lastName': 'Heath', - 'username': '@Espinoza', - 'email': 'marionespinoza@comtours.com', - 'age': 47, - }, { - 'id': 29, - 'firstName': 'Newman', - 'lastName': 'Hicks', - 'username': '@Keith', - 'email': 'newmankeith@comtours.com', - 'age': 15, - }, { - 'id': 30, - 'firstName': 'Boyle', - 'lastName': 'Larson', - 'username': '@Summers', - 'email': 'boylesummers@comtours.com', - 'age': 32, - }, { - 'id': 31, - 'firstName': 'Haynes', - 'lastName': 'Vinson', - 'username': '@Mckenzie', - 'email': 'haynesmckenzie@comtours.com', - 'age': 15, - }, { - 'id': 32, - 'firstName': 'Miller', - 'lastName': 'Acosta', - 'username': '@Young', - 'email': 'milleryoung@comtours.com', - 'age': 55, - }, { - 'id': 33, - 'firstName': 'Johnston', - 'lastName': 'Brown', - 'username': '@Knight', - 'email': 'johnstonknight@comtours.com', - 'age': 29, - }, { - 'id': 34, - 'firstName': 'Lena', - 'lastName': 'Pitts', - 'username': '@Forbes', - 'email': 'lenaforbes@comtours.com', - 'age': 25, - }, { - 'id': 35, - 'firstName': 'Terrie', - 'lastName': 'Kennedy', - 'username': '@Branch', - 'email': 'terriebranch@comtours.com', - 'age': 37, - }, { - 'id': 36, - 'firstName': 'Louise', - 'lastName': 'Aguirre', - 'username': '@Kirby', - 'email': 'louisekirby@comtours.com', - 'age': 44, - }, { - 'id': 37, - 'firstName': 'David', - 'lastName': 'Patton', - 'username': '@Sanders', - 'email': 'davidsanders@comtours.com', - 'age': 26, - }, { - 'id': 38, - 'firstName': 'Holden', - 'lastName': 'Barlow', - 'username': '@Mckinney', - 'email': 'holdenmckinney@comtours.com', - 'age': 11, - }, { - 'id': 39, - 'firstName': 'Baker', - 'lastName': 'Rivera', - 'username': '@Montoya', - 'email': 'bakermontoya@comtours.com', - 'age': 47, - }, { - 'id': 40, - 'firstName': 'Belinda', - 'lastName': 'Lloyd', - 'username': '@Calderon', - 'email': 'belindacalderon@comtours.com', - 'age': 21, - }, { - 'id': 41, - 'firstName': 'Pearson', - 'lastName': 'Patrick', - 'username': '@Clements', - 'email': 'pearsonclements@comtours.com', - 'age': 42, - }, { - 'id': 42, - 'firstName': 'Alyce', - 'lastName': 'Mckee', - 'username': '@Daugherty', - 'email': 'alycedaugherty@comtours.com', - 'age': 55, - }, { - 'id': 43, - 'firstName': 'Valencia', - 'lastName': 'Spence', - 'username': '@Olsen', - 'email': 'valenciaolsen@comtours.com', - 'age': 20, - }, { - 'id': 44, - 'firstName': 'Leach', - 'lastName': 'Holcomb', - 'username': '@Humphrey', - 'email': 'leachhumphrey@comtours.com', - 'age': 28, - }, { - 'id': 45, - 'firstName': 'Moss', - 'lastName': 'Baxter', - 'username': '@Fitzpatrick', - 'email': 'mossfitzpatrick@comtours.com', - 'age': 51, - }, { - 'id': 46, - 'firstName': 'Jeanne', - 'lastName': 'Cooke', - 'username': '@Ward', - 'email': 'jeanneward@comtours.com', - 'age': 59, - }, { - 'id': 47, - 'firstName': 'Wilma', - 'lastName': 'Briggs', - 'username': '@Kidd', - 'email': 'wilmakidd@comtours.com', - 'age': 53, - }, { - 'id': 48, - 'firstName': 'Beatrice', - 'lastName': 'Perry', - 'username': '@Gilbert', - 'email': 'beatricegilbert@comtours.com', - 'age': 39, - }, { - 'id': 49, - 'firstName': 'Whitaker', - 'lastName': 'Hyde', - 'username': '@Mcdonald', - 'email': 'whitakermcdonald@comtours.com', - 'age': 35, - }, { - 'id': 50, - 'firstName': 'Rebekah', - 'lastName': 'Duran', - 'username': '@Gross', - 'email': 'rebekahgross@comtours.com', - 'age': 40, - }, { - 'id': 51, - 'firstName': 'Earline', - 'lastName': 'Mayer', - 'username': '@Woodward', - 'email': 'earlinewoodward@comtours.com', - 'age': 52, - }, { - 'id': 52, - 'firstName': 'Moran', - 'lastName': 'Baxter', - 'username': '@Johns', - 'email': 'moranjohns@comtours.com', - 'age': 20, - }, { - 'id': 53, - 'firstName': 'Nanette', - 'lastName': 'Hubbard', - 'username': '@Cooke', - 'email': 'nanettecooke@comtours.com', - 'age': 55, - }, { - 'id': 54, - 'firstName': 'Dalton', - 'lastName': 'Walker', - 'username': '@Hendricks', - 'email': 'daltonhendricks@comtours.com', - 'age': 25, - }, { - 'id': 55, - 'firstName': 'Bennett', - 'lastName': 'Blake', - 'username': '@Pena', - 'email': 'bennettpena@comtours.com', - 'age': 13, - }, { - 'id': 56, - 'firstName': 'Kellie', - 'lastName': 'Horton', - 'username': '@Weiss', - 'email': 'kellieweiss@comtours.com', - 'age': 48, - }, { - 'id': 57, - 'firstName': 'Hobbs', - 'lastName': 'Talley', - 'username': '@Sanford', - 'email': 'hobbssanford@comtours.com', - 'age': 28, - }, { - 'id': 58, - 'firstName': 'Mcguire', - 'lastName': 'Donaldson', - 'username': '@Roman', - 'email': 'mcguireroman@comtours.com', - 'age': 38, - }, { - 'id': 59, - 'firstName': 'Rodriquez', - 'lastName': 'Saunders', - 'username': '@Harper', - 'email': 'rodriquezharper@comtours.com', - 'age': 20, - }, { - 'id': 60, - 'firstName': 'Lou', - 'lastName': 'Conner', - 'username': '@Sanchez', - 'email': 'lousanchez@comtours.com', - 'age': 16, - }]; - - getData() { - return this.data; - } -} diff --git a/src/frontend/src/app/@core/mock/solar.service.ts b/src/frontend/src/app/@core/mock/solar.service.ts deleted file mode 100644 index 97df9dd..0000000 --- a/src/frontend/src/app/@core/mock/solar.service.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Injectable } from '@angular/core'; -import { of as observableOf, Observable } from 'rxjs'; -import { SolarData } from '../data/solar'; - -@Injectable() -export class SolarService extends SolarData { - private value = 42; - - getSolarData(): Observable { - return observableOf(this.value); - } -} diff --git a/src/frontend/src/app/@core/mock/stats-bar.service.ts b/src/frontend/src/app/@core/mock/stats-bar.service.ts deleted file mode 100644 index 736148c..0000000 --- a/src/frontend/src/app/@core/mock/stats-bar.service.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Injectable } from '@angular/core'; -import { of as observableOf, Observable } from 'rxjs'; -import { StatsBarData } from '../data/stats-bar'; - -@Injectable() -export class StatsBarService extends StatsBarData { - - private statsBarData: number[] = [ - 300, 520, 435, 530, - 730, 620, 660, 860, - ]; - - getStatsBarData(): Observable { - return observableOf(this.statsBarData); - } -} diff --git a/src/frontend/src/app/@core/mock/stats-progress-bar.service.ts b/src/frontend/src/app/@core/mock/stats-progress-bar.service.ts deleted file mode 100644 index 27af689..0000000 --- a/src/frontend/src/app/@core/mock/stats-progress-bar.service.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Injectable } from '@angular/core'; -import { of as observableOf, Observable } from 'rxjs'; -import { ProgressInfo, StatsProgressBarData } from '../data/stats-progress-bar'; - -@Injectable() -export class StatsProgressBarService extends StatsProgressBarData { - private progressInfoData: ProgressInfo[] = [ - { - title: 'Today’s Profit', - value: 572900, - activeProgress: 70, - description: 'Better than last week (70%)', - }, - { - title: 'New Orders', - value: 6378, - activeProgress: 30, - description: 'Better than last week (30%)', - }, - { - title: 'New Comments', - value: 200, - activeProgress: 55, - description: 'Better than last week (55%)', - }, - ]; - - getProgressInfoData(): Observable { - return observableOf(this.progressInfoData); - } -} diff --git a/src/frontend/src/app/@core/mock/temperature-humidity.service.ts b/src/frontend/src/app/@core/mock/temperature-humidity.service.ts deleted file mode 100644 index fc22743..0000000 --- a/src/frontend/src/app/@core/mock/temperature-humidity.service.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Injectable } from '@angular/core'; -import { of as observableOf, Observable } from 'rxjs'; -import { TemperatureHumidityData, Temperature } from '../data/temperature-humidity'; - -@Injectable() -export class TemperatureHumidityService extends TemperatureHumidityData { - - private temperatureDate: Temperature = { - value: 24, - min: 12, - max: 30, - }; - - private humidityDate: Temperature = { - value: 87, - min: 0, - max: 100, - }; - - getTemperatureData(): Observable { - return observableOf(this.temperatureDate); - } - - getHumidityData(): Observable { - return observableOf(this.humidityDate); - } -} diff --git a/src/frontend/src/app/@core/mock/traffic-bar.service.ts b/src/frontend/src/app/@core/mock/traffic-bar.service.ts deleted file mode 100644 index 4ce0005..0000000 --- a/src/frontend/src/app/@core/mock/traffic-bar.service.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Injectable } from '@angular/core'; -import { of as observableOf, Observable } from 'rxjs'; -import { PeriodsService } from './periods.service'; -import { TrafficBarData, TrafficBar } from '../data/traffic-bar'; - -@Injectable() -export class TrafficBarService extends TrafficBarData { - - private data = { }; - - constructor(private period: PeriodsService) { - super(); - this.data = { - week: this.getDataForWeekPeriod(), - month: this.getDataForMonthPeriod(), - year: this.getDataForYearPeriod(), - }; - } - - getDataForWeekPeriod(): TrafficBar { - return { - data: [10, 15, 19, 7, 20, 13, 15], - labels: this.period.getWeeks(), - formatter: '{c0} MB', - }; - } - - getDataForMonthPeriod(): TrafficBar { - return { - data: [0.5, 0.3, 0.8, 0.2, 0.3, 0.7, 0.8, 1, 0.7, 0.8, 0.6, 0.7], - labels: this.period.getMonths(), - formatter: '{c0} GB', - }; - } - - getDataForYearPeriod(): TrafficBar { - return { - data: [10, 15, 19, 7, 20, 13, 15, 19, 11], - labels: this.period.getYears(), - formatter: '{c0} GB', - }; - } - - getTrafficBarData(period: string): Observable { - return observableOf(this.data[period]); - } -} diff --git a/src/frontend/src/app/@core/mock/traffic-chart.service.ts b/src/frontend/src/app/@core/mock/traffic-chart.service.ts deleted file mode 100644 index 95b7d4d..0000000 --- a/src/frontend/src/app/@core/mock/traffic-chart.service.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Injectable } from '@angular/core'; -import { of as observableOf, Observable } from 'rxjs'; -import { TrafficChartData } from '../data/traffic-chart'; - -@Injectable() -export class TrafficChartService extends TrafficChartData { - - private data: number[] = [ - 300, 520, 435, 530, - 730, 620, 660, 860, - ]; - - getTrafficChartData(): Observable { - return observableOf(this.data); - } -} diff --git a/src/frontend/src/app/@core/mock/traffic-list.service.ts b/src/frontend/src/app/@core/mock/traffic-list.service.ts deleted file mode 100644 index 369aa33..0000000 --- a/src/frontend/src/app/@core/mock/traffic-list.service.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { Injectable } from '@angular/core'; -import { of as observableOf, Observable } from 'rxjs'; -import { PeriodsService } from './periods.service'; -import { TrafficList, TrafficListData } from '../data/traffic-list'; - -@Injectable() -export class TrafficListService extends TrafficListData { - - private getRandom = (roundTo: number) => Math.round(Math.random() * roundTo); - private data = {}; - - constructor(private period: PeriodsService) { - super(); - this.data = { - week: this.getDataWeek(), - month: this.getDataMonth(), - year: this.getDataYear(), - }; - } - - private getDataWeek(): TrafficList[] { - const getFirstDateInPeriod = () => { - const weeks = this.period.getWeeks(); - - return weeks[weeks.length - 1]; - }; - - return this.reduceData(this.period.getWeeks(), getFirstDateInPeriod); - } - - private getDataMonth(): TrafficList[] { - const getFirstDateInPeriod = () => { - const months = this.period.getMonths(); - - return months[months.length - 1]; - }; - - return this.reduceData(this.period.getMonths(), getFirstDateInPeriod); - } - - private getDataYear(): TrafficList[] { - const getFirstDateInPeriod = () => { - const years = this.period.getYears(); - - return `${parseInt(years[0], 10) - 1}`; - }; - - return this.reduceData(this.period.getYears(), getFirstDateInPeriod); - } - - private reduceData(timePeriods: string[], getFirstDateInPeriod: () => string): TrafficList[] { - return timePeriods.reduce((result, timePeriod, index) => { - const hasResult = result[index - 1]; - const prevDate = hasResult ? - result[index - 1].comparison.nextDate : - getFirstDateInPeriod(); - const prevValue = hasResult ? - result[index - 1].comparison.nextValue : - this.getRandom(100); - const nextValue = this.getRandom(100); - const deltaValue = prevValue - nextValue; - - const item = { - date: timePeriod, - value: this.getRandom(1000), - delta: { - up: deltaValue <= 0, - value: Math.abs(deltaValue), - }, - comparison: { - prevDate, - prevValue, - nextDate: timePeriod, - nextValue, - }, - }; - - return [...result, item]; - }, []); - } - - getTrafficListData(period: string): Observable { - return observableOf(this.data[period]); - } -} diff --git a/src/frontend/src/app/@core/mock/user-activity.service.ts b/src/frontend/src/app/@core/mock/user-activity.service.ts deleted file mode 100644 index fff78a9..0000000 --- a/src/frontend/src/app/@core/mock/user-activity.service.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { Injectable } from '@angular/core'; -import { of as observableOf, Observable } from 'rxjs'; -import { PeriodsService } from './periods.service'; -import { UserActive, UserActivityData } from '../data/user-activity'; - -@Injectable() -export class UserActivityService extends UserActivityData { - - private getRandom = (roundTo: number) => Math.round(Math.random() * roundTo); - private generateUserActivityRandomData(date) { - return { - date, - pagesVisitCount: this.getRandom(1000), - deltaUp: this.getRandom(1) % 2 === 0, - newVisits: this.getRandom(100), - }; - } - - data = {}; - - constructor(private periods: PeriodsService) { - super(); - this.data = { - week: this.getDataWeek(), - month: this.getDataMonth(), - year: this.getDataYear(), - }; - } - - private getDataWeek(): UserActive[] { - return this.periods.getWeeks().map((week) => { - return this.generateUserActivityRandomData(week); - }); - } - - private getDataMonth(): UserActive[] { - const currentDate = new Date(); - const days = currentDate.getDate(); - const month = this.periods.getMonths()[currentDate.getMonth()]; - - return Array.from(Array(days)).map((_, index) => { - const date = `${index + 1} ${month}`; - - return this.generateUserActivityRandomData(date); - }); - } - - private getDataYear(): UserActive[] { - return this.periods.getYears().map((year) => { - return this.generateUserActivityRandomData(year); - }); - } - - getUserActivityData(period: string): Observable { - return observableOf(this.data[period]); - } -} diff --git a/src/frontend/src/app/@core/mock/users.service.ts b/src/frontend/src/app/@core/mock/users.service.ts deleted file mode 100644 index 8c748ce..0000000 --- a/src/frontend/src/app/@core/mock/users.service.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { of as observableOf, Observable } from 'rxjs'; -import { Injectable } from '@angular/core'; -import { Contacts, RecentUsers, UserData } from '../data/users'; - -@Injectable() -export class UserService extends UserData { - - private time: Date = new Date; - - private users = { - nick: { name: 'Nick Jones', picture: 'assets/images/nick.png' }, - eva: { name: 'Eva Moor', picture: 'assets/images/eva.png' }, - jack: { name: 'Jack Williams', picture: 'assets/images/jack.png' }, - lee: { name: 'Lee Wong', picture: 'assets/images/lee.png' }, - alan: { name: 'Alan Thompson', picture: 'assets/images/alan.png' }, - kate: { name: 'Kate Martinez', picture: 'assets/images/kate.png' }, - }; - private types = { - mobile: 'mobile', - home: 'home', - work: 'work', - }; - private contacts: Contacts[] = [ - { user: this.users.nick, type: this.types.mobile }, - { user: this.users.eva, type: this.types.home }, - { user: this.users.jack, type: this.types.mobile }, - { user: this.users.lee, type: this.types.mobile }, - { user: this.users.alan, type: this.types.home }, - { user: this.users.kate, type: this.types.work }, - ]; - private recentUsers: RecentUsers[] = [ - { user: this.users.alan, type: this.types.home, time: this.time.setHours(21, 12)}, - { user: this.users.eva, type: this.types.home, time: this.time.setHours(17, 45)}, - { user: this.users.nick, type: this.types.mobile, time: this.time.setHours(5, 29)}, - { user: this.users.lee, type: this.types.mobile, time: this.time.setHours(11, 24)}, - { user: this.users.jack, type: this.types.mobile, time: this.time.setHours(10, 45)}, - { user: this.users.kate, type: this.types.work, time: this.time.setHours(9, 42)}, - { user: this.users.kate, type: this.types.work, time: this.time.setHours(9, 31)}, - { user: this.users.jack, type: this.types.mobile, time: this.time.setHours(8, 0)}, - ]; - - getUsers(): Observable { - return observableOf(this.users); - } - - getContacts(): Observable { - return observableOf(this.contacts); - } - - getRecentUsers(): Observable { - return observableOf(this.recentUsers); - } -} diff --git a/src/frontend/src/app/@core/mock/visitors-analytics.service.ts b/src/frontend/src/app/@core/mock/visitors-analytics.service.ts deleted file mode 100644 index f221b26..0000000 --- a/src/frontend/src/app/@core/mock/visitors-analytics.service.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { Injectable } from '@angular/core'; -import { of as observableOf, Observable } from 'rxjs'; -import { PeriodsService } from './periods.service'; -import { OutlineData, VisitorsAnalyticsData } from '../data/visitors-analytics'; - -@Injectable() -export class VisitorsAnalyticsService extends VisitorsAnalyticsData { - - constructor(private periodService: PeriodsService) { - super(); - } - - private pieChartValue = 75; - private innerLinePoints: number[] = [ - 94, 188, 225, 244, 253, 254, 249, 235, 208, - 173, 141, 118, 105, 97, 94, 96, 104, 121, 147, - 183, 224, 265, 302, 333, 358, 375, 388, 395, - 400, 400, 397, 390, 377, 360, 338, 310, 278, - 241, 204, 166, 130, 98, 71, 49, 32, 20, 13, 9, - ]; - private outerLinePoints: number[] = [ - 85, 71, 59, 50, 45, 42, 41, 44 , 58, 88, - 136 , 199, 267, 326, 367, 391, 400, 397, - 376, 319, 200, 104, 60, 41, 36, 37, 44, - 55, 74, 100 , 131, 159, 180, 193, 199, 200, - 195, 184, 164, 135, 103, 73, 50, 33, 22, 15, 11, - ]; - private generateOutlineLineData(): OutlineData[] { - const months = this.periodService.getMonths(); - const outerLinePointsLength = this.outerLinePoints.length; - const monthsLength = months.length; - - return this.outerLinePoints.map((p, index) => { - const monthIndex = Math.round(index / 4); - const label = (index % Math.round(outerLinePointsLength / monthsLength) === 0) - ? months[monthIndex] - : ''; - - return { - label, - value: p, - }; - }); - } - - getInnerLineChartData(): Observable { - return observableOf(this.innerLinePoints); - } - - getOutlineLineChartData(): Observable { - return observableOf(this.generateOutlineLineData()); - } - - getPieChartData(): Observable { - return observableOf(this.pieChartValue); - } -} diff --git a/src/frontend/src/app/@theme/components/footer/footer.component.ts b/src/frontend/src/app/@theme/components/footer/footer.component.ts index c0b8d53..7772138 100644 --- a/src/frontend/src/app/@theme/components/footer/footer.component.ts +++ b/src/frontend/src/app/@theme/components/footer/footer.component.ts @@ -6,10 +6,7 @@ import { Component } from '@angular/core'; template: ` Created with ♥ by Akveo 2019
- - - - +
`, }) diff --git a/src/frontend/src/app/@theme/components/header/header.component.html b/src/frontend/src/app/@theme/components/header/header.component.html index 6fdc5d3..4b98418 100644 --- a/src/frontend/src/app/@theme/components/header/header.component.html +++ b/src/frontend/src/app/@theme/components/header/header.component.html @@ -3,11 +3,8 @@ - + - - {{ theme.name }} -
@@ -18,7 +15,7 @@ - + this.user = users.nick); - + .subscribe((users: any) => this.user = users.lee); + */ + const { xl } = this.breakpointService.getBreakpointsMap(); this.themeService.onMediaQueryChange() .pipe( diff --git a/src/frontend/src/app/@theme/theme.module.ts b/src/frontend/src/app/@theme/theme.module.ts index 5ae45d8..2a8a700 100644 --- a/src/frontend/src/app/@theme/theme.module.ts +++ b/src/frontend/src/app/@theme/theme.module.ts @@ -82,7 +82,7 @@ export class ThemeModule { providers: [ ...NbThemeModule.forRoot( { - name: 'default', + name: 'dark', }, [ DEFAULT_THEME, COSMIC_THEME, CORPORATE_THEME, DARK_THEME ], ).providers, diff --git a/src/frontend/src/app/app-routing.module.ts b/src/frontend/src/app/app-routing.module.ts index e6de7fe..b84eef2 100644 --- a/src/frontend/src/app/app-routing.module.ts +++ b/src/frontend/src/app/app-routing.module.ts @@ -1,7 +1,6 @@ import { ExtraOptions, RouterModule, Routes } from '@angular/router'; import { NgModule } from '@angular/core'; import { - NbAuthComponent, NbLoginComponent, NbLogoutComponent, NbRegisterComponent, @@ -12,39 +11,10 @@ import { const routes: Routes = [ { path: 'pages', - loadChildren: () => import('app/pages/pages.module') + loadChildren: () => import('./pages/pages.module') .then(m => m.PagesModule), }, - { - path: 'auth', - component: NbAuthComponent, - children: [ - { - path: '', - component: NbLoginComponent, - }, - { - path: 'login', - component: NbLoginComponent, - }, - { - path: 'register', - component: NbRegisterComponent, - }, - { - path: 'logout', - component: NbLogoutComponent, - }, - { - path: 'request-password', - component: NbRequestPasswordComponent, - }, - { - path: 'reset-password', - component: NbResetPasswordComponent, - }, - ], - }, + { path: '', redirectTo: 'pages', pathMatch: 'full' }, { path: '**', redirectTo: 'pages' }, ]; diff --git a/src/frontend/src/app/app.component.ts b/src/frontend/src/app/app.component.ts index 925cad6..d9e24c9 100644 --- a/src/frontend/src/app/app.component.ts +++ b/src/frontend/src/app/app.component.ts @@ -5,6 +5,7 @@ */ import { Component, OnInit } from '@angular/core'; import { AnalyticsService } from './@core/utils/analytics.service'; +import { LoginApiService } from './frontcraft/login-api'; @Component({ selector: 'ngx-app', @@ -12,11 +13,12 @@ import { AnalyticsService } from './@core/utils/analytics.service'; }) export class AppComponent implements OnInit { - constructor(private analytics: AnalyticsService) { + constructor(private loginSvc: LoginApiService, private analytics: AnalyticsService) { } ngOnInit(): void { this.analytics.trackPageViews(); + window['s'] = this.loginSvc } } diff --git a/src/frontend/src/app/frontcraft/login-api.ts b/src/frontend/src/app/frontcraft/login-api.ts new file mode 100644 index 0000000..df78391 --- /dev/null +++ b/src/frontend/src/app/frontcraft/login-api.ts @@ -0,0 +1,95 @@ +import { Injectable } from "@angular/core"; +import {RPCSocket} from 'rpclibrary/js/src/Frontend' + +import { Token, Auth, User, _Rank, _Class, FrontcraftFeatureIfc, LoginManagerIfc, } from '../../../../backend/Types/Types' +import { CookieService } from 'ngx-cookie-service'; + +@Injectable() +export class LoginApiService{ + private socket:RPCSocket & LoginManagerIfc; + private auth:Auth + private privSocket: RPCSocket & FrontcraftFeatureIfc + + constructor( + private cookieSvc : CookieService + ){} + + getUnprivilegedSocket = () : RPCSocket & LoginManagerIfc => this.socket + + private getPrivilegedSocket = async (auth:Auth) : Promise => { + if(this.privSocket) return this.privSocket + try{ + const sock: RPCSocket & FrontcraftFeatureIfc = await new RPCSocket(auth.port, window.location.hostname).connect(auth.token.value) + //login success + this.auth = auth + this.privSocket = sock + this.setCookie(auth.token) + return sock + }catch(e){ + //login failed + throw new Error('login failed') + } + } + + getCurrentUser = () : User => this.auth + ? this.auth.user + : { + name: 'Guest', + class: _Class[Math.floor(_Class.length * Math.random())], + pwhash: '', + rank: 'Guest' + } + + authenticate = async (token : Token | string) : Promise => { + const auth = await this.socket.Authenticator.authenticate(token) + return await this.getPrivilegedSocket(auth) + } + + login = async (username, password) => { + const buf = str2arraybuf(password) + const pwHash = await crypto.subtle.digest('SHA-256', buf); + const token = await this.socket.Authenticator.login(username, buf2hex(pwHash)) + return await this.authenticate(token) + } + + logout = () => { + this.cookieSvc.deleteAll() + this.auth = null + if(this.privSocket) this.privSocket.destroy() + this.privSocket = null + } + + private setCookie = (token: string | Token) => { + token = 'string' === typeof token? token : token.value + this.cookieSvc.set('token', token) + } + + private getCookie = () : string | Token | undefined => { + return this.cookieSvc.get('token') + } + + initialize = async () : Promise => { + const sock : RPCSocket & LoginManagerIfc = await new RPCSocket(20000, window.location.hostname).connect() + this.socket = sock + + const cookie = this.getCookie() + if(cookie) { + return await this.authenticate(cookie) + } + + return sock + } +} + +function str2arraybuf(str:string): ArrayBuffer { + return new Buffer(str) + } + +function buf2hex(buffer) { // buffer is an ArrayBuffer + return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join(''); +} + + +export function initializeLoginSvc(svc: LoginApiService): () => Promise { + return svc.initialize +} \ No newline at end of file diff --git a/src/frontend/src/app/frontcraft/user.service.ts b/src/frontend/src/app/frontcraft/user.service.ts new file mode 100644 index 0000000..144241e --- /dev/null +++ b/src/frontend/src/app/frontcraft/user.service.ts @@ -0,0 +1,18 @@ +import { Injectable } from "@angular/core"; +import {RPCSocket} from 'rpclibrary' +var crypto = require('crypto'); + +import { User, } from '../../../../backend/Types/Types' + +@Injectable() +export class UserService{ + + private loginSocket = new RPCSocket(20000, window.location.hostname).connect() + + constructor(){} + + login = async (username:string, password:string) => { + const pwHash = crypto.createHash('sha256').update(password).digest('hex'); + + } +} \ No newline at end of file diff --git a/src/frontend/src/app/pages/pages-menu.ts b/src/frontend/src/app/pages/pages-menu.ts index 6134b31..5ffcb34 100644 --- a/src/frontend/src/app/pages/pages-menu.ts +++ b/src/frontend/src/app/pages/pages-menu.ts @@ -1,247 +1,4 @@ import { NbMenuItem } from '@nebular/theme'; export const MENU_ITEMS: NbMenuItem[] = [ - { - title: 'E-commerce', - icon: 'shopping-cart-outline', - link: '/pages/dashboard', - home: true, - }, - { - title: 'IoT Dashboard', - icon: 'home-outline', - link: '/pages/iot-dashboard', - }, - { - title: 'FEATURES', - group: true, - }, - { - title: 'Layout', - icon: 'layout-outline', - children: [ - { - title: 'Stepper', - link: '/pages/layout/stepper', - }, - { - title: 'List', - link: '/pages/layout/list', - }, - { - title: 'Infinite List', - link: '/pages/layout/infinite-list', - }, - { - title: 'Accordion', - link: '/pages/layout/accordion', - }, - { - title: 'Tabs', - pathMatch: 'prefix', - link: '/pages/layout/tabs', - }, - ], - }, - { - title: 'Forms', - icon: 'edit-2-outline', - children: [ - { - title: 'Form Inputs', - link: '/pages/forms/inputs', - }, - { - title: 'Form Layouts', - link: '/pages/forms/layouts', - }, - { - title: 'Buttons', - link: '/pages/forms/buttons', - }, - { - title: 'Datepicker', - link: '/pages/forms/datepicker', - }, - ], - }, - { - title: 'UI Features', - icon: 'keypad-outline', - link: '/pages/ui-features', - children: [ - { - title: 'Grid', - link: '/pages/ui-features/grid', - }, - { - title: 'Icons', - link: '/pages/ui-features/icons', - }, - { - title: 'Typography', - link: '/pages/ui-features/typography', - }, - { - title: 'Animated Searches', - link: '/pages/ui-features/search-fields', - }, - ], - }, - { - title: 'Modal & Overlays', - icon: 'browser-outline', - children: [ - { - title: 'Dialog', - link: '/pages/modal-overlays/dialog', - }, - { - title: 'Window', - link: '/pages/modal-overlays/window', - }, - { - title: 'Popover', - link: '/pages/modal-overlays/popover', - }, - { - title: 'Toastr', - link: '/pages/modal-overlays/toastr', - }, - { - title: 'Tooltip', - link: '/pages/modal-overlays/tooltip', - }, - ], - }, - { - title: 'Extra Components', - icon: 'message-circle-outline', - children: [ - { - title: 'Calendar', - link: '/pages/extra-components/calendar', - }, - { - title: 'Progress Bar', - link: '/pages/extra-components/progress-bar', - }, - { - title: 'Spinner', - link: '/pages/extra-components/spinner', - }, - { - title: 'Alert', - link: '/pages/extra-components/alert', - }, - { - title: 'Calendar Kit', - link: '/pages/extra-components/calendar-kit', - }, - { - title: 'Chat', - link: '/pages/extra-components/chat', - }, - ], - }, - { - title: 'Maps', - icon: 'map-outline', - children: [ - { - title: 'Google Maps', - link: '/pages/maps/gmaps', - }, - { - title: 'Leaflet Maps', - link: '/pages/maps/leaflet', - }, - { - title: 'Bubble Maps', - link: '/pages/maps/bubble', - }, - { - title: 'Search Maps', - link: '/pages/maps/searchmap', - }, - ], - }, - { - title: 'Charts', - icon: 'pie-chart-outline', - children: [ - { - title: 'Echarts', - link: '/pages/charts/echarts', - }, - { - title: 'Charts.js', - link: '/pages/charts/chartjs', - }, - { - title: 'D3', - link: '/pages/charts/d3', - }, - ], - }, - { - title: 'Editors', - icon: 'text-outline', - children: [ - { - title: 'TinyMCE', - link: '/pages/editors/tinymce', - }, - { - title: 'CKEditor', - link: '/pages/editors/ckeditor', - }, - ], - }, - { - title: 'Tables & Data', - icon: 'grid-outline', - children: [ - { - title: 'Smart Table', - link: '/pages/tables/smart-table', - }, - { - title: 'Tree Grid', - link: '/pages/tables/tree-grid', - }, - ], - }, - { - title: 'Miscellaneous', - icon: 'shuffle-2-outline', - children: [ - { - title: '404', - link: '/pages/miscellaneous/404', - }, - ], - }, - { - title: 'Auth', - icon: 'lock-outline', - children: [ - { - title: 'Login', - link: '/auth/login', - }, - { - title: 'Register', - link: '/auth/register', - }, - { - title: 'Request Password', - link: '/auth/request-password', - }, - { - title: 'Reset Password', - link: '/auth/reset-password', - }, - ], - }, ]; diff --git a/src/frontend/src/app/pages/pages-routing.module.ts b/src/frontend/src/app/pages/pages-routing.module.ts index 376cc4f..29749fa 100644 --- a/src/frontend/src/app/pages/pages-routing.module.ts +++ b/src/frontend/src/app/pages/pages-routing.module.ts @@ -10,64 +10,7 @@ const routes: Routes = [{ path: '', component: PagesComponent, children: [ - { - path: 'dashboard', - component: ECommerceComponent, - }, - { - path: 'iot-dashboard', - component: DashboardComponent, - }, - { - path: 'layout', - loadChildren: () => import('./layout/layout.module') - .then(m => m.LayoutModule), - }, - { - path: 'forms', - loadChildren: () => import('./forms/forms.module') - .then(m => m.FormsModule), - }, - { - path: 'ui-features', - loadChildren: () => import('./ui-features/ui-features.module') - .then(m => m.UiFeaturesModule), - }, - { - path: 'modal-overlays', - loadChildren: () => import('./modal-overlays/modal-overlays.module') - .then(m => m.ModalOverlaysModule), - }, - { - path: 'extra-components', - loadChildren: () => import('./extra-components/extra-components.module') - .then(m => m.ExtraComponentsModule), - }, - { - path: 'maps', - loadChildren: () => import('./maps/maps.module') - .then(m => m.MapsModule), - }, - { - path: 'charts', - loadChildren: () => import('./charts/charts.module') - .then(m => m.ChartsModule), - }, - { - path: 'editors', - loadChildren: () => import('./editors/editors.module') - .then(m => m.EditorsModule), - }, - { - path: 'tables', - loadChildren: () => import('./tables/tables.module') - .then(m => m.TablesModule), - }, - { - path: 'miscellaneous', - loadChildren: () => import('./miscellaneous/miscellaneous.module') - .then(m => m.MiscellaneousModule), - }, + { path: '', redirectTo: 'dashboard', diff --git a/src/frontend/src/tsconfig.app.json b/src/frontend/src/tsconfig.app.json index 5d3e364..86333d8 100644 --- a/src/frontend/src/tsconfig.app.json +++ b/src/frontend/src/tsconfig.app.json @@ -15,7 +15,8 @@ "exclude": [ "test.ts", "**/*.spec.ts", - "../node_modules/@nebular/**/*.spec.ts" + "../node_modules/@nebular/**/*.spec.ts", + "../node_modules/rpclibrary/js/**/*" ], "include": [ "../src/*.ts",