sesame/
profile.rs

1use anyhow::Context;
2use comfy_table::{Table, presets::UTF8_FULL};
3use core_types::{EventKind, ProfileId, SecurityLevel, TrustProfileName};
4use owo_colors::OwoColorize;
5
6use crate::ipc::{connect, rpc};
7
8pub(crate) async fn cmd_profile_list() -> anyhow::Result<()> {
9    let client = connect().await?;
10
11    match rpc(&client, EventKind::ProfileList, SecurityLevel::Internal).await? {
12        EventKind::ProfileListResponse { profiles } => {
13            if profiles.is_empty() {
14                println!("{}", "No profiles configured.".dimmed());
15                return Ok(());
16            }
17
18            let mut table = Table::new();
19            table.load_preset(UTF8_FULL);
20            table.set_header(vec!["Name", "Active", "Default"]);
21
22            for p in &profiles {
23                let active = if p.is_active {
24                    "yes".green().to_string()
25                } else {
26                    "no".dimmed().to_string()
27                };
28                let default = if p.is_default {
29                    "yes".green().to_string()
30                } else {
31                    "".to_string()
32                };
33                let name_str = p.name.to_string();
34                table.add_row(vec![&name_str, &active, &default]);
35            }
36
37            println!("{table}");
38        }
39        other => anyhow::bail!("unexpected response: {other:?}"),
40    }
41
42    Ok(())
43}
44
45pub(crate) async fn cmd_profile_activate(name: &str) -> anyhow::Result<()> {
46    let client = connect().await?;
47    let profile_name = TrustProfileName::try_from(name).map_err(|e| anyhow::anyhow!("{e}"))?;
48
49    let event = EventKind::ProfileActivate {
50        target: ProfileId::new(),
51        profile_name,
52    };
53
54    match rpc(&client, event, SecurityLevel::Internal).await? {
55        EventKind::ProfileActivateResponse { success: true } => {
56            println!("Profile '{}' activated.", name.green());
57        }
58        EventKind::ProfileActivateResponse { success: false } => {
59            anyhow::bail!("failed to activate profile '{name}'");
60        }
61        other => anyhow::bail!("unexpected response: {other:?}"),
62    }
63
64    Ok(())
65}
66
67pub(crate) async fn cmd_profile_deactivate(name: &str) -> anyhow::Result<()> {
68    let client = connect().await?;
69    let profile_name = TrustProfileName::try_from(name).map_err(|e| anyhow::anyhow!("{e}"))?;
70
71    let event = EventKind::ProfileDeactivate {
72        target: ProfileId::new(),
73        profile_name,
74    };
75
76    match rpc(&client, event, SecurityLevel::Internal).await? {
77        EventKind::ProfileDeactivateResponse { success: true } => {
78            println!("Profile '{}' deactivated.", name.green());
79        }
80        EventKind::ProfileDeactivateResponse { success: false } => {
81            anyhow::bail!("failed to deactivate profile '{name}' — not active?");
82        }
83        other => anyhow::bail!("unexpected response: {other:?}"),
84    }
85
86    Ok(())
87}
88
89pub(crate) async fn cmd_profile_default(name: &str) -> anyhow::Result<()> {
90    let client = connect().await?;
91    let profile_name = TrustProfileName::try_from(name).map_err(|e| anyhow::anyhow!("{e}"))?;
92
93    let event = EventKind::SetDefaultProfile { profile_name };
94
95    match rpc(&client, event, SecurityLevel::Internal).await? {
96        EventKind::SetDefaultProfileResponse { success: true } => {
97            println!("Default profile set to '{}'.", name.green());
98        }
99        EventKind::SetDefaultProfileResponse { success: false } => {
100            anyhow::bail!("failed to set default profile to '{name}'");
101        }
102        other => anyhow::bail!("unexpected response: {other:?}"),
103    }
104
105    Ok(())
106}
107
108pub(crate) fn cmd_profile_show(name: &str) -> anyhow::Result<()> {
109    let config = core_config::load_config(None).context("failed to load config")?;
110
111    let profile = config
112        .profiles
113        .get(name)
114        .ok_or_else(|| anyhow::anyhow!("profile '{name}' not found in config"))?;
115
116    let toml_str = toml::to_string_pretty(profile).context("failed to serialize profile config")?;
117
118    println!("Profile: {}", name.bold());
119    if name == config.global.default_profile.as_ref() {
120        println!("(default profile)");
121    }
122    println!();
123    println!("{toml_str}");
124
125    Ok(())
126}