This commit is contained in:
peter
2020-03-11 02:05:54 +01:00
parent 111656b9b4
commit b28f8bc7ce
66 changed files with 1349 additions and 2833 deletions
-25
View File
@@ -1,25 +0,0 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"frontcraft": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src/backend",
"prefix": "app",
"architect": {
"server": {
"builder": "@angular-devkit/build-angular:server",
"options": {
"outputPath": "dist/server",
"main": "src/backend/Launcher.ts",
"tsConfig": "tsconfig.json"
}
}
}
}
},
"defaultProject": "frontcraft"
}
-5
View File
@@ -1,5 +0,0 @@
{
"name": "AAA",
"realm": "Gandling EU",
"description": "Wee woo"
}
-1
View File
@@ -1 +0,0 @@
<table><tr><td><!--nstart--><b class="q4">Spineshatter</b><!--nend--><!--ndstart--><!--ndend--><span class="q"><br>Item Level <!--ilvl-->73</span><br /><!--bo-->Binds when picked up<br />Unique<table width="100%"><tr><td>Main Hand</td><th><!--scstart2:4--><span class="q1">Mace</span><!--scend--></th></tr></table><table width="100%"><tr> <td><span><!--dmg-->99 - 184 Damage</span></td> <th>Speed <!--spd-->2.60</th> </tr></table><!--dps-->(54.42 damage per second)<br><span><!--stat4-->+9 Strength</span><br><span><!--stat7-->+16 Stamina</span><!--ebstats--><!--egstats--><!--eistats--><!--e--><!--ps--><br>Durability 105 / 105</td></tr></table><table><tr><td>Requires Level <!--rlvl-->60<br><span class="q2">Equip: <a href="https://classic.wowhead.com/spell=7518" class="q2">Increased Defense +5.</a></span><!--itemEffects:1--><div class="whtt-sellprice">Sell Price: <span class="moneygold">12</span> <span class="moneysilver">88</span> <span class="moneycopper">25</span></div><div class="whtt-extra whtt-droppedby">Dropped by: Razorgore the Untamed</div></td></tr></table>
+100 -1986
View File
File diff suppressed because it is too large Load Diff
+13 -14
View File
@@ -4,19 +4,17 @@
"version": "1.0.0", "version": "1.0.0",
"scripts": { "scripts": {
"tsc": "tsc", "tsc": "tsc",
"launch": "node dist/server/main.js", "launch": "node lib/src/backend/Launcher.js",
"start": "npm run build && npm run launch", "start": "npm run build && npm run launch",
"start-backend": "npm run build-backend && npm run launch", "start-backend": "npm run build-backend && npm run launch",
"test": "rm -rf data && npm run build-backend && mocha lib/test/backendTest.js", "test": "rm -rf data && npm run build-backend && mocha lib/test/backendTest.js",
"build": "npm run build-backend && npm run build-frontend", "build": "npm run build-frontend && npm run build-backend",
"build-backend": "npm run clean-backend && tsc", "build-backend": "npm run clean-backend && npm run tsc",
"build-frontend": "npm run clean-frontend && (mkdir static || rm -rf static/*) && npm run build-dashboard", "build-frontend": "npm run clean-frontend && (mkdir dist || rm -rf dist/*) && npm run build-dashboard",
"build-dashboard": "cd src/frontend && npm i && npm run build && cp -r dist/* ../../static", "build-dashboard": "cd src/frontend && npm run build && cp -r dist/* ../../dist",
"clean": "rm -rf data && npm run clean-backend && npm run clean-frontend", "clean": "rm -rf data && npm run clean-backend && npm run clean-frontend",
"clean-backend": "rm -rf lib plugins config widget .rpt2_cache *.js *.ts", "clean-backend": "rm -rf lib plugins config widget .rpt2_cache ",
"clean-frontend": "rm -rf src/frontend/dist static", "clean-frontend": "rm -rf src/frontend/dist dist"
"webpack": "webpack --config src/backend/webpack.prod.js --progress --colors",
"setangular": "ng update @angular/cli@8.2.2 @angular/core@8.2.2 @angular/compiler-cli@8.2.2"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@@ -32,6 +30,7 @@
"circular-buffer": "^1.0.2", "circular-buffer": "^1.0.2",
"crypto-js": "^3.1.9-1", "crypto-js": "^3.1.9-1",
"debug": "^4.1.1", "debug": "^4.1.1",
"domino": "^2.1.4",
"express": "^4.16.4", "express": "^4.16.4",
"frontblock": "^0.15.2", "frontblock": "^0.15.2",
"frontblock-generic": "^0.34.8", "frontblock-generic": "^0.34.8",
@@ -42,6 +41,7 @@
"loadson": "^1.0.0", "loadson": "^1.0.0",
"log4js": "^4.5.1", "log4js": "^4.5.1",
"lowdb": "^1.0.0", "lowdb": "^1.0.0",
"ngx-cookie-service": "^2.4.0",
"node-fetch": "^2.6.0", "node-fetch": "^2.6.0",
"path": "^0.12.7", "path": "^0.12.7",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
@@ -54,16 +54,15 @@
"tsyringe": "^4.0.1", "tsyringe": "^4.0.1",
"upgiter": "^1.0.4", "upgiter": "^1.0.4",
"uuid": "^3.3.3", "uuid": "^3.3.3",
"xml2js": "^0.4.22" "xml2js": "^0.4.22",
"xmlhttprequest": "^1.8.0"
}, },
"devDependencies": { "devDependencies": {
"madge": "^3.6.0", "madge": "^3.6.0",
"mocha": "^7.0.0", "mocha": "^7.1.0",
"terser-webpack-plugin": "^1.4.1", "terser-webpack-plugin": "^1.4.1",
"ts-loader": "^5.3.3", "ts-loader": "^5.3.3",
"typescript": "^3.5.3", "typescript": "^3.5.3"
"webpack": "^4.39.2",
"webpack-cli": "^3.3.5"
}, },
"files": [ "files": [
"lib/**/*" "lib/**/*"
+28 -69
View File
@@ -1,6 +1,6 @@
'use strict' 'use strict'
import { getLogger } from 'frontblock-generic/Types'; import { getLogger, Logger, } from "log4js";
import { promises as fs, mkdirSync } from "fs" import { promises as fs, mkdirSync } from "fs"
import { RPCServer } from 'rpclibrary' import { RPCServer } from 'rpclibrary'
import * as Path from 'path' import * as Path from 'path'
@@ -22,12 +22,7 @@ import { Injector } from '../Injector/Injector';
import { Shoutbox } from '../Components/Shoutbox/Shoutbox'; import { Shoutbox } from '../Components/Shoutbox/Shoutbox';
import { PubSub } from '../Components/PubSub/PubSub'; import { PubSub } from '../Components/PubSub/PubSub';
//import { ngExpressEngine } from '../../frontend/node_modules/@nguniversal/express-engine'; getLogger().level = 'debug'
//import { APP_BASE_HREF } from '../../frontend/';
//import { AppServerModule } from './app.server.module';
const logger = getLogger("admin", 'debug')
@RootComponent({ @RootComponent({
injectable: IAdmin, injectable: IAdmin,
@@ -73,15 +68,15 @@ implements TableDefinitionExporter, IAdmin {
await this.makeKnex() await this.makeKnex()
this.startWebsocket() this.startWebsocket()
await Promise.all( this.frontworkComponents.map(c => c.initialize?c.initialize():undefined )) await Promise.all( this.frontworkComponents.map(c => c.initialize?c.initialize():undefined ))
logger.debug(this.frontworkComponents.length+" components initialized") getLogger('Admin#start').debug(this.frontworkComponents.length+" components initialized")
this.startWebserver() await this.startWebserver()
} }
stop(){ stop(){
Promise.all([ Promise.all([
...this.frontworkComponents.map(c => c.stop?c.stop():undefined ), ...this.frontworkComponents.map(c => c.stop?c.stop():undefined ),
]) ])
.catch(e => logger.warn(e)) .catch(e => getLogger('Admin#stop').warn(e))
.finally(() => { .finally(() => {
this.rpcServer.destroy() this.rpcServer.destroy()
process.exit(0) process.exit(0)
@@ -123,92 +118,56 @@ implements TableDefinitionExporter, IAdmin {
], { ], {
visibility: '0.0.0.0' visibility: '0.0.0.0'
}) })
logger.debug("Websocket up on", 20000) getLogger('Admin#startWebsocket').debug("Websocket up on", 20000)
} }
private startWebserver(){ private async startWebserver(){
if(this.httpServer != null || this.express != null){ if(this.httpServer != null || this.express != null){
logger.warn("Webserver is already running") getLogger('Admin#startWebserver').warn("Webserver is already running")
return return
} }
let port:number = this.config.getConfig().httpPort let port:number = this.config.getConfig().httpPort
this.express = express() this.express = express()
/* const distFolder = "../../../../dist"
this.express.engine('html', ngExpressEngine({ const ngExpressServer = Path.join(__dirname, distFolder, 'server.js')
bootstrap: AppServerModule,
}));
this.express.set('view engine', 'html'); this.express.get('*.*', (req, res)=>{
this.express.set('views', 'static'); //console.log('*.*', req.path);
res.sendFile(Path.join(__dirname, distFolder,'browser',decodeURIComponent(req.path)))
// Serve static files from /browser
this.express.get('*.*', express.static('static', {
maxAge: '1y'
}));
this.express.get("/", (request, response) => {
response.status(200)
response.sendFile('index.html');
}) })
// All regular routes use the Universal engine try{
this.express.get('*', (req, res) => { const req = require(distFolder+"/server.js")
res.status(301) await req.attachExpress(this.express)
res.redirect('/') getLogger('Admin#startWebserver').info('Frontend from '+ngExpressServer+" loaded")
//res.render('index', { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] }); }catch(e){
}); getLogger('Admin#startWebserver').error(e)
*/ getLogger('Admin#startWebserver').warn("No angular SSR module was provided in "+ngExpressServer)
/* */ getLogger('Admin#startWebserver').warn("This is not fatal, but your page will not render on *"+port)
// get the compiled FrontendPlugins.js }
this.express.use('/', express.static('static'))
this.express.get('/plugins/:id'+".js", async (request, response) => { this.express.listen(port, () => {
const pth = Path.resolve("plugins/"+request.params.id, "FrontendPlugin.js"); getLogger('Admin#startWebserver').info('Admin panel listening for HTTP on *'+port)
const file = await fs.readFile(pth)
const frontend = file.toString()
response.status(200)
response.set('Content-Type', 'application/javascript')
response.send(frontend)
}) })
// serve the index.html from the static folder
this.express.get("/", (request, response) => {
response.status(200)
response.sendFile('index.html');
})
// redirect all the other traffic to the single page app
this.express.get("*", (request, response) => {
response.status(301)
response.redirect('/')
})
this.httpServer = new http.Server(this.express)
this.httpServer.listen(port, () => {
logger.info('Admin panel listening for HTTP on *'+port)
})
/* */
} }
private stopWebserver(){ private stopWebserver(){
if(this.httpServer == null || this.express == null){ if(this.httpServer == null || this.express == null){
logger.warn("Webserver is not running") getLogger('Admin#stopWebserver').warn("Webserver is not running")
return return
} }
this.httpServer.close() this.httpServer.close()
this.httpServer = null this.httpServer = null
this.express = null this.express = null
logger.info("Webserver stopped") getLogger('Admin#stopWebserver').info("Webserver stopped")
} }
async makeKnex():Promise<Knex>{ async makeKnex():Promise<Knex>{
const conf:Knex.Config = this.config.getConfigKey("dbConf") const conf:Knex.Config = this.config.getConfigKey("dbConf")
logger.debug("Making new knex:", conf) getLogger('Admin#makeKnex').debug("Making new knex:", conf)
if(conf.client === 'sqlite3'){ if(conf.client === 'sqlite3'){
mkdirSync(Path.dirname((<any>conf.connection).filename), {recursive: true}) mkdirSync(Path.dirname((<any>conf.connection).filename), {recursive: true})
} }
@@ -237,6 +196,6 @@ implements TableDefinitionExporter, IAdmin {
} }
process.on( 'SIGINT', function() { process.on( 'SIGINT', function() {
logger.info("Shutting down from SIGINT (Ctrl-C)" ); getLogger('process#SIGINT').info("Shutting down from SIGINT (Ctrl-C)" );
Injector.resolve<FrontworkAdmin>(FrontworkAdmin).stop() Injector.resolve<FrontworkAdmin>(FrontworkAdmin).stop()
}) })
-21
View File
@@ -1,21 +0,0 @@
/*
import { NgModule } from '../../frontend/node_modules/@angular/core';
import { ServerModule } from '../../frontend/node_modules/@angular/platform-server';
import { ModuleMapLoaderModule } from '../../frontend/node_modules/@nguniversal/module-map-ngfactory-loader';
import { AppModule } from '../../frontend/src/app/app.module';
import { AppComponent } from '../../frontend/src/app/app.component';
@NgModule({
imports: [
AppModule,
ServerModule,
ModuleMapLoaderModule
],
providers: [
// Add universal-only providers here
],
bootstrap: [ AppComponent ],
})
export class AppServerModule {}
*/
+192 -181
View File
@@ -17,6 +17,8 @@ import { IRaidManager } from "../Raid/Interface";
import { IItemManager } from "../Item/Interface"; import { IItemManager } from "../Item/Interface";
import { IGuildManager } from "../Guild/Interface"; import { IGuildManager } from "../Guild/Interface";
getLogger().level = "debug"
const uuid = require('uuid/v4') const uuid = require('uuid/v4')
const salt = "6pIbc6yjSN" const salt = "6pIbc6yjSN"
@@ -24,33 +26,33 @@ const ONE_WEEK = 604800000
type Serverstate<SubresT, InterfaceT extends RPCInterface> = { type Serverstate<SubresT, InterfaceT extends RPCInterface> = {
server: RPCServer<SubresT, InterfaceT>, server: RPCServer<SubresT, InterfaceT>,
port : number, port: number,
}; };
@Injectable(IUserManager) @Injectable(IUserManager)
export class UserManager export class UserManager
implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManager{ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManager {
name = "UserManager" as "UserManager" name = "UserManager" as "UserManager"
@Inject(IAdmin) @Inject(IAdmin)
private admin: IAdmin private admin: IAdmin
@Inject(IGuildManager) @Inject(IGuildManager)
private guild : GuildManager private guild: GuildManager
@Inject(IItemManager) @Inject(IItemManager)
private item : ItemManager private item: ItemManager
@Inject(IRaidManager) @Inject(IRaidManager)
private raid : RaidManager private raid: RaidManager
@Inject(ICharacterManager) @Inject(ICharacterManager)
private character : CharacterManager private character: CharacterManager
exporters :any[] = [] exporters: any[] = []
rankServer : Serverstate<{}, FrontcraftFeatureIfc> rankServer: Serverstate<{}, FrontcraftFeatureIfc>
userLogins : {[username in string] : UserRecord} = {} userLogins: { [username in string]: UserRecord } = {}
allowed: string[] = [] allowed: string[] = []
exportRPCs = () => [ exportRPCs = () => [
@@ -64,44 +66,44 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
] ]
exportRPCFeatures = () => [ exportRPCFeatures = () => [
{ {
name: 'manageUser' as 'manageUser', name: 'manageUser' as 'manageUser',
exportRPCs: () => [ exportRPCs: () => [
this.adminLogout, this.adminLogout,
this.changeRank, this.changeRank,
this.adminChangePassword this.adminChangePassword
] ]
},{ }, {
name: 'modifyPermissions' as 'modifyPermissions', name: 'modifyPermissions' as 'modifyPermissions',
exportRPCs: () => [ exportRPCs: () => [
this.getPermissions, this.getPermissions,
this.setPermission, this.setPermission,
] ]
},{ }, {
name: 'softreserveCurrency' as 'softreserveCurrency', name: 'softreserveCurrency' as 'softreserveCurrency',
exportRPCs: () => [ exportRPCs: () => [
this.incrementCurrency, this.incrementCurrency,
this.decrementCurrency, this.decrementCurrency,
this.setCurrency this.setCurrency
] ]
}] }]
changeRank = async (user:User, rank:Rank): Promise<User> => { changeRank = async (user: User, rank: Rank): Promise<User> => {
await this.admin await this.admin
.knex('users') .knex('users')
.where({ .where({
username: user.username username: user.username
}).update({ }).update({
rank: rank rank: rank
}) })
await this.adminLogout(user.username) await this.adminLogout(user.username)
return await this.admin return await this.admin
.knex('users') .knex('users')
.where({ .where({
username: user.username username: user.username
}).first() }).first()
} }
getTableDefinitions = (): TableDefiniton[] => [ getTableDefinitions = (): TableDefiniton[] => [
@@ -116,33 +118,33 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
table.integer(tier).defaultTo(1) table.integer(tier).defaultTo(1)
}) })
} }
},{ }, {
name: 'rpcpermissions', name: 'rpcpermissions',
tableBuilder: (table) => { tableBuilder: (table) => {
table.string("rpcname").primary().notNullable() table.string("rpcname").primary().notNullable()
_Rank.forEach(r => { _Rank.forEach(r => {
if(r === 'ADMIN') if (r === 'ADMIN')
table.boolean(r).defaultTo(true).notNullable() table.boolean(r).defaultTo(true).notNullable()
else else
table.boolean(r).defaultTo(false).notNullable() table.boolean(r).defaultTo(false).notNullable()
}) })
} }
} }
,...this.exporters.flatMap(exp => exp['getTableDefinitions']?exp['getTableDefinitions']():undefined) , ...this.exporters.flatMap(exp => exp['getTableDefinitions'] ? exp['getTableDefinitions']() : undefined)
] ]
initialize = async () => { initialize = async () => {
this.exporters = [this.guild, this.item, this.raid, this.character] this.exporters = [this.guild, this.item, this.raid, this.character]
//set up permissions //set up permissions
getLogger('UserManager').debug('setting up permissions') getLogger('UserManager#initialize').debug('setting up permissions')
await Promise.all( await Promise.all(
[this, ...this.exporters].flatMap(exp => exp.exportRPCFeatures().map(async (feature) => { [this, ...this.exporters].flatMap(exp => exp.exportRPCFeatures().map(async (feature) => {
try{ try {
await this.admin.knex.insert({ rpcname: feature.name }).into('rpcpermissions') await this.admin.knex.insert({ rpcname: feature.name }).into('rpcpermissions')
}catch(e){ } catch (e) {
} }
}))) })))
const rankServer = await this.startRankServer(20001) const rankServer = await this.startRankServer(20001)
this.rankServer = { this.rankServer = {
@@ -157,115 +159,111 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
Object.values(x.connections).forEach(c => c.destroy()) Object.values(x.connections).forEach(c => c.destroy())
}) })
try{ try {
return this.rankServer.server.destroy() return this.rankServer.server.destroy()
}catch(e){ } catch (e) {
//getLogger('UserManager').warn(e) getLogger('UserManager#stop').debug(String(e))
} }
} }
checkExpiredSessions = () => { checkExpiredSessions = () => {
Object.values(this.userLogins).map(userLogin => { Object.values(this.userLogins).map(userLogin => {
const auth = userLogin.auth const auth = userLogin.auth
if(!this.checkToken(auth.token.value)){ if (!this.checkToken(auth.token.value)) {
this.logout(auth.user.username, auth.token.value) this.logout(auth.user.username, auth.token.value)
} }
}) })
} }
checkConnection = async (socket: Socket) => { checkConnection = async (socket: Socket, retries = 0) : Promise<boolean> => {
if(retries < 0){
let data : any return false
let tries = 0
while(!data){
tries ++
if(tries === 5){
getLogger('UserManager').debug('Connection check failed for connection *'+socket.port)
socket.destroy()
return false
}
data = await Promise.race([socket.call('getUserData'), new Promise((res, rej) => { setTimeout(res, 1000);})])
} }
if(!this.userLogins[data.user.username]){ //give the client some time to bind its hooks
await new Promise((res, rej) => { setTimeout(res, 150);})
let data
try{
data = await Promise.race([socket.call('getUserData'), new Promise((res, rej) => { setTimeout(res, 250);})])
}catch(e){
getLogger('UserManager#checkConnection').debug('Client didn\'t respond', e)
return false
}
if(!data) {
if(retries > 0){
return await this.checkConnection(socket, retries-1)
}
return false
}
if (!this.userLogins[data.user.username]) {
await this.logout(data.user.username, data.token.value) await this.logout(data.user.username, data.token.value)
return false return false
} }
this.userLogins[data.user.username].connections[socket.port] = socket this.userLogins[data.user.username].connections[socket.port] = socket
await socket.call('navigate', ["/frontcraft/dashboard"]) getLogger('UserManager#checkConnection').debug(this.userLogins, this.allowed);
return true return true
} }
changePassword = async (userToken:string, pwHash:string) : Promise<User> => { changePassword = async (userToken: string, pwHash: string): Promise<User> => {
const record = this.getUserRecordByToken(userToken) const record = this.getUserRecordByToken(userToken)
if(!record) return {} as User if (!record) return {} as User
return await this.adminChangePassword(record.user, pwHash) return await this.adminChangePassword(record.user, pwHash)
} }
adminChangePassword = async(user:User, pwHash:string) : Promise<User> => { adminChangePassword = async (user: User, pwHash: string): Promise<User> => {
const salted = await saltedHash(pwHash, salt) const salted = await saltedHash(pwHash, salt)
await this.admin.knex('users') await this.admin.knex('users')
.update({pwhash: salted}) .update({ pwhash: salted })
.where({ .where({
username: user.username username: user.username
}) })
const usr = await this.getUser(user.username) const usr = await this.getUser(user.username)
if(!usr) return {} as any if (!usr) return {} as any
await this.adminLogout(usr.username) await this.adminLogout(usr.username)
return usr return usr
} }
setPermission = async (permission: RPCPermission) => { setPermission = async (permission: RPCPermission) => {
await this.admin.knex('rpcpermissions') await this.admin.knex('rpcpermissions')
.where('rpcname', '=', permission.rpcname) .where('rpcname', '=', permission.rpcname)
.update(permission) .update(permission)
await Promise.all( await Promise.all(
Object.entries(this.userLogins).map(([username, record]) => { Object.entries(this.userLogins).map(([username, record]) => {
if(record.user.rank === "ADMIN") return if (record.user.rank === "ADMIN") return
return this.adminLogout(username) return this.adminLogout(username)
}) })
) )
} }
getPermissions = async () : Promise<RPCPermission[]> => { getPermissions = async (): Promise<RPCPermission[]> => {
return await this.admin.knex.select('*').from('rpcpermissions') return await this.admin.knex.select('*').from('rpcpermissions')
} }
getPermission = async (feature: keyof FrontcraftFeatureIfc, rank:Rank) : Promise<boolean> => { getPermission = async (feature: keyof FrontcraftFeatureIfc, rank: Rank): Promise<boolean> => {
const perm : RPCPermission = await this.admin.knex const perm: RPCPermission = await this.admin.knex
.select(rank) .select(rank)
.from('rpcpermissions') .from('rpcpermissions')
.where('rpcname', '=', <string>feature) .where('rpcname', '=', <string>feature)
.first() .first()
if(!perm) return false if (!perm) return false
return perm[rank] return perm[rank]
} }
getRPCForRank = async (rank: Rank): Promise<AnyRPCExporter[]> => { createUser = async (user: User): Promise<User> => {
let rpcs = [ if (user.rank === 'ADMIN') {
...this.exportRPCFeatures(),
...this.exporters.flatMap((exp) => exp.exportRPCFeatures())
]
const bits = await Promise.all(rpcs.map(async (feature) => {
const allowed = await this.getPermission(<keyof FrontcraftFeatureIfc> feature.name, rank)
return allowed
}))
return rpcs.filter(entry => bits.shift())
}
createUser = async(user:User): Promise<User> => {
if(user.rank === 'ADMIN'){
const admins = await this.admin.knex const admins = await this.admin.knex
.select("*") .select("*")
.from('users') .from('users')
.where({rank: 'ADMIN'}) .where({ rank: 'ADMIN' })
if(admins.length > 0){ if (admins.length > 0) {
return {} as User return {} as User
} }
} }
@@ -273,45 +271,54 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
user.pwhash = await saltedHash(user.pwhash, salt) user.pwhash = await saltedHash(user.pwhash, salt)
await this.admin.knex('users') await this.admin.knex('users')
.insert(user) .insert(user)
const userRecord = await this.admin.knex const userRecord = await this.admin.knex
.select("*") .select("*")
.from('users') .from('users')
.where(user) .where(user)
.first() .first()
return userRecord return userRecord
} }
getUser = async (username: string) : Promise<User | void> => await this.admin getUser = async (username: string): Promise<User | void> => await this.admin
.knex('users') .knex('users')
.select('*') .select('*')
.where({ .where({
username: username.toLowerCase() username: username.toLowerCase()
}) })
.first() .first()
logout = async (username:string, tokenValue : string) : Promise<void> => { logout = async (username: string, tokenValue: string): Promise<void> => {
try{ try {
if(!this.checkTokenOwnedByUser(username, tokenValue)) return if (!this.checkTokenOwnedByUser(username, tokenValue)) return
return await this.adminLogout(username) return await this.adminLogout(username)
}catch(e){ } catch (e) {
} }
} }
adminLogout = async(username: string) : Promise<void> => { adminLogout = async (username: string): Promise<void> => {
try{ try {
if(this.userLogins[username]){ if (this.userLogins[username]) {
await Promise.all (Object.values(this.userLogins[username].connections).map(async (sock) => { const token = this.userLogins[username].auth.token.value
await sock.call('kick') //doesn't matter if error or success
})) Object.values(this.userLogins[username].connections).forEach(async (sock) => {
try{
this.allowed = this.allowed.filter(allowed => allowed !== this.userLogins[username].auth.token.value) await sock.call('kick')
}catch(e){
//getLogger('UserManager#adminLogout#kick').debug(String(e))
}
})
this.allowed = this.allowed.filter(allowed => {
return allowed != token
})
delete this.userLogins[username] delete this.userLogins[username]
} }
}catch(e){} } catch (e) {
getLogger('UserManager#adminLogout').debug(String(e), this.userLogins)
}
} }
wipeCurrency = async () => { wipeCurrency = async () => {
@@ -320,81 +327,83 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
update[tier] = 1 update[tier] = 1
return this.admin.knex('users') return this.admin.knex('users')
.update(update) .update(update)
})) }))
} }
login = async(username:string, pwHash:string) : Promise<Auth> => { login = async (username: string, pwHash: string): Promise<Auth> => {
username = username.toLowerCase() username = username.toLowerCase()
const user:User = await this.admin.knex const user: User = await this.admin.knex
.select('*') .select('*')
.from('users') .from('users')
.where({ username: username }) .where({ username: username })
.first() .first()
const salted = await saltedHash(pwHash, salt) const salted = await saltedHash(pwHash, salt)
if(user && salted === user.pwhash){ if (user && salted === user.pwhash) {
delete user.pwhash delete user.pwhash
//return existing auth //return existing auth
if(this.userLogins[username] != null){ if (this.userLogins[username] != null) {
return this.userLogins[username].auth return this.userLogins[username].auth
} }
const token = this.createToken(user) const token = this.createToken(user)
const userAuth : Auth = { const userAuth: Auth = {
token: token, token: token,
user: user, user: user,
port: this.rankServer.port port: this.rankServer.port
} }
this.userLogins[user.username] = {connections: {}, auth: userAuth, user:user} this.userLogins[user.username] = { connections: {}, auth: userAuth, user: user }
this.allowed.push(token.value) this.allowed.push(token.value)
return userAuth return userAuth
} }
throw new Error('login failed') throw new Error('login failed')
} }
getUserRecordByToken(tokenValue: string){ getUserRecordByToken(tokenValue: string) {
return Object.values(this.userLogins).find(login => login.auth.token.value === tokenValue) return Object.values(this.userLogins).find(login => login.auth.token.value === tokenValue)
} }
getAuth = async (tokenValue:string) : Promise<Auth | void> => { getAuth = async (tokenValue: string): Promise<Auth | void> => {
const maybeAuth = this.getUserRecordByToken(tokenValue) const maybeAuth = this.getUserRecordByToken(tokenValue)
if(maybeAuth) if (maybeAuth)
return maybeAuth.auth return maybeAuth.auth
return return
} }
startRankServer = async (port: number) : Promise<RPCServer<{},FrontcraftFeatureIfc>> => { startRankServer = async (port: number): Promise<RPCServer<{}, FrontcraftFeatureIfc>> => {
let rpcs = [ let rpcs = [
...this.exportRPCFeatures(), ...this.exportRPCFeatures(),
...this.exporters.flatMap((exp) => exp.exportRPCFeatures()) ...this.exporters.flatMap((exp) => exp.exportRPCFeatures())
] ]
let rpcServer = new RPCServer<{},FrontcraftFeatureIfc>(port, rpcs, { let rpcServer = new RPCServer<{}, FrontcraftFeatureIfc>(port, rpcs, {
accessFilter: async (sesame, exporter) => { accessFilter: async (sesame, exporter) => {
const record = this.getUserRecordByToken(sesame!) const record = this.getUserRecordByToken(sesame!)
if(!record) return false if (!record) return false
return await this.getPermission(exporter.name, record.user.rank) return await this.getPermission(exporter.name, record.user.rank)
}, },
closeHandler: (socket) => { closeHandler: (socket) => {
Object.values(this.userLogins) Object.values(this.userLogins).forEach(login => delete login.connections[socket.port])
.forEach(login => delete login.connections[socket.port]) getLogger('UserManager#closeHandler').debug(this.userLogins, this.allowed)
}, },
connectionHandler: (socket) => { connectionHandler: (socket) => {
this.checkConnection(socket).then(res => { this.checkConnection(socket, 10).then(res => {
if(!res){ if (!res) {
getLogger('UserManager#connectionHandler').debug("Connection on "+socket.port+" failed to authenticate")
socket.destroy(); socket.destroy();
} }
}).catch((e) => { }).catch((e) => {
getLogger('UserManager#connectionHandler').debug(String(e))
socket.destroy(); socket.destroy();
}) })
}, },
errorHandler: (socket, e, rpcName, args) => { errorHandler: (socket, e, rpcName, args) => {
getLogger('UserManager').error(rpcName, args, e); getLogger('UserManager#errorHandler').error(rpcName, args, e);
}, },
sesame: (sesame) => this.checkToken(sesame), sesame: (sesame) => this.checkToken(sesame),
visibility: '0.0.0.0' visibility: '0.0.0.0'
@@ -403,25 +412,27 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
return rpcServer return rpcServer
} }
checkToken = (token: string) : boolean => this.allowed.includes(token) checkToken = (token: string): boolean => {
&& Object.values(this.userLogins).find(login => login.auth.token.value === token)!.auth.token.created > Date.now() - ONE_WEEK return this.allowed.includes(token)
&& Object.values(this.userLogins).find(login => login.auth.token.value === token)!.auth.token.created > Date.now() - ONE_WEEK
}
checkTokenOwnedByUser = (username: string, tokenValue: string) => { checkTokenOwnedByUser = (username: string, tokenValue: string) => {
username = username.toLowerCase() username = username.toLowerCase()
const maybeRecord = this.getUserRecordByToken(tokenValue) const maybeRecord = this.getUserRecordByToken(tokenValue)
if(!maybeRecord || maybeRecord.auth.user.username != username){ if (!maybeRecord || maybeRecord.auth.user.username != username) {
return false return false
} }
return true return true
} }
createToken = (user:User): Token => { createToken = (user: User): Token => {
if(this.userLogins[user.username]){ if (this.userLogins[user.username]) {
return this.userLogins[user.username].auth.token return this.userLogins[user.username].auth.token
} }
const token:Token = { const token: Token = {
value: uuid(), value: uuid(),
user_id: user.id!, user_id: user.id!,
created: Date.now() created: Date.now()
@@ -430,47 +441,47 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
return token return token
} }
getCurrency = async(user:User, tier?: Tiers) : Promise<number> => { getCurrency = async (user: User, tier?: Tiers): Promise<number> => {
if(!tier) return 0 if (!tier) return 0
const usr : User = await this.admin const usr: User = await this.admin
.knex('users') .knex('users')
.where('username', '=', user.username) .where('username', '=', user.username)
.select('*') .select('*')
.first() .first()
return usr[tier]! return usr[tier]!
} }
decrementCurrency = async (user: User, tier?: Tiers, value = 1) => { decrementCurrency = async (user: User, tier?: Tiers, value = 1) => {
if(!tier || value < 1) return if (!tier || value < 1) return
const usr : User = await this.admin const usr: User = await this.admin
.knex('users') .knex('users')
.where('id', '=', user.id) .where('id', '=', user.id)
.select('*') .select('*')
.first() .first()
if(!usr || usr[tier]! <= 0) return if (!usr || usr[tier]! <= 0) return
await this.admin await this.admin
.knex('users') .knex('users')
.where('id', '=', user.id) .where('id', '=', user.id)
.decrement(tier, value) .decrement(tier, value)
} }
incrementCurrency = async (user: User, tier: Tiers, value = 1) => { incrementCurrency = async (user: User, tier: Tiers, value = 1) => {
if(!tier || value < 1) return if (!tier || value < 1) return
await this.admin await this.admin
.knex('users') .knex('users')
.where('id', '=', user.id) .where('id', '=', user.id)
.increment(tier, value) .increment(tier, value)
} }
setCurrency = async (user: User, tier?:Tiers, value = 0) => { setCurrency = async (user: User, tier?: Tiers, value = 0) => {
if(!tier || value < 0) return if (!tier || value < 0) return
await this.admin await this.admin
.knex('users') .knex('users')
.where('id', '=', user.id) .where('id', '=', user.id)
.update(tier, value) .update(tier, value)
} }
} }
-2
View File
@@ -1,2 +0,0 @@
//import { enableProdMode } from '../frontend/node_modules/@angular/core';
//enableProdMode();
-68
View File
@@ -1,68 +0,0 @@
const path = require('path');
module.exports = [{
mode: 'production',
target: "node",
node: {
global: true,
process: true,
__filename: false,
__dirname: false,
Buffer: true,
},
resolve: {
// Add `.ts` and `.tsx` as a resolvable extension.
extensions: [".ts", ".tsx", ".js"]
},
module: {
rules: [
{ test: /\.ts?$/, loader: "ts-loader" }
]
},
externals: ['knex'],
optimization: {
minimize: false
},
entry: path.resolve(__dirname, 'Installer.ts'),
output: {
path: path.resolve(__dirname, '../../dist'),
filename: 'Installer.js',
libraryTarget: 'commonjs',
}
},{
mode: 'production',
target: "node",
node: {
global: true,
process: true,
__filename: false,
__dirname: false,
Buffer: true,
},
resolve: {
// Add `.ts` and `.tsx` as a resolvable extension.
extensions: [".ts", ".tsx", ".js"]
},
module: {
rules: [
{ test: /\.ts?$/, loader: "ts-loader" }
]
},
externals:["./Installer"],
optimization: {
minimize: false
},
entry: path.resolve(__dirname, 'Launcher.ts'),
output: {
path: path.resolve(__dirname, '../../dist'),
filename: 'FrontblockAdmin.js',
libraryTarget: 'commonjs',
}
}]
+22 -12
View File
@@ -13,10 +13,10 @@
"options": { "options": {
"preserveSymlinks": true, "preserveSymlinks": true,
"rebaseRootRelativeCssUrls": true, "rebaseRootRelativeCssUrls": true,
"outputPath": "dist", "outputPath": "dist/browser",
"index": "src/index.html", "index": "src/index.html",
"main": "src/main.ts", "main": "src/main.ts",
"tsConfig": "src/tsconfig.app.json", "tsConfig": "./tsconfig.app.json",
"polyfills": "src/polyfills.ts", "polyfills": "src/polyfills.ts",
"assets": [ "assets": [
"src/assets", "src/assets",
@@ -51,20 +51,13 @@
"node_modules/echarts/dist/echarts.min.js", "node_modules/echarts/dist/echarts.min.js",
"node_modules/echarts/dist/extension/bmap.min.js", "node_modules/echarts/dist/extension/bmap.min.js",
"node_modules/chart.js/dist/Chart.min.js", "node_modules/chart.js/dist/Chart.min.js",
"node_modules/rpclibrary/js/browser/rpclibrary.browser.js" "node_modules/rpclibrary/js/browser/rpclibrary.browser.js",
"node_modules/js-cookie/src/js.cookie.js"
] ]
}, },
"configurations": { "configurations": {
"production": { "production": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true, "aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [ "fileReplacements": [
{ {
"replace": "src/environments/environment.ts", "replace": "src/environments/environment.ts",
@@ -136,7 +129,7 @@
"builder": "@angular-devkit/build-angular:tslint", "builder": "@angular-devkit/build-angular:tslint",
"options": { "options": {
"tsConfig": [ "tsConfig": [
"src/tsconfig.app.json", "./tsconfig.app.json",
"src/tsconfig.spec.json" "src/tsconfig.spec.json"
], ],
"typeCheck": true, "typeCheck": true,
@@ -167,6 +160,23 @@
} }
} }
} }
},
"frontcraft": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "",
"prefix": "app",
"architect": {
"server": {
"builder": "@angular-devkit/build-angular:server",
"options": {
"outputPath": "dist/server",
"main": "./src/main.server.ts",
"tsConfig": "./tsconfig.server.json"
}
}
}
} }
}, },
"defaultProject": "ngx-admin-demo", "defaultProject": "ngx-admin-demo",
+376 -7
View File
@@ -425,6 +425,7 @@
"version": "8.2.14", "version": "8.2.14",
"resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-8.2.14.tgz", "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-8.2.14.tgz",
"integrity": "sha512-ABZO4E7eeFA1QyJ2trDezxeQM5ZFa1dXw1Mpl/+1vuXDKNjJgNyWYwKp/NwRkLmrsuV0yv4UDCDe4kJOGbPKnw==", "integrity": "sha512-ABZO4E7eeFA1QyJ2trDezxeQM5ZFa1dXw1Mpl/+1vuXDKNjJgNyWYwKp/NwRkLmrsuV0yv4UDCDe4kJOGbPKnw==",
"dev": true,
"requires": { "requires": {
"tslib": "^1.9.0" "tslib": "^1.9.0"
} }
@@ -1350,6 +1351,16 @@
"tslib": "^1.9.0" "tslib": "^1.9.0"
} }
}, },
"@angular/platform-server": {
"version": "8.2.14",
"resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-8.2.14.tgz",
"integrity": "sha512-gGAgxMmac5CyLcwgB+qCD1o75An0NmpREh/lxPgz6n6Zs9JqdqpZROLSIHqGBaU6MWo1qiOfS6L08HwYPx7ipQ==",
"requires": {
"domino": "^2.1.2",
"tslib": "^1.9.0",
"xhr2": "^0.1.4"
}
},
"@angular/router": { "@angular/router": {
"version": "8.2.14", "version": "8.2.14",
"resolved": "https://registry.npmjs.org/@angular/router/-/router-8.2.14.tgz", "resolved": "https://registry.npmjs.org/@angular/router/-/router-8.2.14.tgz",
@@ -2511,11 +2522,11 @@
"integrity": "sha512-jX6R5lApSBtPHcZzgJ1+URxvJhmSodX+YcuDnuYsQJB1nkpC0Kjs6XL5OEONVg4NaoYcxMYmnxRe51lrlQdilg==" "integrity": "sha512-jX6R5lApSBtPHcZzgJ1+URxvJhmSodX+YcuDnuYsQJB1nkpC0Kjs6XL5OEONVg4NaoYcxMYmnxRe51lrlQdilg=="
}, },
"@nebular/theme": { "@nebular/theme": {
"version": "4.4.0", "version": "4.6.0",
"resolved": "https://registry.npmjs.org/@nebular/theme/-/theme-4.4.0.tgz", "resolved": "https://registry.npmjs.org/@nebular/theme/-/theme-4.6.0.tgz",
"integrity": "sha512-UcK1hwMvJXDROU9QiCfRq5LXRV9gB+K+AJtg1UYhvNJ+NzZkLyn+P+wFNX0StI91BjjNw3T699Xvz4B0grWhlA==", "integrity": "sha512-S7topzx0Hf9D7YkQxKJ8UB1G2/sEN3o4eKjkRe8Xv5n7H3WqpKQ9Uef3oW2mTf75dmICBldhKXvopdr6TA5foA==",
"requires": { "requires": {
"intersection-observer": "0.5.0" "intersection-observer": "0.7.0"
} }
}, },
"@ngtools/webpack": { "@ngtools/webpack": {
@@ -2542,6 +2553,24 @@
} }
} }
}, },
"@nguniversal/common": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@nguniversal/common/-/common-9.0.1.tgz",
"integrity": "sha512-AprW7oREmywDudrBI1auy4lB6AQFKHLeebdY7vAXjviIEzBDm9Zd1Z59SqFtp+H4Pce8R7tQ3zoXY1n7azCigg=="
},
"@nguniversal/express-engine": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@nguniversal/express-engine/-/express-engine-9.0.1.tgz",
"integrity": "sha512-uICu/CVrKuRYKUhpn91tRoERRhorDH038zyUsQt3yqsKV5BXyclr+H0lHh94dXyi+W0RKmksvzGNshwc4IWnUA==",
"requires": {
"@nguniversal/common": "9.0.1"
}
},
"@nguniversal/module-map-ngfactory-loader": {
"version": "8.2.6",
"resolved": "https://registry.npmjs.org/@nguniversal/module-map-ngfactory-loader/-/module-map-ngfactory-loader-8.2.6.tgz",
"integrity": "sha512-YcxXSrDZt6iDR+YbesJvprNpHd1nRLeThJwAFlcwvK/GVGSyKeWV6eqk3bRkBkgkw8OwaG/4lOQ4aofxQw+13w=="
},
"@nodelib/fs.stat": { "@nodelib/fs.stat": {
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz",
@@ -6490,6 +6519,12 @@
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
"dev": true "dev": true
}, },
"detect-file": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
"integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=",
"dev": true
},
"detect-indent": { "detect-indent": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
@@ -6785,6 +6820,11 @@
"domelementtype": "1" "domelementtype": "1"
} }
}, },
"domino": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/domino/-/domino-2.1.4.tgz",
"integrity": "sha512-l70mlQ7IjPKC8kT7GljQXJZmt5OqFL+RE91ik5y5WWQtsd9wP8R7gpFnNu96fK5MqAAZRXfLLsnzKtkty5fWGQ=="
},
"domutils": { "domutils": {
"version": "1.5.1", "version": "1.5.1",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
@@ -7547,6 +7587,15 @@
} }
} }
}, },
"expand-tilde": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
"integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=",
"dev": true,
"requires": {
"homedir-polyfill": "^1.0.1"
}
},
"express": { "express": {
"version": "4.17.1", "version": "4.17.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
@@ -8011,6 +8060,18 @@
"integrity": "sha1-WKRmaX34piBc39vzlVNri9d3pfY=", "integrity": "sha1-WKRmaX34piBc39vzlVNri9d3pfY=",
"dev": true "dev": true
}, },
"findup-sync": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz",
"integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==",
"dev": true,
"requires": {
"detect-file": "^1.0.0",
"is-glob": "^4.0.0",
"micromatch": "^3.0.4",
"resolve-dir": "^1.0.1"
}
},
"flat-cache": { "flat-cache": {
"version": "1.3.4", "version": "1.3.4",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz",
@@ -8907,6 +8968,41 @@
"integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=",
"dev": true "dev": true
}, },
"global-modules": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz",
"integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==",
"dev": true,
"requires": {
"global-prefix": "^3.0.0"
},
"dependencies": {
"global-prefix": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
"integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
"dev": true,
"requires": {
"ini": "^1.3.5",
"kind-of": "^6.0.2",
"which": "^1.3.1"
}
}
}
},
"global-prefix": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz",
"integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=",
"dev": true,
"requires": {
"expand-tilde": "^2.0.2",
"homedir-polyfill": "^1.0.1",
"ini": "^1.3.4",
"is-windows": "^1.0.1",
"which": "^1.2.14"
}
},
"globals": { "globals": {
"version": "11.12.0", "version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
@@ -9610,10 +9706,16 @@
"ipaddr.js": "^1.9.0" "ipaddr.js": "^1.9.0"
} }
}, },
"interpret": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz",
"integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==",
"dev": true
},
"intersection-observer": { "intersection-observer": {
"version": "0.5.0", "version": "0.7.0",
"resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.5.0.tgz", "resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.7.0.tgz",
"integrity": "sha512-8Zgt4ijlyvIrQVTA7MPb2W9+KhoetrAbxlh0RmTGxpx0+ZsAXvy7IsbNnZIrqZ6TddAdWeQj49x7Ph7Ir6KRkA==" "integrity": "sha512-Id0Fij0HsB/vKWGeBe9PxeY45ttRiBmhFyyt/geBdDHBYNctMRTE3dC1U3ujzz3lap+hVXlEcVaB56kZP/eEUg=="
}, },
"intl": { "intl": {
"version": "1.2.5", "version": "1.2.5",
@@ -10261,6 +10363,11 @@
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.2.tgz", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.2.tgz",
"integrity": "sha512-Vg8czh0Q7sFBSUMWWArX/miJeBWYBPpdU/3M/DKSaekLMqrqVPaedp+5mZhie/r0lgrcaYBfwXatEew6gwgiQQ==" "integrity": "sha512-Vg8czh0Q7sFBSUMWWArX/miJeBWYBPpdU/3M/DKSaekLMqrqVPaedp+5mZhie/r0lgrcaYBfwXatEew6gwgiQQ=="
}, },
"js-cookie": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz",
"integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ=="
},
"js-tokens": { "js-tokens": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -15544,6 +15651,29 @@
"resolve-from": "^3.0.0" "resolve-from": "^3.0.0"
} }
}, },
"resolve-dir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz",
"integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=",
"dev": true,
"requires": {
"expand-tilde": "^2.0.0",
"global-modules": "^1.0.0"
},
"dependencies": {
"global-modules": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
"integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
"dev": true,
"requires": {
"global-prefix": "^1.0.1",
"is-windows": "^1.0.1",
"resolve-dir": "^1.0.0"
}
}
}
},
"resolve-from": { "resolve-from": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
@@ -18531,6 +18661,12 @@
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
}, },
"v8-compile-cache": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz",
"integrity": "sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==",
"dev": true
},
"v8flags": { "v8flags": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz",
@@ -19409,6 +19545,234 @@
"webpack-sources": "^1.4.1" "webpack-sources": "^1.4.1"
} }
}, },
"webpack-cli": {
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.11.tgz",
"integrity": "sha512-dXlfuml7xvAFwYUPsrtQAA9e4DOe58gnzSxhgrO/ZM/gyXTBowrsYeubyN4mqGhYdpXMFNyQ6emjJS9M7OBd4g==",
"dev": true,
"requires": {
"chalk": "2.4.2",
"cross-spawn": "6.0.5",
"enhanced-resolve": "4.1.0",
"findup-sync": "3.0.0",
"global-modules": "2.0.0",
"import-local": "2.0.0",
"interpret": "1.2.0",
"loader-utils": "1.2.3",
"supports-color": "6.1.0",
"v8-compile-cache": "2.0.3",
"yargs": "13.2.4"
},
"dependencies": {
"ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true
},
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
},
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"cliui": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
"integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
"dev": true,
"requires": {
"string-width": "^3.1.0",
"strip-ansi": "^5.2.0",
"wrap-ansi": "^5.1.0"
}
},
"cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
"integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
"dev": true,
"requires": {
"nice-try": "^1.0.4",
"path-key": "^2.0.1",
"semver": "^5.5.0",
"shebang-command": "^1.2.0",
"which": "^1.2.9"
}
},
"emoji-regex": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
"dev": true
},
"find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"dev": true,
"requires": {
"locate-path": "^3.0.0"
}
},
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true
},
"invert-kv": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
"integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
"dev": true
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"dev": true
},
"lcid": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
"integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
"dev": true,
"requires": {
"invert-kv": "^2.0.0"
}
},
"os-locale": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
"integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
"dev": true,
"requires": {
"execa": "^1.0.0",
"lcid": "^2.0.0",
"mem": "^4.0.0"
}
},
"require-main-filename": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
"dev": true
},
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"dev": true,
"requires": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
}
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"dev": true,
"requires": {
"ansi-regex": "^4.1.0"
}
},
"supports-color": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
},
"which-module": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
"dev": true
},
"wrap-ansi": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
"integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.0",
"string-width": "^3.0.0",
"strip-ansi": "^5.0.0"
}
},
"y18n": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
"dev": true
},
"yargs": {
"version": "13.2.4",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz",
"integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==",
"dev": true,
"requires": {
"cliui": "^5.0.0",
"find-up": "^3.0.0",
"get-caller-file": "^2.0.1",
"os-locale": "^3.1.0",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^3.0.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^13.1.0"
}
},
"yargs-parser": {
"version": "13.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz",
"integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==",
"dev": true,
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
}
}
},
"webpack-core": { "webpack-core": {
"version": "0.6.9", "version": "0.6.9",
"resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz",
@@ -20508,6 +20872,11 @@
"integrity": "sha1-OS2LotDxw00e4tYw8V0O+2jhBIo=", "integrity": "sha1-OS2LotDxw00e4tYw8V0O+2jhBIo=",
"dev": true "dev": true
}, },
"xhr2": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz",
"integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8="
},
"xml2js": { "xml2js": {
"version": "0.4.23", "version": "0.4.23",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
+22 -14
View File
@@ -11,10 +11,11 @@
}, },
"scripts": { "scripts": {
"ng": "ng", "ng": "ng",
"webpack:server": "webpack --config webpack.server.config.js",
"conventional-changelog": "conventional-changelog", "conventional-changelog": "conventional-changelog",
"start": "ng serve", "start": "ng serve",
"build": "ng build", "build": "rm -rf dist serverBundle && npm run ngbuild && ng run frontcraft:server && webpack --config webpack.server.config",
"build:prod": "npm run build -- --prod --aot", "ngbuild": "ng build --prod",
"test": "ng test", "test": "ng test",
"test:coverage": "rimraf coverage && npm run test -- --code-coverage", "test:coverage": "rimraf coverage && npm run test -- --code-coverage",
"lint": "ng lint", "lint": "ng lint",
@@ -26,25 +27,29 @@
"docs": "compodoc -p src/tsconfig.app.json -d docs", "docs": "compodoc -p src/tsconfig.app.json -d docs",
"docs:serve": "compodoc -p src/tsconfig.app.json -d docs -s", "docs:serve": "compodoc -p src/tsconfig.app.json -d docs -s",
"prepush": "npm run lint:ci", "prepush": "npm run lint:ci",
"release:changelog": "npm run conventional-changelog -- -p angular -i CHANGELOG.md -s" "release:changelog": "npm run conventional-changelog -- -p angular -i CHANGELOG.md -s",
"add": "ng add @nguniversal/express-engine",
"tsc": "tsc --project src/tsconfig.server.json && webpack --config extra-webpack.config.js"
}, },
"dependencies": { "dependencies": {
"@agm/core": "^1.0.0-beta.5", "@agm/core": "^1.0.0-beta.5",
"@angular-builders/custom-webpack": "^8.2.0", "@angular-builders/custom-webpack": "^8.4.1",
"@angular/animations": "^8.0.0", "@angular/animations": "^8.2.14",
"@angular/cdk": "^8.0.0", "@angular/cdk": "^8.2.3",
"@angular/common": "^8.0.0", "@angular/common": "^8.2.14",
"@angular/compiler": "^8.0.0", "@angular/core": "^8.2.14",
"@angular/core": "^8.0.0",
"@angular/forms": "^8.0.0", "@angular/forms": "^8.0.0",
"@angular/platform-browser": "^8.0.0", "@angular/platform-browser": "^8.0.0",
"@angular/platform-browser-dynamic": "^8.0.0", "@angular/platform-browser-dynamic": "^8.2.14",
"@angular/platform-server": "^8.2.14",
"@angular/router": "^8.0.0", "@angular/router": "^8.0.0",
"@asymmetrik/ngx-leaflet": "3.0.1", "@asymmetrik/ngx-leaflet": "3.0.1",
"@nebular/auth": "4.4.0", "@nebular/auth": "4.4.0",
"@nebular/eva-icons": "4.4.0", "@nebular/eva-icons": "4.4.0",
"@nebular/security": "4.4.0", "@nebular/security": "4.4.0",
"@nebular/theme": "^4.4.0", "@nebular/theme": "^4.6.0",
"@nguniversal/express-engine": "^9.0.1",
"@nguniversal/module-map-ngfactory-loader": "^8.2.6",
"@swimlane/ngx-charts": "^10.0.0", "@swimlane/ngx-charts": "^10.0.0",
"angular-tree-component": "7.2.0", "angular-tree-component": "7.2.0",
"angular2-chartjs": "0.4.1", "angular2-chartjs": "0.4.1",
@@ -58,6 +63,7 @@
"eva-icons": "^1.1.0", "eva-icons": "^1.1.0",
"intl": "1.2.5", "intl": "1.2.5",
"ionicons": "2.0.1", "ionicons": "2.0.1",
"js-cookie": "^2.2.1",
"leaflet": "1.2.0", "leaflet": "1.2.0",
"nebular-icons": "1.1.0", "nebular-icons": "1.1.0",
"ng2-ckeditor": "^1.2.2", "ng2-ckeditor": "^1.2.2",
@@ -81,8 +87,9 @@
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "~0.803.24", "@angular-devkit/build-angular": "~0.803.24",
"@angular/cli": "^8.0.2", "@angular/cli": "^8.3.25",
"@angular/compiler-cli": "^8.0.0", "@angular/compiler": "^8.2.14",
"@angular/compiler-cli": "^8.2.14",
"@angular/language-service": "8.0.0", "@angular/language-service": "8.0.0",
"@compodoc/compodoc": "^1.1.11", "@compodoc/compodoc": "^1.1.11",
"@fortawesome/fontawesome-free": "^5.2.0", "@fortawesome/fontawesome-free": "^5.2.0",
@@ -109,6 +116,7 @@
"ts-node": "3.2.2", "ts-node": "3.2.2",
"tslint": "^5.7.0", "tslint": "^5.7.0",
"tslint-language-service": "^0.9.9", "tslint-language-service": "^0.9.9",
"typescript": "^3.5.1" "typescript": "^3.5.1",
"webpack-cli": "^3.3.11"
} }
} }
+47
View File
@@ -0,0 +1,47 @@
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import { ngExpressEngine } from '@nguniversal/express-engine';
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';
import { resolve } from 'path';
import { enableProdMode } from '@angular/core';
const domino = require('domino');
const win = domino.createWindow('');
global['window'] = win;
global['document'] = win.document;
global['alert'] = console.log
global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest;
export async function attachExpress(app, staticDir = "./dist") {
const STATIC_FOLDER = resolve(process.cwd(), staticDir);
enableProdMode();
const bundle = require(staticDir + '/server/main');
const ServerApiService = bundle.ServerApiService
const serviceObj = new ServerApiService()
await serviceObj.initialize()
app.set('view engine', 'html');
app.engine(
'html',
ngExpressEngine({
bootstrap: bundle.AppServerModuleNgFactory,
providers: [
provideModuleMap(bundle.LAZY_MODULE_MAP),
{
provide: bundle.IApiService,
useValue: serviceObj,
deps: []
}
]
})
);
app.get('*', (req, res) => {
//console.log('*', req.path);
res.render(resolve(STATIC_FOLDER, 'browser/index'), { req, res })
});
}
+1 -10
View File
@@ -1,20 +1,11 @@
import { ModuleWithProviders, NgModule, Optional, SkipSelf, APP_INITIALIZER } from '@angular/core'; import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { throwIfAlreadyLoaded } from './module-import-guard'; import { throwIfAlreadyLoaded } from './module-import-guard';
import { ApiService, initializeLoginSvc } from '../frontcraft/services/login-api';
import { CookieService } from 'ngx-cookie-service'; import { CookieService } from 'ngx-cookie-service';
import { LayoutService } from './utils'; import { LayoutService } from './utils';
const DATA_SERVICES = [ const DATA_SERVICES = [
{provide: ApiService, useClass: ApiService},
{provide: CookieService, useClass: CookieService},
{
provide: APP_INITIALIZER,
useFactory: initializeLoginSvc,
deps: [ApiService, CookieService],
multi: true
}
]; ];
export const NB_CORE_PROVIDERS = [ export const NB_CORE_PROVIDERS = [
@@ -1,6 +1,6 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { ApiService } from '../../../frontcraft/services/login-api';
import { ShoutMessage } from '../../../../../../backend/Components/Shoutbox/Interface'; import { ShoutMessage } from '../../../../../../backend/Components/Shoutbox/Interface';
import { IApiService } from '../../../frontcraft/services/ApiService';
@Component({ @Component({
selector: 'chat', selector: 'chat',
@@ -31,7 +31,7 @@ export class ChatComponent {
history history
constructor( constructor(
private api: ApiService private api: IApiService
) {} ) {}
submit(event){ submit(event){
@@ -1,14 +1,14 @@
import { Component, OnDestroy, OnInit } from '@angular/core'; import { Component, OnDestroy, OnInit } from '@angular/core';
import { NbMediaBreakpointsService, NbSidebarService, NbThemeService, NbMenuItem, NbDialogService } from '@nebular/theme'; import { NbSidebarService, NbThemeService, NbMenuItem, NbDialogService } from '@nebular/theme';
import { LayoutService } from '../../../@core/utils'; import { LayoutService } from '../../../@core/utils';
import { map, takeUntil } from 'rxjs/operators'; import { map, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { ApiService } from '../../../frontcraft/services/login-api';
import { User } from '../../../../../../backend/Types/Types'; import { User } from '../../../../../../backend/Types/Types';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { ChatComponent } from './chat.component'; import { ChatComponent } from './chat.component';
import { ShoutMessage } from '../../../../../../backend/Components/Shoutbox/Interface'; import { ShoutMessage } from '../../../../../../backend/Components/Shoutbox/Interface';
import { IApiService } from '../../../frontcraft/services/ApiService';
@Component({ @Component({
selector: 'ngx-header', selector: 'ngx-header',
@@ -54,8 +54,7 @@ export class HeaderComponent implements OnInit, OnDestroy {
private router: Router, private router: Router,
private themeService: NbThemeService, private themeService: NbThemeService,
private layoutService: LayoutService, private layoutService: LayoutService,
private breakpointService: NbMediaBreakpointsService, private api: IApiService,
private api: ApiService,
private dialogService : NbDialogService private dialogService : NbDialogService
) {} ) {}
@@ -17,21 +17,9 @@ export class TinyMCEComponent implements OnDestroy, AfterViewInit {
) { } ) { }
ngAfterViewInit() { ngAfterViewInit() {
tinymce.init({
target: this.host.nativeElement,
plugins: ['link', 'paste', 'table'],
skin_url: `${this.locationStrategy.getBaseHref()}assets/skins/lightgray`,
setup: editor => {
this.editor = editor;
editor.on('keyup', () => {
this.editorKeyup.emit(editor.getContent());
});
},
height: '320',
});
} }
ngOnDestroy() { ngOnDestroy() {
tinymce.remove(this.editor);
} }
} }
+78 -9
View File
@@ -1,25 +1,94 @@
import { ExtraOptions, RouterModule, Routes } from '@angular/router'; import { ExtraOptions, RouterModule, Routes } from '@angular/router';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { PagesLayoutComponent } from './frontcraft/pages/pages-layout.component';
import { FrontcraftUserComponent } from './frontcraft/pages/user/user.component';
import { FrontcraftRaidComponent } from './frontcraft/pages/raid/raid.component';
import { FrontcraftArchiveComponent } from './frontcraft/pages/raid/archive.component';
import { FrontcraftRaidsComponent } from './frontcraft/pages/raids/raids.component';
import { FrontcraftCharacterComponent } from './frontcraft/pages/character/character.component';
import { FrontcraftCharactersComponent } from './frontcraft/pages/characters/characters.component';
import { FrontcraftRulesComponent } from './frontcraft/pages/rules/rules.component';
import { FrontcraftArmoryComponent } from './frontcraft/pages/armory/armory.component';
import { RegisterComponent } from './frontcraft/auth/register/register.component';
import { LogoutComponent } from './frontcraft/auth/logout/logout.component';
import { MyLoginComponent } from './frontcraft/auth/login/login.component';
import { AuthComponent } from './frontcraft/auth/auth-layout.component';
import { ChangePermissionsComponent } from './frontcraft/permissions/changePermissions/changePermissions.component';
import { PermissionsComponent } from './frontcraft/permissions/permissions-layout.component';
const routes: Routes = [ const routes: Routes = [
{ {
path: 'permissions', path: 'permissions',
loadChildren: () => import('./frontcraft/permissions/permissions.module') component: PermissionsComponent,
.then(m => m.PermissionsModule), children: [
{
path: '**',
component: ChangePermissionsComponent,
},
]
}, },
{ {
path: 'auth', path: 'auth',
loadChildren: () => import('./frontcraft/auth/auth.module') component: AuthComponent,
.then(m => m.MyAuthModule), children: [
{
path: 'register',
component: RegisterComponent
},
{
path: 'logout',
component: LogoutComponent,
},
{
path: '**',
component: MyLoginComponent,
},
]
}, },
{ {
path: 'frontcraft', path: 'frontcraft',
loadChildren: () => import('./frontcraft/pages/pages.module') component: PagesLayoutComponent,
.then(m => m.FrontcraftPagesModule), children: [
{
path: 'user/:name',
component: FrontcraftUserComponent
},
{
path: 'raid/:id',
component: FrontcraftRaidComponent
},
{
path: 'archive/:id',
component: FrontcraftArchiveComponent
},
{
path: 'raids',
component: FrontcraftRaidsComponent
},
{
path: 'character/:name',
component: FrontcraftCharacterComponent
},
{
path: 'characters',
component: FrontcraftCharactersComponent
},
{
path: 'rules',
component: FrontcraftRulesComponent
},
{
path: 'armory',
component: FrontcraftArmoryComponent
},
{
path: '**',
redirectTo: 'raids'
},
]
}, },
{ path: '', redirectTo: 'frontcraft/raids', pathMatch: 'full' },
{ path: '', redirectTo: 'frontcraft', pathMatch: 'full' }, { path: '**', redirectTo: 'frontcraft/raids' },
{ path: '**', redirectTo: 'frontcraft' },
]; ];
const config: ExtraOptions = { const config: ExtraOptions = {
+3 -15
View File
@@ -3,9 +3,7 @@
* Copyright Akveo. All Rights Reserved. * Copyright Akveo. All Rights Reserved.
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*/ */
import { Component, OnInit, Inject, PLATFORM_ID, APP_ID } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ApiService } from './frontcraft/services/login-api';
import { isPlatformBrowser } from '@angular/common';
@Component({ @Component({
selector: 'ngx-app', selector: 'ngx-app',
@@ -13,17 +11,7 @@ import { isPlatformBrowser } from '@angular/common';
}) })
export class AppComponent implements OnInit { export class AppComponent implements OnInit {
constructor( constructor() { }
private loginSvc: ApiService,
@Inject(PLATFORM_ID) private platformId: Object,
@Inject(APP_ID) private appId: string
) {
if(!isPlatformBrowser(platformId)){
global['window'] = {}
}
}
ngOnInit(): void { ngOnInit(): void { }
}
} }
+13 -15
View File
@@ -5,7 +5,7 @@
*/ */
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule, APP_INITIALIZER } from '@angular/core'; import { NgModule, APP_INITIALIZER, NgZone, Injector } from '@angular/core';
import { HttpClientModule } from '@angular/common/http'; import { HttpClientModule } from '@angular/common/http';
import { ThemeModule } from './@theme/theme.module'; import { ThemeModule } from './@theme/theme.module';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
@@ -19,14 +19,17 @@ import {
NbToastrModule, NbToastrModule,
NbWindowModule, NbWindowModule,
} from '@nebular/theme'; } from '@nebular/theme';
import { ApiService, initializeLoginSvc } from './frontcraft/services/login-api';
import { CookieService } from 'ngx-cookie-service';
import { CoreModule } from './@core/core.module'; import { CoreModule } from './@core/core.module';
import { FrontcraftPagesModule } from './frontcraft/pages/pages.module';
import { MyAuthModule } from './frontcraft/auth/auth.module';
import { PermissionsModule } from './frontcraft/permissions/permissions.module';
@NgModule({ @NgModule({
declarations: [AppComponent], declarations: [
AppComponent
],
imports: [ imports: [
BrowserModule, BrowserModule.withServerTransition({ appId: 'frontcraft' }),
BrowserAnimationsModule, BrowserAnimationsModule,
HttpClientModule, HttpClientModule,
AppRoutingModule, AppRoutingModule,
@@ -41,17 +44,12 @@ import { CoreModule } from './@core/core.module';
messageGoogleMapKey: 'AIzaSyA_wNuCzia92MAmdLRzmqitRGvCF7wCZPY', messageGoogleMapKey: 'AIzaSyA_wNuCzia92MAmdLRzmqitRGvCF7wCZPY',
}), }),
CoreModule.forRoot(), CoreModule.forRoot(),
FrontcraftPagesModule,
MyAuthModule,
PermissionsModule
], ],
bootstrap: [AppComponent], bootstrap: [AppComponent],
providers: [ providers: []
ApiService,
{
provide: APP_INITIALIZER,
deps: [CookieService],
multi: true,
useFactory: initializeLoginSvc
},
]
}) })
export class AppModule { export class FrontcraftAppModule {
} }
+18
View File
@@ -0,0 +1,18 @@
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { ServerModule } from '@angular/platform-server';
import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader';
import { FrontcraftAppModule } from './app.module';
import { AppComponent } from './app.component';
@NgModule({
imports: [
FrontcraftAppModule,
ServerModule,
ModuleMapLoaderModule
],
providers: [],
bootstrap: [ AppComponent ],
})
export class AppServerModule {}
@@ -1,5 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ApiService } from '../services/login-api'; import { ClientApiService } from '../services/client-login-api';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
@Component({ @Component({
@@ -13,8 +13,6 @@ import { Router } from '@angular/router';
export class AuthComponent implements OnInit{ export class AuthComponent implements OnInit{
constructor( constructor(
private loginSvc : ApiService,
private router: Router
){} ){}
ngOnInit(){ ngOnInit(){
@@ -1,34 +0,0 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { MyLoginComponent } from './login/login.component';
import { AuthComponent } from './auth-layout.component';
import { LogoutComponent } from './logout/logout.component';
import { RegisterComponent } from './register/register.component';
export const routes: Routes = [
{
path: '',
component: AuthComponent,
children: [
{
path: 'register',
component: RegisterComponent
},
{
path: 'logout',
component: LogoutComponent,
},
{
path: '**',
component: MyLoginComponent,
},
]
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class MyAuthRoutingModule {
}
@@ -12,7 +12,6 @@ import {
NbCardModule, NbCardModule,
NbSelectModule NbSelectModule
} from '@nebular/theme'; } from '@nebular/theme';
import { MyAuthRoutingModule } from './auth-routing.module';
import { MyLoginComponent } from './login/login.component'; import { MyLoginComponent } from './login/login.component';
import { AuthComponent } from './auth-layout.component'; import { AuthComponent } from './auth-layout.component';
import { ThemeModule } from '../../@theme/theme.module'; import { ThemeModule } from '../../@theme/theme.module';
@@ -22,7 +21,6 @@ import { RegisterComponent } from './register/register.component';
@NgModule({ @NgModule({
imports: [ imports: [
MyAuthRoutingModule,
CommonModule, CommonModule,
FormsModule, FormsModule,
RouterModule, RouterModule,
@@ -29,7 +29,7 @@
id="input-password" id="input-password"
placeholder="Password" placeholder="Password"
fieldSize="giant" fieldSize="giant"
[status]="password.dirty ? (password.invalid ? 'danger' : 'success') : ''" [status]="password.dirty ? (password.invalid ? 'danger' : 'success') : 'basic'"
[required]="true" [required]="true"
[minlength]="1" [minlength]="1"
[maxlength]="15" [maxlength]="15"
@@ -1,6 +1,8 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ApiService } from '../../services/login-api'; import { ClientApiService } from '../../services/client-login-api';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { IApiService } from '../../services/ApiService';
import { NbToastrService } from '@nebular/theme';
@Component({ @Component({
selector: 'mylogin', selector: 'mylogin',
@@ -21,18 +23,26 @@ export class MyLoginComponent implements OnInit{
constructor( constructor(
private router : Router, private router : Router,
private loginApi : ApiService private api : IApiService,
private toastr: NbToastrService
){} ){}
ngOnInit(){ ngOnInit(){
this.loginApi.checkLogin().then(loggedin => { this.api.checkLogin().then(loggedin => {
if(loggedin){ if(loggedin){
this.router.navigateByUrl("/") this.router.navigateByUrl("/")
} }
}); });
} }
login(){ async login(){
this.loginApi.login(this.user.name, this.user.password) const login = await this.api.login(this.user.name, this.user.password)
if(!login){
this.toastr.danger("Login failed", "Error")
return
}else{
window['r'] = this.router
this.router.navigate(["/froncraft"])
}
} }
} }
@@ -1,5 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ApiService } from '../../services/login-api'; import { IApiService } from '../../services/ApiService';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
@Component({ @Component({
@@ -9,11 +9,13 @@ import { Router } from '@angular/router';
export class LogoutComponent implements OnInit{ export class LogoutComponent implements OnInit{
constructor( constructor(
private api : ApiService private api : IApiService,
private router: Router
){} ){}
ngOnInit(){ ngOnInit(){
this.api.logout() this.api.logout().then(() => {
this.router.navigate(['/auth/login'])
})
} }
} }
@@ -1,9 +1,10 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ApiService as ApiService, hash } from '../../services/login-api'; import { ClientApiService as ClientApiService } from '../../services/client-login-api';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { _Rank, _Class, Class, User, _Race } from '../../../../../../backend/Types/Types' import { _Rank, _Class, Class, User, _Race } from '../../../../../../backend/Types/Types'
import { specs } from '../../../../../../backend/Types/PlayerSpecs' import { specs } from '../../../../../../backend/Types/PlayerSpecs'
import { race } from 'rxjs'; import { race } from 'rxjs';
import { hash, IApiService } from '../../services/ApiService';
@Component({ @Component({
@@ -33,7 +34,7 @@ export class RegisterComponent implements OnInit{
constructor( constructor(
private router : Router, private router : Router,
private api : ApiService private api : IApiService
){} ){}
ngOnInit(){ ngOnInit(){
@@ -1,6 +1,5 @@
<nb-card <nb-card
class = "col-12 col-xl-9" class = "col-12 col-xl-9">
status="control">
<nb-card-header style="text-transform: capitalize;"> <nb-card-header style="text-transform: capitalize;">
<h4> <h4>
Armory Armory
@@ -2,7 +2,8 @@ import { Component, OnInit } from '@angular/core';
import { Item, Stats } from '../../../../../../backend/Types/Types'; import { Item, Stats } from '../../../../../../backend/Types/Types';
import { NbToastrService } from '@nebular/theme'; import { NbToastrService } from '@nebular/theme';
import { ApiService } from '../../services/login-api'; import { ClientApiService } from '../../services/client-login-api';
import { IApiService } from '../../services/ApiService';
@Component({ @Component({
selector: 'armory', selector: 'armory',
@@ -18,7 +19,7 @@ export class FrontcraftArmoryComponent implements OnInit {
gear: Item[] = [] gear: Item[] = []
constructor( constructor(
private api: ApiService, private api: IApiService,
private toastr: NbToastrService private toastr: NbToastrService
) { } ) { }
@@ -1,6 +1,5 @@
<nb-card <nb-card
class = "col-12 col-xl-9" class = "col-12 col-xl-9">
status="control">
<nb-card-header style="text-transform: capitalize;"> <nb-card-header style="text-transform: capitalize;">
<h4> <h4>
<a *ngIf="link === 'character'" [ngStyle]="{'color': color}" [routerLink]="'/frontcraft/character/'+char.charactername"> <a *ngIf="link === 'character'" [ngStyle]="{'color': color}" [routerLink]="'/frontcraft/character/'+char.charactername">
@@ -1,9 +1,10 @@
import { Component, OnInit, Input } from '@angular/core'; import { Component, OnInit, Input } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { ApiService as ApiService } from '../../services/login-api'; import { ClientApiService as ClientApiService } from '../../services/client-login-api';
import { Spec, User, Character, Item } from '../../../../../../backend/Types/Types'; import { Spec, User, Character, Item } from '../../../../../../backend/Types/Types';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs'; import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { _Tiers } from '../../../../../../backend/Types/Items'; import { _Tiers } from '../../../../../../backend/Types/Items';
import { IApiService } from '../../services/ApiService';
@Component({ @Component({
selector: 'character', selector: 'character',
@@ -28,7 +29,7 @@ export class FrontcraftCharacterComponent implements OnInit{
gear2:string[] = [] gear2:string[] = []
constructor( constructor(
private api: ApiService, private api: IApiService,
private route: ActivatedRoute, private route: ActivatedRoute,
){} ){}
@@ -1,8 +1,8 @@
import { Component, AfterViewInit, OnDestroy } from '@angular/core'; import { Component, AfterViewInit, OnDestroy } from '@angular/core';
import { NbThemeService } from '@nebular/theme'; import { NbThemeService } from '@nebular/theme';
import { ApiService } from '../../services/login-api';
import { _Class } from '../../../../../../backend/Types/Types'; import { _Class } from '../../../../../../backend/Types/Types';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs'; import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { IApiService } from '../../services/ApiService';
@Component({ @Component({
@@ -17,7 +17,7 @@ export class FrontcraftCharactersComponent implements AfterViewInit, OnDestroy{
allcharacters = [] allcharacters = []
displayedcharacters = [] displayedcharacters = []
constructor(private theme: NbThemeService, private api:ApiService) { constructor(private theme: NbThemeService, private api:IApiService) {
} }
changeSearch(){ changeSearch(){
@@ -1,7 +1,10 @@
import { Component, AfterContentChecked, OnInit, AfterContentInit } from '@angular/core'; import { Component, AfterContentInit, OnInit } from '@angular/core';
import { NbMenuItem } from '@nebular/theme'; import { NbMenuItem } from '@nebular/theme';
import { ApiService } from '../services/login-api'; import { ClientApiService } from '../services/client-login-api';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { IApiService } from '../services/ApiService';
declare const Cookies
@Component({ @Component({
selector: 'page-layout', selector: 'page-layout',
@@ -13,7 +16,8 @@ import { Router } from '@angular/router';
</ngx-one-column-layout> </ngx-one-column-layout>
`, `,
}) })
export class PagesLayoutComponent implements AfterContentInit{ export class PagesLayoutComponent implements OnInit{
menu:NbMenuItem[] = [{ menu:NbMenuItem[] = [{
icon: 'image', icon: 'image',
title: 'Raids', title: 'Raids',
@@ -33,15 +37,17 @@ export class PagesLayoutComponent implements AfterContentInit{
}] }]
constructor( constructor(
private loginSvc : ApiService, private api : IApiService,
private router : Router private router : Router
){} ){}
ngAfterContentInit() : void { ngOnInit(): void {
this.loginSvc.checkLogin().then(loggedin => { /*
if(!loggedin){ const u = this.api.getCurrentUser()
this.router.navigateByUrl("/auth")
} if(!u){
}); this.router.navigate(['/auth/login'])
}
*/
} }
} }
@@ -1,63 +0,0 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { PagesLayoutComponent } from './pages-layout.component';
import { FrontcraftCharacterComponent } from './character/character.component';
import { FrontcraftUserComponent } from './user/user.component';
import { FrontcraftRaidsComponent } from './raids/raids.component';
import { FrontcraftRaidComponent } from './raid/raid.component';
import { FrontcraftArchiveComponent } from './raid/archive.component';
import { FrontcraftRulesComponent } from './rules/rules.component';
import { FrontcraftCharactersComponent } from './characters/characters.component';
import { FrontcraftArmoryComponent } from './armory/armory.component';
export const routes: Routes = [
{
path: '',
component: PagesLayoutComponent,
children: [
{
path: 'user/:name',
component: FrontcraftUserComponent
},
{
path: 'raid/:id',
component: FrontcraftRaidComponent
},
{
path: 'archive/:id',
component: FrontcraftArchiveComponent
},
{
path: 'raids',
component: FrontcraftRaidsComponent
},
{
path: 'character/:name',
component: FrontcraftCharacterComponent
},
{
path: 'characters',
component: FrontcraftCharactersComponent,
},
{
path: 'rules',
component: FrontcraftRulesComponent
},
{
path: 'armory',
component: FrontcraftArmoryComponent
},
{
path: '**',
redirectTo: 'raids'
},
]
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class FrontcraftRoutingModule {
}
@@ -18,7 +18,6 @@ import {
NbDatepickerModule, NbDatepickerModule,
NbSelectModule NbSelectModule
} from '@nebular/theme'; } from '@nebular/theme';
import { FrontcraftRoutingModule } from './pages-routing.module';
import { PagesLayoutComponent } from './pages-layout.component'; import { PagesLayoutComponent } from './pages-layout.component';
import { ThemeModule } from '../../@theme/theme.module'; import { ThemeModule } from '../../@theme/theme.module';
import { FrontcraftCharacterComponent } from './character/character.component'; import { FrontcraftCharacterComponent } from './character/character.component';
@@ -42,7 +41,6 @@ import { FrontcraftArmoryComponent } from './armory/armory.component';
@NgModule({ @NgModule({
imports: [ imports: [
FrontcraftRoutingModule,
CommonModule, CommonModule,
FormsModule, FormsModule,
RouterModule, RouterModule,
@@ -1,8 +1,9 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { ApiService as ApiService } from '../../services/login-api'; import { ClientApiService as ClientApiService } from '../../services/client-login-api';
import { RaidData } from '../../../../../../backend/Types/Types'; import { RaidData } from '../../../../../../backend/Types/Types';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs'; import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { IApiService } from '../../services/ApiService';
@Component({ @Component({
selector: 'archive', selector: 'archive',
@@ -38,7 +39,7 @@ export class FrontcraftArchiveComponent implements OnInit{
search = "" search = ""
constructor( constructor(
private api: ApiService, private api: IApiService,
private route: ActivatedRoute, private route: ActivatedRoute,
){ ){
} }
@@ -60,7 +61,7 @@ export class FrontcraftArchiveComponent implements OnInit{
[ [
...raiddata.tanks, ...raiddata.tanks,
...raiddata.healers, ...raiddata.healers,
...Object.values(raiddata.participants).flat() ...Object.values<any>(raiddata.participants).flat()
].forEach(p => { ].forEach(p => {
p['color'] = getClassColor(p.class) p['color'] = getClassColor(p.class)
}) })
@@ -1,8 +1,9 @@
import { OnInit, Component } from '@angular/core'; import { OnInit, Component } from '@angular/core';
import { NbWindowRef, NbToastrService, NbDialogRef } from '@nebular/theme'; import { NbWindowRef, NbToastrService, NbDialogRef } from '@nebular/theme';
import { RaidData, Character } from '../../../../../../backend/Types/Types'; import { RaidData, Character } from '../../../../../../backend/Types/Types';
import { ApiService } from '../../services/login-api'; import { ClientApiService } from '../../services/client-login-api';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs'; import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { IApiService } from '../../services/ApiService';
@Component({ @Component({
selector: 'characterpicker', selector: 'characterpicker',
@@ -15,7 +16,7 @@ export class FrontcraftCharacerpickerComponent implements OnInit{
constructor( constructor(
protected dialogRef: NbDialogRef<FrontcraftCharacerpickerComponent>, protected dialogRef: NbDialogRef<FrontcraftCharacerpickerComponent>,
private api : ApiService, private api : IApiService,
private toast : NbToastrService private toast : NbToastrService
){} ){}
@@ -1,6 +1,6 @@
<div class="row"> <div class="row">
<div class="col-12 col-xl-6"> <div class="col-12 col-xl-6">
<nb-card [size]="'giant'"> <nb-card>
<nb-card-body> <nb-card-body>
<nb-tabset> <nb-tabset>
<nb-tab tabTitle="Info"> <nb-tab tabTitle="Info">
@@ -68,9 +68,7 @@
[src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" /> [src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
{{ participant.charactername }} {{ participant.charactername }}
</a> </a>
<span <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
*ngIf="participant.rank=='Trial'"
style="font-size: 9px;">
Trial Trial
</span> </span>
</div> </div>
@@ -97,9 +95,7 @@
[src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" /> [src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
{{ participant.charactername }} {{ participant.charactername }}
</a> </a>
<span <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
*ngIf="participant.rank=='Trial'"
style="font-size: 9px;">
Trial Trial
</span> </span>
</div> </div>
@@ -128,9 +124,7 @@
[src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" /> [src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
{{ participant.charactername }} {{ participant.charactername }}
</a> </a>
<span <span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
*ngIf="participant.rank=='Trial'"
style="font-size: 9px;">
Trial Trial
</span> </span>
</div> </div>
@@ -149,41 +143,52 @@
</nb-card> </nb-card>
</div> </div>
<div class="col-12 col-xl-6"> <div class="col-12 col-xl-6">
<nb-card *ngIf="isTier"> <nb-card *ngIf="isTier">
<nb-card-body> <nb-card-body>
<nb-tabset> <nb-tabset>
<nb-tab tabTitle="Reserves" [active]="reservesShown"> <nb-tab tabTitle="Reserves" [active]="reservesShown">
<input type="text" nbInput [(ngModel)]="search" (change)="changeSearch()" placeholder="Search" <input type="text" nbInput [(ngModel)]="search" (change)="changeSearch()" placeholder="Search" fullWidth="true">
fullWidth="true">
<nb-list> <nb-list class="">
<nb-list-item *ngFor="let item of displayedtokens | keyvalue"> <nb-list-item *ngFor="let item of displayedtokens | keyvalue">
<wowhead [item]="item.value[0]"></wowhead><br /> <table>
<div class="row"> <tr>
<div *ngFor="let token of item.value" class="col-12 col-md-6 col-xl-4"> <td>
<span [ngStyle]="{'text-decoration': token.rank=='Trial'? 'line-through' : 'none currentcolor solid' }"> <wowhead [item]="item.value[0]"></wowhead><br />
[ {{token.level}} ]
<span style="text-transform: capitalize;" </td>
[ngStyle]="{'color':token.level>=10?'#ff8000':token.level>=8?'#a335ee':token.level>=6?'#0070dd':token.level>=4?'#1eff00':token.level>=2?'#ffffff':'#9d9d9d'}"> </tr>
{{token.charactername}} <tr>
</span> <td>
</span> <div class="row">
&nbsp; <div
<ng-template #tooltip> *ngFor="let token of item.value"
<div style="color:white"> class="col-12 col-md-6 col-xl-4">
Becomes valid when promoted to Raider <span
[ngStyle]="{'text-decoration': token.rank=='Trial'? 'line-through' : 'none currentcolor solid' }">
<span style="text-transform: capitalize;">
[&nbsp;{{token.level}}&nbsp;]&nbsp;
<a [routerLink]="'/frontcraft/character/'+token.charactername"
[ngStyle]="{'color':token.level>=10?'#ff8000':token.level>=8?'#a335ee':token.level>=6?'#0070dd':token.level>=4?'#1eff00':token.level>=2?'#ffffff':'#9d9d9d'}">
{{token.charactername}}
</a>
</span>
</span>
<ng-template #tooltip>
<div style="color:white">
Becomes valid when promoted to Raider
</div>
</ng-template>
<span *ngIf="token.rank=='Trial'" style="font-size: 9px;" [nbPopover]="tooltip"
nbPopoverTrigger="hover" nbPopoverPlacement="top">
Trial
</span><br />
</div>
</div> </div>
</ng-template>
<span </td>
*ngIf="token.rank=='Trial'" </tr>
style="font-size: 9px;" </table>
[nbPopover]="tooltip"
nbPopoverTrigger="hover"
nbPopoverPlacement="top">
Trial
</span><br />
</div>
</div>
</nb-list-item> </nb-list-item>
</nb-list> </nb-list>
</nb-tab> </nb-tab>
@@ -1,12 +1,13 @@
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute, Router, NavigationStart } from '@angular/router'; import { ActivatedRoute, Router, NavigationStart } from '@angular/router';
import { ApiService as ApiService } from '../../services/login-api'; import { ClientApiService as ClientApiService } from '../../services/client-login-api';
import { RaidData, Raid, Signup, Character, Spec, Item, SRToken } from '../../../../../../backend/Types/Types'; import { RaidData, Raid, Signup, Character, Spec, Item, SRToken } from '../../../../../../backend/Types/Types';
import { NbWindowService, NbToastrService, NbDialogService } from '@nebular/theme'; import { NbWindowService, NbToastrService, NbDialogService } from '@nebular/theme';
import { FrontcraftCharacerpickerComponent } from './characterpicker.component'; import { FrontcraftCharacerpickerComponent } from './characterpicker.component';
import { getClassColor, SpecT } from '../../../../../../backend/Types/PlayerSpecs'; import { getClassColor, SpecT } from '../../../../../../backend/Types/PlayerSpecs';
import { FrontcraftBuyTokenComponent } from '../shop/buytoken.component'; import { FrontcraftBuyTokenComponent } from '../shop/buytoken.component';
import { allItems } from '../../../../../../backend/Types/Items'; import { allItems } from '../../../../../../backend/Types/Items';
import { IApiService } from '../../services/ApiService';
@Component({ @Component({
selector: 'raid', selector: 'raid',
@@ -45,7 +46,7 @@ export class FrontcraftRaidComponent implements OnInit, OnDestroy{
uuid uuid
constructor( constructor(
private api: ApiService, private api: IApiService,
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router, private router: Router,
private dialogService : NbDialogService, private dialogService : NbDialogService,
@@ -1,8 +1,9 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ApiService } from '../../services/login-api'; import { ClientApiService } from '../../services/client-login-api';
import { Raid, RaidData } from '../../../../../../backend/Types/Types'; import { Raid, RaidData } from '../../../../../../backend/Types/Types';
import { NbWindowRef, NbDialogRef } from '@nebular/theme'; import { NbWindowRef, NbDialogRef } from '@nebular/theme';
import { Tiers, _Tiers } from '../../../../../../backend/Types/Items'; import { Tiers, _Tiers } from '../../../../../../backend/Types/Items';
import { IApiService } from '../../services/ApiService';
const ONE_MINUTE = 60000 const ONE_MINUTE = 60000
const ONE_HOUR = 60 * ONE_MINUTE const ONE_HOUR = 60 * ONE_MINUTE
@@ -27,7 +28,7 @@ export class FrontcraftCreateRaidsComponent implements OnInit {
constructor( constructor(
protected dialogRef: NbDialogRef<FrontcraftCreateRaidsComponent>, protected dialogRef: NbDialogRef<FrontcraftCreateRaidsComponent>,
private api: ApiService private api: IApiService
) {} ) {}
loadNext(cardData) { loadNext(cardData) {
@@ -1,8 +1,9 @@
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Component, OnInit, OnDestroy } from '@angular/core';
import { ApiService } from '../../services/login-api'; import { ClientApiService } from '../../services/client-login-api';
import { NbWindowService, NbDialogService } from '@nebular/theme'; import { NbWindowService, NbDialogService } from '@nebular/theme';
import { FrontcraftCreateRaidsComponent } from './createraid.compontent'; import { FrontcraftCreateRaidsComponent } from './createraid.compontent';
import { Router, NavigationStart } from '@angular/router'; import { Router, NavigationStart } from '@angular/router';
import { IApiService } from '../../services/ApiService';
@Component({ @Component({
selector: 'raids', selector: 'raids',
@@ -19,7 +20,7 @@ export class FrontcraftRaidsComponent implements OnInit, OnDestroy{
uuid uuid
constructor( constructor(
private api: ApiService, private api: IApiService,
private router: Router, private router: Router,
private dialogService: NbDialogService private dialogService: NbDialogService
) { ) {
@@ -60,14 +60,21 @@
<nb-tab tabTitle="priorities"> <nb-tab tabTitle="priorities">
<nb-list> <nb-list>
<nb-list-item *ngFor="let item of rules | keyvalue"> <nb-list-item *ngFor="let item of rules | keyvalue">
<wowhead [item]="item.value[0]"></wowhead><br> <table >
<div class="row" *ngFor="let rule of item.value"> <tr>
<div class="col-4"> <td colspan="2">
<span *ngIf="rule.modifier>0">+</span>{{rule.modifier}} {{rule.race}} <span [ngStyle]="{'color':rule.color}">{{rule.specname}} {{rule.class}}</span> <wowhead [item]="item.value[0]"></wowhead>
</div> </td>
<div class="col-8" style="color:white"> ({{rule.description}})</div> </tr>
<br /> <tr *ngFor="let rule of item.value">
</div> <td style="width: 250px;">
<span *ngIf="rule.modifier>0">+</span>{{rule.modifier}} {{rule.race}} <span [ngStyle]="{'color':rule.color}">{{rule.specname}} {{rule.class}}</span>
</td>
<td>
<div style="color:white"> ({{rule.description}})</div>
</td>
</tr>
</table>
</nb-list-item> </nb-list-item>
</nb-list> </nb-list>
</nb-tab> </nb-tab>
@@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ApiService as ApiService } from '../../services/login-api';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs'; import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { IApiService } from '../../services/ApiService';
@Component({ @Component({
selector: 'rules', selector: 'rules',
@@ -12,7 +12,7 @@ export class FrontcraftRulesComponent implements OnInit{
rules = {} rules = {}
constructor( constructor(
private api: ApiService, private api: IApiService,
){ ){
} }
@@ -1,10 +1,11 @@
import { Component, OnInit, ContentChild, AfterContentInit, ViewChild, AfterViewInit, Input, Output, EventEmitter } from '@angular/core'; import { Component, OnInit, ContentChild, AfterContentInit, ViewChild, AfterViewInit, Input, Output, EventEmitter } from '@angular/core';
import { ApiService as ApiService } from '../../services/login-api'; import { ClientApiService as ClientApiService } from '../../services/client-login-api';
import { FrontcraftItemSelectComponent } from './itemselector.component'; import { FrontcraftItemSelectComponent } from './itemselector.component';
import { NbWindowService, NbWindowRef, NbToastrService, NbDialogService, NbDialogRef } from '@nebular/theme'; import { NbWindowService, NbWindowRef, NbToastrService, NbDialogService, NbDialogRef } from '@nebular/theme';
import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types'; import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs'; import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { _Tiers, allItems, Tiers } from '../../../../../../backend/Types/Items'; import { _Tiers, allItems, Tiers } from '../../../../../../backend/Types/Items';
import { IApiService } from '../../services/ApiService';
@Component({ @Component({
selector: 'buyToken', selector: 'buyToken',
@@ -88,7 +89,7 @@ import { _Tiers, allItems, Tiers } from '../../../../../../backend/Types/Items';
constructor( constructor(
private toastr: NbToastrService, private toastr: NbToastrService,
protected dialogRef: NbDialogRef<FrontcraftBuyTokenComponent>, protected dialogRef: NbDialogRef<FrontcraftBuyTokenComponent>,
private api : ApiService private api : IApiService
){} ){}
async ngOnInit() { async ngOnInit() {
@@ -1,6 +1,4 @@
import { Component, OnInit, Input, } from '@angular/core'; import { Component, OnInit, Input, } from '@angular/core';
import { ApiService as ApiService } from '../../services/login-api';
import { NbToastrService, } from '@nebular/theme';
import { Item, } from '../../../../../../backend/Types/Types'; import { Item, } from '../../../../../../backend/Types/Types';
import { _Tiers, } from '../../../../../../backend/Types/Items'; import { _Tiers, } from '../../../../../../backend/Types/Items';
@@ -1,6 +1,7 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { ApiService } from '../../services/login-api'; import { ClientApiService } from '../../services/client-login-api';
import { Item, Character } from '../../../../../../backend/Types/Types'; import { Item, Character } from '../../../../../../backend/Types/Types';
import { IApiService } from '../../services/ApiService';
@Component({ @Component({
selector: 'itemselect', selector: 'itemselect',
@@ -18,7 +19,7 @@ export class FrontcraftItemSelectComponent implements OnInit{
@Output() onSelect = new EventEmitter<Item>(); @Output() onSelect = new EventEmitter<Item>();
constructor( constructor(
private api: ApiService, private api: IApiService,
){} ){}
async ngOnInit(){ async ngOnInit(){
@@ -1,9 +1,7 @@
import { Component, OnInit, ContentChild, AfterContentInit, ViewChild, AfterViewInit, Input, Output, EventEmitter } from '@angular/core'; import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { ApiService as ApiService } from '../../services/login-api'; import { ClientApiService as ClientApiService } from '../../services/client-login-api';
import { FrontcraftItemSelectComponent } from './itemselector.component'; import { NbDialogService } from '@nebular/theme';
import { NbWindowService, NbWindowRef, NbToastrService, NbDialogService, NbDialogRef } from '@nebular/theme'; import { Item, Character, Signup } from '../../../../../../backend/Types/Types';
import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { _Tiers, allItems } from '../../../../../../backend/Types/Items'; import { _Tiers, allItems } from '../../../../../../backend/Types/Items';
@Component({ @Component({
@@ -20,8 +18,6 @@ export class FrontcraftShopComponent implements OnInit{
allItems = allItems allItems = allItems
constructor( constructor(
private api: ApiService,
private dialogService : NbDialogService
){ ){
} }
@@ -1,6 +1,4 @@
import { Component, OnInit, Input } from '@angular/core'; import { Component, OnInit, Input } from '@angular/core';
import { ApiService as ApiService } from '../../services/login-api';
import { NbToastrService } from '@nebular/theme';
import { Item } from '../../../../../../backend/Types/Types'; import { Item } from '../../../../../../backend/Types/Types';
import { _Tiers } from '../../../../../../backend/Types/Items'; import { _Tiers } from '../../../../../../backend/Types/Items';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
@@ -1,11 +1,11 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ApiService, hash } from '../../services/login-api'; import { ActivatedRoute } from '@angular/router';
import { Router, ActivatedRoute } from '@angular/router';
import { User, Spec, Character } from '../../../../../../backend/Types/Types'; import { User, Spec, Character } from '../../../../../../backend/Types/Types';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs'; import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { _Tiers } from '../../../../../../backend/Types/Items'; import { _Tiers } from '../../../../../../backend/Types/Items';
import { _Rank } from '../../../../../../backend/Types/Types'; import { _Rank } from '../../../../../../backend/Types/Types';
import { NbToastrService } from '@nebular/theme'; import { NbToastrService } from '@nebular/theme';
import { hash, IApiService } from '../../services/ApiService';
@Component({ @Component({
selector: 'user-component', selector: 'user-component',
@@ -19,12 +19,16 @@ export class FrontcraftUserComponent implements OnInit{
ranks = _Rank ranks = _Rank
myProfile = false myProfile = false
manageUser manageUser
user:User = {} as any user:User = {
rank: 'Guest',
username: 'Guest',
pwhash: ""
}
characters : (Character & Spec)[] = [] characters : (Character & Spec)[] = []
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private api : ApiService, private api : IApiService,
private toastr: NbToastrService private toastr: NbToastrService
){} ){}
@@ -1,8 +1,9 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ApiService as ApiService } from '../../services/login-api'; import { ClientApiService as ClientApiService } from '../../services/client-login-api';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { _Rank, _Class, _Race, RPCPermission } from '../../../../../../backend/Types/Types' import { _Rank, _Class, _Race, RPCPermission } from '../../../../../../backend/Types/Types'
import { NbToastrService } from '@nebular/theme'; import { NbToastrService } from '@nebular/theme';
import { IApiService } from '../../services/ApiService';
@Component({ @Component({
@@ -15,8 +16,7 @@ export class ChangePermissionsComponent implements OnInit{
ranks = _Rank ranks = _Rank
constructor( constructor(
private router : Router, private api : IApiService,
private api : ApiService,
private toastr: NbToastrService private toastr: NbToastrService
){} ){}
@@ -32,9 +32,6 @@ export class ChangePermissionsComponent implements OnInit{
perm[key] = value perm[key] = value
console.log(perm);
await modify.setPermission(perm).catch(e => { await modify.setPermission(perm).catch(e => {
}) })
@@ -1,5 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ApiService } from '../services/login-api'; import { ClientApiService } from '../services/client-login-api';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
@Component({ @Component({
@@ -13,7 +13,6 @@ import { Router } from '@angular/router';
export class PermissionsComponent implements OnInit{ export class PermissionsComponent implements OnInit{
constructor( constructor(
private loginSvc : ApiService,
private router: Router private router: Router
){} ){}
@@ -1,24 +0,0 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { PermissionsComponent } from './permissions-layout.component';
import { ChangePermissionsComponent } from './changePermissions/changePermissions.component';
export const routes: Routes = [
{
path: '',
component: PermissionsComponent,
children: [
{
path: '**',
component: ChangePermissionsComponent,
},
]
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class PermissionsRoutingModule {
}
@@ -15,13 +15,11 @@ import {
} from '@nebular/theme'; } from '@nebular/theme';
import { PermissionsComponent } from './permissions-layout.component'; import { PermissionsComponent } from './permissions-layout.component';
import { ThemeModule } from '../../@theme/theme.module'; import { ThemeModule } from '../../@theme/theme.module';
import { PermissionsRoutingModule } from './permissions-routing.module';
import { ChangePermissionsComponent } from './changePermissions/changePermissions.component'; import { ChangePermissionsComponent } from './changePermissions/changePermissions.component';
@NgModule({ @NgModule({
imports: [ imports: [
NbToggleModule, NbToggleModule,
PermissionsRoutingModule,
CommonModule, CommonModule,
FormsModule, FormsModule,
RouterModule, RouterModule,
@@ -0,0 +1,23 @@
import { Auth, FrontcraftIfc, FrontcraftFeatureIfc, User, SomeOf } from '../../../../../backend/Types/Types';
import { saltedHash } from '../../../../../backend/Util/hash';
import { RPCSocket } from 'rpclibrary';
export class IApiService{
getUnprivilegedSocket: () => RPCSocket & FrontcraftIfc
getAuth: () => Auth | undefined
checkLogin: () => Promise<boolean>
initialize: () => Promise<any>
getCurrentUser: () => User | undefined
login: (username: string, password: string) => Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>>
connectShoutbox: (callback:Function) => Promise<Function>
kick: () => Promise<void>
logout: () => Promise<void>
get: <K extends (keyof FrontcraftIfc | keyof FrontcraftFeatureIfc)>(feature : K) => K extends keyof FrontcraftIfc?FrontcraftIfc[K]:
K extends keyof FrontcraftFeatureIfc?(FrontcraftFeatureIfc[K] | void):
never
}
export async function hash(value:string) : Promise<string>{
return saltedHash(value, "")
}
@@ -1,31 +1,29 @@
import { Injectable, Injector, NgZone } from "@angular/core"; import { Injectable } from "@angular/core";
import {RPCSocket} from 'rpclibrary/js/src/Frontend' import {RPCSocket} from 'rpclibrary/js/src/Frontend'
import { Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../backend/Types/Types' import { Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../backend/Types/Types'
import { CookieService } from 'ngx-cookie-service';
import { Router } from '@angular/router';
import { ShoutMessage } from '../../../../../backend/Components/Shoutbox/Interface'; import { ShoutMessage } from '../../../../../backend/Components/Shoutbox/Interface';
import { saltedHash } from '../../../../../backend/Util/hash'; import { hash, IApiService } from './ApiService';
import { NbToastrService } from '@nebular/theme';
declare const Cookies
@Injectable() @Injectable()
export class ApiService{ export class ClientApiService implements IApiService{
private socket:RPCSocket & FrontcraftIfc; private socket:RPCSocket & FrontcraftIfc;
private auth:Auth private auth:Auth
private privSocket: RPCSocket & SomeOf<FrontcraftFeatureIfc> private privSocket: RPCSocket & SomeOf<FrontcraftFeatureIfc>
constructor( constructor(){
private injector: Injector, window['s'] = this
private cookieSvc : CookieService, }
private ngZone : NgZone,
private toastr: NbToastrService
){}
getUnprivilegedSocket = () : RPCSocket & FrontcraftIfc => this.socket getUnprivilegedSocket = () : RPCSocket & FrontcraftIfc => this.socket
private getPrivilegedSocket = async (auth:Auth) : Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => { private getPrivilegedSocket = async (auth:Auth) : Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => {
if(this.privSocket) return this.privSocket if(this.privSocket) {
if(auth == null) throw new Error("Bad Auth") return this.privSocket
}
if(auth == null)
throw new Error("Bad Auth")
try{ try{
const sock = new RPCSocket( const sock = new RPCSocket(
@@ -38,24 +36,24 @@ export class ApiService{
}) })
sock.hook('getUserData', () => auth) sock.hook('getUserData', () => auth)
sock.hook('navigate', (where:string) => {
this.ngZone.run( () => {
this.injector.get(Router).navigateByUrl(where)
})
})
sock.on('close', async () => { sock.on('close', async () => {
console.log("priv#close");
//handled via unprivileged socket //handled via unprivileged socket
}) })
sock.on('error', async (e) => { sock.on('error', async (e) => {
console.log("priv#error", e);
//handled via unprivileged socket //handled via unprivileged socket
}) })
const authSock = await sock.connect<RPCSocket & SomeOf<FrontcraftFeatureIfc>>(auth.token.value) const authSock = await sock.connect<RPCSocket & SomeOf<FrontcraftFeatureIfc>>(auth.token.value)
this.auth = auth this.auth = auth
this.privSocket = authSock this.privSocket = authSock
this.cookieSvc.set('token', JSON.stringify(auth)) Cookies.set('token', JSON.stringify(auth))
// document.cookie = JSON.stringify(auth)
return authSock return authSock
}catch(e){ }catch(e){
if(this.privSocket) this.privSocket.destroy() if(this.privSocket) this.privSocket.destroy()
@@ -86,13 +84,11 @@ export class ApiService{
try{ try{
auth = await this.socket.UserManager.login(username, pwHash) auth = await this.socket.UserManager.login(username, pwHash)
}catch(e){ }catch(e){
this.toastr.danger("Login failed", "Error")
return return
} }
if(!auth){ if(!auth){
await this.logout() await this.logout()
this.toastr.danger("Login failed", "Error")
throw new Error("Login failed") throw new Error("Login failed")
} }
@@ -105,8 +101,8 @@ export class ApiService{
return sock return sock
} }
async connectShoutbox(handler) : Promise<Function>{ async connectShoutbox(callback:Function) : Promise<Function>{
const res = await this.get('Shoutbox').subscribe(handler) const res = await this.get('Shoutbox').subscribe(callback)
return async (msg: ShoutMessage) => await this.get('Shoutbox').shout(res.uuid, msg) return async (msg: ShoutMessage) => await this.get('Shoutbox').shout(res.uuid, msg)
} }
@@ -116,25 +112,21 @@ export class ApiService{
} }
logout = async () => { logout = async () => {
this.cookieSvc.set('token', undefined) Cookies.remove('token')
if(this.auth){ if(this.auth){
try{ try{
await this.socket.UserManager.logout(this.auth.user.username, this.auth.token.value) await this.socket.UserManager.logout(this.auth.user.username, this.auth.token.value)
}catch(e){ }catch(e){
//socket is dead console.warn(e);
} }
} }
if(this.privSocket) this.privSocket.destroy() if(this.privSocket) this.privSocket.destroy()
this.privSocket = null this.privSocket = null
this.auth = null this.auth = null
this.ngZone.run(() => {
this.injector.get(Router).navigate(['/auth']);
})
} }
initialize = async () : Promise<any> => { initialize = async (force = false) : Promise<any> => {
if(this.socket){ if(this.socket){
this.socket.destroy() this.socket.destroy()
this.socket = null this.socket = null
@@ -145,8 +137,6 @@ export class ApiService{
conn.on('close', async () => { conn.on('close', async () => {
}) })
this.socket = await conn.connect<FrontcraftIfc>() this.socket = await conn.connect<FrontcraftIfc>()
}catch(e){ }catch(e){
alert('Unable to connect. The server appears to be down.\nPress OK to refresh the page') alert('Unable to connect. The server appears to be down.\nPress OK to refresh the page')
@@ -155,9 +145,9 @@ export class ApiService{
} }
try{ try{
const cookie = JSON.parse(this.cookieSvc.get('token')) const cookie = JSON.parse(Cookies.get('token'))
if(cookie != null) { if(cookie != null && cookie != "") {
try{ try{
const auth = await this.socket.UserManager.getAuth(cookie.token.value) const auth = await this.socket.UserManager.getAuth(cookie.token.value)
if(!auth) return this.socket if(!auth) return this.socket
@@ -168,6 +158,7 @@ export class ApiService{
} }
} }
}catch(e){ }catch(e){
Cookies.remove('token')
} }
} }
@@ -181,12 +172,3 @@ export class ApiService{
return false return false
} }
} }
export async function hash(value:string) : Promise<string>{
return saltedHash(value, "")
}
//angular depenency manager requires this
export function initializeLoginSvc(svc: ApiService): () => Promise<any> {
return ()=>svc.initialize?svc.initialize():undefined
}
@@ -0,0 +1,99 @@
import { Injectable } from "@angular/core";
import {RPCSocket} from 'rpclibrary/js/src/Frontend'
import { Auth, User, _Class, FrontcraftFeatureIfc, SomeOf, FrontcraftIfc, } from '../../../../../backend/Types/Types'
import { hash, IApiService } from './ApiService';
declare const Cookies
@Injectable()
export class ServerApiService implements IApiService{
private socket:RPCSocket & FrontcraftIfc;
private auth:Auth
private privSocket: RPCSocket & SomeOf<FrontcraftFeatureIfc>
constructor(){}
getUnprivilegedSocket = () : RPCSocket & FrontcraftIfc => this.socket
get = <K extends (keyof FrontcraftIfc | keyof FrontcraftFeatureIfc)>(feature : K) : K extends keyof FrontcraftIfc?FrontcraftIfc[K]:
K extends keyof FrontcraftFeatureIfc?(FrontcraftFeatureIfc[K] | void):
never => {
//@ts-ignore
return this.socket[feature]
}
getCurrentUser = () : User | undefined => {
return this.auth?this.auth.user:undefined
}
login = async (username: string, password: string) : Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => {
const pwHash = await hash(password)
let auth
try{
auth = await this.socket.UserManager.login(username, pwHash)
}catch(e){
return
}
if(!auth){
await this.logout()
throw new Error("Login failed")
}
//attach error handler now so failed logins dont trigger reloads
this.socket.on('error', async (err) => {
console.log(err);
})
}
async connectShoutbox(callback:Function) : Promise<Function>{
return console.log
}
kick = async () => {
}
logout = async () => {
Cookies.remove('token')
if(this.auth){
try{
await this.socket.UserManager.logout(this.auth.user.username, this.auth.token.value)
}catch(e){
console.warn(e);
}
}
if(this.privSocket) this.privSocket.destroy()
this.privSocket = null
this.auth = null
}
initialize = async () : Promise<any> => {
if(this.socket){
this.socket.destroy()
this.socket = null
}
try{
let conn = new RPCSocket(20000, window.location.hostname)
conn.on('close', async () => {
})
this.socket = await conn.connect<FrontcraftIfc>()
}catch(e){
console.log(e);
throw new Error("Websocket cannot connect")
}
}
getAuth = () => this.auth
async checkLogin() : Promise<boolean>{
if(!this.auth) return false
const valid = this.socket.UserManager.checkToken(this.auth.token.value, this.auth.user.rank)
if(valid) return true
await this.logout()
return false
}
}
+9
View File
@@ -0,0 +1,9 @@
import { enableProdMode } from '@angular/core';
enableProdMode()
export { AppServerModule } from './app/app.server.module';
import { IApiService } from './app/frontcraft/services/ApiService';
export { IApiService }
export { ServerApiService } from './app/frontcraft/services/server-login-api';
+14 -3
View File
@@ -6,12 +6,23 @@
import { enableProdMode } from '@angular/core'; import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module'; import { FrontcraftAppModule } from './app/app.module';
import { environment } from './environments/environment'; import { environment } from './environments/environment';
import { IApiService } from "./app/frontcraft/services/ApiService"
import { ClientApiService } from './app/frontcraft/services/client-login-api';
if (environment.production) { if (environment.production) {
enableProdMode(); enableProdMode();
} }
platformBrowserDynamic().bootstrapModule(AppModule) const serviceObj = new ClientApiService()
.catch(err => console.error(err)); serviceObj.initialize().then(_ => {
platformBrowserDynamic([
{
provide: IApiService,
deps: [],
useValue: serviceObj
}
]).bootstrapModule(FrontcraftAppModule)
.catch(err => console.error(err));
})
-26
View File
@@ -1,26 +0,0 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"baseUrl": "./",
"paths": {
"@angular/*": [
"../node_modules/@angular/*"
],
"@nebular/*": [
"../node_modules/@nebular/*"
]
}
},
"exclude": [
"test.ts",
"**/*.spec.ts",
"../node_modules/@nebular/**/*.spec.ts",
"../node_modules/rpclibrary/js/**/*"
],
"include": [
"../src/*.ts",
"../src/**/*.ts",
"../node_modules/@nebular/**/*.ts"
]
}
+24
View File
@@ -0,0 +1,24 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"paths": {
"@angular/*": [
"./node_modules/@angular/*"
],
"@nebular/*": [
"./node_modules/@nebular/*"
]
}
},
"exclude": [
"test.ts",
"**/*.spec.ts",
"./node_modules/@nebular/**/*.spec.ts",
"./node_modules/rpclibrary/js/**/*"
],
"include": [
"./src/*.ts",
"./src/**/*.ts",
]
}
+9 -7
View File
@@ -1,15 +1,14 @@
{ {
"compileOnSave": false, "compileOnSave": false,
"compilerOptions": { "compilerOptions": {
"importHelpers": true, "outDir": "./out-tsc",
"module": "commonjs", "baseUrl": "./",
"outDir": "./dist/out-tsc", "declaration": true,
"sourceMap": true,
"declaration": false,
"moduleResolution": "node", "moduleResolution": "node",
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"target": "es5", "importHelpers": true,
"target": "es2015",
"typeRoots": [ "typeRoots": [
"node_modules/@types" "node_modules/@types"
], ],
@@ -20,5 +19,8 @@
"plugins": [ "plugins": [
{ "name": "tslint-language-service"} { "name": "tslint-language-service"}
] ]
} },
"angularCompilerOptions": {
"enableIvy": false,
},
} }
+15
View File
@@ -0,0 +1,15 @@
{
"extends": "./tsconfig.app.json",
"compilerOptions": {
"outDir": "./out-tsc/app-server",
"module": "commonjs",
"types": ["node"]
},
"files": [
"src/main.server.ts",
"server.ts"
],
"angularCompilerOptions": {
"entryModule": "./src/app/app.server.module#AppServerModule"
}
}
+36
View File
@@ -0,0 +1,36 @@
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: { server: './server.ts' },
resolve: { extensions: ['.js', '.ts'] },
mode: 'none',
target: 'node',
externals: [/(node_modules|main(\\|\/)..*(\\|\/).js)/],
output: {
path: path.join(__dirname, `dist`),
filename: '[name].js',
libraryTarget: 'commonjs'
},
module: {
rules: [
{ test: /\.ts$/, loader: 'ts-loader', exclude: /^(?!.*\.spec\.ts$).*\.ts$/ },
{
test: /(\\|\/)@angular(\\|\/)core(\\|\/).+\.js$/,
parser: { system: true }
}
]
},
plugins: [
new webpack.ContextReplacementPlugin(
/(.+)?angular(\\|\/)core(.+)?/,
path.join(__dirname, 'src'), // location of your src
{} // a map of your routes
),
new webpack.ContextReplacementPlugin(
/(.+)?express(\\|\/)(.+)?/,
path.join(__dirname, 'src'),
{}
)
]
};
+3 -9
View File
@@ -9,18 +9,12 @@
"strict": true, "strict": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"baseUrl": "./",
"outDir": "./lib", "outDir": "./lib",
//"types": ["node"], "types": ["node", "mocha"],
"strictNullChecks": false "strictNullChecks": false
}, },
"include": ["src/backend/**/*"], "include": ["src", "test"],
"exclude": [
"./src/frontend/**/*",
"./node_modules/**/*",
"./src/frontend/node_modules/**/*",
"./test",
],
"angularCompilerOptions": { "angularCompilerOptions": {
"enableIvy": false, "enableIvy": false,
"entryModule": "./src/backend/Admin/app.server.module#AppServerModule" "entryModule": "./src/backend/Admin/app.server.module#AppServerModule"