@@ -343,7 +343,7 @@ impl RuntimeAuthority {
343
343
webview : & str ,
344
344
origin : & Origin ,
345
345
) -> String {
346
- fn print_references ( resolved : Vec < & ResolvedCommand > ) -> String {
346
+ fn print_references ( resolved : & [ ResolvedCommand ] ) -> String {
347
347
resolved
348
348
. iter ( )
349
349
. map ( |r| {
@@ -356,6 +356,53 @@ impl RuntimeAuthority {
356
356
. join ( " || " )
357
357
}
358
358
359
+ fn print_allowed_on ( resolved : & [ ResolvedCommand ] ) -> String {
360
+ if resolved. is_empty ( ) {
361
+ "command not allowed on any window/webview/URL context" . to_string ( )
362
+ } else {
363
+ let mut s = "allowed on: " . to_string ( ) ;
364
+
365
+ let last_index = resolved. len ( ) - 1 ;
366
+ for ( index, cmd) in resolved. iter ( ) . enumerate ( ) {
367
+ let windows = cmd
368
+ . windows
369
+ . iter ( )
370
+ . map ( |w| format ! ( "\" {}\" " , w. as_str( ) ) )
371
+ . collect :: < Vec < _ > > ( )
372
+ . join ( ", " ) ;
373
+ let webviews = cmd
374
+ . webviews
375
+ . iter ( )
376
+ . map ( |w| format ! ( "\" {}\" " , w. as_str( ) ) )
377
+ . collect :: < Vec < _ > > ( )
378
+ . join ( ", " ) ;
379
+
380
+ s. push ( '[' ) ;
381
+
382
+ if !windows. is_empty ( ) {
383
+ s. push_str ( & format ! ( "windows: {windows}, " ) ) ;
384
+ }
385
+
386
+ if !webviews. is_empty ( ) {
387
+ s. push_str ( & format ! ( "webviews: {webviews}, " ) ) ;
388
+ }
389
+
390
+ match & cmd. context {
391
+ ExecutionContext :: Local => s. push_str ( "URL: local" ) ,
392
+ ExecutionContext :: Remote { url } => s. push_str ( & format ! ( "URL: {}" , url. as_str( ) ) ) ,
393
+ }
394
+
395
+ s. push ( ']' ) ;
396
+
397
+ if index != last_index {
398
+ s. push_str ( ", " ) ;
399
+ }
400
+ }
401
+
402
+ s
403
+ }
404
+ }
405
+
359
406
fn has_permissions_allowing_command (
360
407
manifest : & crate :: utils:: acl:: manifest:: Manifest ,
361
408
set : & crate :: utils:: acl:: PermissionSet ,
@@ -393,35 +440,34 @@ impl RuntimeAuthority {
393
440
format ! ( "{key}.{command_name}" )
394
441
} ;
395
442
396
- if let Some ( resolved) = self . denied_commands . get ( & command) . map ( |r| {
397
- r. iter ( )
398
- . filter ( |cmd| origin. matches ( & cmd. context ) )
399
- . collect ( )
400
- } ) {
443
+ if let Some ( resolved) = self . denied_commands . get ( & command) {
401
444
format ! (
402
- "{command_pretty_name} denied on origin {origin}, referenced by: {}" ,
445
+ "{command_pretty_name} explicitly denied on origin {origin}\n \n referenced by: {}" ,
403
446
print_references( resolved)
404
447
)
405
448
} else {
406
449
let command_matches = self . allowed_commands . get ( & command) ;
407
450
408
- if let Some ( resolved) = self . allowed_commands . get ( & command) . map ( |r| {
409
- r. iter ( )
451
+ if let Some ( resolved) = self . allowed_commands . get ( & command) {
452
+ let resolved_matching_origin = resolved
453
+ . iter ( )
410
454
. filter ( |cmd| origin. matches ( & cmd. context ) )
411
- . collect :: < Vec < & ResolvedCommand > > ( )
412
- } ) {
413
- if resolved
455
+ . collect :: < Vec < & ResolvedCommand > > ( ) ;
456
+ if resolved_matching_origin
414
457
. iter ( )
415
458
. any ( |cmd| cmd. webviews . iter ( ) . any ( |w| w. matches ( webview) ) )
416
- || resolved
459
+ || resolved_matching_origin
417
460
. iter ( )
418
461
. any ( |cmd| cmd. windows . iter ( ) . any ( |w| w. matches ( window) ) )
419
462
{
420
463
"allowed" . to_string ( )
421
464
} else {
422
- format ! ( "{command_pretty_name} not allowed on window {window}, webview {webview}, allowed windows: {}, allowed webviews: {}, referenced by {}" ,
423
- resolved. iter( ) . flat_map( |cmd| cmd. windows. iter( ) . map( |w| w. as_str( ) ) ) . collect:: <Vec <_>>( ) . join( ", " ) ,
424
- resolved. iter( ) . flat_map( |cmd| cmd. webviews. iter( ) . map( |w| w. as_str( ) ) ) . collect:: <Vec <_>>( ) . join( ", " ) ,
465
+ format ! ( "{command_pretty_name} not allowed on window \" {window}\" , webview \" {webview}\" , URL: {}\n \n {}\n \n referenced by: {}" ,
466
+ match origin {
467
+ Origin :: Local => "local" ,
468
+ Origin :: Remote { url } => url. as_str( )
469
+ } ,
470
+ print_allowed_on( resolved) ,
425
471
print_references( resolved)
426
472
)
427
473
}
@@ -451,20 +497,25 @@ impl RuntimeAuthority {
451
497
452
498
permissions_referencing_command. sort ( ) ;
453
499
454
- format ! (
455
- "Permissions associated with this command: {}" ,
456
- permissions_referencing_command
457
- . iter( )
458
- . map( |p| if key == APP_ACL_KEY {
500
+ let associated_permissions = permissions_referencing_command
501
+ . iter ( )
502
+ . map ( |p| {
503
+ if key == APP_ACL_KEY {
459
504
p. to_string ( )
460
505
} else {
461
506
format ! ( "{key}:{p}" )
462
- } )
463
- . collect:: <Vec <_>>( )
464
- . join( ", " )
465
- )
507
+ }
508
+ } )
509
+ . collect :: < Vec < _ > > ( )
510
+ . join ( ", " ) ;
511
+
512
+ if associated_permissions. is_empty ( ) {
513
+ "Command not found" . to_string ( )
514
+ } else {
515
+ format ! ( "Permissions associated with this command: {associated_permissions}" )
516
+ }
466
517
} else {
467
- "Plugin did not define its manifest " . to_string ( )
518
+ "Plugin not found " . to_string ( )
468
519
} ;
469
520
470
521
if let Some ( resolved_cmds) = command_matches {
@@ -985,4 +1036,153 @@ mod tests {
985
1036
. resolve_access( command, window, webview, & Origin :: Local )
986
1037
. is_none( ) ) ;
987
1038
}
1039
+
1040
+ #[ cfg( debug_assertions) ]
1041
+ #[ test]
1042
+ fn resolve_access_message ( ) {
1043
+ use tauri_utils:: acl:: manifest:: Manifest ;
1044
+
1045
+ let plugin_name = "myplugin" ;
1046
+ let command_allowed_on_window = "my-command-window" ;
1047
+ let command_allowed_on_webview_window = "my-command-webview-window" ;
1048
+ let window = "main-*" ;
1049
+ let webview = "webview-*" ;
1050
+ let remote_url = "http://localhost:8080" ;
1051
+
1052
+ let referenced_by = tauri_utils:: acl:: resolved:: ResolvedCommandReference {
1053
+ capability : "maincap" . to_string ( ) ,
1054
+ permission : "allow-command" . to_string ( ) ,
1055
+ } ;
1056
+
1057
+ let resolved_window_cmd = ResolvedCommand {
1058
+ windows : vec ! [ Pattern :: new( window) . unwrap( ) ] ,
1059
+ referenced_by : referenced_by. clone ( ) ,
1060
+ ..Default :: default ( )
1061
+ } ;
1062
+ let resolved_webview_window_cmd = ResolvedCommand {
1063
+ windows : vec ! [ Pattern :: new( window) . unwrap( ) ] ,
1064
+ webviews : vec ! [ Pattern :: new( webview) . unwrap( ) ] ,
1065
+ referenced_by : referenced_by. clone ( ) ,
1066
+ ..Default :: default ( )
1067
+ } ;
1068
+ let resolved_webview_window_remote_cmd = ResolvedCommand {
1069
+ windows : vec ! [ Pattern :: new( window) . unwrap( ) ] ,
1070
+ webviews : vec ! [ Pattern :: new( webview) . unwrap( ) ] ,
1071
+ referenced_by : referenced_by. clone ( ) ,
1072
+ context : ExecutionContext :: Remote {
1073
+ url : remote_url. parse ( ) . unwrap ( ) ,
1074
+ } ,
1075
+ ..Default :: default ( )
1076
+ } ;
1077
+
1078
+ let allowed_commands = [
1079
+ (
1080
+ format ! ( "plugin:{plugin_name}|{command_allowed_on_window}" ) ,
1081
+ vec ! [ resolved_window_cmd] ,
1082
+ ) ,
1083
+ (
1084
+ format ! ( "plugin:{plugin_name}|{command_allowed_on_webview_window}" ) ,
1085
+ vec ! [
1086
+ resolved_webview_window_cmd,
1087
+ resolved_webview_window_remote_cmd,
1088
+ ] ,
1089
+ ) ,
1090
+ ]
1091
+ . into_iter ( )
1092
+ . collect ( ) ;
1093
+
1094
+ let authority = RuntimeAuthority :: new (
1095
+ [ (
1096
+ plugin_name. to_string ( ) ,
1097
+ Manifest {
1098
+ default_permission : None ,
1099
+ permissions : Default :: default ( ) ,
1100
+ permission_sets : Default :: default ( ) ,
1101
+ global_scope_schema : None ,
1102
+ } ,
1103
+ ) ]
1104
+ . into_iter ( )
1105
+ . collect ( ) ,
1106
+ Resolved {
1107
+ allowed_commands,
1108
+ ..Default :: default ( )
1109
+ } ,
1110
+ ) ;
1111
+
1112
+ // unknown plugin
1113
+ assert_eq ! (
1114
+ authority. resolve_access_message(
1115
+ "unknown-plugin" ,
1116
+ command_allowed_on_window,
1117
+ window,
1118
+ webview,
1119
+ & Origin :: Local
1120
+ ) ,
1121
+ "unknown-plugin.my-command-window not allowed. Plugin not found"
1122
+ ) ;
1123
+
1124
+ // unknown command
1125
+ assert_eq ! (
1126
+ authority. resolve_access_message(
1127
+ plugin_name,
1128
+ "unknown-command" ,
1129
+ window,
1130
+ webview,
1131
+ & Origin :: Local
1132
+ ) ,
1133
+ "myplugin.unknown-command not allowed. Command not found"
1134
+ ) ;
1135
+
1136
+ // window/webview do not match
1137
+ assert_eq ! (
1138
+ authority. resolve_access_message(
1139
+ plugin_name,
1140
+ command_allowed_on_window,
1141
+ "other-window" ,
1142
+ "any-webview" ,
1143
+ & Origin :: Local
1144
+ ) ,
1145
+ "myplugin.my-command-window not allowed on window \" other-window\" , webview \" any-webview\" , URL: local\n \n allowed on: [windows: \" main-*\" , URL: local]\n \n referenced by: capability: maincap, permission: allow-command"
1146
+ ) ;
1147
+
1148
+ // window matches, but not origin
1149
+ assert_eq ! (
1150
+ authority. resolve_access_message(
1151
+ plugin_name,
1152
+ command_allowed_on_window,
1153
+ window,
1154
+ "any-webview" ,
1155
+ & Origin :: Remote {
1156
+ url: "http://localhst" . parse( ) . unwrap( )
1157
+ }
1158
+ ) ,
1159
+ "myplugin.my-command-window not allowed on window \" main-*\" , webview \" any-webview\" , URL: http://localhst/\n \n allowed on: [windows: \" main-*\" , URL: local]\n \n referenced by: capability: maincap, permission: allow-command"
1160
+ ) ;
1161
+
1162
+ // window/webview do not match
1163
+ assert_eq ! (
1164
+ authority. resolve_access_message(
1165
+ plugin_name,
1166
+ command_allowed_on_webview_window,
1167
+ "other-window" ,
1168
+ "other-webview" ,
1169
+ & Origin :: Local
1170
+ ) ,
1171
+ "myplugin.my-command-webview-window not allowed on window \" other-window\" , webview \" other-webview\" , URL: local\n \n allowed on: [windows: \" main-*\" , webviews: \" webview-*\" , URL: local], [windows: \" main-*\" , webviews: \" webview-*\" , URL: http://localhost:8080]\n \n referenced by: capability: maincap, permission: allow-command || capability: maincap, permission: allow-command"
1172
+ ) ;
1173
+
1174
+ // window/webview matches, but not origin
1175
+ assert_eq ! (
1176
+ authority. resolve_access_message(
1177
+ plugin_name,
1178
+ command_allowed_on_webview_window,
1179
+ window,
1180
+ webview,
1181
+ & Origin :: Remote {
1182
+ url: "http://localhost:123" . parse( ) . unwrap( )
1183
+ }
1184
+ ) ,
1185
+ "myplugin.my-command-webview-window not allowed on window \" main-*\" , webview \" webview-*\" , URL: http://localhost:123/\n \n allowed on: [windows: \" main-*\" , webviews: \" webview-*\" , URL: local], [windows: \" main-*\" , webviews: \" webview-*\" , URL: http://localhost:8080]\n \n referenced by: capability: maincap, permission: allow-command || capability: maincap, permission: allow-command"
1186
+ ) ;
1187
+ }
988
1188
}
0 commit comments