change pw, change rank UI, auto-refresh on disconnect, new loading screen
This commit is contained in:
Generated
+29
-29
@@ -1050,9 +1050,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "3.0.3",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||||
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
|
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1476,9 +1476,9 @@
|
|||||||
"integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg="
|
"integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg="
|
||||||
},
|
},
|
||||||
"cyclist": {
|
"cyclist": {
|
||||||
"version": "0.2.2",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
|
||||||
"integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=",
|
"integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"dashdash": {
|
"dashdash": {
|
||||||
@@ -5465,12 +5465,12 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"parallel-transform": {
|
"parallel-transform": {
|
||||||
"version": "1.1.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz",
|
||||||
"integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=",
|
"integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"cyclist": "~0.2.2",
|
"cyclist": "^1.0.1",
|
||||||
"inherits": "^2.0.3",
|
"inherits": "^2.0.3",
|
||||||
"readable-stream": "^2.1.5"
|
"readable-stream": "^2.1.5"
|
||||||
}
|
}
|
||||||
@@ -6130,9 +6130,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rpclibrary": {
|
"rpclibrary": {
|
||||||
"version": "1.7.1",
|
"version": "1.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.8.3.tgz",
|
||||||
"integrity": "sha512-Ibo3qfURnQgZAq0eA2o+L9+PWaloJ4PHZs4ak42LL9fRgdWZXn33HAtowV0K2HVckbvrBvFqj/+PWTrWWBSOeg==",
|
"integrity": "sha512-8pQRbMXQKCf3+v+XM01d+1Bw73pg5YzgyhW/ACpYON1I4re5fZAjWGPyLc+ms+MlYQIlKc3Uk92PGot2sbb85Q==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"bsock": "^0.1.9",
|
"bsock": "^0.1.9",
|
||||||
"http": "0.0.0",
|
"http": "0.0.0",
|
||||||
@@ -6252,9 +6252,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"serialize-javascript": {
|
"serialize-javascript": {
|
||||||
"version": "1.8.0",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz",
|
||||||
"integrity": "sha512-3tHgtF4OzDmeKYj6V9nSyceRS0UJ3C7VqyD2Yj28vC/z2j6jG5FmFGahOKMD9CrglxTm3tETr87jEypaYV8DUg==",
|
"integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"serve-static": {
|
"serve-static": {
|
||||||
@@ -6503,9 +6503,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"source-map-support": {
|
"source-map-support": {
|
||||||
"version": "0.5.13",
|
"version": "0.5.16",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz",
|
||||||
"integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
|
"integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"buffer-from": "^1.0.0",
|
"buffer-from": "^1.0.0",
|
||||||
@@ -6637,9 +6637,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"stream-shift": {
|
"stream-shift": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
|
||||||
"integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=",
|
"integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"streamroller": {
|
"streamroller": {
|
||||||
@@ -6799,9 +6799,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"terser": {
|
"terser": {
|
||||||
"version": "4.2.0",
|
"version": "4.6.4",
|
||||||
"resolved": "https://registry.npmjs.org/terser/-/terser-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/terser/-/terser-4.6.4.tgz",
|
||||||
"integrity": "sha512-6lPt7lZdZ/13icQJp8XasFOwZjFJkxFFIb/N1fhYEQNoNI3Ilo3KABZ9OocZvZoB39r6SiIk/0+v/bt8nZoSeA==",
|
"integrity": "sha512-5fqgBPLgVHZ/fVvqRhhUp9YUiGXhFJ9ZkrZWD9vQtFBR4QIGTnbsb+/kKqSqfgp3WnBwGWAFnedGTtmX1YTn0w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"commander": "^2.20.0",
|
"commander": "^2.20.0",
|
||||||
@@ -6810,16 +6810,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"terser-webpack-plugin": {
|
"terser-webpack-plugin": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz",
|
||||||
"integrity": "sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg==",
|
"integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"cacache": "^12.0.2",
|
"cacache": "^12.0.2",
|
||||||
"find-cache-dir": "^2.1.0",
|
"find-cache-dir": "^2.1.0",
|
||||||
"is-wsl": "^1.1.0",
|
"is-wsl": "^1.1.0",
|
||||||
"schema-utils": "^1.0.0",
|
"schema-utils": "^1.0.0",
|
||||||
"serialize-javascript": "^1.7.0",
|
"serialize-javascript": "^2.1.2",
|
||||||
"source-map": "^0.6.1",
|
"source-map": "^0.6.1",
|
||||||
"terser": "^4.1.2",
|
"terser": "^4.1.2",
|
||||||
"webpack-sources": "^1.4.0",
|
"webpack-sources": "^1.4.0",
|
||||||
|
|||||||
+1
-1
@@ -45,7 +45,7 @@
|
|||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.0",
|
"rimraf": "^3.0.0",
|
||||||
"rpclibrary": "^1.7.1",
|
"rpclibrary": "^1.8.3",
|
||||||
"simple-git": "^1.124.0",
|
"simple-git": "^1.124.0",
|
||||||
"spawn-sync": "^2.0.0",
|
"spawn-sync": "^2.0.0",
|
||||||
"sqlite3": "^4.1.1",
|
"sqlite3": "^4.1.1",
|
||||||
|
|||||||
@@ -74,11 +74,14 @@ implements TableDefinitionExporter, IAdmin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stop(){
|
stop(){
|
||||||
Promise.race([
|
Promise.all([
|
||||||
Promise.all( this.frontworkComponents.map(c => c.stop?c.stop():undefined )),
|
...this.frontworkComponents.map(c => c.stop?c.stop():undefined ),
|
||||||
new Promise((res, rej) => { setTimeout(res, 250);})
|
])
|
||||||
]).catch(e => logger.warn(e))
|
.catch(e => logger.warn(e))
|
||||||
.finally(() => { process.exit(0) })
|
.finally(() => {
|
||||||
|
this.rpcServer.destroy()
|
||||||
|
process.exit(0)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
protected configChangeHandler = (conf:AdminConf, key?:string) => {
|
protected configChangeHandler = (conf:AdminConf, key?:string) => {
|
||||||
@@ -202,7 +205,6 @@ implements TableDefinitionExporter, IAdmin {
|
|||||||
return await this.knex.schema.createTable(def.name, def.tableBuilder)
|
return await this.knex.schema.createTable(def.name, def.tableBuilder)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
return this.knex
|
return this.knex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,6 @@ export type ItemManagerFeatureIfc = {
|
|||||||
}
|
}
|
||||||
managePriorities: {
|
managePriorities: {
|
||||||
setPriority:IItemManager['setPriority']
|
setPriority:IItemManager['setPriority']
|
||||||
deletePriorits: IItemManager['deletePriority']
|
deletePriority: IItemManager['deletePriority']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,11 +11,13 @@ export class IUserManager{
|
|||||||
checkToken: (token: string, rank: Rank) => boolean
|
checkToken: (token: string, rank: Rank) => boolean
|
||||||
getUserRecordByToken: (tokenValue: string) => UserRecord | void
|
getUserRecordByToken: (tokenValue: string) => UserRecord | void
|
||||||
getUser: (username: string) => Promise<User | void>
|
getUser: (username: string) => Promise<User | void>
|
||||||
|
adminLogout: (username: string) => Promise<void>
|
||||||
decrementCurrency: (user: User, tier:Tiers, value: number) => Promise<void>
|
decrementCurrency: (user: User, tier:Tiers, value: number) => Promise<void>
|
||||||
incrementCurrency: (user: User, tier:Tiers, value: number) => Promise<void>
|
incrementCurrency: (user: User, tier:Tiers, value: number) => Promise<void>
|
||||||
setCurrency: (user: User, tier:Tiers, value: number) => Promise<void>
|
setCurrency: (user: User, tier:Tiers, value: number) => Promise<void>
|
||||||
getCurrency: (user:User, tier:Tiers) => Promise<number>
|
getCurrency: (user:User, tier:Tiers) => Promise<number>
|
||||||
changeRank: (user:User, rank: Rank) => Promise<User>
|
changeRank: (user:User, rank: Rank) => Promise<User>
|
||||||
wipeCurrency: () => Promise<void>
|
wipeCurrency: () => Promise<void>
|
||||||
|
changePassword: (userToken: string, pwHash: string) => Promise<User>
|
||||||
|
adminChangePassword: (user:User, pwHash: string) => Promise<User>
|
||||||
}
|
}
|
||||||
@@ -8,14 +8,20 @@ export type UserManagerIfc = {
|
|||||||
createUser: IUserManager['createUser']
|
createUser: IUserManager['createUser']
|
||||||
getAuth: IUserManager['getAuth']
|
getAuth: IUserManager['getAuth']
|
||||||
getUser: IUserManager['getUser']
|
getUser: IUserManager['getUser']
|
||||||
|
changePassword: IUserManager['changePassword']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UserManagerFeatureIfc = {
|
export type UserManagerFeatureIfc = {
|
||||||
|
manageUser: {
|
||||||
|
changeRank: IUserManager['changeRank']
|
||||||
|
adminLogout: IUserManager['adminLogout']
|
||||||
|
adminChangePassword: IUserManager['adminChangePassword']
|
||||||
|
}
|
||||||
|
|
||||||
modifyPermissions: {
|
modifyPermissions: {
|
||||||
setPermission: IUserManager['setPermission']
|
setPermission: IUserManager['setPermission']
|
||||||
getPermissions: IUserManager['getPermissions']
|
getPermissions: IUserManager['getPermissions']
|
||||||
changeRank: IUserManager['changeRank']
|
|
||||||
}
|
}
|
||||||
|
|
||||||
softreserveCurrency: {
|
softreserveCurrency: {
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ import { IUserManager } from "./Interface";
|
|||||||
import { getLogger, Logger } from "log4js";
|
import { getLogger, Logger } from "log4js";
|
||||||
import { saltedHash } from "../../Util/hash";
|
import { saltedHash } from "../../Util/hash";
|
||||||
import { _Tiers, Tiers } from "../../Types/Items";
|
import { _Tiers, Tiers } from "../../Types/Items";
|
||||||
|
import { ICharacterManager } from "../Character/Interface";
|
||||||
|
import { IRaidManager } from "../Raid/Interface";
|
||||||
|
import { IItemManager } from "../Item/Interface";
|
||||||
|
import { IGuildManager } from "../Guild/Interface";
|
||||||
|
|
||||||
const uuid = require('uuid/v4')
|
const uuid = require('uuid/v4')
|
||||||
|
|
||||||
@@ -34,16 +38,16 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
|
|||||||
@Inject(IAdmin)
|
@Inject(IAdmin)
|
||||||
private admin: FrontworkAdmin
|
private admin: FrontworkAdmin
|
||||||
|
|
||||||
@Inject(GuildManager)
|
@Inject(IGuildManager)
|
||||||
private guild : GuildManager
|
private guild : GuildManager
|
||||||
|
|
||||||
@Inject(ItemManager)
|
@Inject(IItemManager)
|
||||||
private item : ItemManager
|
private item : ItemManager
|
||||||
|
|
||||||
@Inject(RaidManager)
|
@Inject(IRaidManager)
|
||||||
private raid : RaidManager
|
private raid : RaidManager
|
||||||
|
|
||||||
@Inject(CharacterManager)
|
@Inject(ICharacterManager)
|
||||||
private character : CharacterManager
|
private character : CharacterManager
|
||||||
|
|
||||||
exporters :any[] = []
|
exporters :any[] = []
|
||||||
@@ -56,15 +60,23 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
|
|||||||
this.getAuth,
|
this.getAuth,
|
||||||
this.checkToken,
|
this.checkToken,
|
||||||
this.createUser,
|
this.createUser,
|
||||||
this.getUser
|
this.getUser,
|
||||||
|
this.changePassword
|
||||||
]
|
]
|
||||||
|
|
||||||
exportRPCFeatures = () => [{
|
exportRPCFeatures = () => [
|
||||||
|
{
|
||||||
|
name: 'manageUser' as 'manageUser',
|
||||||
|
exportRPCs: () => [
|
||||||
|
this.adminLogout,
|
||||||
|
this.changeRank,
|
||||||
|
this.adminChangePassword
|
||||||
|
]
|
||||||
|
},{
|
||||||
name: 'modifyPermissions' as 'modifyPermissions',
|
name: 'modifyPermissions' as 'modifyPermissions',
|
||||||
exportRPCs: () => [
|
exportRPCs: () => [
|
||||||
this.getPermissions,
|
this.getPermissions,
|
||||||
this.setPermission,
|
this.setPermission,
|
||||||
this.changeRank
|
|
||||||
]
|
]
|
||||||
},{
|
},{
|
||||||
name: 'softreserveCurrency' as 'softreserveCurrency',
|
name: 'softreserveCurrency' as 'softreserveCurrency',
|
||||||
@@ -84,6 +96,8 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
|
|||||||
rank: rank
|
rank: rank
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await this.adminLogout(user.username)
|
||||||
|
|
||||||
return await this.admin
|
return await this.admin
|
||||||
.knex('users')
|
.knex('users')
|
||||||
.where({
|
.where({
|
||||||
@@ -132,8 +146,6 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
|
|||||||
})))
|
})))
|
||||||
|
|
||||||
//start rankServers
|
//start rankServers
|
||||||
getLogger('UserManager').debug('Starting rank servers')
|
|
||||||
|
|
||||||
let rankServers = { } as any
|
let rankServers = { } as any
|
||||||
await Promise.all(_Rank.map(async (r,i) => {
|
await Promise.all(_Rank.map(async (r,i) => {
|
||||||
const port = 20001 + i
|
const port = 20001 + i
|
||||||
@@ -145,25 +157,23 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
this.rankServers = rankServers
|
this.rankServers = rankServers
|
||||||
|
getLogger('UserManager').debug(Object.values(this.rankServers).length+" rank servers started")
|
||||||
|
|
||||||
setInterval(this.checkExpiredSessions, 600_000)
|
setInterval(this.checkExpiredSessions, 600_000)
|
||||||
}
|
}
|
||||||
|
|
||||||
stop = async () => {
|
stop = async () => {
|
||||||
Object.values(this.userLogins).forEach(x => Object.values(x.connections).forEach(c => c.destroy()))
|
Object.values(this.userLogins).forEach(x => {
|
||||||
|
Object.values(x.connections).forEach(c => c.destroy())
|
||||||
|
})
|
||||||
|
|
||||||
await Promise.all(Object
|
Object.values(this.rankServers)
|
||||||
.values(this.rankServers)
|
.map(state => {
|
||||||
.map(async state => {
|
try{
|
||||||
try{
|
return state.server.destroy()
|
||||||
//return await state.server.destroy()
|
}catch(e){
|
||||||
}catch(e){
|
getLogger('UserManager').warn(e)
|
||||||
getLogger('UserManager').warn(e)
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
checkExpiredSessions = () => {
|
checkExpiredSessions = () => {
|
||||||
@@ -198,6 +208,26 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changePassword = async (userToken:string, pwHash:string) : Promise<User> => {
|
||||||
|
const record = this.getUserRecordByToken(userToken)
|
||||||
|
if(!record) return {} as User
|
||||||
|
return await this.adminChangePassword(record.user, pwHash)
|
||||||
|
}
|
||||||
|
|
||||||
|
adminChangePassword = async(user:User, pwHash:string) : Promise<User> => {
|
||||||
|
const salted = await saltedHash(pwHash, salt)
|
||||||
|
await this.admin.knex('users')
|
||||||
|
.update({pwhash: salted})
|
||||||
|
.where({
|
||||||
|
username: user.username
|
||||||
|
})
|
||||||
|
|
||||||
|
const usr = await this.getUser(user.username)
|
||||||
|
if(!usr) return {} as any
|
||||||
|
await this.adminLogout(usr.username)
|
||||||
|
return usr
|
||||||
|
}
|
||||||
|
|
||||||
setPermission = async (permission: RPCPermission) => {
|
setPermission = async (permission: RPCPermission) => {
|
||||||
await this.admin.knex('rpcpermissions')
|
await this.admin.knex('rpcpermissions')
|
||||||
.where('rpcname', '=', permission.rpcname)
|
.where('rpcname', '=', permission.rpcname)
|
||||||
@@ -270,21 +300,27 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
|
|||||||
logout = async (username:string, tokenValue : string) : Promise<void> => {
|
logout = async (username:string, tokenValue : string) : Promise<void> => {
|
||||||
try{
|
try{
|
||||||
if(!this.checkTokenOwnedByUser(username, tokenValue)) return
|
if(!this.checkTokenOwnedByUser(username, tokenValue)) return
|
||||||
|
return await this.adminLogout(username)
|
||||||
|
}catch(e){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adminLogout = async(username: string) : Promise<void> => {
|
||||||
|
try{
|
||||||
if(this.userLogins[username]){
|
if(this.userLogins[username]){
|
||||||
await Promise.all (Object.values(this.userLogins[username].connections).map(async (sock) => {
|
await Promise.all (Object.values(this.userLogins[username].connections).map(async (sock) => {
|
||||||
await sock.call('navigate', '/auth/login')
|
await sock.call('kick')
|
||||||
}))
|
}))
|
||||||
}
|
|
||||||
|
Object.values(this.rankServers)
|
||||||
Object.values(this.rankServers)
|
|
||||||
.forEach(state => {
|
.forEach(state => {
|
||||||
state.allowed = state.allowed.filter(allowed => allowed !== tokenValue)
|
state.allowed = state.allowed.filter(allowed => allowed !== this.userLogins[username].auth.token.value)
|
||||||
})
|
})
|
||||||
|
delete this.userLogins[username]
|
||||||
delete this.userLogins[username]
|
}
|
||||||
}catch(e){
|
}catch(e){
|
||||||
console.log(e)
|
getLogger('UserManager').warn(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,9 +426,6 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
|
|||||||
username = username.toLowerCase()
|
username = username.toLowerCase()
|
||||||
const maybeRecord = this.getUserRecordByToken(tokenValue)
|
const maybeRecord = this.getUserRecordByToken(tokenValue)
|
||||||
if(!maybeRecord || maybeRecord.auth.user.username != username){
|
if(!maybeRecord || maybeRecord.auth.user.username != username){
|
||||||
getLogger('UserManager').warn(`Bad logout attempt
|
|
||||||
token by: ${maybeRecord?maybeRecord.auth.user.username:tokenValue}
|
|
||||||
tried to logout: ${username}`)
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { FrontworkComponent } from '../Types/FrontworkComponent';
|
|||||||
export const Injector = new class {
|
export const Injector = new class {
|
||||||
|
|
||||||
injectionQueue :any[] = []
|
injectionQueue :any[] = []
|
||||||
|
rootObj: any
|
||||||
rootInterface : Type<any>
|
rootInterface : Type<any>
|
||||||
root : Type<any>
|
root : Type<any>
|
||||||
rootModules: Type<any>[] = []
|
rootModules: Type<any>[] = []
|
||||||
@@ -29,6 +29,7 @@ export const Injector = new class {
|
|||||||
return this.moduleObjs[target.name] as any
|
return this.moduleObjs[target.name] as any
|
||||||
|
|
||||||
if(target.name === this.rootInterface.name || target.name === this.root.name){
|
if(target.name === this.rootInterface.name || target.name === this.root.name){
|
||||||
|
if(this.rootObj) return this.rootObj
|
||||||
let modules = this.modules.map(m => {
|
let modules = this.modules.map(m => {
|
||||||
const module = new m.implementation()
|
const module = new m.implementation()
|
||||||
if(m.implements)
|
if(m.implements)
|
||||||
@@ -36,10 +37,10 @@ export const Injector = new class {
|
|||||||
this.moduleObjs[m.implementation.name] = module
|
this.moduleObjs[m.implementation.name] = module
|
||||||
return module
|
return module
|
||||||
})
|
})
|
||||||
const rootobj = new this.root(modules);
|
const rootObj = new this.root(modules);
|
||||||
|
|
||||||
this.moduleObjs[this.rootInterface.name] = rootobj
|
this.moduleObjs[this.rootInterface.name] = rootObj
|
||||||
this.moduleObjs[target.name] = rootobj
|
this.moduleObjs[target.name] = rootObj
|
||||||
while(this.injectionQueue.length > 0){
|
while(this.injectionQueue.length > 0){
|
||||||
const i = this.injectionQueue.shift()
|
const i = this.injectionQueue.shift()
|
||||||
if(this.moduleObjs[i.what.name])
|
if(this.moduleObjs[i.what.name])
|
||||||
@@ -47,8 +48,8 @@ export const Injector = new class {
|
|||||||
else
|
else
|
||||||
this.injectionQueue.push(i)
|
this.injectionQueue.push(i)
|
||||||
}
|
}
|
||||||
|
this.rootObj = rootObj
|
||||||
return rootobj
|
return rootObj
|
||||||
}
|
}
|
||||||
this.moduleObjs[target.name] = new target()
|
this.moduleObjs[target.name] = new target()
|
||||||
return this.moduleObjs[target.name] as any
|
return this.moduleObjs[target.name] as any
|
||||||
|
|||||||
@@ -9,12 +9,8 @@
|
|||||||
"projectType": "application",
|
"projectType": "application",
|
||||||
"architect": {
|
"architect": {
|
||||||
"build": {
|
"build": {
|
||||||
"builder": "@angular-builders/custom-webpack:browser",
|
"builder": "@angular-devkit/build-angular:browser",
|
||||||
"options": {
|
"options": {
|
||||||
"customWebpackConfig": {
|
|
||||||
"path": "./custom-webpack.config.js",
|
|
||||||
"replaceDuplicatePlugins": true
|
|
||||||
},
|
|
||||||
"preserveSymlinks": true,
|
"preserveSymlinks": true,
|
||||||
"rebaseRootRelativeCssUrls": true,
|
"rebaseRootRelativeCssUrls": true,
|
||||||
"outputPath": "dist",
|
"outputPath": "dist",
|
||||||
@@ -79,7 +75,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"serve": {
|
"serve": {
|
||||||
"builder": "@angular-builders/custom-webpack:dev-server",
|
"builder": "@angular-devkit/build-angular:dev-server",
|
||||||
"options": {
|
"options": {
|
||||||
"browserTarget": "ngx-admin-demo:build"
|
"browserTarget": "ngx-admin-demo:build"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
externals: ['http', 'fs'],
|
|
||||||
node: {global: true, fs: 'empty'}
|
|
||||||
}
|
|
||||||
Generated
+6102
-2794
File diff suppressed because it is too large
Load Diff
@@ -50,7 +50,7 @@
|
|||||||
"angular2-chartjs": "0.4.1",
|
"angular2-chartjs": "0.4.1",
|
||||||
"angular2-toaster": "^7.0.0",
|
"angular2-toaster": "^7.0.0",
|
||||||
"bootstrap": "4.3.1",
|
"bootstrap": "4.3.1",
|
||||||
"chart.js": "2.7.1",
|
"chart.js": "^2.9.3",
|
||||||
"ckeditor": "4.7.3",
|
"ckeditor": "4.7.3",
|
||||||
"classlist.js": "1.1.20150312",
|
"classlist.js": "1.1.20150312",
|
||||||
"core-js": "2.5.1",
|
"core-js": "2.5.1",
|
||||||
@@ -65,11 +65,11 @@
|
|||||||
"ng2-smart-table": "1.3.5",
|
"ng2-smart-table": "1.3.5",
|
||||||
"ngx-cookie-service": "^2.2.0",
|
"ngx-cookie-service": "^2.2.0",
|
||||||
"ngx-echarts": "^4.0.1",
|
"ngx-echarts": "^4.0.1",
|
||||||
"node-sass": "^4.12.0",
|
"node-sass": "^4.13.1",
|
||||||
"normalize.css": "6.0.0",
|
"normalize.css": "6.0.0",
|
||||||
"pace-js": "1.0.2",
|
"pace-js": "1.0.2",
|
||||||
"roboto-fontface": "0.8.0",
|
"roboto-fontface": "0.8.0",
|
||||||
"rpclibrary": "^1.7.1",
|
"rpclibrary": "^1.8.3",
|
||||||
"rxjs": "6.5.2",
|
"rxjs": "6.5.2",
|
||||||
"rxjs-compat": "6.3.0",
|
"rxjs-compat": "6.3.0",
|
||||||
"socicon": "3.0.5",
|
"socicon": "3.0.5",
|
||||||
@@ -80,11 +80,11 @@
|
|||||||
"zone.js": "~0.9.1"
|
"zone.js": "~0.9.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-devkit/build-angular": "~0.800.2",
|
"@angular-devkit/build-angular": "~0.803.24",
|
||||||
"@angular/cli": "^8.0.2",
|
"@angular/cli": "^8.0.2",
|
||||||
"@angular/compiler-cli": "^8.0.0",
|
"@angular/compiler-cli": "^8.0.0",
|
||||||
"@angular/language-service": "8.0.0",
|
"@angular/language-service": "8.0.0",
|
||||||
"@compodoc/compodoc": "1.0.1",
|
"@compodoc/compodoc": "^1.1.11",
|
||||||
"@fortawesome/fontawesome-free": "^5.2.0",
|
"@fortawesome/fontawesome-free": "^5.2.0",
|
||||||
"@types/d3-color": "1.0.5",
|
"@types/d3-color": "1.0.5",
|
||||||
"@types/googlemaps": "^3.30.4",
|
"@types/googlemaps": "^3.30.4",
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
<div class="header-container">
|
<div class="header-container">
|
||||||
<div>
|
|
||||||
<a (click)="toggleSidebar()" href="#" class="sidebar-toggle">
|
|
||||||
<nb-icon icon="menu-2-outline"></nb-icon>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="logo-container">
|
<div class="logo-container">
|
||||||
<a (click)="toggleSidebar()" href="#" class="sidebar-toggle">
|
<a (click)="toggleSidebar()" href="#" class="sidebar-toggle">
|
||||||
<nb-icon icon="menu-2-outline"></nb-icon>
|
<nb-icon icon="menu-2-outline"></nb-icon>
|
||||||
|
|||||||
@@ -35,12 +35,7 @@
|
|||||||
[maxlength]="15"
|
[maxlength]="15"
|
||||||
[attr.aria-invalid]="password.invalid && password.touched ? true : null">
|
[attr.aria-invalid]="password.invalid && password.touched ? true : null">
|
||||||
</div>
|
</div>
|
||||||
|
<br />
|
||||||
<div class="form-control-group accept-group">
|
|
||||||
<nb-checkbox name="rememberMe" [(ngModel)]="user.rememberMe" *ngIf="rememberMe">Remember me</nb-checkbox>
|
|
||||||
<a class="forgot-password" routerLink="../request-password">Forgot Password?</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button nbButton
|
<button nbButton
|
||||||
fullWidth
|
fullWidth
|
||||||
status="primary"
|
status="primary"
|
||||||
|
|||||||
@@ -35,28 +35,32 @@
|
|||||||
[attr.aria-invalid]="password.invalid && password.touched ? true : null">
|
[attr.aria-invalid]="password.invalid && password.touched ? true : null">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-control-group accept-group">
|
|
||||||
<nb-checkbox name="rememberMe" [(ngModel)]="user.rememberMe" *ngIf="rememberMe">Remember me</nb-checkbox>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<nb-card>
|
<nb-card>
|
||||||
<nb-card-body>
|
<nb-card-body>
|
||||||
<nb-checkbox [(ngModel)]="showApplication" name="amMember" #checkbox><!--I am already a member-->I understand this is super beta and things might not work or are not very pretty</nb-checkbox>
|
<nb-checkbox [(ngModel)]="showApplication" name="amMember" #checkbox><!--I am already a member-->I understand this is super beta and things might not work or are not very pretty</nb-checkbox>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<span > <!--*ngIf="showApplication"-->
|
<span > <!--*ngIf="showApplication"-->
|
||||||
And my main is <input name="preMember" [(ngModel)]="character.name" nbInput>, a
|
And my main is <input nbInput [required]="true" name="preMember" [(ngModel)]="character.name" >, a
|
||||||
<nb-select [(selected)]="character.race" placeholder="Race" (selectedChange)="onSelectRace()">
|
<nb-select [(selected)]="character.race" placeholder="Race" (selectedChange)="onSelectRace()">
|
||||||
<nb-option *ngFor="let race of races" [value]="race">{{race}}</nb-option>
|
<nb-option *ngFor="let race of races" [value]="race">{{race}}</nb-option>
|
||||||
</nb-select>
|
</nb-select>
|
||||||
<nb-select [(selected)]="character.spec" placeholder="Spec" (selectedChange)="onSelectSpec()">
|
<nb-select
|
||||||
|
[(selected)]="character.spec"
|
||||||
|
placeholder="Spec"
|
||||||
|
(selectedChange)="onSelectSpec()">
|
||||||
<nb-option *ngFor="let spec of specs" [value]="spec">{{spec}}</nb-option>
|
<nb-option *ngFor="let spec of specs" [value]="spec">{{spec}}</nb-option>
|
||||||
</nb-select>
|
</nb-select>
|
||||||
<nb-select [(selected)]="character.class" placeholder="Class" (selectedChange)="onSelectClass()">
|
<nb-select
|
||||||
|
[(selected)]="character.class"
|
||||||
|
placeholder="Class"
|
||||||
|
(selectedChange)="onSelectClass()">
|
||||||
<nb-option *ngFor="let class of classes" [value]="class">{{class}}</nb-option>
|
<nb-option *ngFor="let class of classes" [value]="class">{{class}}</nb-option>
|
||||||
</nb-select>
|
</nb-select>
|
||||||
with rank
|
with rank
|
||||||
<nb-select [(selected)]="user.rank" placeholder="Rank">
|
<nb-select
|
||||||
|
[(selected)]="user.rank"
|
||||||
|
placeholder="Rank">
|
||||||
<nb-option *ngFor="let rank of ranks" [value]="rank" >{{rank}}</nb-option>
|
<nb-option *ngFor="let rank of ranks" [value]="rank" >{{rank}}</nb-option>
|
||||||
</nb-select>
|
</nb-select>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ export class FrontcraftRaidComponent implements OnInit, OnDestroy{
|
|||||||
this.displayedtokens = this.tokens
|
this.displayedtokens = this.tokens
|
||||||
}else{
|
}else{
|
||||||
this.displayedtokens = {}
|
this.displayedtokens = {}
|
||||||
Object.entries(this.tokens).forEach((e: [string, (Character & SRToken & Item)[]]) => {
|
Object.entries(this.tokens).forEach((e: [string /*itemname*/, (Character & SRToken & Item)[]]) => {
|
||||||
const filteredTokens = e[1].filter(item => {
|
const filteredTokens = e[1].filter(item => {
|
||||||
return item.itemname.toLocaleLowerCase().includes(this.search.toLocaleLowerCase())
|
return item.itemname.toLocaleLowerCase().includes(this.search.toLocaleLowerCase())
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { _Tiers, allItems, Tiers } from '../../../../../../backend/Types/Items';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'buyToken',
|
selector: 'buyToken',
|
||||||
template: `
|
template: `
|
||||||
<nb-card class="col-12 col-xl-9">
|
<nb-card style="width: 500px">
|
||||||
<nb-card-header>
|
<nb-card-header>
|
||||||
Buy {{item.itemname}}
|
Buy {{item.itemname}}
|
||||||
</nb-card-header>
|
</nb-card-header>
|
||||||
@@ -19,8 +19,10 @@ import { _Tiers, allItems, Tiers } from '../../../../../../backend/Types/Items';
|
|||||||
</p>
|
</p>
|
||||||
<div *ngIf="currency>0">
|
<div *ngIf="currency>0">
|
||||||
<nb-alert accent="danger" *ngIf="invalidatedTokens.length > 0">
|
<nb-alert accent="danger" *ngIf="invalidatedTokens.length > 0">
|
||||||
Claiming this reserve invalidates the following streaks. <br />
|
Claiming this reserve puts the following streaks to zero <br />
|
||||||
This is not reversible.
|
<span>
|
||||||
|
<nb-icon icon="alert-triangle-outline" status="warning"></nb-icon> This is not reversible <nb-icon icon="alert-triangle-outline" status="warning"></nb-icon>
|
||||||
|
</span>
|
||||||
<ul *ngFor="let item of invalidatedTokens">
|
<ul *ngFor="let item of invalidatedTokens">
|
||||||
<li>
|
<li>
|
||||||
[ {{item.level}} ]
|
[ {{item.level}} ]
|
||||||
|
|||||||
@@ -6,12 +6,65 @@ accent="info">
|
|||||||
<h2 style="text-transform: capitalize;">{{user.username}}</h2>
|
<h2 style="text-transform: capitalize;">{{user.username}}</h2>
|
||||||
</nb-card-header>
|
</nb-card-header>
|
||||||
<nb-card-body>
|
<nb-card-body>
|
||||||
{{user.MC}} MC
|
|
||||||
{{user.BWL}} BWL
|
<h3>Rank</h3>
|
||||||
{{user.ZG}} ZG
|
<span *ngIf="!manageUser">
|
||||||
{{user.AQ20}} AQ20
|
{{user.rank}}
|
||||||
{{user.AQ40}} AQ40
|
</span>
|
||||||
|
<nb-select
|
||||||
|
*ngIf="manageUser"
|
||||||
|
[(selected)]="user.rank"
|
||||||
|
placeholder="Rank"
|
||||||
|
(selectedChange)="onSelectRank()">
|
||||||
|
|
||||||
|
<nb-option *ngFor="let rank of ranks" [value]="rank" >{{rank}}</nb-option>
|
||||||
|
</nb-select>
|
||||||
|
|
||||||
|
<h3 *ngIf="myProfile || manageUser">Password</h3>
|
||||||
|
<form (ngSubmit)="submitPasswordChange()" #form="ngForm" aria-labelledby="title" *ngIf="myProfile || manageUser">
|
||||||
|
<input nbInput
|
||||||
|
fullWidth
|
||||||
|
type="password"
|
||||||
|
[(ngModel)]="newPw"
|
||||||
|
name="newPw"
|
||||||
|
id="input-newPw"
|
||||||
|
pattern=".+"
|
||||||
|
placeholder="New Password"
|
||||||
|
fieldSize="small"
|
||||||
|
autofocus
|
||||||
|
[required]="true">
|
||||||
|
|
||||||
|
<input nbInput
|
||||||
|
fullWidth
|
||||||
|
type="password"
|
||||||
|
[(ngModel)]="newPwConfirm"
|
||||||
|
name="newPwConfirm"
|
||||||
|
id="input-newPwConfirm"
|
||||||
|
pattern=".+"
|
||||||
|
placeholder="Confirm Password"
|
||||||
|
fieldSize="small"
|
||||||
|
autofocus
|
||||||
|
[required]="true">
|
||||||
|
|
||||||
|
<button nbButton
|
||||||
|
fullWidth
|
||||||
|
status="primary"
|
||||||
|
size="small"
|
||||||
|
[disabled]="!form.valid || newPw != newPwConfirm"
|
||||||
|
[class.btn-pulse]="submitted">
|
||||||
|
Change
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<h3>Avaiable Reserves</h3>
|
||||||
|
{{user.MC}} MC |
|
||||||
|
{{user.BWL}} BWL |
|
||||||
|
{{user.ZG}} ZG |
|
||||||
|
{{user.AQ20}} AQ20 |
|
||||||
|
{{user.AQ40}} AQ40 |
|
||||||
{{user.Naxx}} Naxx
|
{{user.Naxx}} Naxx
|
||||||
|
<br />
|
||||||
<ng-container *ngFor="let char of characters">
|
<ng-container *ngFor="let char of characters">
|
||||||
<character [name]="char.charactername" [link]="'character'"></character>
|
<character [name]="char.charactername" [link]="'character'"></character>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ApiService } from '../../services/login-api';
|
import { ApiService, hash } from '../../services/login-api';
|
||||||
import { Router, ActivatedRoute } from '@angular/router';
|
import { Router, ActivatedRoute } from '@angular/router';
|
||||||
import { User, Spec, Character } from '../../../../../../backend/Types/Types';
|
import { User, Spec, Character } from '../../../../../../backend/Types/Types';
|
||||||
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
|
import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
|
||||||
import { _Tiers } from '../../../../../../backend/Types/Items';
|
import { _Tiers } from '../../../../../../backend/Types/Items';
|
||||||
|
import { _Rank } from '../../../../../../backend/Types/Types';
|
||||||
|
import { NbToastrService } from '@nebular/theme';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'user-component',
|
selector: 'user-component',
|
||||||
@@ -11,22 +13,31 @@ import { _Tiers } from '../../../../../../backend/Types/Items';
|
|||||||
})
|
})
|
||||||
export class FrontcraftUserComponent implements OnInit{
|
export class FrontcraftUserComponent implements OnInit{
|
||||||
|
|
||||||
|
newPw
|
||||||
|
newPwConfirm
|
||||||
|
|
||||||
|
ranks = _Rank
|
||||||
|
myProfile = false
|
||||||
|
manageUser
|
||||||
user:User = {} as any
|
user:User = {} as any
|
||||||
characters : (Character & Spec)[] = []
|
characters : (Character & Spec)[] = []
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private api : ApiService
|
private api : ApiService,
|
||||||
|
private toastr: NbToastrService
|
||||||
){}
|
){}
|
||||||
|
|
||||||
async ngOnInit(){
|
async ngOnInit(){
|
||||||
const param = this.route.snapshot.paramMap.get('name');
|
const param = this.route.snapshot.paramMap.get('name');
|
||||||
const usr = await this.api.get('UserManager').getUser(param)
|
const usr = await this.api.get('UserManager').getUser(param)
|
||||||
|
|
||||||
|
|
||||||
if(!usr) return
|
if(!usr) return
|
||||||
this.user = usr
|
this.user = usr
|
||||||
|
|
||||||
|
this.manageUser = this.api.get('manageUser')
|
||||||
|
this.myProfile = this.api.getCurrentUser().username === this.user.username
|
||||||
|
|
||||||
const characters = await this.api.get('CharacterManager').getCharactersOfUser(this.user.username)
|
const characters = await this.api.get('CharacterManager').getCharactersOfUser(this.user.username)
|
||||||
characters.forEach(async c => {
|
characters.forEach(async c => {
|
||||||
const tokens = await this.api.get('ItemManager').getTokens(c, _Tiers, true)
|
const tokens = await this.api.get('ItemManager').getTokens(c, _Tiers, true)
|
||||||
@@ -35,4 +46,24 @@ export class FrontcraftUserComponent implements OnInit{
|
|||||||
})
|
})
|
||||||
this.characters = characters
|
this.characters = characters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onSelectRank(){
|
||||||
|
const manage = this.api.get('manageUser')
|
||||||
|
if(!manage) return
|
||||||
|
await manage.changeRank(this.user, this.user.rank)
|
||||||
|
this.toastr.success("Rank changed to "+this.user.rank, "Update success")
|
||||||
|
}
|
||||||
|
|
||||||
|
async submitPasswordChange(){
|
||||||
|
const pw = await hash(this.newPw)
|
||||||
|
this.newPw = null
|
||||||
|
this.newPwConfirm = null
|
||||||
|
|
||||||
|
const manage = this.api.get('manageUser')
|
||||||
|
if(!manage){
|
||||||
|
await this.api.get('UserManager').changePassword(this.api.getAuth().token.value, pw)
|
||||||
|
}else{
|
||||||
|
await manage.adminChangePassword(this.user, pw)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ import { CookieService } from 'ngx-cookie-service';
|
|||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { ShoutMessage } from '../../../../../backend/Components/Shoutbox/Interface';
|
import { ShoutMessage } from '../../../../../backend/Components/Shoutbox/Interface';
|
||||||
import { saltedHash } from '../../../../../backend/Util/hash';
|
import { saltedHash } from '../../../../../backend/Util/hash';
|
||||||
|
import { NbToastrService } from '@nebular/theme';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ApiService{
|
export class ApiService{
|
||||||
@@ -16,7 +17,8 @@ export class ApiService{
|
|||||||
constructor(
|
constructor(
|
||||||
private injector: Injector,
|
private injector: Injector,
|
||||||
private cookieSvc : CookieService,
|
private cookieSvc : CookieService,
|
||||||
private ngZone : NgZone
|
private ngZone : NgZone,
|
||||||
|
private toastr: NbToastrService
|
||||||
){}
|
){}
|
||||||
|
|
||||||
getUnprivilegedSocket = () : RPCSocket & FrontcraftIfc => this.socket
|
getUnprivilegedSocket = () : RPCSocket & FrontcraftIfc => this.socket
|
||||||
@@ -30,30 +32,34 @@ export class ApiService{
|
|||||||
auth.port,
|
auth.port,
|
||||||
window.location.hostname
|
window.location.hostname
|
||||||
)
|
)
|
||||||
|
|
||||||
const authSock = await sock.connect<RPCSocket & SomeOf<FrontcraftFeatureIfc>>(auth.token.value)
|
|
||||||
|
|
||||||
sock.hook('kick', () => {
|
sock.hook('kick', () => {
|
||||||
console.log("I got kicked");
|
this.logout()
|
||||||
})
|
})
|
||||||
|
|
||||||
sock.hook('getUserData', () => auth)
|
sock.hook('getUserData', () => auth)
|
||||||
sock.hook('navigate', (where:string) => {
|
sock.hook('navigate', (where:string) => {
|
||||||
this.ngZone.run( () => {
|
this.ngZone.run( () => {
|
||||||
this.injector.get(Router).navigateByUrl(where)
|
this.injector.get(Router).navigateByUrl(where)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
sock.on('error', (e) => {
|
|
||||||
sock.destroy();
|
sock.on('close', async () => {
|
||||||
|
//handled via unprivileged socket
|
||||||
})
|
})
|
||||||
|
|
||||||
|
sock.on('error', async (e) => {
|
||||||
|
//handled via unprivileged socket
|
||||||
|
})
|
||||||
|
const authSock = await sock.connect<RPCSocket & SomeOf<FrontcraftFeatureIfc>>(auth.token.value)
|
||||||
|
|
||||||
this.auth = auth
|
this.auth = auth
|
||||||
this.privSocket = authSock
|
this.privSocket = authSock
|
||||||
this.cookieSvc.set('token', JSON.stringify(auth))
|
this.cookieSvc.set('token', JSON.stringify(auth))
|
||||||
return authSock
|
return authSock
|
||||||
}catch(e){
|
}catch(e){
|
||||||
//login failed
|
if(this.privSocket) this.privSocket.destroy()
|
||||||
throw new Error(e)
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,12 +82,25 @@ export class ApiService{
|
|||||||
|
|
||||||
login = async (username: string, password: string) : Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => {
|
login = async (username: string, password: string) : Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => {
|
||||||
const pwHash = await hash(password)
|
const pwHash = await hash(password)
|
||||||
const auth = await this.socket.UserManager.login(username, pwHash)
|
let auth
|
||||||
|
try{
|
||||||
|
auth = await this.socket.UserManager.login(username, pwHash)
|
||||||
|
}catch(e){
|
||||||
|
this.toastr.danger("Login failed", "Error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if(!auth){
|
if(!auth){
|
||||||
await this.logout()
|
await this.logout()
|
||||||
|
this.toastr.danger("Login failed", "Error")
|
||||||
throw new Error("Login failed")
|
throw new Error("Login failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//attach error handler now so failed logins dont trigger reloads
|
||||||
|
this.socket.on('error', async (err) => {
|
||||||
|
location.reload()
|
||||||
|
})
|
||||||
|
|
||||||
const sock = await this.getPrivilegedSocket(auth)
|
const sock = await this.getPrivilegedSocket(auth)
|
||||||
return sock
|
return sock
|
||||||
}
|
}
|
||||||
@@ -93,26 +112,50 @@ export class ApiService{
|
|||||||
|
|
||||||
logout = async () => {
|
logout = async () => {
|
||||||
this.cookieSvc.set('token', undefined)
|
this.cookieSvc.set('token', undefined)
|
||||||
if(this.auth) await this.socket.UserManager.logout(this.auth.user.username, this.auth.token.value)
|
if(this.auth){
|
||||||
|
try{
|
||||||
|
await this.socket.UserManager.logout(this.auth.user.username, this.auth.token.value)
|
||||||
|
}catch(e){
|
||||||
|
//socket is dead
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(this.privSocket) this.privSocket.destroy()
|
if(this.privSocket) this.privSocket.destroy()
|
||||||
this.privSocket = null
|
this.privSocket = null
|
||||||
this.auth = null
|
this.auth = null
|
||||||
|
|
||||||
this.ngZone.run(() => {
|
this.ngZone.run(() => {
|
||||||
this.injector.get(Router).navigate(['/auth']);
|
this.injector.get(Router).navigate(['/auth']);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize = async () : Promise<any> => {
|
initialize = async () : Promise<any> => {
|
||||||
const sock = await RPCSocket.makeSocket<FrontcraftIfc>(20000, window.location.hostname)
|
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){
|
||||||
|
alert('Unable to connect. The server appears to be down.\nPress OK to refresh the page')
|
||||||
|
location.reload()
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.socket = sock
|
|
||||||
try{
|
try{
|
||||||
const cookie = JSON.parse(this.cookieSvc.get('token'))
|
const cookie = JSON.parse(this.cookieSvc.get('token'))
|
||||||
|
|
||||||
if(cookie != null) {
|
if(cookie != null) {
|
||||||
try{
|
try{
|
||||||
const auth = await sock.UserManager.getAuth(cookie.token.value)
|
const auth = await this.socket.UserManager.getAuth(cookie.token.value)
|
||||||
if(!auth) return sock
|
if(!auth) return this.socket
|
||||||
return await this.getPrivilegedSocket(auth)
|
return await this.getPrivilegedSocket(auth)
|
||||||
}catch(e){
|
}catch(e){
|
||||||
await this.logout()
|
await this.logout()
|
||||||
|
|||||||
+35
-12
@@ -2,7 +2,35 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>ngx-admin Demo Application</title>
|
<title>Frontcraft</title>
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Montserrat">
|
||||||
|
<style>
|
||||||
|
@import url('https://fonts.googleapis.com/css?family=Montserrat');
|
||||||
|
|
||||||
|
.loadTitle {
|
||||||
|
font-family: 'Montserrat';
|
||||||
|
text-align: center;
|
||||||
|
color: #FFF;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
padding-top: calc(50vh - 120px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.loadH {
|
||||||
|
background-image: url('https://media.giphy.com/media/26BROrSHlmyzzHf3i/giphy.gif');
|
||||||
|
background-size: cover;
|
||||||
|
color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
-moz-background-clip: text;
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: min(10vw, 120px);
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<base href="/">
|
<base href="/">
|
||||||
|
|
||||||
@@ -11,17 +39,12 @@
|
|||||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<ngx-app>Loading...</ngx-app>
|
<ngx-app></ngx-app>
|
||||||
|
<div id="nb-global-spinner" class="spinner" style="background-color: #111; height: 100vh;">
|
||||||
<style>@-webkit-keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@-moz-keyframes spin{0%{-moz-transform:rotate(0)}100%{-moz-transform:rotate(360deg)}}@keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}.spinner{position:fixed;top:0;left:0;width:100%;height:100%;z-index:1003;background: #000000;overflow:hidden} .spinner div:first-child{display:block;position:relative;left:50%;top:50%;width:150px;height:150px;margin:-75px 0 0 -75px;border-radius:50%;box-shadow:0 3px 3px 0 rgba(255,56,106,1);transform:translate3d(0,0,0);animation:spin 2s linear infinite} .spinner div:first-child:after,.spinner div:first-child:before{content:'';position:absolute;border-radius:50%} .spinner div:first-child:before{top:5px;left:5px;right:5px;bottom:5px;box-shadow:0 3px 3px 0 rgb(255, 228, 32);-webkit-animation:spin 3s linear infinite;animation:spin 3s linear infinite} .spinner div:first-child:after{top:15px;left:15px;right:15px;bottom:15px;box-shadow:0 3px 3px 0 rgba(61, 175, 255,1);animation:spin 1.5s linear infinite}</style>
|
<div class="loadTitle">
|
||||||
<div id="nb-global-spinner" class="spinner">
|
<h1 class="loadH">Tranquil</h1>
|
||||||
<div class="blob blob-0"></div>
|
</div>
|
||||||
<div class="blob blob-1"></div>
|
|
||||||
<div class="blob blob-2"></div>
|
|
||||||
<div class="blob blob-3"></div>
|
|
||||||
<div class="blob blob-4"></div>
|
|
||||||
<div class="blob blob-5"></div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -55,3 +55,6 @@ import 'core-js/es7/object';
|
|||||||
if (typeof SVGElement.prototype.contains === 'undefined') {
|
if (typeof SVGElement.prototype.contains === 'undefined') {
|
||||||
SVGElement.prototype.contains = HTMLDivElement.prototype.contains;
|
SVGElement.prototype.contains = HTMLDivElement.prototype.contains;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(window as any).global = window;
|
||||||
|
(window as any).global.Buffer = (window as any).global.Buffer || require('buffer').Buffer;
|
||||||
|
|||||||
+2
-17
@@ -53,6 +53,8 @@ const defaultPermissions = [
|
|||||||
rpcname: 'softreserveCurrency', ...adminsOnly
|
rpcname: 'softreserveCurrency', ...adminsOnly
|
||||||
}, {
|
}, {
|
||||||
rpcname: 'manageRaid', ...adminsOnly
|
rpcname: 'manageRaid', ...adminsOnly
|
||||||
|
}, {
|
||||||
|
rpcname: 'manageUser', ...adminsOnly
|
||||||
}]
|
}]
|
||||||
|
|
||||||
const testAccounts: protoAccount[] = [
|
const testAccounts: protoAccount[] = [
|
||||||
@@ -271,12 +273,6 @@ describe('Frontcraft', () => {
|
|||||||
undefined, 2, "str-to-ap bias"
|
undefined, 2, "str-to-ap bias"
|
||||||
),
|
),
|
||||||
|
|
||||||
makePrio(
|
|
||||||
'Band of Accuria',
|
|
||||||
{ class: 'Warrior', specname: 'Protection' },
|
|
||||||
undefined, 2, "hit bias"
|
|
||||||
),
|
|
||||||
|
|
||||||
makePrio(
|
makePrio(
|
||||||
'Bracers of Arcane Accuracy',
|
'Bracers of Arcane Accuracy',
|
||||||
{ class: 'Warlock', specname: 'Demonology' },
|
{ class: 'Warlock', specname: 'Demonology' },
|
||||||
@@ -376,22 +372,11 @@ describe('Frontcraft', () => {
|
|||||||
undefined, 1, "hit bias"
|
undefined, 1, "hit bias"
|
||||||
),
|
),
|
||||||
|
|
||||||
makePrio(
|
|
||||||
'Chromatic Boots',
|
|
||||||
{ class: 'Warrior', specname: 'Protection' },
|
|
||||||
undefined, 2, "hit bias"
|
|
||||||
),
|
|
||||||
|
|
||||||
makePrio(
|
makePrio(
|
||||||
'Crul\'shorukh, Edge of Chaos',
|
'Crul\'shorukh, Edge of Chaos',
|
||||||
undefined,
|
undefined,
|
||||||
"Human", -2, "Non-human"
|
"Human", -2, "Non-human"
|
||||||
),
|
),
|
||||||
makePrio(
|
|
||||||
'Crul\'shorukh, Edge of Chaos',
|
|
||||||
{ class: 'Warrior', specname: 'Protection' },
|
|
||||||
undefined, 2, "nice dps bias"
|
|
||||||
),
|
|
||||||
makePrio(
|
makePrio(
|
||||||
'Crul\'shorukh, Edge of Chaos',
|
'Crul\'shorukh, Edge of Chaos',
|
||||||
{ class: 'Warrior', specname: 'Fury' },
|
{ class: 'Warrior', specname: 'Fury' },
|
||||||
|
|||||||
Reference in New Issue
Block a user