@@ -11,7 +11,7 @@ use std::{net::IpAddr, num::ParseIntError, str::FromStr};
11
11
use tui_input:: { backend:: crossterm:: EventHandler , Input } ;
12
12
use uuid;
13
13
14
- use crate :: { app:: AppResult , notification:: Notification } ;
14
+ use crate :: { app:: AppResult , filter :: direction :: TrafficDirection , notification:: Notification } ;
15
15
16
16
#[ derive( Debug , Clone ) ]
17
17
pub struct FirewallRule {
@@ -20,6 +20,7 @@ pub struct FirewallRule {
20
20
pub enabled : bool ,
21
21
pub ip : IpAddr ,
22
22
pub port : BlockedPort ,
23
+ direction : TrafficDirection ,
23
24
}
24
25
25
26
#[ derive( Debug , Clone , PartialEq ) ]
@@ -48,6 +49,7 @@ impl FromStr for BlockedPort {
48
49
}
49
50
}
50
51
52
+ // TODO: Add direction
51
53
impl Display for FirewallRule {
52
54
fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
53
55
write ! ( f, "{} {}" , self . ip, self . port)
@@ -58,14 +60,16 @@ pub enum FocusedInput {
58
60
Name ,
59
61
Ip ,
60
62
Port ,
63
+ Direction ,
61
64
}
62
65
63
66
#[ derive( Debug , Clone ) ]
64
67
struct UserInput {
65
68
id : Option < uuid:: Uuid > ,
66
- pub name : UserInputField ,
67
- pub ip : UserInputField ,
68
- pub port : UserInputField ,
69
+ name : UserInputField ,
70
+ ip : UserInputField ,
71
+ port : UserInputField ,
72
+ direction : TrafficDirection ,
69
73
focus_input : FocusedInput ,
70
74
}
71
75
@@ -82,6 +86,7 @@ impl UserInput {
82
86
name : UserInputField :: default ( ) ,
83
87
ip : UserInputField :: default ( ) ,
84
88
port : UserInputField :: default ( ) ,
89
+ direction : TrafficDirection :: Ingress ,
85
90
focus_input : FocusedInput :: Name ,
86
91
}
87
92
}
@@ -137,7 +142,7 @@ impl UserInput {
137
142
. direction ( Direction :: Horizontal )
138
143
. constraints ( [
139
144
Constraint :: Fill ( 1 ) ,
140
- Constraint :: Max ( 80 ) ,
145
+ Constraint :: Percentage ( 80 ) ,
141
146
Constraint :: Fill ( 1 ) ,
142
147
] )
143
148
. flex ( ratatui:: layout:: Flex :: SpaceBetween )
@@ -172,8 +177,22 @@ impl UserInput {
172
177
}
173
178
} )
174
179
. fg( Color :: Black ) ,
180
+ Cell :: from( self . direction. to_string( ) )
181
+ . bg( {
182
+ if self . focus_input == FocusedInput :: Direction {
183
+ Color :: Gray
184
+ } else {
185
+ Color :: DarkGray
186
+ }
187
+ } )
188
+ . fg( Color :: Black ) ,
189
+ ] ) ,
190
+ Row :: new ( vec ! [
191
+ Cell :: new( "" ) ,
192
+ Cell :: new( "" ) ,
193
+ Cell :: new( "" ) ,
194
+ Cell :: new( "" ) ,
175
195
] ) ,
176
- Row :: new ( vec ! [ Cell :: new( "" ) , Cell :: new( "" ) , Cell :: new( "" ) ] ) ,
177
196
Row :: new ( vec ! [
178
197
Cell :: from( {
179
198
if let Some ( error) = & self . name. error {
@@ -199,13 +218,15 @@ impl UserInput {
199
218
}
200
219
} )
201
220
. red( ) ,
221
+ Cell :: new( "" ) ,
202
222
] ) ,
203
223
] ;
204
224
205
225
let widths = [
206
- Constraint :: Percentage ( 33 ) ,
207
- Constraint :: Percentage ( 33 ) ,
208
- Constraint :: Percentage ( 33 ) ,
226
+ Constraint :: Percentage ( 25 ) ,
227
+ Constraint :: Percentage ( 25 ) ,
228
+ Constraint :: Percentage ( 25 ) ,
229
+ Constraint :: Percentage ( 25 ) ,
209
230
] ;
210
231
211
232
let table = Table :: new ( rows, widths)
@@ -214,6 +235,7 @@ impl UserInput {
214
235
Line :: from( "Name" ) . centered( ) ,
215
236
Line :: from( "IP" ) . centered( ) ,
216
237
Line :: from( "Port" ) . centered( ) ,
238
+ Line :: from( "Direction" ) . centered( ) ,
217
239
] )
218
240
. style ( Style :: new ( ) . bold ( ) )
219
241
. bottom_margin ( 1 ) ,
@@ -252,6 +274,7 @@ impl From<FirewallRule> for UserInput {
252
274
field : Input :: from ( rule. port . to_string ( ) ) ,
253
275
error : None ,
254
276
} ,
277
+ direction : rule. direction ,
255
278
focus_input : FocusedInput :: Name ,
256
279
}
257
280
}
@@ -318,6 +341,9 @@ impl Firewall {
318
341
self . rules . retain ( |r| r. name != rule. name ) ;
319
342
}
320
343
344
+ pub fn remove_ingress_rules ( & mut self ) { }
345
+ pub fn remove_egress_rules ( & mut self ) { }
346
+
321
347
pub fn handle_keys (
322
348
& mut self ,
323
349
key_event : KeyEvent ,
@@ -350,12 +376,14 @@ impl Firewall {
350
376
rule. ip = IpAddr :: from_str ( user_input. ip . field . value ( ) ) . unwrap ( ) ;
351
377
rule. port =
352
378
BlockedPort :: from_str ( user_input. port . field . value ( ) ) . unwrap ( ) ;
379
+ rule. direction = user_input. direction ;
353
380
} else {
354
381
let rule = FirewallRule {
355
382
id : uuid:: Uuid :: new_v4 ( ) ,
356
383
name : user_input. name . field . to_string ( ) ,
357
384
ip : IpAddr :: from_str ( user_input. ip . field . value ( ) ) . unwrap ( ) ,
358
385
port : BlockedPort :: from_str ( user_input. port . field . value ( ) ) . unwrap ( ) ,
386
+ direction : user_input. direction ,
359
387
enabled : false ,
360
388
} ;
361
389
self . rules . push ( rule) ;
@@ -369,7 +397,8 @@ impl Firewall {
369
397
match user_input. focus_input {
370
398
FocusedInput :: Name => user_input. focus_input = FocusedInput :: Ip ,
371
399
FocusedInput :: Ip => user_input. focus_input = FocusedInput :: Port ,
372
- FocusedInput :: Port => user_input. focus_input = FocusedInput :: Name ,
400
+ FocusedInput :: Port => user_input. focus_input = FocusedInput :: Direction ,
401
+ FocusedInput :: Direction => user_input. focus_input = FocusedInput :: Name ,
373
402
}
374
403
}
375
404
}
@@ -384,6 +413,15 @@ impl Firewall {
384
413
FocusedInput :: Port => {
385
414
user_input. port . field . handle_event ( & Event :: Key ( key_event) ) ;
386
415
}
416
+ FocusedInput :: Direction => match key_event. code {
417
+ KeyCode :: Char ( 'j' ) | KeyCode :: Down => {
418
+ user_input. direction = TrafficDirection :: Ingress ;
419
+ }
420
+ KeyCode :: Char ( 'k' ) | KeyCode :: Up => {
421
+ user_input. direction = TrafficDirection :: Egress ;
422
+ }
423
+ _ => { }
424
+ } ,
387
425
} ,
388
426
}
389
427
} else {
@@ -394,9 +432,15 @@ impl Firewall {
394
432
395
433
KeyCode :: Char ( ' ' ) => {
396
434
if let Some ( index) = self . state . selected ( ) {
397
- self . rules [ index] . enabled = !self . rules [ index] . enabled ;
398
- self . ingress_sender . send ( self . rules [ index] . clone ( ) ) ?;
399
- self . egress_sender . send ( self . rules [ index] . clone ( ) ) ?
435
+ let rule = & mut self . rules [ index] ;
436
+ rule. enabled = !rule. enabled ;
437
+
438
+ match rule. direction {
439
+ TrafficDirection :: Ingress => {
440
+ self . ingress_sender . send ( rule. clone ( ) ) ?;
441
+ }
442
+ TrafficDirection :: Egress => self . egress_sender . send ( rule. clone ( ) ) ?,
443
+ }
400
444
}
401
445
}
402
446
@@ -417,9 +461,16 @@ impl Firewall {
417
461
418
462
KeyCode :: Char ( 'd' ) => {
419
463
if let Some ( index) = self . state . selected ( ) {
420
- self . rules [ index] . enabled = false ;
421
- self . ingress_sender . send ( self . rules [ index] . clone ( ) ) ?;
422
- self . egress_sender . send ( self . rules [ index] . clone ( ) ) ?;
464
+ let rule = & mut self . rules [ index] ;
465
+
466
+ rule. enabled = false ;
467
+ match rule. direction {
468
+ TrafficDirection :: Ingress => {
469
+ self . ingress_sender . send ( rule. clone ( ) ) ?;
470
+ }
471
+ TrafficDirection :: Egress => self . egress_sender . send ( rule. clone ( ) ) ?,
472
+ }
473
+
423
474
self . rules . remove ( index) ;
424
475
}
425
476
}
@@ -483,16 +534,22 @@ impl Firewall {
483
534
Constraint :: Max ( 20 ) ,
484
535
Constraint :: Length ( 10 ) ,
485
536
Constraint :: Length ( 14 ) ,
537
+ Constraint :: Length ( 14 ) ,
486
538
] ;
487
539
488
540
let rows = self . rules . iter ( ) . map ( |rule| {
489
541
Row :: new ( vec ! [
490
542
Line :: from( rule. name. clone( ) ) . centered( ) . bold( ) ,
491
- Line :: from( rule. ip. to_string( ) ) . centered( ) . centered( ) . bold( ) ,
492
- Line :: from( rule. port. to_string( ) )
493
- . centered( )
494
- . centered( )
495
- . bold( ) ,
543
+ Line :: from( rule. ip. to_string( ) ) . centered( ) . bold( ) ,
544
+ Line :: from( rule. port. to_string( ) ) . centered( ) . bold( ) ,
545
+ Line :: from( {
546
+ match rule. direction {
547
+ TrafficDirection :: Ingress => String :: from( "Ingress " ) ,
548
+ TrafficDirection :: Egress => String :: from( "Egress " ) ,
549
+ }
550
+ } )
551
+ . centered( )
552
+ . bold( ) ,
496
553
Line :: from( {
497
554
if rule. enabled {
498
555
"Enabled" . to_string( )
@@ -501,7 +558,6 @@ impl Firewall {
501
558
}
502
559
} )
503
560
. centered( )
504
- . centered( )
505
561
. bold( ) ,
506
562
] )
507
563
} ) ;
@@ -519,6 +575,7 @@ impl Firewall {
519
575
Line :: from( "Name" ) . centered( ) . blue( ) ,
520
576
Line :: from( "IP" ) . centered( ) . blue( ) ,
521
577
Line :: from( "Port" ) . centered( ) . blue( ) ,
578
+ Line :: from( "Direction" ) . centered( ) . blue( ) ,
522
579
Line :: from( "Status" ) . centered( ) . blue( ) ,
523
580
] )
524
581
. style ( Style :: new ( ) . bold ( ) )
0 commit comments