use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum SecurityProfile {
ReadonlyDashboard,
StandardDashboard,
AccountSettings,
}
impl SecurityProfile {
pub fn permissions(self) -> &'static [&'static str] {
match self {
Self::ReadonlyDashboard => &[
"core:default",
"core:event:allow-listen",
"core:event:allow-unlisten",
],
Self::StandardDashboard => &[
"core:default",
"core:event:allow-listen",
"core:event:allow-unlisten",
],
Self::AccountSettings => &[
"core:default",
"core:event:allow-listen",
"core:event:allow-unlisten",
"core:window:allow-close",
],
}
}
pub fn identifier(self) -> &'static str {
match self {
Self::ReadonlyDashboard => "readonly-dashboard",
Self::StandardDashboard => "standard-dashboard",
Self::AccountSettings => "account-settings",
}
}
pub fn description(self) -> &'static str {
match self {
Self::ReadonlyDashboard => {
"Reads application state and receives platform events. No filesystem, \
no shell, no process execution."
}
Self::StandardDashboard => {
"Main window: reads application state and receives platform events. No \
filesystem, no shell, no process execution."
}
Self::AccountSettings => {
"Settings window: manages accounts through commands. Credentials never \
reach the frontend."
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn no_profile_grants_filesystem_shell_or_process_access() {
for profile in [
SecurityProfile::ReadonlyDashboard,
SecurityProfile::StandardDashboard,
SecurityProfile::AccountSettings,
] {
for permission in profile.permissions() {
assert!(
!permission.starts_with("fs:")
&& !permission.starts_with("shell:")
&& !permission.starts_with("process:"),
"{} grants {permission}",
profile.identifier()
);
}
}
}
#[test]
fn profiles_round_trip_through_the_manifest_format() {
let parsed: SecurityProfile = toml::from_str("value = \"account-settings\"")
.map(|table: toml::Table| table["value"].clone())
.map(|value| value.try_into().unwrap())
.unwrap();
assert_eq!(parsed, SecurityProfile::AccountSettings);
assert_eq!(parsed.identifier(), "account-settings");
}
}