@smbcloud / cli / commits / 4287896

Handle expired session on logout and clear token on 401

- Treat 401 Unauthorized during logout as success since the session is already expired on the server - Clear the local token and show a helpful message when any command fails with "Unauthorized access." - Add clear_smb_token helper to remove the token file for an environment

keypair34 committed Apr 6, 2026 at 22:47 UTC 4287896a8a2186bb4b5751a52b4db59f031f132a
5 files changed +42 -10
crates/cli/src/account/logout/mod.rs
+9 -1
@@ -70,6 +70,14 @@ async fn do_process_logout(env: Environment) -> Result<()> {
70 let token = get_smb_token(env)?;
71 match logout(env, client(), token).await {
72 Ok(_) => Ok(()),
73 - Err(e) => Err(anyhow!("{e}")),
73 + Err(e) => {
74 + // A 401 means the session is already expired on the server.
75 + // Treat this as success — the session is gone either way.
76 + if e.to_string().contains("Unauthorized") {
77 + Ok(())
78 + } else {
79 + Err(anyhow!("{e}"))
80 + }
81 + }
82 }
83 }
crates/cli/src/lib.rs
+2
@@ -7,6 +7,8 @@ pub mod project;
7 mod token;
8 mod ui;
9
10 +pub use token::clear_smb_token::clear_smb_token;
11 +
12 pub(crate) fn client() -> (&'static SmbClient, &'static str) {
13 let secret = env!("CLI_CLIENT_SECRET");
14 (&SmbClient::Cli, secret)
crates/cli/src/main.rs
+19 -9
@@ -4,6 +4,7 @@ use {
4 console::style,
5 smbcloud_cli::{
6 account::{login::process_login, logout::process_logout, me::process_me, process_account},
7 + clear_smb_token,
8 cli::{Cli, CommandResult, Commands},
9 deploy::process_deploy::process_deploy,
10 project::{crud_create::process_project_init, process::process_project},
@@ -72,25 +73,34 @@ fn setup_logging(env: Environment, level: Option<EnvFilter>) -> Result<()> {
73
74 #[tokio::main]
75 async fn main() {
75 - match run().await {
76 + let cli = Cli::parse();
77 + let environment = cli.environment;
78 + match run(cli).await {
79 Ok(result) => {
80 result.stop_and_persist();
81 std::process::exit(0);
82 }
83 Err(e) => {
81 - println!(
82 - "\n{} {}",
83 - style("✘".to_string()).for_stderr().red(),
84 - style(e).red()
85 - );
84 + if e.to_string().contains("Unauthorized access.") {
85 + let _ = clear_smb_token(environment);
86 + println!(
87 + "\n{} {}",
88 + style("✘".to_string()).for_stderr().red(),
89 + style("Your session has expired. Please login again with `smb login`.").red()
90 + );
91 + } else {
92 + println!(
93 + "\n{} {}",
94 + style("✘".to_string()).for_stderr().red(),
95 + style(e).red()
96 + );
97 + }
98 std::process::exit(1);
99 }
100 }
101 }
102
91 -async fn run() -> Result<CommandResult> {
92 - let cli = Cli::parse();
93 -
103 +async fn run(cli: Cli) -> Result<CommandResult> {
104 // println!("Environment: {}", cli.environment);
105
106 let log_level_error: Result<CommandResult> = Err(anyhow!(
crates/cli/src/token/clear_smb_token.rs new
+11
@@ -0,0 +1,11 @@
1 +use {
2 + crate::token::smb_token_file_path::smb_token_file_path, anyhow::Result,
3 + smbcloud_network::environment::Environment, std::fs,
4 +};
5 +
6 +pub fn clear_smb_token(env: Environment) -> Result<()> {
7 + if let Some(path) = smb_token_file_path(env) {
8 + fs::remove_file(path)?;
9 + }
10 + Ok(())
11 +}
crates/cli/src/token/mod.rs
+1
@@ -1,3 +1,4 @@
1 +pub(crate) mod clear_smb_token;
2 pub(crate) mod get_smb_token;
3 pub(crate) mod is_logged_in;
4 pub(crate) mod smb_token_file_path;