peter преди 4 години
родител
ревизия
f8d475cb53
променени са 4 файла, в които са добавени 43 реда и са изтрити 14 реда
  1. 12
    5
      src/Backend.ts
  2. 3
    3
      src/Frontend.ts
  3. 3
    2
      src/Types.ts
  4. 25
    4
      test/Test.ts

+ 12
- 5
src/Backend.ts Целия файл

@@ -25,6 +25,7 @@ export class RPCServer<
25 25
     private errorHandler: T.ErrorHandler
26 26
     private connectionHandler: T.ConnectionHandler
27 27
     private sesame? : T.SesameFunction
28
+    private accessFilter: T.AccessFilter<InterfaceT, SubResType>
28 29
 
29 30
     /**
30 31
      * @throws On RPC with no name
@@ -35,10 +36,12 @@ export class RPCServer<
35 36
     constructor(
36 37
         private port:number,
37 38
         private exporters: Exporters<InterfaceT, SubResType> = [],
38
-        conf: T.ServerConf =  {}
39
+        conf: T.ServerConf<InterfaceT, SubResType> =  {}
39 40
     ){
40 41
         if(!conf.visibility) this.visibility = "127.0.0.1"        
41 42
         
43
+        this.accessFilter = conf.accessFilter || (async () => true)
44
+
42 45
         if(conf.sesame){
43 46
             this.sesame = U.makeSesameFunction(conf.sesame)
44 47
         }
@@ -87,10 +90,14 @@ export class RPCServer<
87 90
     }
88 91
 
89 92
     protected initRPCs(socket:I.Socket){
90
-        socket.hook('info', () => rpcInfos)
91
-        const rpcInfos:T.ExtendedRpcInfo[] = [
92
-            ...this.exporters.flatMap(exporter => U.rpcHooker(socket, exporter, this.errorHandler, this.sesame))
93
-        ]
93
+        socket.hook('info', async (sesame? : string) => {
94
+            const rpcs = await Promise.all(this.exporters.map(async exp => {
95
+                const allowed = await this.accessFilter(sesame, exp)
96
+                if(!allowed) return []
97
+                return U.rpcHooker(socket, exp, this.errorHandler, this.sesame)
98
+            }))
99
+            return rpcs.flat()
100
+        })
94 101
     }
95 102
 
96 103
     /**

+ 3
- 3
src/Frontend.ts Целия файл

@@ -136,7 +136,7 @@ export class RPCSocket implements I.Socket{
136 136
             this.socket.hook(kv[0], kv[1])
137 137
         })
138 138
 
139
-        const info:T.ExtendedRpcInfo[] = await this.info()
139
+        const info:T.ExtendedRpcInfo[] = await this.info(sesame)
140 140
         info.forEach(i => {
141 141
             let f: any
142 142
             
@@ -159,9 +159,9 @@ export class RPCSocket implements I.Socket{
159 159
     /**
160 160
      * Get a list of available RPCs from the server
161 161
      */
162
-    public async info(){
162
+    public async info(sesame?:string){
163 163
         if(!this.socket) throw new Error("The socket is not connected! Use socket.connect() first")
164
-        return await this.socket.call('info')
164
+        return await this.socket.call('info', sesame)
165 165
     }
166 166
 
167 167
     /**

+ 3
- 2
src/Types.ts Целия файл

@@ -2,7 +2,7 @@ import * as I from "./Interfaces";
2 2
 
3 3
 export type AnyFunction = (...args:any) => any
4 4
 export type HookFunction<F extends AnyFunction = AnyFunction, SubresT = {}> = (...args: Parameters<F>) => Promise<SubscriptionResponse<SubresT> | ErrorResponse>
5
-
5
+export type AccessFilter<InterfaceT extends RPCInterface, SubresT> = (sesame:string|undefined, exporter: I.RPCExporter<RPCInterface<InterfaceT>, keyof InterfaceT, SubresT>) => Promise<boolean> 
6 6
 export type Visibility = "127.0.0.1" | "0.0.0.0"
7 7
 export type ConnectionHandler = (socket:I.Socket) => void
8 8
 export type ErrorHandler = (socket:I.Socket, error:any, rpcName: string, args: any[]) => void
@@ -17,7 +17,8 @@ export type FrontEndHandlerType = {
17 17
     'close' : () => void
18 18
 }
19 19
 
20
-export type ServerConf = {
20
+export type ServerConf<InterfaceT extends RPCInterface, SubresT> = {
21
+    accessFilter?: AccessFilter<InterfaceT, SubresT>
21 22
     connectionHandler?: ConnectionHandler
22 23
     errorHandler?: ErrorHandler
23 24
     closeHandler?: CloseHandler

+ 25
- 4
test/Test.ts Целия файл

@@ -542,8 +542,9 @@ type myExporterIfc = {
542 542
 describe("Class binding", ()=>{
543 543
 
544 544
     let exporter1 : MyExporter
545
-    let serv : RPCServer
545
+    let serv : RPCServer<{}, myExporterIfc>
546 546
     let sock: RPCSocket & myExporterIfc
547
+    let allowed = true
547 548
 
548 549
     class MyExporter implements RPCExporter<myExporterIfc>{
549 550
         name = "MyExporter" as "MyExporter";
@@ -563,20 +564,34 @@ describe("Class binding", ()=>{
563 564
             this.myRPC
564 565
         ]
565 566
 
566
-        myRPC = async () => "Hello Borld"
567
+        myRPC = async () => { 
568
+            return "Hello Borld"
569
+        }
567 570
 
568 571
     }
569 572
 
570 573
     before(done => {
571 574
         exporter1 = new MyExporter()
572
-        serv = new RPCServer(21004, [exporter1])
575
+        serv = new RPCServer<{}, myExporterIfc>(21004, [exporter1], {
576
+            accessFilter: async (sesame,exporter) => {
577
+                switch(exporter.name){
578
+                    case "MyExporter": 
579
+                        if(!allowed) return false
580
+                        allowed = false
581
+                        return sesame==='xxx';
582
+                    default:
583
+                        return false
584
+                }
585
+            },
586
+            sesame: "xxx"
587
+        })
573 588
         done()
574 589
     })
575 590
         
576 591
     beforeEach((done)=>{
577 592
         
578 593
         const s = new RPCSocket(21004, 'localhost')
579
-        s.connect<myExporterIfc>().then(conn => {
594
+        s.connect<myExporterIfc>("xxx").then(conn => {
580 595
             sock = conn
581 596
             done()
582 597
         })
@@ -596,6 +611,7 @@ describe("Class binding", ()=>{
596 611
             done(new Error(res))
597 612
         }).catch(e => {
598 613
             //job will time out because of setExporters
614
+            allowed = true
599 615
             done()
600 616
         })
601 617
     })
@@ -608,6 +624,11 @@ describe("Class binding", ()=>{
608 624
                 done(new Error(res))
609 625
         })
610 626
     })
627
+
628
+    it("use sesameFilter", (done) => {
629
+        if(!sock['MyExporter']) done()
630
+        else done(new Error("RPC supposed to be gone"))
631
+    })
611 632
 })
612 633
 
613 634
 

Loading…
Отказ
Запис