1use crate::app::App;
2use crate::common::{CyclicEnum, InputFocus, PageSize};
3use crate::ui::iam::{
4 filtered_iam_policies, filtered_iam_roles, filtered_iam_users, filtered_last_accessed,
5 filtered_tags as filtered_iam_tags, filtered_user_tags, GroupTab, RoleTab, UserTab,
6 GROUP_FILTER_CONTROLS, HISTORY_FILTER, POLICY_FILTER_CONTROLS, POLICY_TYPE_DROPDOWN,
7 ROLE_FILTER_CONTROLS, USER_LAST_ACCESSED_FILTER_CONTROLS, USER_SIMPLE_FILTER_CONTROLS,
8};
9
10pub fn apply_filter_reset_users(app: &mut App) {
13 if app.iam_state.current_user.is_some() {
14 app.iam_state.user_tags.reset();
15 app.iam_state.policies.reset();
16 } else {
17 app.iam_state.users.reset();
18 }
19}
20
21pub fn apply_filter_reset_roles(app: &mut App) {
22 if app.iam_state.current_role.is_some() {
23 app.iam_state.tags.reset();
24 app.iam_state.policies.reset();
25 } else {
26 app.iam_state.roles.reset();
27 }
28}
29
30pub fn apply_filter_reset_groups(app: &mut App) {
31 if app.iam_state.current_group.is_some() {
32 app.iam_state.policies.reset();
33 app.iam_state.group_users.reset();
34 } else {
35 app.iam_state.groups.reset();
36 }
37}
38
39pub fn reset_on_service_select_roles(app: &mut App) {
40 app.iam_state.roles.reset();
41}
42
43pub fn reset_on_service_select_users(app: &mut App) {
44 app.iam_state.users.reset();
45}
46
47pub fn reset_on_service_select_groups(app: &mut App) {
48 app.iam_state.groups.reset();
49}
50
51pub fn next_filter_focus_roles(app: &mut App) {
54 if app.iam_state.current_role.is_some() {
55 app.iam_state.policy_input_focus = app
56 .iam_state
57 .policy_input_focus
58 .next(&POLICY_FILTER_CONTROLS);
59 } else {
60 app.iam_state.role_input_focus = app.iam_state.role_input_focus.next(&ROLE_FILTER_CONTROLS);
61 }
62}
63
64pub fn prev_filter_focus_roles(app: &mut App) {
65 if app.iam_state.current_role.is_some() {
66 app.iam_state.policy_input_focus = app
67 .iam_state
68 .policy_input_focus
69 .prev(&POLICY_FILTER_CONTROLS);
70 } else {
71 app.iam_state.role_input_focus = app.iam_state.role_input_focus.prev(&ROLE_FILTER_CONTROLS);
72 }
73}
74
75pub fn next_filter_focus_users(app: &mut App) {
76 if app.iam_state.user_tab == UserTab::Permissions {
77 app.iam_state.policy_input_focus = app
78 .iam_state
79 .policy_input_focus
80 .next(&POLICY_FILTER_CONTROLS);
81 } else if app.iam_state.user_tab == UserTab::LastAccessed {
82 app.iam_state.last_accessed_input_focus = app
83 .iam_state
84 .last_accessed_input_focus
85 .next(&USER_LAST_ACCESSED_FILTER_CONTROLS);
86 } else {
87 app.iam_state.user_input_focus = app
88 .iam_state
89 .user_input_focus
90 .next(&USER_SIMPLE_FILTER_CONTROLS);
91 }
92}
93
94pub fn prev_filter_focus_users(app: &mut App) {
95 if app.iam_state.user_tab == UserTab::Permissions {
96 app.iam_state.policy_input_focus = app
97 .iam_state
98 .policy_input_focus
99 .prev(&POLICY_FILTER_CONTROLS);
100 } else if app.iam_state.user_tab == UserTab::LastAccessed {
101 app.iam_state.last_accessed_input_focus = app
102 .iam_state
103 .last_accessed_input_focus
104 .prev(&USER_LAST_ACCESSED_FILTER_CONTROLS);
105 } else {
106 app.iam_state.user_input_focus = app
107 .iam_state
108 .user_input_focus
109 .prev(&USER_SIMPLE_FILTER_CONTROLS);
110 }
111}
112
113pub fn next_filter_focus_groups(app: &mut App) {
114 app.iam_state.group_input_focus = app.iam_state.group_input_focus.next(&GROUP_FILTER_CONTROLS);
115}
116
117pub fn prev_filter_focus_groups(app: &mut App) {
118 app.iam_state.group_input_focus = app.iam_state.group_input_focus.prev(&GROUP_FILTER_CONTROLS);
119}
120
121pub fn is_pagination_focused_roles(app: &App) -> bool {
122 app.iam_state.current_role.is_none() && app.iam_state.role_input_focus == InputFocus::Pagination
123}
124
125pub fn is_filter_focused_roles(app: &App) -> bool {
126 app.iam_state.current_role.is_none() && app.iam_state.role_input_focus == InputFocus::Filter
127}
128
129pub fn is_filter_focused_policy_view(app: &App) -> bool {
130 app.iam_state.policy_input_focus == InputFocus::Filter
131}
132
133pub fn is_pagination_focused_policy_view(app: &App) -> bool {
134 app.iam_state.policy_input_focus == InputFocus::Pagination
135}
136
137pub fn next_item_users(app: &mut App) {
140 if app.iam_state.current_user.is_some() {
141 if app.iam_state.user_tab == UserTab::Tags {
142 let filtered = filtered_user_tags(app);
143 if !filtered.is_empty() {
144 app.iam_state.user_tags.next_item(filtered.len());
145 }
146 } else {
147 let filtered = filtered_iam_policies(app);
148 if !filtered.is_empty() {
149 app.iam_state.policies.next_item(filtered.len());
150 }
151 }
152 } else {
153 let filtered = filtered_iam_users(app);
154 if !filtered.is_empty() {
155 app.iam_state.users.next_item(filtered.len());
156 }
157 }
158}
159
160pub fn next_item_roles(app: &mut App) {
161 if app.iam_state.current_role.is_some() {
162 match app.iam_state.role_tab {
163 RoleTab::TrustRelationships => {
164 let lines = app.iam_state.trust_policy_document.lines().count();
165 let max_scroll = lines.saturating_sub(1);
166 app.iam_state.trust_policy_scroll =
167 (app.iam_state.trust_policy_scroll + 1).min(max_scroll);
168 }
169 RoleTab::RevokeSessions => {
170 app.iam_state.revoke_sessions_scroll =
171 (app.iam_state.revoke_sessions_scroll + 1).min(19);
172 }
173 RoleTab::Tags => {
174 let filtered = filtered_iam_tags(app);
175 if !filtered.is_empty() {
176 app.iam_state.tags.next_item(filtered.len());
177 }
178 }
179 RoleTab::LastAccessed => {
180 let filtered = filtered_last_accessed(app);
181 if !filtered.is_empty() {
182 app.iam_state
183 .last_accessed_services
184 .next_item(filtered.len());
185 }
186 }
187 _ => {
188 let filtered = filtered_iam_policies(app);
189 if !filtered.is_empty() {
190 app.iam_state.policies.next_item(filtered.len());
191 }
192 }
193 }
194 } else {
195 let filtered = filtered_iam_roles(app);
196 if !filtered.is_empty() {
197 app.iam_state.roles.next_item(filtered.len());
198 }
199 }
200}
201
202pub fn next_item_groups(app: &mut App) {
203 if app.iam_state.current_group.is_some() {
204 match app.iam_state.group_tab {
205 GroupTab::Users => {
206 let filtered: Vec<_> = app
207 .iam_state
208 .group_users
209 .items
210 .iter()
211 .filter(|u| {
212 app.iam_state.group_users.filter.is_empty()
213 || u.user_name
214 .to_lowercase()
215 .contains(&app.iam_state.group_users.filter.to_lowercase())
216 })
217 .collect();
218 if !filtered.is_empty() {
219 app.iam_state.group_users.next_item(filtered.len());
220 }
221 }
222 GroupTab::Permissions => {
223 let filtered = filtered_iam_policies(app);
224 if !filtered.is_empty() {
225 app.iam_state.policies.next_item(filtered.len());
226 }
227 }
228 GroupTab::AccessAdvisor => {
229 let filtered = filtered_last_accessed(app);
230 if !filtered.is_empty() {
231 app.iam_state
232 .last_accessed_services
233 .next_item(filtered.len());
234 }
235 }
236 }
237 } else {
238 let filtered: Vec<_> = app
239 .iam_state
240 .groups
241 .items
242 .iter()
243 .filter(|g| {
244 app.iam_state.groups.filter.is_empty()
245 || g.group_name
246 .to_lowercase()
247 .contains(&app.iam_state.groups.filter.to_lowercase())
248 })
249 .collect();
250 if !filtered.is_empty() {
251 app.iam_state.groups.next_item(filtered.len());
252 }
253 }
254}
255
256pub fn prev_item_users(app: &mut App) {
257 app.iam_state.users.prev_item();
258}
259
260pub fn prev_item_roles(app: &mut App) {
261 if app.iam_state.current_role.is_some() {
262 match app.iam_state.role_tab {
263 RoleTab::TrustRelationships => {
264 app.iam_state.trust_policy_scroll =
265 app.iam_state.trust_policy_scroll.saturating_sub(1);
266 }
267 RoleTab::RevokeSessions => {
268 app.iam_state.revoke_sessions_scroll =
269 app.iam_state.revoke_sessions_scroll.saturating_sub(1);
270 }
271 RoleTab::Tags => app.iam_state.tags.prev_item(),
272 RoleTab::LastAccessed => app.iam_state.last_accessed_services.prev_item(),
273 _ => app.iam_state.policies.prev_item(),
274 }
275 } else {
276 app.iam_state.roles.prev_item();
277 }
278}
279
280pub fn prev_item_groups(app: &mut App) {
281 if app.iam_state.current_group.is_some() {
282 match app.iam_state.group_tab {
283 GroupTab::Users => app.iam_state.group_users.prev_item(),
284 GroupTab::Permissions => app.iam_state.policies.prev_item(),
285 GroupTab::AccessAdvisor => app.iam_state.last_accessed_services.prev_item(),
286 }
287 } else {
288 app.iam_state.groups.prev_item();
289 }
290}
291
292pub fn page_down_filter_input_roles(app: &mut App) {
293 let page_size = app.iam_state.roles.page_size.value();
294 let filtered_count = filtered_iam_roles(app).len();
295 app.iam_state.role_input_focus.handle_page_down(
296 &mut app.iam_state.roles.selected,
297 &mut app.iam_state.roles.scroll_offset,
298 page_size,
299 filtered_count,
300 );
301}
302
303pub fn page_down_filter_input_policy_view(app: &mut App) {
304 let page_size = app.iam_state.policies.page_size.value();
305 let filtered_count = filtered_iam_policies(app).len();
306 app.iam_state.policy_input_focus.handle_page_down(
307 &mut app.iam_state.policies.selected,
308 &mut app.iam_state.policies.scroll_offset,
309 page_size,
310 filtered_count,
311 );
312}
313
314pub fn page_down_normal_users(app: &mut App) {
315 let len = filtered_iam_users(app).len();
316 crate::app::nav_page_down(&mut app.iam_state.users.selected, len, 10);
317}
318
319pub fn page_down_normal_roles(app: &mut App) {
320 if app.iam_state.current_role.is_some() {
321 let filtered = filtered_iam_policies(app);
322 if !filtered.is_empty() {
323 app.iam_state.policies.page_down(filtered.len());
324 }
325 } else {
326 let filtered = filtered_iam_roles(app);
327 app.iam_state.roles.page_down(filtered.len());
328 }
329}
330
331pub fn page_down_normal_groups(app: &mut App) {
332 if app.iam_state.current_group.is_some() {
333 match app.iam_state.group_tab {
334 GroupTab::Users => {
335 let filtered: Vec<_> = app
336 .iam_state
337 .group_users
338 .items
339 .iter()
340 .filter(|u| {
341 app.iam_state.group_users.filter.is_empty()
342 || u.user_name
343 .to_lowercase()
344 .contains(&app.iam_state.group_users.filter.to_lowercase())
345 })
346 .collect();
347 if !filtered.is_empty() {
348 app.iam_state.group_users.page_down(filtered.len());
349 }
350 }
351 GroupTab::Permissions => {
352 let filtered = filtered_iam_policies(app);
353 if !filtered.is_empty() {
354 app.iam_state.policies.page_down(filtered.len());
355 }
356 }
357 GroupTab::AccessAdvisor => {
358 let filtered = filtered_last_accessed(app);
359 if !filtered.is_empty() {
360 app.iam_state
361 .last_accessed_services
362 .page_down(filtered.len());
363 }
364 }
365 }
366 } else {
367 let filtered: Vec<_> = app
368 .iam_state
369 .groups
370 .items
371 .iter()
372 .filter(|g| {
373 app.iam_state.groups.filter.is_empty()
374 || g.group_name
375 .to_lowercase()
376 .contains(&app.iam_state.groups.filter.to_lowercase())
377 })
378 .collect();
379 if !filtered.is_empty() {
380 app.iam_state.groups.page_down(filtered.len());
381 }
382 }
383}
384
385pub fn page_up_filter_input_roles(app: &mut App) {
386 let page_size = app.iam_state.roles.page_size.value();
387 app.iam_state.role_input_focus.handle_page_up(
388 &mut app.iam_state.roles.selected,
389 &mut app.iam_state.roles.scroll_offset,
390 page_size,
391 );
392}
393
394pub fn page_up_filter_input_policy_view(app: &mut App) {
395 let page_size = app.iam_state.policies.page_size.value();
396 app.iam_state.policy_input_focus.handle_page_up(
397 &mut app.iam_state.policies.selected,
398 &mut app.iam_state.policies.scroll_offset,
399 page_size,
400 );
401}
402
403pub fn page_up_normal_users(app: &mut App) {
404 app.iam_state.users.page_up();
405}
406
407pub fn page_up_normal_roles(app: &mut App) {
408 if app.iam_state.current_role.is_some() {
409 app.iam_state.policies.page_up();
410 } else {
411 app.iam_state.roles.page_up();
412 }
413}
414
415pub fn go_to_page_users(app: &mut App, page: usize) {
416 let filtered_count = filtered_iam_users(app).len();
417 app.iam_state.users.goto_page(page, filtered_count);
418}
419
420pub fn go_to_page_roles(app: &mut App, page: usize) {
421 let filtered_count = filtered_iam_roles(app).len();
422 app.iam_state.roles.goto_page(page, filtered_count);
423}
424
425pub fn scroll_up_policy_view(app: &mut App) {
426 app.iam_state.policy_scroll = app.iam_state.policy_scroll.saturating_sub(10);
427}
428
429pub fn scroll_down_policy_view(app: &mut App) {
430 let lines = app.iam_state.policy_document.lines().count();
431 let max_scroll = lines.saturating_sub(1);
432 app.iam_state.policy_scroll = (app.iam_state.policy_scroll + 10).min(max_scroll);
433}
434
435pub fn scroll_up_trust_policy(app: &mut App) {
436 app.iam_state.trust_policy_scroll = app.iam_state.trust_policy_scroll.saturating_sub(10);
437}
438
439pub fn scroll_down_trust_policy(app: &mut App) {
440 let lines = app.iam_state.trust_policy_document.lines().count();
441 let max_scroll = lines.saturating_sub(1);
442 app.iam_state.trust_policy_scroll = (app.iam_state.trust_policy_scroll + 10).min(max_scroll);
443}
444
445pub fn scroll_up_revoke_sessions(app: &mut App) {
446 app.iam_state.revoke_sessions_scroll = app.iam_state.revoke_sessions_scroll.saturating_sub(10);
447}
448
449pub fn scroll_down_revoke_sessions(app: &mut App) {
450 app.iam_state.revoke_sessions_scroll = (app.iam_state.revoke_sessions_scroll + 10).min(19);
451}
452
453pub fn scroll_down_policy_view_one(app: &mut App) {
454 let lines = app.iam_state.policy_document.lines().count();
455 let max_scroll = lines.saturating_sub(1);
456 app.iam_state.policy_scroll = (app.iam_state.policy_scroll + 1).min(max_scroll);
457}
458
459pub fn scroll_up_policy_view_one(app: &mut App) {
460 app.iam_state.policy_scroll = app.iam_state.policy_scroll.saturating_sub(1);
461}
462
463pub fn next_item_filter_input_users(app: &mut App) {
466 if app.iam_state.user_tab == UserTab::Permissions
467 && app.iam_state.policy_input_focus == POLICY_TYPE_DROPDOWN
468 {
469 cycle_policy_type_next(app);
470 } else if app.iam_state.user_tab == UserTab::LastAccessed
471 && app.iam_state.last_accessed_input_focus == HISTORY_FILTER
472 {
473 app.iam_state.last_accessed_history_filter =
474 app.iam_state.last_accessed_history_filter.next();
475 app.iam_state.last_accessed_services.reset();
476 }
477}
478
479pub fn prev_item_filter_input_users(app: &mut App) {
480 if app.iam_state.user_tab == UserTab::Permissions
481 && app.iam_state.policy_input_focus == POLICY_TYPE_DROPDOWN
482 {
483 cycle_policy_type_prev(app);
484 } else if app.iam_state.user_tab == UserTab::LastAccessed
485 && app.iam_state.last_accessed_input_focus == HISTORY_FILTER
486 {
487 app.iam_state.last_accessed_history_filter =
488 app.iam_state.last_accessed_history_filter.prev();
489 app.iam_state.last_accessed_services.reset();
490 }
491}
492
493pub fn next_item_filter_input_roles(app: &mut App) {
494 if app.iam_state.role_tab == RoleTab::Permissions
495 && app.iam_state.policy_input_focus == POLICY_TYPE_DROPDOWN
496 {
497 cycle_policy_type_next(app);
498 }
499}
500
501pub fn prev_item_filter_input_roles(app: &mut App) {
502 if app.iam_state.role_tab == RoleTab::Permissions
503 && app.iam_state.policy_input_focus == POLICY_TYPE_DROPDOWN
504 {
505 cycle_policy_type_prev(app);
506 }
507}
508
509fn cycle_policy_type_next(app: &mut App) {
510 let types = ["All types", "AWS managed", "Customer managed"];
511 let current_idx = types
512 .iter()
513 .position(|&t| t == app.iam_state.policy_type_filter)
514 .unwrap_or(0);
515 app.iam_state.policy_type_filter = types[(current_idx + 1) % types.len()].to_string();
516 app.iam_state.policies.reset();
517}
518
519fn cycle_policy_type_prev(app: &mut App) {
520 let types = ["All types", "AWS managed", "Customer managed"];
521 let current_idx = types
522 .iter()
523 .position(|&t| t == app.iam_state.policy_type_filter)
524 .unwrap_or(0);
525 let prev_idx = if current_idx == 0 {
526 types.len() - 1
527 } else {
528 current_idx - 1
529 };
530 app.iam_state.policy_type_filter = types[prev_idx].to_string();
531 app.iam_state.policies.reset();
532}
533
534pub fn expand_row_users(app: &mut App) {
537 if app.iam_state.current_user.is_some() {
538 if app.iam_state.user_tab == UserTab::Tags {
539 if app.iam_state.user_tags.expanded_item != Some(app.iam_state.user_tags.selected) {
540 app.iam_state.user_tags.expanded_item = Some(app.iam_state.user_tags.selected);
541 }
542 } else if app.iam_state.policies.expanded_item != Some(app.iam_state.policies.selected) {
543 app.iam_state.policies.toggle_expand();
544 }
545 } else if !app.iam_state.users.is_expanded() {
546 app.iam_state.users.toggle_expand();
547 }
548}
549
550pub fn expand_row_roles(app: &mut App) {
551 if app.iam_state.current_role.is_some() {
552 match app.iam_state.role_tab {
553 RoleTab::Tags => {
554 if !app.iam_state.tags.is_expanded() {
555 app.iam_state.tags.expand();
556 }
557 }
558 RoleTab::LastAccessed => {
559 if !app.iam_state.last_accessed_services.is_expanded() {
560 app.iam_state.last_accessed_services.expand();
561 }
562 }
563 _ => {
564 if !app.iam_state.policies.is_expanded() {
565 app.iam_state.policies.expand();
566 }
567 }
568 }
569 } else if !app.iam_state.roles.is_expanded() {
570 app.iam_state.roles.expand();
571 }
572}
573
574pub fn expand_row_groups(app: &mut App) {
575 if app.iam_state.current_group.is_some() {
576 match app.iam_state.group_tab {
577 GroupTab::Users => {
578 if !app.iam_state.group_users.is_expanded() {
579 app.iam_state.group_users.expand();
580 }
581 }
582 GroupTab::Permissions => {
583 if !app.iam_state.policies.is_expanded() {
584 app.iam_state.policies.expand();
585 }
586 }
587 GroupTab::AccessAdvisor => {
588 if !app.iam_state.last_accessed_services.is_expanded() {
589 app.iam_state.last_accessed_services.expand();
590 }
591 }
592 }
593 } else if !app.iam_state.groups.is_expanded() {
594 app.iam_state.groups.expand();
595 }
596}
597
598pub fn prev_pane_users(app: &mut App) {
599 if app.iam_state.users.has_expanded_item() {
600 app.iam_state.users.collapse();
601 }
602}
603
604pub fn prev_pane_roles(app: &mut App) {
605 if app.view_mode == crate::app::ViewMode::PolicyView {
606 app.view_mode = crate::app::ViewMode::Detail;
607 app.iam_state.current_policy = None;
608 app.iam_state.policy_document.clear();
609 app.iam_state.policy_scroll = 0;
610 } else if app.iam_state.current_role.is_some() {
611 if app.iam_state.role_tab == RoleTab::Tags && app.iam_state.tags.has_expanded_item() {
612 app.iam_state.tags.collapse();
613 } else if app.iam_state.role_tab == RoleTab::LastAccessed
614 && app.iam_state.last_accessed_services.expanded_item.is_some()
615 {
616 app.iam_state.last_accessed_services.collapse();
617 } else if app.iam_state.policies.has_expanded_item() {
618 app.iam_state.policies.collapse();
619 }
620 } else if app.iam_state.roles.has_expanded_item() {
621 app.iam_state.roles.collapse();
622 }
623}
624
625pub fn prev_pane_groups(app: &mut App) {
626 if app.iam_state.current_group.is_some() {
627 if app.iam_state.group_tab == GroupTab::Users
628 && app.iam_state.group_users.has_expanded_item()
629 {
630 app.iam_state.group_users.collapse();
631 } else if app.iam_state.group_tab == GroupTab::Permissions
632 && app.iam_state.policies.has_expanded_item()
633 {
634 app.iam_state.policies.collapse();
635 } else if app.iam_state.group_tab == GroupTab::AccessAdvisor
636 && app.iam_state.last_accessed_services.expanded_item.is_some()
637 {
638 app.iam_state.last_accessed_services.collapse();
639 }
640 } else if app.iam_state.groups.has_expanded_item() {
641 app.iam_state.groups.collapse();
642 }
643}
644
645pub fn collapse_row_users(app: &mut App) {
646 if app.iam_state.current_user.is_some() {
647 match app.iam_state.user_tab {
648 UserTab::Permissions => app.iam_state.policies.collapse(),
649 UserTab::Groups => app.iam_state.user_group_memberships.collapse(),
650 UserTab::Tags => app.iam_state.user_tags.collapse(),
651 _ => {}
652 }
653 } else {
654 app.iam_state.users.collapse();
655 }
656}
657
658pub fn collapse_row_roles(app: &mut App) {
659 if app.iam_state.current_role.is_some() {
660 match app.iam_state.role_tab {
661 RoleTab::Permissions => app.iam_state.policies.collapse(),
662 RoleTab::Tags => app.iam_state.tags.collapse(),
663 _ => {}
664 }
665 } else {
666 app.iam_state.roles.collapse();
667 }
668}
669
670pub fn collapse_row_groups(app: &mut App) {
671 app.iam_state.groups.collapse();
672}
673
674pub fn go_back_users(app: &mut App) {
677 app.iam_state.current_user = None;
678 app.iam_state.policies.items.clear();
679 app.iam_state.policies.reset();
680 app.update_current_tab_breadcrumb();
681}
682
683pub fn go_back_groups(app: &mut App) {
684 app.iam_state.current_group = None;
685 app.update_current_tab_breadcrumb();
686}
687
688pub fn go_back_roles(app: &mut App) {
689 if app.view_mode == crate::app::ViewMode::PolicyView {
690 app.view_mode = crate::app::ViewMode::Detail;
691 app.iam_state.current_policy = None;
692 app.iam_state.policy_document.clear();
693 app.iam_state.policy_scroll = 0;
694 app.update_current_tab_breadcrumb();
695 } else if app.iam_state.current_role.is_some() {
696 app.iam_state.current_role = None;
697 app.iam_state.policies.items.clear();
698 app.iam_state.policies.reset();
699 app.update_current_tab_breadcrumb();
700 }
701}
702
703pub fn next_detail_tab_roles(app: &mut App) {
706 app.iam_state.role_tab = app.iam_state.role_tab.next();
707 if app.iam_state.role_tab == RoleTab::Tags {
708 app.iam_state.tags.loading = true;
709 }
710}
711
712pub fn prev_detail_tab_roles(app: &mut App) {
713 app.iam_state.role_tab = app.iam_state.role_tab.prev();
714}
715
716pub fn next_detail_tab_users(app: &mut App) {
717 app.iam_state.user_tab = app.iam_state.user_tab.next();
718 if app.iam_state.user_tab == UserTab::Tags {
719 app.iam_state.user_tags.loading = true;
720 }
721}
722
723pub fn prev_detail_tab_users(app: &mut App) {
724 app.iam_state.user_tab = app.iam_state.user_tab.prev();
725}
726
727pub fn next_detail_tab_groups(app: &mut App) {
728 app.iam_state.group_tab = app.iam_state.group_tab.next();
729}
730
731pub fn prev_detail_tab_groups(app: &mut App) {
732 app.iam_state.group_tab = app.iam_state.group_tab.prev();
733}
734
735pub fn select_item_users(app: &mut App) {
738 if app.iam_state.current_user.is_some() {
739 if app.iam_state.user_tab == UserTab::Permissions {
740 let filtered = filtered_iam_policies(app);
741 if let Some(policy) = app.iam_state.policies.get_selected(&filtered) {
742 app.iam_state.current_policy = Some(policy.policy_name.clone());
743 app.iam_state.policy_scroll = 0;
744 app.view_mode = crate::app::ViewMode::PolicyView;
745 app.iam_state.policies.loading = true;
746 app.update_current_tab_breadcrumb();
747 }
748 }
749 } else {
750 let filtered = filtered_iam_users(app);
751 if let Some(user) = app.iam_state.users.get_selected(&filtered) {
752 app.iam_state.current_user = Some(user.user_name.clone());
753 app.iam_state.user_tab = UserTab::Permissions;
754 app.iam_state.policies.reset();
755 app.update_current_tab_breadcrumb();
756 }
757 }
758}
759
760pub fn select_item_roles(app: &mut App) {
761 if app.iam_state.current_role.is_some() {
762 if app.iam_state.role_tab == RoleTab::Permissions {
763 let filtered = filtered_iam_policies(app);
764 if let Some(policy) = app.iam_state.policies.get_selected(&filtered) {
765 app.iam_state.current_policy = Some(policy.policy_name.clone());
766 app.iam_state.policy_scroll = 0;
767 app.view_mode = crate::app::ViewMode::PolicyView;
768 app.iam_state.policies.loading = true;
769 app.update_current_tab_breadcrumb();
770 }
771 }
772 } else {
773 let filtered = filtered_iam_roles(app);
774 if let Some(role) = app.iam_state.roles.get_selected(&filtered) {
775 app.iam_state.current_role = Some(role.role_name.clone());
776 app.iam_state.role_tab = RoleTab::Permissions;
777 app.iam_state.policies.reset();
778 app.update_current_tab_breadcrumb();
779 }
780 }
781}
782
783pub fn select_item_groups(app: &mut App) {
784 if app.iam_state.current_group.is_none() {
785 let filtered: Vec<_> = app
786 .iam_state
787 .groups
788 .items
789 .iter()
790 .filter(|g| {
791 app.iam_state.groups.filter.is_empty()
792 || g.group_name
793 .to_lowercase()
794 .contains(&app.iam_state.groups.filter.to_lowercase())
795 })
796 .collect();
797 if let Some(group) = app.iam_state.groups.get_selected(&filtered) {
798 app.iam_state.current_group = Some(group.group_name.clone());
799 app.update_current_tab_breadcrumb();
800 }
801 }
802}
803
804pub fn yank_users(app: &App) {
807 use crate::app::copy_to_clipboard;
808 if app.view_mode == crate::app::ViewMode::PolicyView {
810 if !app.iam_state.policy_document.is_empty() {
811 copy_to_clipboard(&app.iam_state.policy_document);
812 }
813 return;
814 }
815 if app.iam_state.current_user.is_some() {
816 if let Some(user_name) = &app.iam_state.current_user {
817 if let Some(user) = app
818 .iam_state
819 .users
820 .items
821 .iter()
822 .find(|u| u.user_name == *user_name)
823 {
824 copy_to_clipboard(&user.arn);
825 }
826 }
827 } else {
828 let filtered = filtered_iam_users(app);
829 if let Some(user) = app.iam_state.users.get_selected(&filtered) {
830 copy_to_clipboard(&user.arn);
831 }
832 }
833}
834
835pub fn yank_roles(app: &App) {
836 use crate::app::copy_to_clipboard;
837 if app.view_mode == crate::app::ViewMode::PolicyView {
839 if !app.iam_state.policy_document.is_empty() {
840 copy_to_clipboard(&app.iam_state.policy_document);
841 }
842 return;
843 }
844 if app.iam_state.current_role.is_some() {
845 if let Some(role_name) = &app.iam_state.current_role {
846 if let Some(role) = app
847 .iam_state
848 .roles
849 .items
850 .iter()
851 .find(|r| r.role_name == *role_name)
852 {
853 copy_to_clipboard(&role.arn);
854 }
855 }
856 } else {
857 let filtered = filtered_iam_roles(app);
858 if let Some(role) = app.iam_state.roles.get_selected(&filtered) {
859 copy_to_clipboard(&role.arn);
860 }
861 }
862}
863
864pub fn yank_groups(app: &App) {
865 use crate::app::copy_to_clipboard;
866 use crate::iam;
867 if let Some(group_name) = &app.iam_state.current_group {
868 let arn = iam::format_arn(&app.config.account_id, "group", group_name);
869 copy_to_clipboard(&arn);
870 } else {
871 let filtered: Vec<_> = app
872 .iam_state
873 .groups
874 .items
875 .iter()
876 .filter(|g| {
877 app.iam_state.groups.filter.is_empty()
878 || g.group_name
879 .to_lowercase()
880 .contains(&app.iam_state.groups.filter.to_lowercase())
881 })
882 .collect();
883 if let Some(group) = app.iam_state.groups.get_selected(&filtered) {
884 let arn = iam::format_arn(&app.config.account_id, "group", &group.group_name);
885 copy_to_clipboard(&arn);
886 }
887 }
888}
889
890pub fn toggle_column_users(app: &mut App) {
893 use crate::app::{toggle_iam_page_size_only, toggle_iam_preference_static};
894 let idx = app.column_selector_index;
895 if app.iam_state.current_user.is_some() {
896 match app.iam_state.user_tab {
897 UserTab::Permissions => {
898 if idx > 0 && idx <= app.iam_policy_column_ids.len() {
899 if let Some(col) = app.iam_policy_column_ids.get(idx - 1) {
900 if let Some(pos) = app
901 .iam_policy_visible_column_ids
902 .iter()
903 .position(|c| c == col)
904 {
905 app.iam_policy_visible_column_ids.remove(pos);
906 } else {
907 app.iam_policy_visible_column_ids.push(col.clone());
908 }
909 }
910 } else if idx == app.iam_policy_column_ids.len() + 3 {
911 app.iam_state.policies.page_size = PageSize::Ten;
912 } else if idx == app.iam_policy_column_ids.len() + 4 {
913 app.iam_state.policies.page_size = PageSize::TwentyFive;
914 } else if idx == app.iam_policy_column_ids.len() + 5 {
915 app.iam_state.policies.page_size = PageSize::Fifty;
916 }
917 }
918 UserTab::Groups => toggle_iam_page_size_only(
919 idx,
920 5,
921 &mut app.iam_state.user_group_memberships.page_size,
922 ),
923 UserTab::Tags => {
924 toggle_iam_page_size_only(idx, 5, &mut app.iam_state.user_tags.page_size)
925 }
926 UserTab::LastAccessed => toggle_iam_page_size_only(
927 idx,
928 6,
929 &mut app.iam_state.last_accessed_services.page_size,
930 ),
931 _ => {}
932 }
933 } else {
934 toggle_iam_preference_static(
935 idx,
936 &app.iam_user_column_ids.clone(),
937 &mut app.iam_user_visible_column_ids,
938 &mut app.iam_state.users.page_size,
939 );
940 }
941}
942
943pub fn toggle_column_roles(app: &mut App) {
944 use crate::app::{
945 toggle_iam_page_size_only, toggle_iam_preference, toggle_iam_preference_static,
946 };
947 let idx = app.column_selector_index;
948 if app.iam_state.current_role.is_some() {
949 match app.iam_state.role_tab {
950 RoleTab::Permissions => toggle_iam_preference(
951 idx,
952 &app.iam_policy_column_ids.clone(),
953 &mut app.iam_policy_visible_column_ids,
954 &mut app.iam_state.policies.page_size,
955 ),
956 RoleTab::LastAccessed => toggle_iam_page_size_only(
957 idx,
958 6,
959 &mut app.iam_state.last_accessed_services.page_size,
960 ),
961 _ => {}
962 }
963 } else {
964 toggle_iam_preference_static(
965 idx,
966 &app.iam_role_column_ids.clone(),
967 &mut app.iam_role_visible_column_ids,
968 &mut app.iam_state.roles.page_size,
969 );
970 }
971}
972
973pub fn toggle_column_groups(app: &mut App) {
974 use crate::app::toggle_iam_preference;
975 toggle_iam_preference(
976 app.column_selector_index,
977 &app.iam_group_column_ids.clone(),
978 &mut app.iam_group_visible_column_ids,
979 &mut app.iam_state.groups.page_size,
980 );
981}
982
983pub fn next_preferences_users(app: &mut App) {
986 if app.iam_state.current_user.is_some() {
987 match app.iam_state.user_tab {
988 UserTab::Permissions => {
989 let page_size_idx = app.iam_policy_column_ids.len() + 2;
990 if app.column_selector_index < page_size_idx {
991 app.column_selector_index = page_size_idx;
992 } else {
993 app.column_selector_index = 0;
994 }
995 }
996 UserTab::Groups | UserTab::Tags => {
997 if app.column_selector_index < 4 {
998 app.column_selector_index = 4;
999 } else {
1000 app.column_selector_index = 0;
1001 }
1002 }
1003 UserTab::LastAccessed => {
1004 if app.column_selector_index < 5 {
1005 app.column_selector_index = 5;
1006 } else {
1007 app.column_selector_index = 0;
1008 }
1009 }
1010 _ => {}
1011 }
1012 } else {
1013 let page_size_idx = app.iam_user_column_ids.len() + 2;
1014 if app.column_selector_index < page_size_idx {
1015 app.column_selector_index = page_size_idx;
1016 } else {
1017 app.column_selector_index = 0;
1018 }
1019 }
1020}
1021
1022pub fn prev_preferences_users(app: &mut App) {
1023 if app.iam_state.current_user.is_some() {
1024 match app.iam_state.user_tab {
1025 UserTab::Permissions => {
1026 let page_size_idx = app.iam_policy_column_ids.len() + 2;
1027 if app.column_selector_index >= page_size_idx {
1028 app.column_selector_index = 0;
1029 } else {
1030 app.column_selector_index = page_size_idx;
1031 }
1032 }
1033 UserTab::Groups | UserTab::Tags => {
1034 if app.column_selector_index >= 4 {
1035 app.column_selector_index = 0;
1036 } else {
1037 app.column_selector_index = 4;
1038 }
1039 }
1040 UserTab::LastAccessed => {
1041 if app.column_selector_index >= 5 {
1042 app.column_selector_index = 0;
1043 } else {
1044 app.column_selector_index = 5;
1045 }
1046 }
1047 _ => {}
1048 }
1049 } else {
1050 let page_size_idx = app.iam_user_column_ids.len() + 2;
1051 if app.column_selector_index >= page_size_idx {
1052 app.column_selector_index = 0;
1053 } else {
1054 app.column_selector_index = page_size_idx;
1055 }
1056 }
1057}
1058
1059pub fn next_preferences_roles(app: &mut App) {
1060 if app.iam_state.current_role.is_some() {
1061 match app.iam_state.role_tab {
1062 RoleTab::Permissions => {
1063 let page_size_idx = app.iam_policy_column_ids.len() + 2;
1064 if app.column_selector_index < page_size_idx {
1065 app.column_selector_index = page_size_idx;
1066 } else {
1067 app.column_selector_index = 0;
1068 }
1069 }
1070 RoleTab::Tags => {
1071 if app.column_selector_index < 4 {
1072 app.column_selector_index = 4;
1073 } else {
1074 app.column_selector_index = 0;
1075 }
1076 }
1077 RoleTab::LastAccessed => {
1078 if app.column_selector_index < 5 {
1079 app.column_selector_index = 5;
1080 } else {
1081 app.column_selector_index = 0;
1082 }
1083 }
1084 _ => {}
1085 }
1086 } else {
1087 let page_size_idx = app.iam_role_column_ids.len() + 2;
1088 if app.column_selector_index < page_size_idx {
1089 app.column_selector_index = page_size_idx;
1090 } else {
1091 app.column_selector_index = 0;
1092 }
1093 }
1094}
1095
1096pub fn prev_preferences_roles(app: &mut App) {
1097 if app.iam_state.current_role.is_some() {
1098 match app.iam_state.role_tab {
1099 RoleTab::Permissions => {
1100 let page_size_idx = app.iam_policy_column_ids.len() + 2;
1101 if app.column_selector_index >= page_size_idx {
1102 app.column_selector_index = 0;
1103 } else {
1104 app.column_selector_index = page_size_idx;
1105 }
1106 }
1107 RoleTab::Tags => {
1108 if app.column_selector_index >= 4 {
1109 app.column_selector_index = 0;
1110 } else {
1111 app.column_selector_index = 4;
1112 }
1113 }
1114 RoleTab::LastAccessed => {
1115 if app.column_selector_index >= 5 {
1116 app.column_selector_index = 0;
1117 } else {
1118 app.column_selector_index = 5;
1119 }
1120 }
1121 _ => {}
1122 }
1123 } else {
1124 let page_size_idx = app.iam_role_column_ids.len() + 2;
1125 if app.column_selector_index >= page_size_idx {
1126 app.column_selector_index = 0;
1127 } else {
1128 app.column_selector_index = page_size_idx;
1129 }
1130 }
1131}
1132
1133pub fn next_preferences_groups(app: &mut App) {
1134 let page_size_idx = app.iam_group_column_ids.len() + 2;
1135 if app.column_selector_index < page_size_idx {
1136 app.column_selector_index = page_size_idx;
1137 } else {
1138 app.column_selector_index = 0;
1139 }
1140}
1141
1142pub fn prev_preferences_groups(app: &mut App) {
1143 let page_size_idx = app.iam_group_column_ids.len() + 2;
1144 if app.column_selector_index >= page_size_idx {
1145 app.column_selector_index = 0;
1146 } else {
1147 app.column_selector_index = page_size_idx;
1148 }
1149}
1150
1151pub fn column_selector_max_users(app: &App) -> usize {
1152 if app.iam_state.current_user.is_some() {
1153 app.iam_policy_column_ids.len() + 5
1154 } else {
1155 app.iam_user_column_ids.len() + 5
1156 }
1157}
1158
1159pub fn column_count_users(app: &App) -> usize {
1160 if app.iam_state.current_user.is_some() {
1161 app.iam_policy_column_ids.len()
1162 } else {
1163 app.iam_user_column_ids.len()
1164 }
1165}
1166
1167pub fn column_selector_max_roles(app: &App) -> usize {
1168 if app.iam_state.current_role.is_some() {
1169 app.iam_policy_column_ids.len() + 5
1170 } else {
1171 app.iam_role_column_ids.len() + 5
1172 }
1173}
1174
1175pub fn column_count_roles(app: &App) -> usize {
1176 if app.iam_state.current_role.is_some() {
1177 app.iam_policy_column_ids.len()
1178 } else {
1179 app.iam_role_column_ids.len()
1180 }
1181}
1182
1183pub fn column_selector_max_groups(app: &App) -> usize {
1184 app.iam_group_column_ids.len() + 5
1185}
1186
1187pub fn column_count_groups(app: &App) -> usize {
1188 app.iam_group_column_ids.len()
1189}
1190
1191pub fn breadcrumb_users() -> Vec<String> {
1194 vec!["IAM".to_string(), "Users".to_string()]
1195}
1196
1197pub fn breadcrumb_roles(app: &App) -> Vec<String> {
1198 let mut parts = vec!["IAM".to_string(), "Roles".to_string()];
1199 if let Some(role_name) = &app.iam_state.current_role {
1200 parts.push(role_name.clone());
1201 if let Some(policy_name) = &app.iam_state.current_policy {
1202 parts.push(policy_name.clone());
1203 }
1204 }
1205 parts
1206}
1207
1208pub fn breadcrumb_groups(app: &App) -> Vec<String> {
1209 let mut parts = vec!["IAM".to_string(), "User Groups".to_string()];
1210 if let Some(group_name) = &app.iam_state.current_group {
1211 parts.push(group_name.clone());
1212 }
1213 parts
1214}
1215
1216pub fn console_url_users(app: &App) -> String {
1217 use crate::iam;
1218 if let Some(user_name) = &app.iam_state.current_user {
1219 let section = match app.iam_state.user_tab {
1220 UserTab::Permissions => "permissions",
1221 UserTab::Groups => "groups",
1222 UserTab::Tags => "tags",
1223 UserTab::SecurityCredentials => "security_credentials",
1224 UserTab::LastAccessed => "access_advisor",
1225 };
1226 iam::console_url_user_detail(&app.config.region, user_name, section)
1227 } else {
1228 iam::console_url_users(&app.config.region)
1229 }
1230}
1231
1232pub fn console_url_roles(app: &App) -> String {
1233 use crate::iam;
1234 if let Some(policy_name) = &app.iam_state.current_policy {
1235 if let Some(role_name) = &app.iam_state.current_role {
1236 return iam::console_url_role_policy(&app.config.region, role_name, policy_name);
1237 }
1238 }
1239 if let Some(role_name) = &app.iam_state.current_role {
1240 let section = match app.iam_state.role_tab {
1241 RoleTab::Permissions => "permissions",
1242 RoleTab::TrustRelationships => "trust_relationships",
1243 RoleTab::Tags => "tags",
1244 RoleTab::LastAccessed => "access_advisor",
1245 RoleTab::RevokeSessions => "revoke_sessions",
1246 };
1247 iam::console_url_role_detail(&app.config.region, role_name, section)
1248 } else {
1249 iam::console_url_roles(&app.config.region)
1250 }
1251}
1252
1253pub fn console_url_groups(app: &App) -> String {
1254 use crate::iam;
1255 iam::console_url_groups(&app.config.region)
1256}