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>
+98 -1984
View File
File diff suppressed because it is too large Load Diff
+13 -14
View File
@@ -4,19 +4,17 @@
"version": "1.0.0",
"scripts": {
"tsc": "tsc",
"launch": "node dist/server/main.js",
"launch": "node lib/src/backend/Launcher.js",
"start": "npm run build && 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",
"build": "npm run build-backend && npm run build-frontend",
"build-backend": "npm run clean-backend && tsc",
"build-frontend": "npm run clean-frontend && (mkdir static || rm -rf static/*) && npm run build-dashboard",
"build-dashboard": "cd src/frontend && npm i && npm run build && cp -r dist/* ../../static",
"build": "npm run build-frontend && npm run build-backend",
"build-backend": "npm run clean-backend && npm run tsc",
"build-frontend": "npm run clean-frontend && (mkdir dist || rm -rf dist/*) && npm run build-dashboard",
"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-backend": "rm -rf lib plugins config widget .rpt2_cache *.js *.ts",
"clean-frontend": "rm -rf src/frontend/dist static",
"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"
"clean-backend": "rm -rf lib plugins config widget .rpt2_cache ",
"clean-frontend": "rm -rf src/frontend/dist dist"
},
"repository": {
"type": "git",
@@ -32,6 +30,7 @@
"circular-buffer": "^1.0.2",
"crypto-js": "^3.1.9-1",
"debug": "^4.1.1",
"domino": "^2.1.4",
"express": "^4.16.4",
"frontblock": "^0.15.2",
"frontblock-generic": "^0.34.8",
@@ -42,6 +41,7 @@
"loadson": "^1.0.0",
"log4js": "^4.5.1",
"lowdb": "^1.0.0",
"ngx-cookie-service": "^2.4.0",
"node-fetch": "^2.6.0",
"path": "^0.12.7",
"reflect-metadata": "^0.1.13",
@@ -54,16 +54,15 @@
"tsyringe": "^4.0.1",
"upgiter": "^1.0.4",
"uuid": "^3.3.3",
"xml2js": "^0.4.22"
"xml2js": "^0.4.22",
"xmlhttprequest": "^1.8.0"
},
"devDependencies": {
"madge": "^3.6.0",
"mocha": "^7.0.0",
"mocha": "^7.1.0",
"terser-webpack-plugin": "^1.4.1",
"ts-loader": "^5.3.3",
"typescript": "^3.5.3",
"webpack": "^4.39.2",
"webpack-cli": "^3.3.5"
"typescript": "^3.5.3"
},
"files": [
"lib/**/*"
+28 -69
View File
@@ -1,6 +1,6 @@
'use strict'
import { getLogger } from 'frontblock-generic/Types';
import { getLogger, Logger, } from "log4js";
import { promises as fs, mkdirSync } from "fs"
import { RPCServer } from 'rpclibrary'
import * as Path from 'path'
@@ -22,12 +22,7 @@ import { Injector } from '../Injector/Injector';
import { Shoutbox } from '../Components/Shoutbox/Shoutbox';
import { PubSub } from '../Components/PubSub/PubSub';
//import { ngExpressEngine } from '../../frontend/node_modules/@nguniversal/express-engine';
//import { APP_BASE_HREF } from '../../frontend/';
//import { AppServerModule } from './app.server.module';
const logger = getLogger("admin", 'debug')
getLogger().level = 'debug'
@RootComponent({
injectable: IAdmin,
@@ -73,15 +68,15 @@ implements TableDefinitionExporter, IAdmin {
await this.makeKnex()
this.startWebsocket()
await Promise.all( this.frontworkComponents.map(c => c.initialize?c.initialize():undefined ))
logger.debug(this.frontworkComponents.length+" components initialized")
this.startWebserver()
getLogger('Admin#start').debug(this.frontworkComponents.length+" components initialized")
await this.startWebserver()
}
stop(){
Promise.all([
...this.frontworkComponents.map(c => c.stop?c.stop():undefined ),
])
.catch(e => logger.warn(e))
.catch(e => getLogger('Admin#stop').warn(e))
.finally(() => {
this.rpcServer.destroy()
process.exit(0)
@@ -123,92 +118,56 @@ implements TableDefinitionExporter, IAdmin {
], {
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){
logger.warn("Webserver is already running")
getLogger('Admin#startWebserver').warn("Webserver is already running")
return
}
let port:number = this.config.getConfig().httpPort
this.express = express()
/*
this.express.engine('html', ngExpressEngine({
bootstrap: AppServerModule,
}));
const distFolder = "../../../../dist"
const ngExpressServer = Path.join(__dirname, distFolder, 'server.js')
this.express.set('view engine', 'html');
this.express.set('views', 'static');
// 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');
this.express.get('*.*', (req, res)=>{
//console.log('*.*', req.path);
res.sendFile(Path.join(__dirname, distFolder,'browser',decodeURIComponent(req.path)))
})
// All regular routes use the Universal engine
this.express.get('*', (req, res) => {
res.status(301)
res.redirect('/')
//res.render('index', { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
});
*/
/* */
// get the compiled FrontendPlugins.js
this.express.use('/', express.static('static'))
try{
const req = require(distFolder+"/server.js")
await req.attachExpress(this.express)
getLogger('Admin#startWebserver').info('Frontend from '+ngExpressServer+" loaded")
}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)
}
this.express.get('/plugins/:id'+".js", async (request, response) => {
const pth = Path.resolve("plugins/"+request.params.id, "FrontendPlugin.js");
const file = await fs.readFile(pth)
const frontend = file.toString()
response.status(200)
response.set('Content-Type', 'application/javascript')
response.send(frontend)
this.express.listen(port, () => {
getLogger('Admin#startWebserver').info('Admin panel listening for HTTP on *'+port)
})
// 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(){
if(this.httpServer == null || this.express == null){
logger.warn("Webserver is not running")
getLogger('Admin#stopWebserver').warn("Webserver is not running")
return
}
this.httpServer.close()
this.httpServer = null
this.express = null
logger.info("Webserver stopped")
getLogger('Admin#stopWebserver').info("Webserver stopped")
}
async makeKnex():Promise<Knex>{
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'){
mkdirSync(Path.dirname((<any>conf.connection).filename), {recursive: true})
}
@@ -237,6 +196,6 @@ implements TableDefinitionExporter, IAdmin {
}
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()
})
-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 {}
*/
+117 -106
View File
@@ -17,6 +17,8 @@ import { IRaidManager } from "../Raid/Interface";
import { IItemManager } from "../Item/Interface";
import { IGuildManager } from "../Guild/Interface";
getLogger().level = "debug"
const uuid = require('uuid/v4')
const salt = "6pIbc6yjSN"
@@ -24,33 +26,33 @@ const ONE_WEEK = 604800000
type Serverstate<SubresT, InterfaceT extends RPCInterface> = {
server: RPCServer<SubresT, InterfaceT>,
port : number,
port: number,
};
@Injectable(IUserManager)
export class UserManager
implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManager{
implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManager {
name = "UserManager" as "UserManager"
@Inject(IAdmin)
private admin: IAdmin
@Inject(IGuildManager)
private guild : GuildManager
private guild: GuildManager
@Inject(IItemManager)
private item : ItemManager
private item: ItemManager
@Inject(IRaidManager)
private raid : RaidManager
private raid: RaidManager
@Inject(ICharacterManager)
private character : CharacterManager
private character: CharacterManager
exporters :any[] = []
rankServer : Serverstate<{}, FrontcraftFeatureIfc>
userLogins : {[username in string] : UserRecord} = {}
exporters: any[] = []
rankServer: Serverstate<{}, FrontcraftFeatureIfc>
userLogins: { [username in string]: UserRecord } = {}
allowed: string[] = []
exportRPCs = () => [
@@ -71,13 +73,13 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
this.changeRank,
this.adminChangePassword
]
},{
}, {
name: 'modifyPermissions' as 'modifyPermissions',
exportRPCs: () => [
this.getPermissions,
this.setPermission,
]
},{
}, {
name: 'softreserveCurrency' as 'softreserveCurrency',
exportRPCs: () => [
this.incrementCurrency,
@@ -86,7 +88,7 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
]
}]
changeRank = async (user:User, rank:Rank): Promise<User> => {
changeRank = async (user: User, rank: Rank): Promise<User> => {
await this.admin
.knex('users')
.where({
@@ -116,31 +118,31 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
table.integer(tier).defaultTo(1)
})
}
},{
}, {
name: 'rpcpermissions',
tableBuilder: (table) => {
table.string("rpcname").primary().notNullable()
_Rank.forEach(r => {
if(r === 'ADMIN')
if (r === 'ADMIN')
table.boolean(r).defaultTo(true).notNullable()
else
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 () => {
this.exporters = [this.guild, this.item, this.raid, this.character]
//set up permissions
getLogger('UserManager').debug('setting up permissions')
getLogger('UserManager#initialize').debug('setting up permissions')
await Promise.all(
[this, ...this.exporters].flatMap(exp => exp.exportRPCFeatures().map(async (feature) => {
try{
try {
await this.admin.knex.insert({ rpcname: feature.name }).into('rpcpermissions')
}catch(e){
} catch (e) {
}
})))
@@ -157,61 +159,71 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
Object.values(x.connections).forEach(c => c.destroy())
})
try{
try {
return this.rankServer.server.destroy()
}catch(e){
//getLogger('UserManager').warn(e)
} catch (e) {
getLogger('UserManager#stop').debug(String(e))
}
}
checkExpiredSessions = () => {
Object.values(this.userLogins).map(userLogin => {
const auth = userLogin.auth
if(!this.checkToken(auth.token.value)){
if (!this.checkToken(auth.token.value)) {
this.logout(auth.user.username, auth.token.value)
}
})
}
checkConnection = async (socket: Socket) => {
let data : any
let tries = 0
while(!data){
tries ++
if(tries === 5){
getLogger('UserManager').debug('Connection check failed for connection *'+socket.port)
socket.destroy()
checkConnection = async (socket: Socket, retries = 0) : Promise<boolean> => {
if(retries < 0){
return false
}
data = await Promise.race([socket.call('getUserData'), new Promise((res, rej) => { setTimeout(res, 1000);})])
//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(!this.userLogins[data.user.username]){
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)
return false
}
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
}
changePassword = async (userToken:string, pwHash:string) : Promise<User> => {
changePassword = async (userToken: string, pwHash: string): Promise<User> => {
const record = this.getUserRecordByToken(userToken)
if(!record) return {} as User
if (!record) return {} as User
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)
await this.admin.knex('users')
.update({pwhash: salted})
.update({ pwhash: salted })
.where({
username: user.username
})
const usr = await this.getUser(user.username)
if(!usr) return {} as any
if (!usr) return {} as any
await this.adminLogout(usr.username)
return usr
}
@@ -223,49 +235,35 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
await Promise.all(
Object.entries(this.userLogins).map(([username, record]) => {
if(record.user.rank === "ADMIN") return
if (record.user.rank === "ADMIN") return
return this.adminLogout(username)
})
)
}
getPermissions = async () : Promise<RPCPermission[]> => {
getPermissions = async (): Promise<RPCPermission[]> => {
return await this.admin.knex.select('*').from('rpcpermissions')
}
getPermission = async (feature: keyof FrontcraftFeatureIfc, rank:Rank) : Promise<boolean> => {
const perm : RPCPermission = await this.admin.knex
getPermission = async (feature: keyof FrontcraftFeatureIfc, rank: Rank): Promise<boolean> => {
const perm: RPCPermission = await this.admin.knex
.select(rank)
.from('rpcpermissions')
.where('rpcname', '=', <string>feature)
.first()
if(!perm) return false
if (!perm) return false
return perm[rank]
}
getRPCForRank = async (rank: Rank): Promise<AnyRPCExporter[]> => {
let rpcs = [
...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'){
createUser = async (user: User): Promise<User> => {
if (user.rank === 'ADMIN') {
const admins = await this.admin.knex
.select("*")
.from('users')
.where({rank: 'ADMIN'})
.where({ rank: 'ADMIN' })
if(admins.length > 0){
if (admins.length > 0) {
return {} as User
}
}
@@ -284,7 +282,7 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
return userRecord
}
getUser = async (username: string) : Promise<User | void> => await this.admin
getUser = async (username: string): Promise<User | void> => await this.admin
.knex('users')
.select('*')
.where({
@@ -292,26 +290,35 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
})
.first()
logout = async (username:string, tokenValue : string) : Promise<void> => {
try{
if(!this.checkTokenOwnedByUser(username, tokenValue)) return
logout = async (username: string, tokenValue: string): Promise<void> => {
try {
if (!this.checkTokenOwnedByUser(username, tokenValue)) return
return await this.adminLogout(username)
}catch(e){
} catch (e) {
}
}
adminLogout = async(username: string) : Promise<void> => {
adminLogout = async (username: string): Promise<void> => {
try {
if (this.userLogins[username]) {
const token = this.userLogins[username].auth.token.value
//doesn't matter if error or success
Object.values(this.userLogins[username].connections).forEach(async (sock) => {
try{
if(this.userLogins[username]){
await Promise.all (Object.values(this.userLogins[username].connections).map(async (sock) => {
await sock.call('kick')
}))
this.allowed = this.allowed.filter(allowed => allowed !== this.userLogins[username].auth.token.value)
}catch(e){
//getLogger('UserManager#adminLogout#kick').debug(String(e))
}
})
this.allowed = this.allowed.filter(allowed => {
return allowed != token
})
delete this.userLogins[username]
}
}catch(e){}
} catch (e) {
getLogger('UserManager#adminLogout').debug(String(e), this.userLogins)
}
}
wipeCurrency = async () => {
@@ -324,9 +331,9 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
}))
}
login = async(username:string, pwHash:string) : Promise<Auth> => {
login = async (username: string, pwHash: string): Promise<Auth> => {
username = username.toLowerCase()
const user:User = await this.admin.knex
const user: User = await this.admin.knex
.select('*')
.from('users')
.where({ username: username })
@@ -334,67 +341,69 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
const salted = await saltedHash(pwHash, salt)
if(user && salted === user.pwhash){
if (user && salted === user.pwhash) {
delete user.pwhash
//return existing auth
if(this.userLogins[username] != null){
if (this.userLogins[username] != null) {
return this.userLogins[username].auth
}
const token = this.createToken(user)
const userAuth : Auth = {
const userAuth: Auth = {
token: token,
user: user,
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)
return userAuth
}
throw new Error('login failed')
}
getUserRecordByToken(tokenValue: string){
getUserRecordByToken(tokenValue: string) {
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)
if(maybeAuth)
if (maybeAuth)
return maybeAuth.auth
return
}
startRankServer = async (port: number) : Promise<RPCServer<{},FrontcraftFeatureIfc>> => {
startRankServer = async (port: number): Promise<RPCServer<{}, FrontcraftFeatureIfc>> => {
let rpcs = [
...this.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) => {
const record = this.getUserRecordByToken(sesame!)
if(!record) return false
if (!record) return false
return await this.getPermission(exporter.name, record.user.rank)
},
closeHandler: (socket) => {
Object.values(this.userLogins)
.forEach(login => delete login.connections[socket.port])
Object.values(this.userLogins).forEach(login => delete login.connections[socket.port])
getLogger('UserManager#closeHandler').debug(this.userLogins, this.allowed)
},
connectionHandler: (socket) => {
this.checkConnection(socket).then(res => {
if(!res){
this.checkConnection(socket, 10).then(res => {
if (!res) {
getLogger('UserManager#connectionHandler').debug("Connection on "+socket.port+" failed to authenticate")
socket.destroy();
}
}).catch((e) => {
getLogger('UserManager#connectionHandler').debug(String(e))
socket.destroy();
})
},
errorHandler: (socket, e, rpcName, args) => {
getLogger('UserManager').error(rpcName, args, e);
getLogger('UserManager#errorHandler').error(rpcName, args, e);
},
sesame: (sesame) => this.checkToken(sesame),
visibility: '0.0.0.0'
@@ -403,25 +412,27 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
return rpcServer
}
checkToken = (token: string) : boolean => this.allowed.includes(token)
checkToken = (token: string): boolean => {
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) => {
username = username.toLowerCase()
const maybeRecord = this.getUserRecordByToken(tokenValue)
if(!maybeRecord || maybeRecord.auth.user.username != username){
if (!maybeRecord || maybeRecord.auth.user.username != username) {
return false
}
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
}
const token:Token = {
const token: Token = {
value: uuid(),
user_id: user.id!,
created: Date.now()
@@ -430,9 +441,9 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
return token
}
getCurrency = async(user:User, tier?: Tiers) : Promise<number> => {
if(!tier) return 0
const usr : User = await this.admin
getCurrency = async (user: User, tier?: Tiers): Promise<number> => {
if (!tier) return 0
const usr: User = await this.admin
.knex('users')
.where('username', '=', user.username)
.select('*')
@@ -442,15 +453,15 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
}
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')
.where('id', '=', user.id)
.select('*')
.first()
if(!usr || usr[tier]! <= 0) return
if (!usr || usr[tier]! <= 0) return
await this.admin
.knex('users')
@@ -459,15 +470,15 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
}
incrementCurrency = async (user: User, tier: Tiers, value = 1) => {
if(!tier || value < 1) return
if (!tier || value < 1) return
await this.admin
.knex('users')
.where('id', '=', user.id)
.increment(tier, value)
}
setCurrency = async (user: User, tier?:Tiers, value = 0) => {
if(!tier || value < 0) return
setCurrency = async (user: User, tier?: Tiers, value = 0) => {
if (!tier || value < 0) return
await this.admin
.knex('users')
.where('id', '=', user.id)
-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": {
"preserveSymlinks": true,
"rebaseRootRelativeCssUrls": true,
"outputPath": "dist",
"outputPath": "dist/browser",
"index": "src/index.html",
"main": "src/main.ts",
"tsConfig": "src/tsconfig.app.json",
"tsConfig": "./tsconfig.app.json",
"polyfills": "src/polyfills.ts",
"assets": [
"src/assets",
@@ -51,20 +51,13 @@
"node_modules/echarts/dist/echarts.min.js",
"node_modules/echarts/dist/extension/bmap.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": {
"production": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
@@ -136,7 +129,7 @@
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"./tsconfig.app.json",
"src/tsconfig.spec.json"
],
"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",
+376 -7
View File
@@ -425,6 +425,7 @@
"version": "8.2.14",
"resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-8.2.14.tgz",
"integrity": "sha512-ABZO4E7eeFA1QyJ2trDezxeQM5ZFa1dXw1Mpl/+1vuXDKNjJgNyWYwKp/NwRkLmrsuV0yv4UDCDe4kJOGbPKnw==",
"dev": true,
"requires": {
"tslib": "^1.9.0"
}
@@ -1350,6 +1351,16 @@
"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": {
"version": "8.2.14",
"resolved": "https://registry.npmjs.org/@angular/router/-/router-8.2.14.tgz",
@@ -2511,11 +2522,11 @@
"integrity": "sha512-jX6R5lApSBtPHcZzgJ1+URxvJhmSodX+YcuDnuYsQJB1nkpC0Kjs6XL5OEONVg4NaoYcxMYmnxRe51lrlQdilg=="
},
"@nebular/theme": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/@nebular/theme/-/theme-4.4.0.tgz",
"integrity": "sha512-UcK1hwMvJXDROU9QiCfRq5LXRV9gB+K+AJtg1UYhvNJ+NzZkLyn+P+wFNX0StI91BjjNw3T699Xvz4B0grWhlA==",
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/@nebular/theme/-/theme-4.6.0.tgz",
"integrity": "sha512-S7topzx0Hf9D7YkQxKJ8UB1G2/sEN3o4eKjkRe8Xv5n7H3WqpKQ9Uef3oW2mTf75dmICBldhKXvopdr6TA5foA==",
"requires": {
"intersection-observer": "0.5.0"
"intersection-observer": "0.7.0"
}
},
"@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": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz",
@@ -6490,6 +6519,12 @@
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
"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": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
@@ -6785,6 +6820,11 @@
"domelementtype": "1"
}
},
"domino": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/domino/-/domino-2.1.4.tgz",
"integrity": "sha512-l70mlQ7IjPKC8kT7GljQXJZmt5OqFL+RE91ik5y5WWQtsd9wP8R7gpFnNu96fK5MqAAZRXfLLsnzKtkty5fWGQ=="
},
"domutils": {
"version": "1.5.1",
"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": {
"version": "4.17.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
@@ -8011,6 +8060,18 @@
"integrity": "sha1-WKRmaX34piBc39vzlVNri9d3pfY=",
"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": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz",
@@ -8907,6 +8968,41 @@
"integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=",
"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": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
@@ -9610,10 +9706,16 @@
"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": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.5.0.tgz",
"integrity": "sha512-8Zgt4ijlyvIrQVTA7MPb2W9+KhoetrAbxlh0RmTGxpx0+ZsAXvy7IsbNnZIrqZ6TddAdWeQj49x7Ph7Ir6KRkA=="
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.7.0.tgz",
"integrity": "sha512-Id0Fij0HsB/vKWGeBe9PxeY45ttRiBmhFyyt/geBdDHBYNctMRTE3dC1U3ujzz3lap+hVXlEcVaB56kZP/eEUg=="
},
"intl": {
"version": "1.2.5",
@@ -10261,6 +10363,11 @@
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.2.tgz",
"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": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -15544,6 +15651,29 @@
"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": {
"version": "3.0.0",
"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",
"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": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz",
@@ -19409,6 +19545,234 @@
"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": {
"version": "0.6.9",
"resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz",
@@ -20508,6 +20872,11 @@
"integrity": "sha1-OS2LotDxw00e4tYw8V0O+2jhBIo=",
"dev": true
},
"xhr2": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz",
"integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8="
},
"xml2js": {
"version": "0.4.23",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
+22 -14
View File
@@ -11,10 +11,11 @@
},
"scripts": {
"ng": "ng",
"webpack:server": "webpack --config webpack.server.config.js",
"conventional-changelog": "conventional-changelog",
"start": "ng serve",
"build": "ng build",
"build:prod": "npm run build -- --prod --aot",
"build": "rm -rf dist serverBundle && npm run ngbuild && ng run frontcraft:server && webpack --config webpack.server.config",
"ngbuild": "ng build --prod",
"test": "ng test",
"test:coverage": "rimraf coverage && npm run test -- --code-coverage",
"lint": "ng lint",
@@ -26,25 +27,29 @@
"docs": "compodoc -p src/tsconfig.app.json -d docs",
"docs:serve": "compodoc -p src/tsconfig.app.json -d docs -s",
"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": {
"@agm/core": "^1.0.0-beta.5",
"@angular-builders/custom-webpack": "^8.2.0",
"@angular/animations": "^8.0.0",
"@angular/cdk": "^8.0.0",
"@angular/common": "^8.0.0",
"@angular/compiler": "^8.0.0",
"@angular/core": "^8.0.0",
"@angular-builders/custom-webpack": "^8.4.1",
"@angular/animations": "^8.2.14",
"@angular/cdk": "^8.2.3",
"@angular/common": "^8.2.14",
"@angular/core": "^8.2.14",
"@angular/forms": "^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",
"@asymmetrik/ngx-leaflet": "3.0.1",
"@nebular/auth": "4.4.0",
"@nebular/eva-icons": "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",
"angular-tree-component": "7.2.0",
"angular2-chartjs": "0.4.1",
@@ -58,6 +63,7 @@
"eva-icons": "^1.1.0",
"intl": "1.2.5",
"ionicons": "2.0.1",
"js-cookie": "^2.2.1",
"leaflet": "1.2.0",
"nebular-icons": "1.1.0",
"ng2-ckeditor": "^1.2.2",
@@ -81,8 +87,9 @@
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.803.24",
"@angular/cli": "^8.0.2",
"@angular/compiler-cli": "^8.0.0",
"@angular/cli": "^8.3.25",
"@angular/compiler": "^8.2.14",
"@angular/compiler-cli": "^8.2.14",
"@angular/language-service": "8.0.0",
"@compodoc/compodoc": "^1.1.11",
"@fortawesome/fontawesome-free": "^5.2.0",
@@ -109,6 +116,7 @@
"ts-node": "3.2.2",
"tslint": "^5.7.0",
"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 { throwIfAlreadyLoaded } from './module-import-guard';
import { ApiService, initializeLoginSvc } from '../frontcraft/services/login-api';
import { CookieService } from 'ngx-cookie-service';
import { LayoutService } from './utils';
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 = [
@@ -1,6 +1,6 @@
import { Component } from '@angular/core';
import { ApiService } from '../../../frontcraft/services/login-api';
import { ShoutMessage } from '../../../../../../backend/Components/Shoutbox/Interface';
import { IApiService } from '../../../frontcraft/services/ApiService';
@Component({
selector: 'chat',
@@ -31,7 +31,7 @@ export class ChatComponent {
history
constructor(
private api: ApiService
private api: IApiService
) {}
submit(event){
@@ -1,14 +1,14 @@
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 { map, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { ApiService } from '../../../frontcraft/services/login-api';
import { User } from '../../../../../../backend/Types/Types';
import { Router } from '@angular/router';
import { ChatComponent } from './chat.component';
import { ShoutMessage } from '../../../../../../backend/Components/Shoutbox/Interface';
import { IApiService } from '../../../frontcraft/services/ApiService';
@Component({
selector: 'ngx-header',
@@ -54,8 +54,7 @@ export class HeaderComponent implements OnInit, OnDestroy {
private router: Router,
private themeService: NbThemeService,
private layoutService: LayoutService,
private breakpointService: NbMediaBreakpointsService,
private api: ApiService,
private api: IApiService,
private dialogService : NbDialogService
) {}
@@ -17,21 +17,9 @@ export class TinyMCEComponent implements OnDestroy, AfterViewInit {
) { }
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() {
tinymce.remove(this.editor);
}
}
+78 -9
View File
@@ -1,25 +1,94 @@
import { ExtraOptions, RouterModule, Routes } from '@angular/router';
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 = [
{
path: 'permissions',
loadChildren: () => import('./frontcraft/permissions/permissions.module')
.then(m => m.PermissionsModule),
component: PermissionsComponent,
children: [
{
path: '**',
component: ChangePermissionsComponent,
},
]
},
{
path: 'auth',
loadChildren: () => import('./frontcraft/auth/auth.module')
.then(m => m.MyAuthModule),
component: AuthComponent,
children: [
{
path: 'register',
component: RegisterComponent
},
{
path: 'logout',
component: LogoutComponent,
},
{
path: '**',
component: MyLoginComponent,
},
]
},
{
path: 'frontcraft',
loadChildren: () => import('./frontcraft/pages/pages.module')
.then(m => m.FrontcraftPagesModule),
component: PagesLayoutComponent,
children: [
{
path: 'user/:name',
component: FrontcraftUserComponent
},
{ path: '', redirectTo: 'frontcraft', pathMatch: 'full' },
{ path: '**', redirectTo: 'frontcraft' },
{
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/raids' },
];
const config: ExtraOptions = {
+3 -15
View File
@@ -3,9 +3,7 @@
* Copyright Akveo. All Rights Reserved.
* 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 { ApiService } from './frontcraft/services/login-api';
import { isPlatformBrowser } from '@angular/common';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'ngx-app',
@@ -13,17 +11,7 @@ import { isPlatformBrowser } from '@angular/common';
})
export class AppComponent implements OnInit {
constructor(
private loginSvc: ApiService,
@Inject(PLATFORM_ID) private platformId: Object,
@Inject(APP_ID) private appId: string
) {
if(!isPlatformBrowser(platformId)){
global['window'] = {}
}
}
constructor() { }
ngOnInit(): void {
}
ngOnInit(): void { }
}
+13 -15
View File
@@ -5,7 +5,7 @@
*/
import { BrowserModule } from '@angular/platform-browser';
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 { ThemeModule } from './@theme/theme.module';
import { AppComponent } from './app.component';
@@ -19,14 +19,17 @@ import {
NbToastrModule,
NbWindowModule,
} from '@nebular/theme';
import { ApiService, initializeLoginSvc } from './frontcraft/services/login-api';
import { CookieService } from 'ngx-cookie-service';
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({
declarations: [AppComponent],
declarations: [
AppComponent
],
imports: [
BrowserModule,
BrowserModule.withServerTransition({ appId: 'frontcraft' }),
BrowserAnimationsModule,
HttpClientModule,
AppRoutingModule,
@@ -41,17 +44,12 @@ import { CoreModule } from './@core/core.module';
messageGoogleMapKey: 'AIzaSyA_wNuCzia92MAmdLRzmqitRGvCF7wCZPY',
}),
CoreModule.forRoot(),
FrontcraftPagesModule,
MyAuthModule,
PermissionsModule
],
bootstrap: [AppComponent],
providers: [
ApiService,
{
provide: APP_INITIALIZER,
deps: [CookieService],
multi: true,
useFactory: initializeLoginSvc
},
]
providers: []
})
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 { ApiService } from '../services/login-api';
import { ClientApiService } from '../services/client-login-api';
import { Router } from '@angular/router';
@Component({
@@ -13,8 +13,6 @@ import { Router } from '@angular/router';
export class AuthComponent implements OnInit{
constructor(
private loginSvc : ApiService,
private router: Router
){}
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,
NbSelectModule
} from '@nebular/theme';
import { MyAuthRoutingModule } from './auth-routing.module';
import { MyLoginComponent } from './login/login.component';
import { AuthComponent } from './auth-layout.component';
import { ThemeModule } from '../../@theme/theme.module';
@@ -22,7 +21,6 @@ import { RegisterComponent } from './register/register.component';
@NgModule({
imports: [
MyAuthRoutingModule,
CommonModule,
FormsModule,
RouterModule,
@@ -29,7 +29,7 @@
id="input-password"
placeholder="Password"
fieldSize="giant"
[status]="password.dirty ? (password.invalid ? 'danger' : 'success') : ''"
[status]="password.dirty ? (password.invalid ? 'danger' : 'success') : 'basic'"
[required]="true"
[minlength]="1"
[maxlength]="15"
@@ -1,6 +1,8 @@
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 { IApiService } from '../../services/ApiService';
import { NbToastrService } from '@nebular/theme';
@Component({
selector: 'mylogin',
@@ -21,18 +23,26 @@ export class MyLoginComponent implements OnInit{
constructor(
private router : Router,
private loginApi : ApiService
private api : IApiService,
private toastr: NbToastrService
){}
ngOnInit(){
this.loginApi.checkLogin().then(loggedin => {
this.api.checkLogin().then(loggedin => {
if(loggedin){
this.router.navigateByUrl("/")
}
});
}
login(){
this.loginApi.login(this.user.name, this.user.password)
async login(){
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 { ApiService } from '../../services/login-api';
import { IApiService } from '../../services/ApiService';
import { Router } from '@angular/router';
@Component({
@@ -9,11 +9,13 @@ import { Router } from '@angular/router';
export class LogoutComponent implements OnInit{
constructor(
private api : ApiService
private api : IApiService,
private router: Router
){}
ngOnInit(){
this.api.logout()
this.api.logout().then(() => {
this.router.navigate(['/auth/login'])
})
}
}
@@ -1,9 +1,10 @@
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 { _Rank, _Class, Class, User, _Race } from '../../../../../../backend/Types/Types'
import { specs } from '../../../../../../backend/Types/PlayerSpecs'
import { race } from 'rxjs';
import { hash, IApiService } from '../../services/ApiService';
@Component({
@@ -33,7 +34,7 @@ export class RegisterComponent implements OnInit{
constructor(
private router : Router,
private api : ApiService
private api : IApiService
){}
ngOnInit(){
@@ -1,6 +1,5 @@
<nb-card
class = "col-12 col-xl-9"
status="control">
class = "col-12 col-xl-9">
<nb-card-header style="text-transform: capitalize;">
<h4>
Armory
@@ -2,7 +2,8 @@ import { Component, OnInit } from '@angular/core';
import { Item, Stats } from '../../../../../../backend/Types/Types';
import { NbToastrService } from '@nebular/theme';
import { ApiService } from '../../services/login-api';
import { ClientApiService } from '../../services/client-login-api';
import { IApiService } from '../../services/ApiService';
@Component({
selector: 'armory',
@@ -18,7 +19,7 @@ export class FrontcraftArmoryComponent implements OnInit {
gear: Item[] = []
constructor(
private api: ApiService,
private api: IApiService,
private toastr: NbToastrService
) { }
@@ -1,6 +1,5 @@
<nb-card
class = "col-12 col-xl-9"
status="control">
class = "col-12 col-xl-9">
<nb-card-header style="text-transform: capitalize;">
<h4>
<a *ngIf="link === 'character'" [ngStyle]="{'color': color}" [routerLink]="'/frontcraft/character/'+char.charactername">
@@ -1,9 +1,10 @@
import { Component, OnInit, Input } from '@angular/core';
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 { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { _Tiers } from '../../../../../../backend/Types/Items';
import { IApiService } from '../../services/ApiService';
@Component({
selector: 'character',
@@ -28,7 +29,7 @@ export class FrontcraftCharacterComponent implements OnInit{
gear2:string[] = []
constructor(
private api: ApiService,
private api: IApiService,
private route: ActivatedRoute,
){}
@@ -1,8 +1,8 @@
import { Component, AfterViewInit, OnDestroy } from '@angular/core';
import { NbThemeService } from '@nebular/theme';
import { ApiService } from '../../services/login-api';
import { _Class } from '../../../../../../backend/Types/Types';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { IApiService } from '../../services/ApiService';
@Component({
@@ -17,7 +17,7 @@ export class FrontcraftCharactersComponent implements AfterViewInit, OnDestroy{
allcharacters = []
displayedcharacters = []
constructor(private theme: NbThemeService, private api:ApiService) {
constructor(private theme: NbThemeService, private api:IApiService) {
}
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 { ApiService } from '../services/login-api';
import { ClientApiService } from '../services/client-login-api';
import { Router } from '@angular/router';
import { IApiService } from '../services/ApiService';
declare const Cookies
@Component({
selector: 'page-layout',
@@ -13,7 +16,8 @@ import { Router } from '@angular/router';
</ngx-one-column-layout>
`,
})
export class PagesLayoutComponent implements AfterContentInit{
export class PagesLayoutComponent implements OnInit{
menu:NbMenuItem[] = [{
icon: 'image',
title: 'Raids',
@@ -33,15 +37,17 @@ export class PagesLayoutComponent implements AfterContentInit{
}]
constructor(
private loginSvc : ApiService,
private api : IApiService,
private router : Router
){}
ngAfterContentInit() : void {
this.loginSvc.checkLogin().then(loggedin => {
if(!loggedin){
this.router.navigateByUrl("/auth")
ngOnInit(): void {
/*
const u = this.api.getCurrentUser()
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,
NbSelectModule
} from '@nebular/theme';
import { FrontcraftRoutingModule } from './pages-routing.module';
import { PagesLayoutComponent } from './pages-layout.component';
import { ThemeModule } from '../../@theme/theme.module';
import { FrontcraftCharacterComponent } from './character/character.component';
@@ -42,7 +41,6 @@ import { FrontcraftArmoryComponent } from './armory/armory.component';
@NgModule({
imports: [
FrontcraftRoutingModule,
CommonModule,
FormsModule,
RouterModule,
@@ -1,8 +1,9 @@
import { Component, OnInit } from '@angular/core';
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 { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { IApiService } from '../../services/ApiService';
@Component({
selector: 'archive',
@@ -38,7 +39,7 @@ export class FrontcraftArchiveComponent implements OnInit{
search = ""
constructor(
private api: ApiService,
private api: IApiService,
private route: ActivatedRoute,
){
}
@@ -60,7 +61,7 @@ export class FrontcraftArchiveComponent implements OnInit{
[
...raiddata.tanks,
...raiddata.healers,
...Object.values(raiddata.participants).flat()
...Object.values<any>(raiddata.participants).flat()
].forEach(p => {
p['color'] = getClassColor(p.class)
})
@@ -1,8 +1,9 @@
import { OnInit, Component } from '@angular/core';
import { NbWindowRef, NbToastrService, NbDialogRef } from '@nebular/theme';
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 { IApiService } from '../../services/ApiService';
@Component({
selector: 'characterpicker',
@@ -15,7 +16,7 @@ export class FrontcraftCharacerpickerComponent implements OnInit{
constructor(
protected dialogRef: NbDialogRef<FrontcraftCharacerpickerComponent>,
private api : ApiService,
private api : IApiService,
private toast : NbToastrService
){}
@@ -1,6 +1,6 @@
<div class="row">
<div class="col-12 col-xl-6">
<nb-card [size]="'giant'">
<nb-card>
<nb-card-body>
<nb-tabset>
<nb-tab tabTitle="Info">
@@ -68,9 +68,7 @@
[src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
{{ participant.charactername }}
</a>
<span
*ngIf="participant.rank=='Trial'"
style="font-size: 9px;">
<span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
Trial
</span>
</div>
@@ -97,9 +95,7 @@
[src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
{{ participant.charactername }}
</a>
<span
*ngIf="participant.rank=='Trial'"
style="font-size: 9px;">
<span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
Trial
</span>
</div>
@@ -128,9 +124,7 @@
[src]="'../../../../assets/images/'+participant.class.toLowerCase()+'.png'" />
{{ participant.charactername }}
</a>
<span
*ngIf="participant.rank=='Trial'"
style="font-size: 9px;">
<span *ngIf="participant.rank=='Trial'" style="font-size: 9px;">
Trial
</span>
</div>
@@ -153,37 +147,48 @@
<nb-card-body>
<nb-tabset>
<nb-tab tabTitle="Reserves" [active]="reservesShown">
<input type="text" nbInput [(ngModel)]="search" (change)="changeSearch()" placeholder="Search"
fullWidth="true">
<input type="text" nbInput [(ngModel)]="search" (change)="changeSearch()" placeholder="Search" fullWidth="true">
<nb-list>
<nb-list class="">
<nb-list-item *ngFor="let item of displayedtokens | keyvalue">
<table>
<tr>
<td>
<wowhead [item]="item.value[0]"></wowhead><br />
</td>
</tr>
<tr>
<td>
<div class="row">
<div *ngFor="let token of item.value" class="col-12 col-md-6 col-xl-4">
<span [ngStyle]="{'text-decoration': token.rank=='Trial'? 'line-through' : 'none currentcolor solid' }">
[ {{token.level}} ]
<span style="text-transform: capitalize;"
<div
*ngFor="let token of item.value"
class="col-12 col-md-6 col-xl-4">
<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>
&nbsp;
<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">
<span *ngIf="token.rank=='Trial'" style="font-size: 9px;" [nbPopover]="tooltip"
nbPopoverTrigger="hover" nbPopoverPlacement="top">
Trial
</span><br />
</div>
</div>
</td>
</tr>
</table>
</nb-list-item>
</nb-list>
</nb-tab>
@@ -1,12 +1,13 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
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 { NbWindowService, NbToastrService, NbDialogService } from '@nebular/theme';
import { FrontcraftCharacerpickerComponent } from './characterpicker.component';
import { getClassColor, SpecT } from '../../../../../../backend/Types/PlayerSpecs';
import { FrontcraftBuyTokenComponent } from '../shop/buytoken.component';
import { allItems } from '../../../../../../backend/Types/Items';
import { IApiService } from '../../services/ApiService';
@Component({
selector: 'raid',
@@ -45,7 +46,7 @@ export class FrontcraftRaidComponent implements OnInit, OnDestroy{
uuid
constructor(
private api: ApiService,
private api: IApiService,
private route: ActivatedRoute,
private router: Router,
private dialogService : NbDialogService,
@@ -1,8 +1,9 @@
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 { NbWindowRef, NbDialogRef } from '@nebular/theme';
import { Tiers, _Tiers } from '../../../../../../backend/Types/Items';
import { IApiService } from '../../services/ApiService';
const ONE_MINUTE = 60000
const ONE_HOUR = 60 * ONE_MINUTE
@@ -27,7 +28,7 @@ export class FrontcraftCreateRaidsComponent implements OnInit {
constructor(
protected dialogRef: NbDialogRef<FrontcraftCreateRaidsComponent>,
private api: ApiService
private api: IApiService
) {}
loadNext(cardData) {
@@ -1,8 +1,9 @@
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 { FrontcraftCreateRaidsComponent } from './createraid.compontent';
import { Router, NavigationStart } from '@angular/router';
import { IApiService } from '../../services/ApiService';
@Component({
selector: 'raids',
@@ -19,7 +20,7 @@ export class FrontcraftRaidsComponent implements OnInit, OnDestroy{
uuid
constructor(
private api: ApiService,
private api: IApiService,
private router: Router,
private dialogService: NbDialogService
) {
@@ -60,14 +60,21 @@
<nb-tab tabTitle="priorities">
<nb-list>
<nb-list-item *ngFor="let item of rules | keyvalue">
<wowhead [item]="item.value[0]"></wowhead><br>
<div class="row" *ngFor="let rule of item.value">
<div class="col-4">
<table >
<tr>
<td colspan="2">
<wowhead [item]="item.value[0]"></wowhead>
</td>
</tr>
<tr *ngFor="let rule of item.value">
<td style="width: 250px;">
<span *ngIf="rule.modifier>0">+</span>{{rule.modifier}} {{rule.race}} <span [ngStyle]="{'color':rule.color}">{{rule.specname}} {{rule.class}}</span>
</div>
<div class="col-8" style="color:white"> ({{rule.description}})</div>
<br />
</div>
</td>
<td>
<div style="color:white"> ({{rule.description}})</div>
</td>
</tr>
</table>
</nb-list-item>
</nb-list>
</nb-tab>
@@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { ApiService as ApiService } from '../../services/login-api';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { IApiService } from '../../services/ApiService';
@Component({
selector: 'rules',
@@ -12,7 +12,7 @@ export class FrontcraftRulesComponent implements OnInit{
rules = {}
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 { ApiService as ApiService } from '../../services/login-api';
import { ClientApiService as ClientApiService } from '../../services/client-login-api';
import { FrontcraftItemSelectComponent } from './itemselector.component';
import { NbWindowService, NbWindowRef, NbToastrService, NbDialogService, NbDialogRef } from '@nebular/theme';
import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { _Tiers, allItems, Tiers } from '../../../../../../backend/Types/Items';
import { IApiService } from '../../services/ApiService';
@Component({
selector: 'buyToken',
@@ -88,7 +89,7 @@ import { _Tiers, allItems, Tiers } from '../../../../../../backend/Types/Items';
constructor(
private toastr: NbToastrService,
protected dialogRef: NbDialogRef<FrontcraftBuyTokenComponent>,
private api : ApiService
private api : IApiService
){}
async ngOnInit() {
@@ -1,6 +1,4 @@
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 { _Tiers, } from '../../../../../../backend/Types/Items';
@@ -1,6 +1,7 @@
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 { IApiService } from '../../services/ApiService';
@Component({
selector: 'itemselect',
@@ -18,7 +19,7 @@ export class FrontcraftItemSelectComponent implements OnInit{
@Output() onSelect = new EventEmitter<Item>();
constructor(
private api: ApiService,
private api: IApiService,
){}
async ngOnInit(){
@@ -1,9 +1,7 @@
import { Component, OnInit, ContentChild, AfterContentInit, ViewChild, AfterViewInit, Input, Output, EventEmitter } from '@angular/core';
import { ApiService as ApiService } from '../../services/login-api';
import { FrontcraftItemSelectComponent } from './itemselector.component';
import { NbWindowService, NbWindowRef, NbToastrService, NbDialogService, NbDialogRef } from '@nebular/theme';
import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { ClientApiService as ClientApiService } from '../../services/client-login-api';
import { NbDialogService } from '@nebular/theme';
import { Item, Character, Signup } from '../../../../../../backend/Types/Types';
import { _Tiers, allItems } from '../../../../../../backend/Types/Items';
@Component({
@@ -20,8 +18,6 @@ export class FrontcraftShopComponent implements OnInit{
allItems = allItems
constructor(
private api: ApiService,
private dialogService : NbDialogService
){
}
@@ -1,6 +1,4 @@
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 { _Tiers } from '../../../../../../backend/Types/Items';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
@@ -1,11 +1,11 @@
import { Component, OnInit } from '@angular/core';
import { ApiService, hash } from '../../services/login-api';
import { Router, ActivatedRoute } from '@angular/router';
import { ActivatedRoute } from '@angular/router';
import { User, Spec, Character } from '../../../../../../backend/Types/Types';
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
import { _Tiers } from '../../../../../../backend/Types/Items';
import { _Rank } from '../../../../../../backend/Types/Types';
import { NbToastrService } from '@nebular/theme';
import { hash, IApiService } from '../../services/ApiService';
@Component({
selector: 'user-component',
@@ -19,12 +19,16 @@ export class FrontcraftUserComponent implements OnInit{
ranks = _Rank
myProfile = false
manageUser
user:User = {} as any
user:User = {
rank: 'Guest',
username: 'Guest',
pwhash: ""
}
characters : (Character & Spec)[] = []
constructor(
private route: ActivatedRoute,
private api : ApiService,
private api : IApiService,
private toastr: NbToastrService
){}
@@ -1,8 +1,9 @@
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 { _Rank, _Class, _Race, RPCPermission } from '../../../../../../backend/Types/Types'
import { NbToastrService } from '@nebular/theme';
import { IApiService } from '../../services/ApiService';
@Component({
@@ -15,8 +16,7 @@ export class ChangePermissionsComponent implements OnInit{
ranks = _Rank
constructor(
private router : Router,
private api : ApiService,
private api : IApiService,
private toastr: NbToastrService
){}
@@ -32,9 +32,6 @@ export class ChangePermissionsComponent implements OnInit{
perm[key] = value
console.log(perm);
await modify.setPermission(perm).catch(e => {
})
@@ -1,5 +1,5 @@
import { Component, OnInit } from '@angular/core';
import { ApiService } from '../services/login-api';
import { ClientApiService } from '../services/client-login-api';
import { Router } from '@angular/router';
@Component({
@@ -13,7 +13,6 @@ import { Router } from '@angular/router';
export class PermissionsComponent implements OnInit{
constructor(
private loginSvc : ApiService,
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';
import { PermissionsComponent } from './permissions-layout.component';
import { ThemeModule } from '../../@theme/theme.module';
import { PermissionsRoutingModule } from './permissions-routing.module';
import { ChangePermissionsComponent } from './changePermissions/changePermissions.component';
@NgModule({
imports: [
NbToggleModule,
PermissionsRoutingModule,
CommonModule,
FormsModule,
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 { 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 { saltedHash } from '../../../../../backend/Util/hash';
import { NbToastrService } from '@nebular/theme';
import { hash, IApiService } from './ApiService';
declare const Cookies
@Injectable()
export class ApiService{
export class ClientApiService implements IApiService{
private socket:RPCSocket & FrontcraftIfc;
private auth:Auth
private privSocket: RPCSocket & SomeOf<FrontcraftFeatureIfc>
constructor(
private injector: Injector,
private cookieSvc : CookieService,
private ngZone : NgZone,
private toastr: NbToastrService
){}
constructor(){
window['s'] = this
}
getUnprivilegedSocket = () : RPCSocket & FrontcraftIfc => this.socket
private getPrivilegedSocket = async (auth:Auth) : Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => {
if(this.privSocket) return this.privSocket
if(auth == null) throw new Error("Bad Auth")
if(this.privSocket) {
return this.privSocket
}
if(auth == null)
throw new Error("Bad Auth")
try{
const sock = new RPCSocket(
@@ -38,24 +36,24 @@ export class ApiService{
})
sock.hook('getUserData', () => auth)
sock.hook('navigate', (where:string) => {
this.ngZone.run( () => {
this.injector.get(Router).navigateByUrl(where)
})
})
sock.on('close', async () => {
console.log("priv#close");
//handled via unprivileged socket
})
sock.on('error', async (e) => {
console.log("priv#error", e);
//handled via unprivileged socket
})
const authSock = await sock.connect<RPCSocket & SomeOf<FrontcraftFeatureIfc>>(auth.token.value)
this.auth = auth
this.privSocket = authSock
this.cookieSvc.set('token', JSON.stringify(auth))
Cookies.set('token', JSON.stringify(auth))
// document.cookie = JSON.stringify(auth)
return authSock
}catch(e){
if(this.privSocket) this.privSocket.destroy()
@@ -86,13 +84,11 @@ export class ApiService{
try{
auth = await this.socket.UserManager.login(username, pwHash)
}catch(e){
this.toastr.danger("Login failed", "Error")
return
}
if(!auth){
await this.logout()
this.toastr.danger("Login failed", "Error")
throw new Error("Login failed")
}
@@ -105,8 +101,8 @@ export class ApiService{
return sock
}
async connectShoutbox(handler) : Promise<Function>{
const res = await this.get('Shoutbox').subscribe(handler)
async connectShoutbox(callback:Function) : Promise<Function>{
const res = await this.get('Shoutbox').subscribe(callback)
return async (msg: ShoutMessage) => await this.get('Shoutbox').shout(res.uuid, msg)
}
@@ -116,25 +112,21 @@ export class ApiService{
}
logout = async () => {
this.cookieSvc.set('token', undefined)
Cookies.remove('token')
if(this.auth){
try{
await this.socket.UserManager.logout(this.auth.user.username, this.auth.token.value)
}catch(e){
//socket is dead
console.warn(e);
}
}
if(this.privSocket) this.privSocket.destroy()
this.privSocket = 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){
this.socket.destroy()
this.socket = null
@@ -145,8 +137,6 @@ export class ApiService{
conn.on('close', async () => {
})
this.socket = await conn.connect<FrontcraftIfc>()
}catch(e){
alert('Unable to connect. The server appears to be down.\nPress OK to refresh the page')
@@ -155,9 +145,9 @@ export class ApiService{
}
try{
const cookie = JSON.parse(this.cookieSvc.get('token'))
const cookie = JSON.parse(Cookies.get('token'))
if(cookie != null) {
if(cookie != null && cookie != "") {
try{
const auth = await this.socket.UserManager.getAuth(cookie.token.value)
if(!auth) return this.socket
@@ -168,6 +158,7 @@ export class ApiService{
}
}
}catch(e){
Cookies.remove('token')
}
}
@@ -181,12 +172,3 @@ export class ApiService{
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';
+13 -2
View File
@@ -6,12 +6,23 @@
import { enableProdMode } from '@angular/core';
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 { IApiService } from "./app/frontcraft/services/ApiService"
import { ClientApiService } from './app/frontcraft/services/client-login-api';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
const serviceObj = new ClientApiService()
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,
"compilerOptions": {
"importHelpers": true,
"module": "commonjs",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"outDir": "./out-tsc",
"baseUrl": "./",
"declaration": true,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"importHelpers": true,
"target": "es2015",
"typeRoots": [
"node_modules/@types"
],
@@ -20,5 +19,8 @@
"plugins": [
{ "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,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"baseUrl": "./",
"outDir": "./lib",
//"types": ["node"],
"types": ["node", "mocha"],
"strictNullChecks": false
},
"include": ["src/backend/**/*"],
"exclude": [
"./src/frontend/**/*",
"./node_modules/**/*",
"./src/frontend/node_modules/**/*",
"./test",
],
"include": ["src", "test"],
"angularCompilerOptions": {
"enableIvy": false,
"entryModule": "./src/backend/Admin/app.server.module#AppServerModule"