1use sim_kernel::{CapabilityName, Cx, GrantSeat};
4
5use crate::OfficeError;
6
7pub const NET_CONNECT_CAPABILITY: &str = "net-connect";
9pub const PROCESS_SPAWN_CAPABILITY: &str = "process-spawn";
11pub const WALL_CLOCK_CAPABILITY: &str = "wall-clock";
13pub const CREDENTIALS_CAPABILITY: &str = "credentials";
15
16pub struct OfficeCapabilityProfile;
18
19macro_rules! grant_into_result {
20 ($grant:expr) => {{
21 #[allow(clippy::let_unit_value)]
22 let grant_result = $grant;
23 #[allow(clippy::unit_arg)]
24 grant_result.into_result()
25 }};
26}
27
28impl OfficeCapabilityProfile {
29 #[must_use]
31 pub fn granted() -> Vec<CapabilityName> {
32 Vec::new()
33 }
34
35 #[must_use]
37 pub fn denied() -> Vec<CapabilityName> {
38 [
39 NET_CONNECT_CAPABILITY,
40 PROCESS_SPAWN_CAPABILITY,
41 WALL_CLOCK_CAPABILITY,
42 CREDENTIALS_CAPABILITY,
43 ]
44 .into_iter()
45 .map(CapabilityName::new)
46 .collect()
47 }
48
49 pub fn seat(seat: &GrantSeat, cx: &mut Cx) -> Result<(), OfficeError> {
51 for capability in Self::granted() {
52 grant_into_result!(seat.grant(cx, capability))?;
53 }
54 Ok(())
55 }
56}
57
58trait GrantOutcome {
59 fn into_result(self) -> Result<(), OfficeError>;
60}
61
62impl GrantOutcome for () {
63 fn into_result(self) -> Result<(), OfficeError> {
64 Ok(())
65 }
66}
67
68impl GrantOutcome for sim_kernel::Result<()> {
69 fn into_result(self) -> Result<(), OfficeError> {
70 self.map_err(OfficeError::from)
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use std::sync::Arc;
77
78 use sim_kernel::{DefaultFactory, NoopEvalPolicy};
79
80 use super::*;
81
82 #[test]
83 fn default_profile_denies_live_capabilities() {
84 let denied: Vec<_> = OfficeCapabilityProfile::denied()
85 .into_iter()
86 .map(|capability| capability.as_str().to_owned())
87 .collect();
88
89 assert_eq!(
90 denied,
91 vec![
92 NET_CONNECT_CAPABILITY,
93 PROCESS_SPAWN_CAPABILITY,
94 WALL_CLOCK_CAPABILITY,
95 CREDENTIALS_CAPABILITY,
96 ]
97 );
98 assert!(OfficeCapabilityProfile::granted().is_empty());
99 }
100
101 #[test]
102 fn seating_default_profile_does_not_grant_live_network() {
103 let (mut cx, seat) = sim_kernel::Cx::new_seated(
104 Arc::new(NoopEvalPolicy),
105 Arc::new(DefaultFactory),
106 sim_kernel::HandleSeed::new(0xce27_937d_0a0a_e3ea),
107 );
108
109 OfficeCapabilityProfile::seat(&seat, &mut cx).unwrap();
110
111 let network = CapabilityName::new(NET_CONNECT_CAPABILITY);
112 assert!(cx.require(&network).is_err());
113 }
114}