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
     private errorHandler: T.ErrorHandler
25
     private errorHandler: T.ErrorHandler
26
     private connectionHandler: T.ConnectionHandler
26
     private connectionHandler: T.ConnectionHandler
27
     private sesame? : T.SesameFunction
27
     private sesame? : T.SesameFunction
28
+    private accessFilter: T.AccessFilter<InterfaceT, SubResType>
28
 
29
 
29
     /**
30
     /**
30
      * @throws On RPC with no name
31
      * @throws On RPC with no name
35
     constructor(
36
     constructor(
36
         private port:number,
37
         private port:number,
37
         private exporters: Exporters<InterfaceT, SubResType> = [],
38
         private exporters: Exporters<InterfaceT, SubResType> = [],
38
-        conf: T.ServerConf =  {}
39
+        conf: T.ServerConf<InterfaceT, SubResType> =  {}
39
     ){
40
     ){
40
         if(!conf.visibility) this.visibility = "127.0.0.1"        
41
         if(!conf.visibility) this.visibility = "127.0.0.1"        
41
         
42
         
43
+        this.accessFilter = conf.accessFilter || (async () => true)
44
+
42
         if(conf.sesame){
45
         if(conf.sesame){
43
             this.sesame = U.makeSesameFunction(conf.sesame)
46
             this.sesame = U.makeSesameFunction(conf.sesame)
44
         }
47
         }
87
     }
90
     }
88
 
91
 
89
     protected initRPCs(socket:I.Socket){
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
             this.socket.hook(kv[0], kv[1])
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
         info.forEach(i => {
140
         info.forEach(i => {
141
             let f: any
141
             let f: any
142
             
142
             
159
     /**
159
     /**
160
      * Get a list of available RPCs from the server
160
      * Get a list of available RPCs from the server
161
      */
161
      */
162
-    public async info(){
162
+    public async info(sesame?:string){
163
         if(!this.socket) throw new Error("The socket is not connected! Use socket.connect() first")
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
 
2
 
3
 export type AnyFunction = (...args:any) => any
3
 export type AnyFunction = (...args:any) => any
4
 export type HookFunction<F extends AnyFunction = AnyFunction, SubresT = {}> = (...args: Parameters<F>) => Promise<SubscriptionResponse<SubresT> | ErrorResponse>
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
 export type Visibility = "127.0.0.1" | "0.0.0.0"
6
 export type Visibility = "127.0.0.1" | "0.0.0.0"
7
 export type ConnectionHandler = (socket:I.Socket) => void
7
 export type ConnectionHandler = (socket:I.Socket) => void
8
 export type ErrorHandler = (socket:I.Socket, error:any, rpcName: string, args: any[]) => void
8
 export type ErrorHandler = (socket:I.Socket, error:any, rpcName: string, args: any[]) => void
17
     'close' : () => void
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
     connectionHandler?: ConnectionHandler
22
     connectionHandler?: ConnectionHandler
22
     errorHandler?: ErrorHandler
23
     errorHandler?: ErrorHandler
23
     closeHandler?: CloseHandler
24
     closeHandler?: CloseHandler

+ 25
- 4
test/Test.ts Прегледај датотеку

542
 describe("Class binding", ()=>{
542
 describe("Class binding", ()=>{
543
 
543
 
544
     let exporter1 : MyExporter
544
     let exporter1 : MyExporter
545
-    let serv : RPCServer
545
+    let serv : RPCServer<{}, myExporterIfc>
546
     let sock: RPCSocket & myExporterIfc
546
     let sock: RPCSocket & myExporterIfc
547
+    let allowed = true
547
 
548
 
548
     class MyExporter implements RPCExporter<myExporterIfc>{
549
     class MyExporter implements RPCExporter<myExporterIfc>{
549
         name = "MyExporter" as "MyExporter";
550
         name = "MyExporter" as "MyExporter";
563
             this.myRPC
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
     before(done => {
573
     before(done => {
571
         exporter1 = new MyExporter()
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
         done()
588
         done()
574
     })
589
     })
575
         
590
         
576
     beforeEach((done)=>{
591
     beforeEach((done)=>{
577
         
592
         
578
         const s = new RPCSocket(21004, 'localhost')
593
         const s = new RPCSocket(21004, 'localhost')
579
-        s.connect<myExporterIfc>().then(conn => {
594
+        s.connect<myExporterIfc>("xxx").then(conn => {
580
             sock = conn
595
             sock = conn
581
             done()
596
             done()
582
         })
597
         })
596
             done(new Error(res))
611
             done(new Error(res))
597
         }).catch(e => {
612
         }).catch(e => {
598
             //job will time out because of setExporters
613
             //job will time out because of setExporters
614
+            allowed = true
599
             done()
615
             done()
600
         })
616
         })
601
     })
617
     })
608
                 done(new Error(res))
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…
Откажи
Сачувај