before frontend login
This commit is contained in:
@@ -3,52 +3,26 @@
|
||||
import { getLogger } from 'frontblock-generic/Types';
|
||||
import { promises as fs, mkdirSync } from "fs"
|
||||
import { RPCServer } from 'rpclibrary'
|
||||
import { AdminConf, TableDefiniton } from './Types';
|
||||
import { RPCConfigLoader } from './RPCConfigLoader';
|
||||
import { RPCPluginLoader } from './PluginLoader';
|
||||
import { AdminConf, TableDefiniton } from '../Types/Types';
|
||||
import { RPCConfigLoader } from '../Components/RPCConfigLoader';
|
||||
import * as Path from 'path'
|
||||
import Knex = require('knex');
|
||||
import http = require('http');
|
||||
import express = require('express');
|
||||
import { TableDefinitionExporter } from './Interfaces';
|
||||
import { FrontworkEventBus } from './Eventbus';
|
||||
import * as Knex from 'knex';
|
||||
import * as http from 'http';
|
||||
import * as express from 'express';
|
||||
import { TableDefinitionExporter } from '../Types/Interfaces';
|
||||
import { FrontworkComponent } from '../Types/FrontworkComponent';
|
||||
|
||||
const logger = getLogger("admin", 'debug')
|
||||
|
||||
export class FrontworkAdmin
|
||||
implements TableDefinitionExporter {
|
||||
knex:Knex
|
||||
config: RPCConfigLoader<AdminConf>
|
||||
|
||||
private express
|
||||
private httpServer
|
||||
private pluginLoader:RPCPluginLoader = new RPCPluginLoader(this)
|
||||
private eventBus:FrontworkEventBus = new FrontworkEventBus(this)
|
||||
config: RPCConfigLoader<AdminConf>
|
||||
knex:Knex
|
||||
|
||||
constructor(){}
|
||||
|
||||
async start(){
|
||||
this.initConfig()
|
||||
await this.makeKnex()
|
||||
this.startWebsocket()
|
||||
this.startWebserver()
|
||||
}
|
||||
|
||||
protected configChangeHandler = (conf:AdminConf, key?:string) => {
|
||||
if(key === 'dbConf'){
|
||||
this.makeKnex()
|
||||
}
|
||||
}
|
||||
|
||||
getConfigKey(key:string){
|
||||
return this.config.getConfigKey(key)
|
||||
}
|
||||
|
||||
setConfigKey(key:string, value:any){
|
||||
return this.config.setConfigKey(key, value)
|
||||
}
|
||||
|
||||
private initConfig(){
|
||||
constructor(private components: FrontworkComponent[]){
|
||||
this.config = new RPCConfigLoader<AdminConf>({
|
||||
name: "FrontworkAdminConf",
|
||||
getDefaultConfig: () => {
|
||||
@@ -65,20 +39,44 @@ implements TableDefinitionExporter {
|
||||
}
|
||||
}
|
||||
}, './config', this.configChangeHandler)
|
||||
|
||||
components.forEach(c => {
|
||||
c.admin = this
|
||||
if(c.onSetAdmin) c.onSetAdmin(this)
|
||||
})
|
||||
}
|
||||
|
||||
async start(){
|
||||
await this.makeKnex()
|
||||
this.startWebsocket()
|
||||
await Promise.all( this.components.map(c => c.initialize?c.initialize():undefined ))
|
||||
this.startWebserver()
|
||||
|
||||
}
|
||||
|
||||
protected configChangeHandler = (conf:AdminConf, key?:string) => {
|
||||
if(key === 'dbConf'){
|
||||
this.makeKnex()
|
||||
}
|
||||
}
|
||||
|
||||
getConfigKey(key:string){
|
||||
return this.config.getConfigKey(key)
|
||||
}
|
||||
|
||||
setConfigKey(key:string, value:any){
|
||||
return this.config.setConfigKey(key, value)
|
||||
}
|
||||
|
||||
getTableDefinitions(): TableDefiniton[]{
|
||||
return [
|
||||
this.eventBus,
|
||||
...this.pluginLoader.getPlugins()
|
||||
...this.components
|
||||
].flatMap(exporter => exporter.getTableDefinitions())
|
||||
}
|
||||
|
||||
private startWebsocket(){
|
||||
new RPCServer(20000, [
|
||||
this.config,
|
||||
this.pluginLoader,
|
||||
this.eventBus
|
||||
...this.components,
|
||||
])
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { RPCExporter } from "rpclibrary"
|
||||
import { FrontworkAdmin } from "../../Admin/Admin"
|
||||
import { TableDefiniton } from "../../Types/Types"
|
||||
import { PrivilegedRPCExporter } from "../../Types/PrivilegedRPCExporter"
|
||||
import { FrontworkComponent } from "../../Types/FrontworkComponent"
|
||||
|
||||
export class Debugger
|
||||
implements FrontworkComponent<any,any>{
|
||||
public admin: FrontworkAdmin
|
||||
name = "Debugger"
|
||||
|
||||
|
||||
constructor(private exporters: PrivilegedRPCExporter[]){
|
||||
}
|
||||
|
||||
exportRPCs(){
|
||||
|
||||
return [{
|
||||
name: 'getTable',
|
||||
call: async(table:string) => this.admin.knex.select('*').from(table)
|
||||
},
|
||||
...this.exporters.flatMap(e => e.exportRPCs()),
|
||||
...this.exporters.flatMap(e => e.exportRPCFeatures().flatMap(e => e.exportRPCs()))]
|
||||
}
|
||||
|
||||
exportRPCFeatures(): RPCExporter<any, any, {}>[] {
|
||||
return []
|
||||
}
|
||||
|
||||
getTableDefinitions(): TableDefiniton[] {
|
||||
return []
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
import { RPCExporter, SubscriptionResponse, ErrorResponse, SuccessResponse } from "rpclibrary";
|
||||
import { FrontworkAdmin } from "./Admin";
|
||||
import { TableDefinitionExporter } from "./Interfaces";
|
||||
import { FrontworkAdmin } from "../Admin/Admin";
|
||||
import { TableDefinitionExporter } from "../Types/Interfaces";
|
||||
import { getLogger } from 'frontblock-generic/Types';
|
||||
|
||||
import * as uuid from 'uuid/v4'
|
||||
import { TableDefiniton } from "../Types/Types";
|
||||
|
||||
export type NotificationSeverity = 'Info' | 'Important' | 'Error'
|
||||
|
||||
@@ -84,11 +85,11 @@ implements RPCExporter<EventbusIfc, "Eventbus">, TableDefinitionExporter {
|
||||
}]
|
||||
}
|
||||
|
||||
getTableDefinitions(){
|
||||
getTableDefinitions(): TableDefiniton[]{
|
||||
return [{
|
||||
name: 'notifications',
|
||||
tableBuilder: (table) => {
|
||||
table.increments('ID');
|
||||
table.increments('ID').primary();
|
||||
table.string('severity');
|
||||
table.string('topic');
|
||||
table.string('message');
|
||||
@@ -0,0 +1,107 @@
|
||||
import { TableDefinitionExporter } from "../../Types/Interfaces";
|
||||
import { TableDefiniton, _Rank } from "../../Types/Types";
|
||||
import { FrontworkAdmin } from "../../Admin/Admin";
|
||||
import { T1 } from "../../Types/Items";
|
||||
import { FrontworkComponent } from "../../Types/FrontworkComponent";
|
||||
import { RPC } from "rpclibrary";
|
||||
const fetch = require('node-fetch')
|
||||
const xml2js = require('xml2js');
|
||||
const parser = new xml2js.Parser(/* options */);
|
||||
|
||||
|
||||
export type ItemManagerFeatureIfc = any
|
||||
|
||||
export type Item = {
|
||||
id?:number
|
||||
name:string
|
||||
iconname:string
|
||||
url:string
|
||||
quality:string
|
||||
hidden:boolean
|
||||
}
|
||||
|
||||
export class ItemManager
|
||||
implements FrontworkComponent<ItemManagerFeatureIfc>, TableDefinitionExporter{
|
||||
|
||||
admin:FrontworkAdmin
|
||||
name = "ItemManager";
|
||||
|
||||
exportRPCs(): RPC<any, any>[]{
|
||||
return [{
|
||||
name: 'getItems',
|
||||
call: async () => await this.getItems()
|
||||
},{
|
||||
name: 'getItem',
|
||||
call: async (name:string) => await this.getItem(name)
|
||||
}]
|
||||
}
|
||||
|
||||
exportRPCFeatures() {
|
||||
return []
|
||||
}
|
||||
|
||||
getItems = async () :Promise<Item[]> => await this.admin.knex.select('*').from('items')
|
||||
|
||||
getItem = async (name:string):Promise<Item> => {
|
||||
const res = await fetch('https://classic.wowhead.com/item='+name+'&xml');
|
||||
const txt = await res.text();
|
||||
const r = await parser.parseStringPromise(txt);
|
||||
|
||||
try{
|
||||
return <Item>{
|
||||
name: r.wowhead.item[0].name[0],
|
||||
iconname: r.wowhead.item[0].icon[0]._,
|
||||
url: r.wowhead.item[0].link[0],
|
||||
quality: r.wowhead.item[0].quality[0]._,
|
||||
}
|
||||
}catch (e){
|
||||
console.log(name)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
getTableDefinitions(): TableDefiniton[] {
|
||||
return [
|
||||
{
|
||||
name: 'reservations',
|
||||
tableBuilder: (table) => {
|
||||
table.integer("user_id").primary()
|
||||
table.foreign("user_id").references("id").inTable('users')
|
||||
table.integer("item_id").primary()
|
||||
table.foreign("item_id").references("id").inTable('items')
|
||||
table.integer("raid_id").primary()
|
||||
table.foreign("raid_id").references("id").inTable('raids')
|
||||
}
|
||||
},{
|
||||
name: 'items',
|
||||
tableBuilder: (table) => {
|
||||
table.increments("id").primary()
|
||||
table.string('name').unique().notNullable()
|
||||
table.string('iconname').notNullable()
|
||||
table.string('url').notNullable()
|
||||
table.string('quality').defaultTo('Epic').notNullable()
|
||||
table.boolean('hidden').defaultTo(false).notNullable()
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
countItems = async() :Promise<number> => {
|
||||
const count = await this.admin.knex('items').count('*');
|
||||
return <number>count[0]['count(*)']
|
||||
}
|
||||
|
||||
initialize = async() => {
|
||||
const allItems = [...T1]
|
||||
const countCache = await this.countItems()
|
||||
if(countCache != allItems.length){
|
||||
const items:Item[] = await Promise.all(allItems.map(async (i) => this.getItem(i)))
|
||||
try{
|
||||
await this.admin
|
||||
.knex('items')
|
||||
.insert(items)
|
||||
}catch(e){
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
import { RPCServer } from "rpclibrary";
|
||||
import { TableDefiniton, AnyRPCExporter, User, RPCPermission, _Rank, Token, Auth } from "../../Types/Types";
|
||||
import { FrontworkAdmin } from "../../Admin/Admin";
|
||||
import { PrivilegedRPCExporter } from "../../Types/PrivilegedRPCExporter";
|
||||
import { FrontworkComponent } from "../../Types/FrontworkComponent";
|
||||
const uuid = require('uuid/v4')
|
||||
|
||||
|
||||
export class LoginManager
|
||||
implements FrontworkComponent{
|
||||
name = "Authenticator" as "Authenticator";
|
||||
admin:FrontworkAdmin
|
||||
|
||||
constructor(private exporters: PrivilegedRPCExporter[]){}
|
||||
|
||||
exportRPCs() {
|
||||
return [
|
||||
{
|
||||
name: 'login' as 'login',
|
||||
call: async (username:string, pwHash:string) => await this.login(username, pwHash)
|
||||
},{
|
||||
name: 'authenticate' as 'authenticate',
|
||||
call: async (tokenValue:string | Token) => await this.authenticate(tokenValue)
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
onSetAdmin(admin:FrontworkAdmin){
|
||||
this.exporters.forEach(e => e['admin'] = admin)
|
||||
}
|
||||
|
||||
exportRPCFeatures() {
|
||||
return [{
|
||||
name: 'createUser' as 'createUser',
|
||||
exportRPCs: () => [{
|
||||
name: 'createUser' as 'createUser',
|
||||
call: async (user:User) => {
|
||||
return await this.createUser(user)
|
||||
}
|
||||
}]
|
||||
},{
|
||||
name: 'modifyPermissions' as 'modifyPermissions',
|
||||
exportRPCs: () => [{
|
||||
name: 'getPermissions' as 'getPermissions',
|
||||
call: async () => await this.getPermissions()
|
||||
},{
|
||||
name: 'setPermission' as 'setPermission',
|
||||
call: async (perm: RPCPermission) => await this.setPermission(perm)
|
||||
}]
|
||||
}]
|
||||
}
|
||||
|
||||
getTableDefinitions(): TableDefiniton[] {
|
||||
return [
|
||||
{
|
||||
name: 'users',
|
||||
tableBuilder: (table) => {
|
||||
table.increments("id").primary()
|
||||
table.string("name").notNullable().unique()
|
||||
table.string("pwhash").notNullable()
|
||||
table.string("rank").notNullable()
|
||||
table.string("class").notNullable()
|
||||
table.string("email").nullable().unique()
|
||||
}
|
||||
},{
|
||||
name: 'rpcpermissions',
|
||||
tableBuilder: (table) => {
|
||||
table.string("rpcName").primary().notNullable()
|
||||
table.boolean("ADMIN").defaultTo(true).notNullable()
|
||||
_Rank.forEach(r => table.boolean(r).defaultTo(false).notNullable())
|
||||
}
|
||||
},{
|
||||
name: 'tokens',
|
||||
tableBuilder: (table) => {
|
||||
table.string('value').primary()
|
||||
table.integer('user_id').notNullable()
|
||||
table.foreign('user_id').references('users')
|
||||
table.dateTime('created').defaultTo(this.admin.knex.fn.now())
|
||||
}
|
||||
}
|
||||
,...this.exporters.flatMap(exp => exp['getTableDefinitions']?exp['getTableDefinitions']():undefined)]
|
||||
}
|
||||
|
||||
async initialize(){
|
||||
await Promise.all(
|
||||
[this, ...this.exporters].flatMap(exp => exp.exportRPCFeatures().map(async (rpc) => {
|
||||
try{
|
||||
await this.admin.knex.insert({ rpcname: rpc.name }).into('rpcpermissions')
|
||||
}catch(e){}
|
||||
})))
|
||||
|
||||
await Promise.all(this.exporters.map(ex => ex['initialize']?ex['initialize']():undefined))
|
||||
}
|
||||
|
||||
async setPermission(permission: RPCPermission){
|
||||
await this.admin.knex('rpcpermissions')
|
||||
.where('rpcname', '=', permission.name)
|
||||
.update(permission)
|
||||
}
|
||||
|
||||
getPermissions = async () : Promise<RPCPermission[]> => {
|
||||
return await this.admin.knex.select('*').from('rpcpermissions')
|
||||
}
|
||||
|
||||
getRPCForUser = async (user:User): Promise<AnyRPCExporter[]> => {
|
||||
return [...this.exportRPCFeatures(), ...this.exporters.flatMap((exp) => exp.exportRPCFeatures())]
|
||||
}
|
||||
|
||||
createUser = async(user:User): Promise<User> => {
|
||||
await this.admin.knex('users')
|
||||
.insert(user)
|
||||
|
||||
const users = await this.admin.knex
|
||||
.select("*")
|
||||
.from('users')
|
||||
.where(user)
|
||||
return users[0]
|
||||
}
|
||||
|
||||
login = async(username:string, pwHash:string) : Promise<Token> => {
|
||||
const res:User[] = await this.admin.knex
|
||||
.select("*")
|
||||
.from('users')
|
||||
.where({ name: username })
|
||||
|
||||
if(res.length > 0 && pwHash === res[0].pwhash){
|
||||
return await this.createToken(res[0])
|
||||
}
|
||||
|
||||
throw new Error('login failed')
|
||||
}
|
||||
|
||||
authenticate = async(tokenValue: string | Token) : Promise<Auth> => {
|
||||
if(typeof tokenValue !== 'string') tokenValue = tokenValue.value
|
||||
|
||||
const res : User[] = await this.admin.knex
|
||||
.select('users.id', 'name', 'class', 'rank', 'email')
|
||||
.from('tokens')
|
||||
.join('users', function(){
|
||||
this.on('users.id', '=', 'tokens.user_id')
|
||||
})
|
||||
.where({ value: tokenValue})
|
||||
|
||||
if(res.length === 0)
|
||||
throw new Error('authentication failed')
|
||||
|
||||
const allowedRPCs = await this.getRPCForUser(res[0])
|
||||
const randomPort = 20000 + Math.floor(Math.random() * 10000)
|
||||
while(true){
|
||||
try{
|
||||
let commSock = new RPCServer(randomPort, allowedRPCs, {
|
||||
closeHandler: () => {
|
||||
console.log(res[0].name, 'disconnected')
|
||||
commSock.destroy()
|
||||
},
|
||||
connectionHandler: () => {
|
||||
console.log(res[0].name, 'connected')
|
||||
cancelTimeout()
|
||||
},
|
||||
sesame: tokenValue
|
||||
})
|
||||
const timeout = setTimeout(() => {
|
||||
console.log(res[0].name, 'timeout')
|
||||
commSock.destroy()
|
||||
}, 10000)
|
||||
const cancelTimeout = () => { clearTimeout(timeout) }
|
||||
break;
|
||||
}catch(e){
|
||||
//retry
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
port: randomPort,
|
||||
user: res[0],
|
||||
token: {
|
||||
value: tokenValue,
|
||||
user_id: res[0].id!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createToken = async(user:User): Promise<Token> => {
|
||||
const old = await this.admin.knex.select('*').from('tokens').where({user_id: user.id})
|
||||
if(old.length === 0){
|
||||
const token:Token = {
|
||||
value: uuid(),
|
||||
user_id: user.id!
|
||||
}
|
||||
await this.admin.knex('tokens').insert(token)
|
||||
return token
|
||||
}else{
|
||||
return old[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import { RPCExporter } from "rpclibrary";
|
||||
import { Git } from "upgiter"
|
||||
import { FolderStatus } from "upgiter/js/src/Types";
|
||||
import { Plugin } from "./Plugin";
|
||||
import { FrontworkAdmin } from "./Admin";
|
||||
import { Plugin } from "../Types/Plugin";
|
||||
import { FrontworkAdmin } from "../Admin/Admin";
|
||||
|
||||
class PluginLoader {
|
||||
private runningPlugins: Plugin[] = []
|
||||
@@ -0,0 +1,95 @@
|
||||
import { TableDefiniton, User, _Rank, Raid, Signup, RaidManagerFeatureIfc } from "../../Types/Types";
|
||||
import { FrontworkAdmin } from "../../Admin/Admin";
|
||||
import { FrontworkComponent } from "../../Types/FrontworkComponent";
|
||||
|
||||
|
||||
export class RaidManager
|
||||
implements FrontworkComponent<RaidManagerFeatureIfc>{
|
||||
name = "RaidManager";
|
||||
admin: FrontworkAdmin
|
||||
|
||||
exportRPCs = () => []
|
||||
|
||||
exportRPCFeatures() {
|
||||
return [{
|
||||
name: 'manageRaid' as 'manageRaid',
|
||||
exportRPCs: () => [{
|
||||
name: 'createRaid' as 'createRaid',
|
||||
call: async (raid:Raid) => await this.createRaid(raid)
|
||||
},{
|
||||
name: 'addSignup' as 'addSignup',
|
||||
call: async(signup: Signup) => await this.addSignup(signup)
|
||||
},{
|
||||
name: 'removeSignup' as 'removeSignup',
|
||||
call: async(signup: Signup) => await this.removeSignup(signup)
|
||||
}]
|
||||
},{
|
||||
name: 'signup' as 'signup',
|
||||
exportRPCs: () => [{
|
||||
name: 'getRaids' as 'getRaids',
|
||||
call: async () => await this.getRaids()
|
||||
},{
|
||||
name: 'getSingups' as 'getSingups',
|
||||
call: async(raid: Raid) => await this.getSignups(raid)
|
||||
},{
|
||||
name: 'sign' as 'sign',
|
||||
call: async(user:User, raid:Raid) => await this.sign(user, raid)
|
||||
}]
|
||||
},]
|
||||
}
|
||||
|
||||
getTableDefinitions(): TableDefiniton[] {
|
||||
return [
|
||||
{
|
||||
name: 'raids',
|
||||
tableBuilder: (table) => {
|
||||
table.increments('id').primary()
|
||||
table.dateTime('start').notNullable()
|
||||
table.string('description').notNullable()
|
||||
table.string('title').notNullable()
|
||||
table.integer('minrank').notNullable()
|
||||
}
|
||||
},{
|
||||
name: 'signups',
|
||||
tableBuilder: (table) => {
|
||||
table.integer('raid_id').primary()
|
||||
table.foreign('raid_id').references('id').inTable('raids')
|
||||
table.integer('user_id').primary()
|
||||
table.foreign('user_id').references('id').inTable('users')
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
createRaid = async (raid:Raid) => await this.admin
|
||||
.knex('raids')
|
||||
.insert(raid)
|
||||
|
||||
addSignup = async (signup: Signup) => await this.admin
|
||||
.knex('signups')
|
||||
.insert(signup)
|
||||
|
||||
removeSignup = async (signup: Signup) => await this.admin
|
||||
.knex('signups')
|
||||
.where({
|
||||
raid_id: signup.raid_id,
|
||||
user_id: signup.user_id
|
||||
})
|
||||
.delete()
|
||||
|
||||
getRaids = async () => await this.admin.knex
|
||||
.select('*')
|
||||
.from('raids')
|
||||
|
||||
getSignups = async (raid:Raid) => await this.admin.knex
|
||||
.select('*')
|
||||
.from('signups')
|
||||
.where('raid_id', '=', raid.id!)
|
||||
|
||||
sign = async (user:User, raid:Raid) => await this.admin
|
||||
.knex('signups')
|
||||
.insert({
|
||||
raid_id: raid.id!,
|
||||
user_id: user.id!
|
||||
})
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import { Plugin } from "./Plugin"
|
||||
import { getLogger } from "frontblock-generic/Types"
|
||||
import { FrontworkAdmin } from "./Admin";
|
||||
var exec = require('child-process-promise').exec;
|
||||
|
||||
const logger = getLogger("installer", 'info')
|
||||
|
||||
export type NPMPkgName = string
|
||||
export type NPMVersion = string
|
||||
|
||||
export const installAdmin = (plugins: Plugin[] = []) => {
|
||||
|
||||
const npmPkgs:[NPMPkgName, NPMVersion][] = [['sqlite3', '4.1.0'], ['knex', '0.19.2']]
|
||||
const deps = npmPkgs.map(tuple => tuple.join('@') ).join(" ")
|
||||
logger.info("Installing plaform dependencies: "+deps)
|
||||
|
||||
exec("npm i " + deps).then(async process => {
|
||||
logger.debug(process.stdout)
|
||||
const Admin = require("./Admin").FrontworkAdmin
|
||||
const fbAdmin:FrontworkAdmin = new Admin(plugins)
|
||||
fbAdmin.start()
|
||||
})
|
||||
|
||||
}
|
||||
+20
-2
@@ -1,2 +1,20 @@
|
||||
import { installAdmin } from "./Installer";
|
||||
installAdmin()
|
||||
import { FrontworkAdmin } from './Admin/Admin'
|
||||
import { RaidManager } from "./Components/Raid/RaidManager";
|
||||
import { ItemManager } from "./Components/Item/ItemManager";
|
||||
import { LoginManager } from "./Components/Login/LoginManager";
|
||||
import { Debugger } from './Components/Debugger/Debugger';
|
||||
import { FrontworkComponent } from './Types/FrontworkComponent';
|
||||
require('events').EventEmitter.defaultMaxListeners = 0;
|
||||
|
||||
let raidManager = new RaidManager()
|
||||
let itemManager = new ItemManager()
|
||||
let loginManager = new LoginManager([
|
||||
raidManager,
|
||||
itemManager
|
||||
])
|
||||
|
||||
let components:FrontworkComponent[] = [ raidManager, itemManager, loginManager ]
|
||||
let dbg = new Debugger(components)
|
||||
|
||||
|
||||
new FrontworkAdmin([dbg, ...components]).start()
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import Knex = require("knex")
|
||||
|
||||
export declare type NotificationSeverity = 'Info' | 'Important' | 'Error';
|
||||
|
||||
export type AdminConf = {
|
||||
httpPort: number,
|
||||
dbConf:Knex.Config,
|
||||
eventBusConf: { [topic in string]: NotificationSeverity}
|
||||
}
|
||||
|
||||
export type TableDefiniton = {
|
||||
name: string,
|
||||
tableBuilder: (table: Knex.CreateTableBuilder) => void
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { PrivilegedRPCExporter } from "./PrivilegedRPCExporter";
|
||||
import { RPCInterface, RPC, AnyFunction, RPCExporter } from "rpclibrary";
|
||||
import { TableDefinitionExporter } from "./Interfaces";
|
||||
import { FrontworkAdmin } from "../Admin/Admin";
|
||||
import { TableDefiniton } from "./Types";
|
||||
|
||||
export interface FrontworkComponent<
|
||||
Ifc extends RPCInterface = RPCInterface,
|
||||
Name extends keyof Ifc = keyof Ifc,
|
||||
SubresT = {}
|
||||
> extends
|
||||
PrivilegedRPCExporter<Ifc, Name, SubresT>,
|
||||
TableDefinitionExporter
|
||||
{
|
||||
admin:FrontworkAdmin
|
||||
name: string;
|
||||
|
||||
exportRPCFeatures(): RPCExporter<Ifc, Name, SubresT>[]
|
||||
exportRPCs(): RPC<string, AnyFunction, {}>[]
|
||||
getTableDefinitions(): TableDefiniton[]
|
||||
|
||||
initialize?(): Promise<any>
|
||||
onSetAdmin?(admin:FrontworkAdmin): void
|
||||
}
|
||||
@@ -2,4 +2,4 @@ import { TableDefiniton } from "./Types";
|
||||
|
||||
export interface TableDefinitionExporter{
|
||||
getTableDefinitions(): TableDefiniton[]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
export const T1 = [
|
||||
"Robe of Volatile Power",
|
||||
"Salamander Scale Pants",
|
||||
"Heavy Dark Iron Ring",
|
||||
"Ring of Spell Power",
|
||||
"Sorcerous Dagger",
|
||||
"Wristguards of Stability",
|
||||
"Helm of the Lifegiver",
|
||||
"Fire Runed Grimoire",
|
||||
"Crimson Shocker",
|
||||
"Mana Igniting Cord",
|
||||
"Quick Strike Ring",
|
||||
"Seal of the Archmagus",
|
||||
"Talisman of Ephemeral Power",
|
||||
"Flameguard Gauntlets",
|
||||
"Magma Tempered Boots",
|
||||
"Obsidian Edged Blade",
|
||||
"Aged Core Leather Gloves",
|
||||
"Sabatons of the Flamewalker",
|
||||
"Striker's Mark",
|
||||
"Medallion of Steadfast Might",
|
||||
"Earthshaker",
|
||||
"Brutality Blade",
|
||||
"Aurastone Hammer",
|
||||
"Gutgore Ripper",
|
||||
"Drillborer Disk",
|
||||
"Azuresong Mageblade",
|
||||
"Staff of Dominance",
|
||||
"Blastershot Launcher",
|
||||
"The Eye of Divinity",
|
||||
"Ancient Petrified Leaf",
|
||||
"Finkle's Lava Dredger",
|
||||
"Core Hound Tooth",
|
||||
"Core Forged Greaves",
|
||||
"Gloves of the Hypnotic Flame",
|
||||
"Sash of Whispered Secrets",
|
||||
"Wild Growth Spaulders",
|
||||
"Fireproof Cloak",
|
||||
"Wristguards of True Flight",
|
||||
"Fireguard Shoulders",
|
||||
"Cauterizing Band",
|
||||
"Onslaught Girdle",
|
||||
"Perdition's Blade",
|
||||
"Cloak of the Shrouded Mists",
|
||||
"Band of Accuria",
|
||||
"Crown of Destruction",
|
||||
"Choker of the Fire Lord",
|
||||
"Band of Sulfuras",
|
||||
"Dragon's Blood Cape",
|
||||
"Malistar's Defender",
|
||||
"Spinal Reaper",
|
||||
"Bonereaver's Edge",
|
||||
"Shard of the Flame",
|
||||
"Essence of the Pure Flame",
|
||||
"Eye of Sulfuras",
|
||||
"Deathbringer",
|
||||
"Vis'kag the Bloodletter",
|
||||
"Sapphiron Drape",
|
||||
"Ancient Cornerstone Grimoire",
|
||||
"Eskhandar's Collar",
|
||||
"Ring of Binding",
|
||||
"Shard of the Scale",
|
||||
"Head of Onyxia",
|
||||
"Bindings of the Windseeker"]
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FrontworkAdmin } from "./Admin"
|
||||
import { FrontworkAdmin } from "../Admin/Admin"
|
||||
import { RPC, RPCExporter } from "rpclibrary"
|
||||
import { TableDefiniton } from "./Types"
|
||||
import { TableDefinitionExporter } from "./Interfaces"
|
||||
@@ -0,0 +1,7 @@
|
||||
import { RPCExporter, RPCInterface, RPC, RPCInterfaceArray } from "rpclibrary";
|
||||
|
||||
export interface PrivilegedRPCExporter <Ifc extends RPCInterface = RPCInterface, Name extends keyof Ifc = keyof Ifc, SubresT = {}>
|
||||
extends RPCExporter<any,any>{
|
||||
|
||||
exportRPCFeatures() : RPCExporter<Ifc, Name, SubresT>[]
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import * as Knex from "knex"
|
||||
import { RPCExporter } from "rpclibrary";
|
||||
|
||||
export declare type NotificationSeverity = 'Info' | 'Important' | 'Error';
|
||||
|
||||
export type AdminConf = {
|
||||
httpPort: number,
|
||||
dbConf:Knex.Config,
|
||||
eventBusConf: { [topic in string]: NotificationSeverity}
|
||||
}
|
||||
|
||||
export type TableDefiniton = {
|
||||
name: string,
|
||||
tableBuilder: (table: Knex.CreateTableBuilder) => void
|
||||
}
|
||||
|
||||
export type Rank = "ADMIN" | "Guildmaster" | "Officer" | "Classleader" | "Raider" | "Trial" | "Social" | "Guest"
|
||||
export const _Rank : Rank[] = ["Guildmaster" , "Officer" , "Classleader" , "Raider" , "Trial" , "Social" , "Guest"]
|
||||
export type Class = "Warrior" | "Rogue" | "Hunter" | "Mage" | "Warlock" | "Priest" | "Shaman" | "Paladin" | "Druid"
|
||||
export const _Class : Class[] = ["Warrior" , "Rogue" , "Hunter" , "Mage" , "Warlock" , "Priest" , "Shaman" , "Paladin" , "Druid"]
|
||||
|
||||
export type AnyRPCExporter = RPCExporter<any,any>
|
||||
|
||||
export type RPCPermission = {
|
||||
name: string
|
||||
} & {
|
||||
[rank in Rank] : boolean
|
||||
}
|
||||
|
||||
export type User = {
|
||||
id?: number
|
||||
name: string
|
||||
pwhash: string
|
||||
class: Class
|
||||
rank: Rank
|
||||
email?: string
|
||||
}
|
||||
|
||||
export type Raid = {
|
||||
id?: number
|
||||
title: string
|
||||
description: string
|
||||
start: string
|
||||
minrank: Rank
|
||||
}
|
||||
|
||||
export type Signup = {
|
||||
raid_id: number
|
||||
user_id: number
|
||||
}
|
||||
|
||||
export type Token = {
|
||||
value: string
|
||||
user_id: number
|
||||
created?: number
|
||||
}
|
||||
|
||||
export type Auth = {port: number, user: User, token: Token}
|
||||
|
||||
export type FrontcraftFeatureIfc = RaidManagerFeatureIfc & LoginManagerFeatureIfc
|
||||
|
||||
|
||||
export type LoginManagerIfc = {
|
||||
Authenticator: {
|
||||
login: (username:string, pwHash:string) => Promise<Token>
|
||||
authenticate: (token:string | Token) => Promise<Auth>
|
||||
}
|
||||
}
|
||||
|
||||
export type LoginManagerFeatureIfc = {
|
||||
createUser: {
|
||||
createUser: (user:User) => Promise<User>
|
||||
}
|
||||
modifyPermissions: {
|
||||
setPermission: (perm: RPCPermission) => Promise<void>
|
||||
getPermissions: () => Promise<RPCPermission[]>
|
||||
}
|
||||
}
|
||||
|
||||
export type RaidManagerFeatureIfc = {
|
||||
manageRaid: {
|
||||
createRaid: (raid:Raid) => Promise<any>
|
||||
addSignup: (signup: Signup) => Promise<any>
|
||||
removeSignup: (signup: Signup) => Promise<any>
|
||||
}
|
||||
signup: {
|
||||
getRaids: () => Promise<Raid[]>
|
||||
getSingups: (raid:Raid) => Promise<Signup[]>
|
||||
sign: (user:User, raid:Raid, attending:boolean) => Promise<any>
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user