sesamefilter

This commit is contained in:
2020-03-05 18:14:40 +01:00
parent 0057625800
commit f8d475cb53
4 changed files with 43 additions and 14 deletions
+12 -5
View File
@@ -25,6 +25,7 @@ export class RPCServer<
private errorHandler: T.ErrorHandler private errorHandler: T.ErrorHandler
private connectionHandler: T.ConnectionHandler private connectionHandler: T.ConnectionHandler
private sesame? : T.SesameFunction private sesame? : T.SesameFunction
private accessFilter: T.AccessFilter<InterfaceT, SubResType>
/** /**
* @throws On RPC with no name * @throws On RPC with no name
@@ -35,10 +36,12 @@ export class RPCServer<
constructor( constructor(
private port:number, private port:number,
private exporters: Exporters<InterfaceT, SubResType> = [], private exporters: Exporters<InterfaceT, SubResType> = [],
conf: T.ServerConf = {} conf: T.ServerConf<InterfaceT, SubResType> = {}
){ ){
if(!conf.visibility) this.visibility = "127.0.0.1" if(!conf.visibility) this.visibility = "127.0.0.1"
this.accessFilter = conf.accessFilter || (async () => true)
if(conf.sesame){ if(conf.sesame){
this.sesame = U.makeSesameFunction(conf.sesame) this.sesame = U.makeSesameFunction(conf.sesame)
} }
@@ -87,10 +90,14 @@ export class RPCServer<
} }
protected initRPCs(socket:I.Socket){ protected initRPCs(socket:I.Socket){
socket.hook('info', () => rpcInfos) socket.hook('info', async (sesame? : string) => {
const rpcInfos:T.ExtendedRpcInfo[] = [ const rpcs = await Promise.all(this.exporters.map(async exp => {
...this.exporters.flatMap(exporter => U.rpcHooker(socket, exporter, this.errorHandler, this.sesame)) const allowed = await this.accessFilter(sesame, exp)
] if(!allowed) return []
return U.rpcHooker(socket, exp, this.errorHandler, this.sesame)
}))
return rpcs.flat()
})
} }
/** /**
+3 -3
View File
@@ -136,7 +136,7 @@ export class RPCSocket implements I.Socket{
this.socket.hook(kv[0], kv[1]) this.socket.hook(kv[0], kv[1])
}) })
const info:T.ExtendedRpcInfo[] = await this.info() const info:T.ExtendedRpcInfo[] = await this.info(sesame)
info.forEach(i => { info.forEach(i => {
let f: any let f: any
@@ -159,9 +159,9 @@ export class RPCSocket implements I.Socket{
/** /**
* Get a list of available RPCs from the server * Get a list of available RPCs from the server
*/ */
public async info(){ public async info(sesame?:string){
if(!this.socket) throw new Error("The socket is not connected! Use socket.connect() first") if(!this.socket) throw new Error("The socket is not connected! Use socket.connect() first")
return await this.socket.call('info') return await this.socket.call('info', sesame)
} }
/** /**
+3 -2
View File
@@ -2,7 +2,7 @@ import * as I from "./Interfaces";
export type AnyFunction = (...args:any) => any export type AnyFunction = (...args:any) => any
export type HookFunction<F extends AnyFunction = AnyFunction, SubresT = {}> = (...args: Parameters<F>) => Promise<SubscriptionResponse<SubresT> | ErrorResponse> export type HookFunction<F extends AnyFunction = AnyFunction, SubresT = {}> = (...args: Parameters<F>) => Promise<SubscriptionResponse<SubresT> | ErrorResponse>
export type AccessFilter<InterfaceT extends RPCInterface, SubresT> = (sesame:string|undefined, exporter: I.RPCExporter<RPCInterface<InterfaceT>, keyof InterfaceT, SubresT>) => Promise<boolean>
export type Visibility = "127.0.0.1" | "0.0.0.0" export type Visibility = "127.0.0.1" | "0.0.0.0"
export type ConnectionHandler = (socket:I.Socket) => void export type ConnectionHandler = (socket:I.Socket) => void
export type ErrorHandler = (socket:I.Socket, error:any, rpcName: string, args: any[]) => void export type ErrorHandler = (socket:I.Socket, error:any, rpcName: string, args: any[]) => void
@@ -17,7 +17,8 @@ export type FrontEndHandlerType = {
'close' : () => void 'close' : () => void
} }
export type ServerConf = { export type ServerConf<InterfaceT extends RPCInterface, SubresT> = {
accessFilter?: AccessFilter<InterfaceT, SubresT>
connectionHandler?: ConnectionHandler connectionHandler?: ConnectionHandler
errorHandler?: ErrorHandler errorHandler?: ErrorHandler
closeHandler?: CloseHandler closeHandler?: CloseHandler
+25 -4
View File
@@ -542,8 +542,9 @@ type myExporterIfc = {
describe("Class binding", ()=>{ describe("Class binding", ()=>{
let exporter1 : MyExporter let exporter1 : MyExporter
let serv : RPCServer let serv : RPCServer<{}, myExporterIfc>
let sock: RPCSocket & myExporterIfc let sock: RPCSocket & myExporterIfc
let allowed = true
class MyExporter implements RPCExporter<myExporterIfc>{ class MyExporter implements RPCExporter<myExporterIfc>{
name = "MyExporter" as "MyExporter"; name = "MyExporter" as "MyExporter";
@@ -563,20 +564,34 @@ describe("Class binding", ()=>{
this.myRPC this.myRPC
] ]
myRPC = async () => "Hello Borld" myRPC = async () => {
return "Hello Borld"
}
} }
before(done => { before(done => {
exporter1 = new MyExporter() exporter1 = new MyExporter()
serv = new RPCServer(21004, [exporter1]) serv = new RPCServer<{}, myExporterIfc>(21004, [exporter1], {
accessFilter: async (sesame,exporter) => {
switch(exporter.name){
case "MyExporter":
if(!allowed) return false
allowed = false
return sesame==='xxx';
default:
return false
}
},
sesame: "xxx"
})
done() done()
}) })
beforeEach((done)=>{ beforeEach((done)=>{
const s = new RPCSocket(21004, 'localhost') const s = new RPCSocket(21004, 'localhost')
s.connect<myExporterIfc>().then(conn => { s.connect<myExporterIfc>("xxx").then(conn => {
sock = conn sock = conn
done() done()
}) })
@@ -596,6 +611,7 @@ describe("Class binding", ()=>{
done(new Error(res)) done(new Error(res))
}).catch(e => { }).catch(e => {
//job will time out because of setExporters //job will time out because of setExporters
allowed = true
done() done()
}) })
}) })
@@ -608,6 +624,11 @@ describe("Class binding", ()=>{
done(new Error(res)) done(new Error(res))
}) })
}) })
it("use sesameFilter", (done) => {
if(!sock['MyExporter']) done()
else done(new Error("RPC supposed to be gone"))
})
}) })