changepermissions & 1 rankserver

This commit is contained in:
peter
2020-03-05 20:36:19 +01:00
parent 26dbf8312b
commit c4ca96fef9
15 changed files with 262 additions and 94 deletions
+3 -3
View File
@@ -6130,9 +6130,9 @@
} }
}, },
"rpclibrary": { "rpclibrary": {
"version": "1.8.3", "version": "1.9.2",
"resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.8.3.tgz", "resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.9.2.tgz",
"integrity": "sha512-8pQRbMXQKCf3+v+XM01d+1Bw73pg5YzgyhW/ACpYON1I4re5fZAjWGPyLc+ms+MlYQIlKc3Uk92PGot2sbb85Q==", "integrity": "sha512-MOtVm0IBRLryXag1IwkYNPVFegbvW10+MbCjhr3GptO3MA7nHZ545ammgoCWnREtGOgFeN4Jib/EBDOJ9Ep41Q==",
"requires": { "requires": {
"bsock": "^0.1.9", "bsock": "^0.1.9",
"http": "0.0.0", "http": "0.0.0",
+1 -1
View File
@@ -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.8.3", "rpclibrary": "^1.9.2",
"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",
+36 -51
View File
@@ -1,4 +1,4 @@
import { RPCServer, Socket } from "rpclibrary"; import { RPCServer, Socket, RPCInterface } from "rpclibrary";
import { Inject, Injectable } from "../../Injector/ServiceDecorator"; import { Inject, Injectable } from "../../Injector/ServiceDecorator";
import { FrontworkAdmin } from "../../Admin/Admin"; import { FrontworkAdmin } from "../../Admin/Admin";
import { GuildManager } from "../Guild/GuildManager"; import { GuildManager } from "../Guild/GuildManager";
@@ -23,10 +23,9 @@ const uuid = require('uuid/v4')
const salt = "6pIbc6yjSN" const salt = "6pIbc6yjSN"
const ONE_WEEK = 604800000 const ONE_WEEK = 604800000
type Serverstate = { type Serverstate<SubresT, InterfaceT extends RPCInterface> = {
server: RPCServer, server: RPCServer<SubresT, InterfaceT>,
port : number, port : number,
allowed: string[]
}; };
@@ -51,8 +50,9 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
private character : CharacterManager private character : CharacterManager
exporters :any[] = [] exporters :any[] = []
rankServers : {[rank in Rank] : Serverstate} rankServer : Serverstate<{}, FrontcraftFeatureIfc>
userLogins : {[username in string] : UserRecord} = {} userLogins : {[username in string] : UserRecord} = {}
allowed: string[] = []
exportRPCs = () => [ exportRPCs = () => [
this.login, this.login,
@@ -145,19 +145,11 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
} }
}))) })))
//start rankServers const rankServer = await this.startRankServer(20001)
let rankServers = { } as any this.rankServer = {
await Promise.all(_Rank.map(async (r,i) => {
const port = 20001 + i
const rankServer = await this.startRankServer(r, port)
rankServers[r] = {
server: rankServer, server: rankServer,
port: port, port: 20001
allowed: []
} }
}))
this.rankServers = rankServers
getLogger('UserManager').debug(Object.values(this.rankServers).length+" rank servers started")
setInterval(this.checkExpiredSessions, 600_000) setInterval(this.checkExpiredSessions, 600_000)
} }
@@ -166,20 +158,17 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
Object.values(x.connections).forEach(c => c.destroy()) Object.values(x.connections).forEach(c => c.destroy())
}) })
Object.values(this.rankServers)
.map(state => {
try{ try{
return state.server.destroy() return this.rankServer.server.destroy()
}catch(e){ }catch(e){
getLogger('UserManager').warn(e) //getLogger('UserManager').warn(e)
} }
})
} }
checkExpiredSessions = () => { checkExpiredSessions = () => {
Object.values(this.userLogins).map(userLogin => { Object.values(this.userLogins).map(userLogin => {
const auth = userLogin.auth const auth = userLogin.auth
if(!this.checkToken(auth.token.value, auth.user.rank)){ if(!this.checkToken(auth.token.value)){
this.logout(auth.user.username, auth.token.value) this.logout(auth.user.username, auth.token.value)
} }
}) })
@@ -232,6 +221,13 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
await this.admin.knex('rpcpermissions') await this.admin.knex('rpcpermissions')
.where('rpcname', '=', permission.rpcname) .where('rpcname', '=', permission.rpcname)
.update(permission) .update(permission)
await Promise.all(
Object.entries(this.userLogins).map(([username, record]) => {
if(record.user.rank === "ADMIN") return
return this.adminLogout(username)
})
)
} }
getPermissions = async () : Promise<RPCPermission[]> => { getPermissions = async () : Promise<RPCPermission[]> => {
@@ -313,15 +309,10 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
await sock.call('kick') await sock.call('kick')
})) }))
Object.values(this.rankServers) this.allowed = this.allowed.filter(allowed => allowed !== this.userLogins[username].auth.token.value)
.forEach(state => {
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){}
getLogger('UserManager').warn(e)
}
} }
wipeCurrency = async () => { wipeCurrency = async () => {
@@ -356,11 +347,11 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
const userAuth : Auth = { const userAuth : Auth = {
token: token, token: token,
user: user, user: user,
port: this.rankServers[user.rank].port port: this.rankServer.port
} }
this.userLogins[user.username] = {connections: {}, auth: userAuth, user:user} this.userLogins[user.username] = {connections: {}, auth: userAuth, user:user}
this.rankServers[user.rank].allowed.push(token.value) this.allowed.push(token.value)
return userAuth return userAuth
} }
@@ -378,16 +369,17 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
return return
} }
startRankServer = async (rank : Rank, port: number) : Promise<RPCServer> => { startRankServer = async (port: number) : Promise<RPCServer<{},FrontcraftFeatureIfc>> => {
let rpcs = [
const allowedRPCs = await this.getRPCForRank(rank) ...this.exportRPCFeatures(),
let rpcServer ...this.exporters.flatMap((exp) => exp.exportRPCFeatures())
let n = 0 ]
while(!rpcServer){ let rpcServer = new RPCServer<{},FrontcraftFeatureIfc>(port, rpcs, {
n++ accessFilter: async (sesame, exporter) => {
await Promise.race([ const record = this.getUserRecordByToken(sesame!)
new Promise((res, rej) => { if(!record) return false
rpcServer = new RPCServer(port, allowedRPCs, { return await this.getPermission(exporter.name, record.user.rank)
},
closeHandler: (socket) => { closeHandler: (socket) => {
Object.values(this.userLogins) Object.values(this.userLogins)
.forEach(login => delete login.connections[socket.port]) .forEach(login => delete login.connections[socket.port])
@@ -400,26 +392,19 @@ implements FrontworkComponent<UserManagerIfc, UserManagerFeatureIfc>, IUserManag
} }
}).catch((e) => { }).catch((e) => {
socket.destroy(); socket.destroy();
getLogger('UserManager').warn(e);
}) })
}, },
errorHandler: (socket, e, rpcName, args) => { errorHandler: (socket, e, rpcName, args) => {
getLogger('UserManager').error(rpcName, args, e); getLogger('UserManager').error(rpcName, args, e);
}, },
sesame: (sesame) => this.checkToken(sesame, rank), sesame: (sesame) => this.checkToken(sesame),
visibility: '0.0.0.0' visibility: '0.0.0.0'
}) })
res()
}),
new Promise((res, rej) => setTimeout(res, 500))
])
if(!rpcServer && n>1)
getLogger('UserManager').warn("createServer retry nr.", n, 'port', port)
}
return rpcServer return rpcServer
} }
checkToken = (token: string, rank: Rank) : boolean => this.rankServers[rank].allowed.includes(token) checkToken = (token: string) : boolean => this.allowed.includes(token)
&& Object.values(this.userLogins).find(login => login.auth.token.value === token)!.auth.token.created > Date.now() - ONE_WEEK && Object.values(this.userLogins).find(login => login.auth.token.value === token)!.auth.token.created > Date.now() - ONE_WEEK
checkTokenOwnedByUser = (username: string, tokenValue: string) => { checkTokenOwnedByUser = (username: string, tokenValue: string) => {
+3 -3
View File
@@ -17940,9 +17940,9 @@
"integrity": "sha512-ZYzRkETgBrdEGzL5JSKimvjI2CX7ioyZCkX2BpcfyjqI+079W0wHAyj5W4rIZMcDSOHgLZtgz1IdDi/vU77KEQ==" "integrity": "sha512-ZYzRkETgBrdEGzL5JSKimvjI2CX7ioyZCkX2BpcfyjqI+079W0wHAyj5W4rIZMcDSOHgLZtgz1IdDi/vU77KEQ=="
}, },
"rpclibrary": { "rpclibrary": {
"version": "1.8.3", "version": "1.9.2",
"resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.8.3.tgz", "resolved": "https://registry.npmjs.org/rpclibrary/-/rpclibrary-1.9.2.tgz",
"integrity": "sha512-8pQRbMXQKCf3+v+XM01d+1Bw73pg5YzgyhW/ACpYON1I4re5fZAjWGPyLc+ms+MlYQIlKc3Uk92PGot2sbb85Q==", "integrity": "sha512-MOtVm0IBRLryXag1IwkYNPVFegbvW10+MbCjhr3GptO3MA7nHZ545ammgoCWnREtGOgFeN4Jib/EBDOJ9Ep41Q==",
"requires": { "requires": {
"bsock": "^0.1.9", "bsock": "^0.1.9",
"http": "0.0.0", "http": "0.0.0",
+1 -1
View File
@@ -69,7 +69,7 @@
"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.8.3", "rpclibrary": "^1.9.2",
"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",
@@ -9,7 +9,11 @@
<div class="header-container"> <div class="header-container">
<nb-actions size="small"> <nb-actions size="small">
<nb-action
*ngIf="modifyPermissions"
icon="settings-2-outline"
link="/permissions">
</nb-action>
<nb-action <nb-action
*ngIf="!newmessage" *ngIf="!newmessage"
icon="message-square-outline" icon="message-square-outline"
@@ -48,6 +48,7 @@ export class HeaderComponent implements OnInit, OnDestroy {
chatlog: ShoutMessage[] = [] chatlog: ShoutMessage[] = []
newmessage = false newmessage = false
lastmessage = "asdasd" lastmessage = "asdasd"
modifyPermissions
constructor(private sidebarService: NbSidebarService, constructor(private sidebarService: NbSidebarService,
private router: Router, private router: Router,
@@ -62,7 +63,7 @@ export class HeaderComponent implements OnInit, OnDestroy {
this.themeService.changeTheme("dark"); this.themeService.changeTheme("dark");
this.currentTheme = this.themeService.currentTheme; this.currentTheme = this.themeService.currentTheme;
this.modifyPermissions = this.api.get('modifyPermissions')
this.user = this.api.getCurrentUser() this.user = this.api.getCurrentUser()
if(this.user) if(this.user)
this.userMenu.unshift({ title: 'Profile', link: '/frontcraft/user/'+this.user.username }); this.userMenu.unshift({ title: 'Profile', link: '/frontcraft/user/'+this.user.username });
+5 -1
View File
@@ -2,7 +2,11 @@ import { ExtraOptions, RouterModule, Routes } from '@angular/router';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
const routes: Routes = [ const routes: Routes = [
{
path: 'permissions',
loadChildren: () => import('./frontcraft/permissions/permissions.module')
.then(m => m.PermissionsModule),
},
{ {
path: 'auth', path: 'auth',
loadChildren: () => import('./frontcraft/auth/auth.module') loadChildren: () => import('./frontcraft/auth/auth.module')
@@ -0,0 +1,23 @@
<nb-card>
<nb-card-body>
<table>
<tr>
<th>
Name
</th>
<th *ngFor="let rank of ranks">
{{rank}}
</th>
</tr>
<tr *ngFor="let perm of permissions">
<td>{{perm.rpcname}}</td>
<td *ngFor="let rank of ranks">
<nb-toggle
[(ngModel)]="perm[rank]"
(checkedChange)="settingChanged($event, rank, perm)">
</nb-toggle>
</td>
</tr>
</table>
</nb-card-body>
</nb-card>
@@ -0,0 +1,43 @@
import { Component, OnInit } from '@angular/core';
import { ApiService as ApiService } from '../../services/login-api';
import { Router } from '@angular/router';
import { _Rank, _Class, _Race, RPCPermission } from '../../../../../../backend/Types/Types'
import { NbToastrService } from '@nebular/theme';
@Component({
selector: 'changePermissions',
templateUrl: './changePermissions.component.html',
})
export class ChangePermissionsComponent implements OnInit{
permissions:RPCPermission[] = []
ranks = _Rank
constructor(
private router : Router,
private api : ApiService,
private toastr: NbToastrService
){}
async ngOnInit(){
const modify = this.api.get('modifyPermissions')
if(!modify) return
this.permissions = await modify.getPermissions()
}
settingChanged = async (value, key, perm:RPCPermission) => {
const modify = this.api.get('modifyPermissions')
if(!modify) return
perm[key] = value
console.log(perm);
await modify.setPermission(perm).catch(e => {
})
this.toastr.success('Permission updated', 'Success')
}
}
@@ -0,0 +1,22 @@
import { Component, OnInit } from '@angular/core';
import { ApiService } from '../services/login-api';
import { Router } from '@angular/router';
@Component({
selector: 'auth-layout',
template: `
<ngx-one-column-no-sidebar-layout>
<router-outlet></router-outlet>
</ngx-one-column-no-sidebar-layout>
`,
})
export class PermissionsComponent implements OnInit{
constructor(
private loginSvc : ApiService,
private router: Router
){}
ngOnInit(){
}
}
@@ -0,0 +1,24 @@
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 {
}
@@ -0,0 +1,43 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import {
NbAlertModule,
NbButtonModule,
NbCheckboxModule,
NbInputModule,
NbMenuModule,
NbCardModule,
NbSelectModule,
NbToggleModule
} 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,
NbAlertModule,
NbInputModule,
NbButtonModule,
NbCheckboxModule,
ThemeModule,
NbMenuModule,
NbCardModule,
NbSelectModule
],
declarations: [
PermissionsComponent,
ChangePermissionsComponent,
],
})
export class PermissionsModule {
}
@@ -34,7 +34,7 @@ export class ApiService{
) )
sock.hook('kick', () => { sock.hook('kick', () => {
this.logout() this.kick()
}) })
sock.hook('getUserData', () => auth) sock.hook('getUserData', () => auth)
@@ -110,6 +110,11 @@ export class ApiService{
return async (msg: ShoutMessage) => await this.get('Shoutbox').shout(res.uuid, msg) return async (msg: ShoutMessage) => await this.get('Shoutbox').shout(res.uuid, msg)
} }
kick = async () => {
await this.logout()
location.reload()
}
logout = async () => { logout = async () => {
this.cookieSvc.set('token', undefined) this.cookieSvc.set('token', undefined)
if(this.auth){ if(this.auth){
+21 -7
View File
@@ -129,6 +129,18 @@ describe('Frontcraft', () => {
return client.UserManager.createUser(user) return client.UserManager.createUser(user)
} }
const login = async (name: string) : Promise<Auth> => {
const auth = await client.UserManager.login(name, 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb')
if(users[name]) users[name] = {
...users[name],
auth: auth
}
return auth
}
const createAccountAndUser = async (acc: protoAccount) => { const createAccountAndUser = async (acc: protoAccount) => {
const account = await createAccount({ const account = await createAccount({
pwhash: 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb', //sha256("a") pwhash: 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb', //sha256("a")
@@ -199,6 +211,14 @@ describe('Frontcraft', () => {
server.stop() server.stop()
}) })
it('can set permissions', (done) => {
Promise.all(
defaultPermissions.map(perm => adminClient.modifyPermissions.setPermission(perm)),
).then(_ => {
done()
})
})
it('create raids', (done) => { it('create raids', (done) => {
let insertRaid = <Raid>{ let insertRaid = <Raid>{
description: "Test raid 1", description: "Test raid 1",
@@ -587,13 +607,7 @@ describe('Frontcraft', () => {
}) })
}) })
it('can set permissions', (done) => {
Promise.all(
defaultPermissions.map(perm => adminClient.modifyPermissions.setPermission(perm)),
).then(_ => {
done()
})
})
it('start raid', (done) => { it('start raid', (done) => {
client.RaidManager.getRaids().then((r) => { client.RaidManager.getRaids().then((r) => {