@@ -552,11 +552,39 @@ fn render_prompt_context(request: &ActiveRequest) -> String { |
| 552 | 552 | lines.push(format!("Icon: {}", request.icon_name.trim())); |
| 553 | 553 | } |
| 554 | 554 | |
| 555 | + if let Some(vendor) = first_detail_value( |
| 556 | + &request.details, |
| 557 | + &[ |
| 558 | + "vendor", |
| 559 | + "vendor_name", |
| 560 | + "polkit.vendor", |
| 561 | + "polkit.vendor_name", |
| 562 | + ], |
| 563 | + ) { |
| 564 | + lines.push(format!("Vendor: {}", vendor)); |
| 565 | + } |
| 566 | + |
| 567 | + if let Some(application) = first_detail_value( |
| 568 | + &request.details, |
| 569 | + &[ |
| 570 | + "application", |
| 571 | + "application_name", |
| 572 | + "program_name", |
| 573 | + "polkit.program_name", |
| 574 | + ], |
| 575 | + ) { |
| 576 | + lines.push(format!("Application: {}", application)); |
| 577 | + } |
| 578 | + |
| 555 | 579 | let detail_keys = [ |
| 556 | 580 | "program", |
| 581 | + "polkit.exec.path", |
| 582 | + "polkit.exec.argv1", |
| 557 | 583 | "command_line", |
| 558 | 584 | "unit", |
| 559 | 585 | "verb", |
| 586 | + "polkit.message", |
| 587 | + "polkit.gettext_domain", |
| 560 | 588 | "polkit.retains_authorization_after_challenge", |
| 561 | 589 | ]; |
| 562 | 590 | for key in detail_keys { |
@@ -688,12 +716,30 @@ fn identity_options_from_subjects(identities: &[Subject]) -> Vec<String> { |
| 688 | 716 | options |
| 689 | 717 | } |
| 690 | 718 | |
| 719 | +fn first_detail_value(details: &Details, keys: &[&str]) -> Option<String> { |
| 720 | + for key in keys { |
| 721 | + let Some(value) = details.get(*key) else { |
| 722 | + continue; |
| 723 | + }; |
| 724 | + let trimmed = value.trim(); |
| 725 | + if !trimmed.is_empty() { |
| 726 | + return Some(trimmed.to_string()); |
| 727 | + } |
| 728 | + } |
| 729 | + |
| 730 | + None |
| 731 | +} |
| 732 | + |
| 691 | 733 | fn detail_key_label(key: &str) -> &'static str { |
| 692 | 734 | match key { |
| 693 | 735 | "program" => "Program", |
| 736 | + "polkit.exec.path" => "Executable", |
| 737 | + "polkit.exec.argv1" => "Executable Arg", |
| 694 | 738 | "command_line" => "Command", |
| 695 | 739 | "unit" => "Unit", |
| 696 | 740 | "verb" => "Verb", |
| 741 | + "polkit.message" => "Policy Message", |
| 742 | + "polkit.gettext_domain" => "Text Domain", |
| 697 | 743 | "polkit.retains_authorization_after_challenge" => "Retains authorization", |
| 698 | 744 | _ => "Detail", |
| 699 | 745 | } |
@@ -1419,7 +1465,7 @@ mod tests { |
| 1419 | 1465 | let mut first_line = String::new(); |
| 1420 | 1466 | reader.read_line(&mut first_line).expect("read first line"); |
| 1421 | 1467 | let first = first_line.trim().to_string(); |
| 1422 | | - if first == "alice" { |
| 1468 | + if first == "operator" { |
| 1423 | 1469 | let mut cookie = String::new(); |
| 1424 | 1470 | reader.read_line(&mut cookie).expect("read cookie"); |
| 1425 | 1471 | } |
@@ -1459,8 +1505,8 @@ mod tests { |
| 1459 | 1505 | detail_count: 0, |
| 1460 | 1506 | details: HashMap::new(), |
| 1461 | 1507 | cookie: "cookie-1".to_string(), |
| 1462 | | - username: "alice".to_string(), |
| 1463 | | - identity_options: vec!["alice".to_string()], |
| 1508 | + username: "operator".to_string(), |
| 1509 | + identity_options: vec!["operator".to_string()], |
| 1464 | 1510 | }; |
| 1465 | 1511 | let mut prompts = SequencedPrompt::new(vec![ |
| 1466 | 1512 | PromptResponse::Submitted("correct horse".to_string()), |
@@ -1489,7 +1535,7 @@ mod tests { |
| 1489 | 1535 | |
| 1490 | 1536 | let mut first_line = String::new(); |
| 1491 | 1537 | reader.read_line(&mut first_line).expect("read first line"); |
| 1492 | | - if first_line.trim() == "alice" { |
| 1538 | + if first_line.trim() == "operator" { |
| 1493 | 1539 | let mut cookie = String::new(); |
| 1494 | 1540 | reader.read_line(&mut cookie).expect("read cookie"); |
| 1495 | 1541 | } |
@@ -1517,8 +1563,8 @@ mod tests { |
| 1517 | 1563 | detail_count: 0, |
| 1518 | 1564 | details: HashMap::new(), |
| 1519 | 1565 | cookie: "cookie-timeout".to_string(), |
| 1520 | | - username: "alice".to_string(), |
| 1521 | | - identity_options: vec!["alice".to_string()], |
| 1566 | + username: "operator".to_string(), |
| 1567 | + identity_options: vec!["operator".to_string()], |
| 1522 | 1568 | }; |
| 1523 | 1569 | let mut prompts = SequencedPrompt::new(vec![PromptResponse::TimedOut]); |
| 1524 | 1570 | |
@@ -1535,7 +1581,13 @@ mod tests { |
| 1535 | 1581 | #[test] |
| 1536 | 1582 | fn render_prompt_context_includes_policy_details() { |
| 1537 | 1583 | let mut details = HashMap::new(); |
| 1584 | + details.insert("vendor".to_string(), "Gardesk".to_string()); |
| 1585 | + details.insert("application_name".to_string(), "Meson".to_string()); |
| 1538 | 1586 | details.insert("program".to_string(), "/usr/bin/meson".to_string()); |
| 1587 | + details.insert( |
| 1588 | + "polkit.exec.path".to_string(), |
| 1589 | + "/usr/bin/pkexec".to_string(), |
| 1590 | + ); |
| 1539 | 1591 | details.insert("command_line".to_string(), "meson install".to_string()); |
| 1540 | 1592 | details.insert( |
| 1541 | 1593 | "polkit.retains_authorization_after_challenge".to_string(), |
@@ -1548,35 +1600,38 @@ mod tests { |
| 1548 | 1600 | detail_count: details.len(), |
| 1549 | 1601 | details, |
| 1550 | 1602 | cookie: "cookie-ctx".to_string(), |
| 1551 | | - username: "alice".to_string(), |
| 1552 | | - identity_options: vec!["alice".to_string()], |
| 1603 | + username: "operator".to_string(), |
| 1604 | + identity_options: vec!["operator".to_string()], |
| 1553 | 1605 | }; |
| 1554 | 1606 | |
| 1555 | 1607 | let context = render_prompt_context(&request); |
| 1556 | 1608 | assert!(context.contains("Authentication is required to install this project")); |
| 1557 | 1609 | assert!(context.contains("Action: com.mesonbuild.install.run")); |
| 1558 | 1610 | assert!(context.contains("Icon: preferences-system")); |
| 1611 | + assert!(context.contains("Vendor: Gardesk")); |
| 1612 | + assert!(context.contains("Application: Meson")); |
| 1559 | 1613 | assert!(context.contains("Program: /usr/bin/meson")); |
| 1614 | + assert!(context.contains("Executable: /usr/bin/pkexec")); |
| 1560 | 1615 | assert!(context.contains("Command: meson install")); |
| 1561 | 1616 | assert!(context.contains("Retains authorization: 1")); |
| 1562 | 1617 | } |
| 1563 | 1618 | |
| 1564 | 1619 | #[test] |
| 1565 | 1620 | fn parse_identity_selection_accepts_blank_index_and_name() { |
| 1566 | | - let options = vec!["alice".to_string(), "root".to_string()]; |
| 1621 | + let options = vec!["operator".to_string(), "root".to_string()]; |
| 1567 | 1622 | assert_eq!( |
| 1568 | | - parse_identity_selection("", &options, "alice"), |
| 1569 | | - Some("alice".to_string()) |
| 1623 | + parse_identity_selection("", &options, "operator"), |
| 1624 | + Some("operator".to_string()) |
| 1570 | 1625 | ); |
| 1571 | 1626 | assert_eq!( |
| 1572 | | - parse_identity_selection("2", &options, "alice"), |
| 1627 | + parse_identity_selection("2", &options, "operator"), |
| 1573 | 1628 | Some("root".to_string()) |
| 1574 | 1629 | ); |
| 1575 | 1630 | assert_eq!( |
| 1576 | | - parse_identity_selection("ROOT", &options, "alice"), |
| 1631 | + parse_identity_selection("ROOT", &options, "operator"), |
| 1577 | 1632 | Some("root".to_string()) |
| 1578 | 1633 | ); |
| 1579 | | - assert_eq!(parse_identity_selection("99", &options, "alice"), None); |
| 1634 | + assert_eq!(parse_identity_selection("99", &options, "operator"), None); |
| 1580 | 1635 | } |
| 1581 | 1636 | |
| 1582 | 1637 | #[test] |
@@ -1588,8 +1643,8 @@ mod tests { |
| 1588 | 1643 | detail_count: 0, |
| 1589 | 1644 | details: HashMap::new(), |
| 1590 | 1645 | cookie: "cookie-identity".to_string(), |
| 1591 | | - username: "alice".to_string(), |
| 1592 | | - identity_options: vec!["alice".to_string(), "root".to_string()], |
| 1646 | + username: "operator".to_string(), |
| 1647 | + identity_options: vec!["operator".to_string(), "root".to_string()], |
| 1593 | 1648 | }; |
| 1594 | 1649 | let mut prompts = SequencedPrompt::new(vec![PromptResponse::Submitted("2".to_string())]); |
| 1595 | 1650 | |
@@ -1610,8 +1665,8 @@ mod tests { |
| 1610 | 1665 | detail_count: 0, |
| 1611 | 1666 | details: HashMap::new(), |
| 1612 | 1667 | cookie: "cookie-identity-cancel".to_string(), |
| 1613 | | - username: "alice".to_string(), |
| 1614 | | - identity_options: vec!["alice".to_string(), "root".to_string()], |
| 1668 | + username: "operator".to_string(), |
| 1669 | + identity_options: vec!["operator".to_string(), "root".to_string()], |
| 1615 | 1670 | }; |
| 1616 | 1671 | let mut prompts = SequencedPrompt::new(vec![PromptResponse::Canceled]); |
| 1617 | 1672 | |