Skip to content

Commit c5fa5d6

Browse files
Fix spacetime login --token falling through to web login (#4579)
## Bug PR #4367 (login/logout UX overhaul) accidentally removed the early `return Ok(())` after saving a token via `spacetime login --token`. This caused the command to fall through into the web login flow (`spacetimedb_login_and_save`), which fails when no browser or server is available. ## Impact All tests that use `spacetime login --token` are broken: - 4 replication tests (`test_enable_disable_replication`, `test_enable_replication_on_suspended_database`, `test_enable_replication_fails_if_not_suspended`, `test_prefer_leader`) - 5 teams tests (`test_permissions_clear_org`, `test_permissions_delete_org`, `test_org_permissions_mut_sql_org_members`, `test_org_permissions_private_tables`, `test_permissions_publish_org_members`) ## Fix One line: restore `return Ok(())` after the `--token` branch. --------- Signed-off-by: Zeke Foppa <196249+bfops@users.noreply.github.com> Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com> Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com> Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
1 parent 154287c commit c5fa5d6

2 files changed

Lines changed: 61 additions & 0 deletions

File tree

crates/cli/src/subcommands/login.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ pub async fn exec(mut config: Config, args: &ArgMatches) -> Result<(), anyhow::E
7171
Ok(identity) => println!("Logged in with identity {identity}"),
7272
Err(_) => println!("Token saved."),
7373
}
74+
return Ok(());
7475
}
7576

7677
if let Some(server) = server_issued_login {

crates/smoketests/tests/smoketests/cli/auth.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use spacetimedb_smoketests::{require_local_server, Smoketest};
44
use std::fs;
55
use std::process::Output;
6+
use std::time::{Duration, Instant};
67

78
fn output_stdout(output: &Output) -> String {
89
String::from_utf8_lossy(&output.stdout).to_string()
@@ -170,3 +171,62 @@ fn cli_logging_in_twice_works() {
170171
second_stdout
171172
);
172173
}
174+
175+
fn try_until_timeout<F: FnMut() -> Option<R>, R>(timeout: Duration, mut f: F) -> Option<R> {
176+
let start = Instant::now();
177+
loop {
178+
match f() {
179+
Some(result) => return Some(result),
180+
None => {
181+
if start.elapsed() > timeout {
182+
return None;
183+
}
184+
std::thread::sleep(std::time::Duration::from_millis(200));
185+
}
186+
}
187+
}
188+
}
189+
190+
/// Test that `spacetime login --token <token>` exits immediately after saving
191+
/// the token, without falling through to the interactive web login flow.
192+
///
193+
/// Without the fix in PR #4579, the command would fall through to the web
194+
/// login flow, which hangs waiting for a browser callback.
195+
#[test]
196+
fn cli_login_with_token() {
197+
use std::io::Read;
198+
use std::process::{Command, Stdio};
199+
200+
let test = Smoketest::builder().autopublish(false).build();
201+
let cli_path = spacetimedb_guard::ensure_binaries_built();
202+
203+
let mut child = Command::new(&cli_path)
204+
.arg("--config-path")
205+
.arg(&test.config_path)
206+
.args(["login", "--token", "test-dummy-token", "--no-browser"])
207+
.env_remove("BROWSER")
208+
.stdout(Stdio::piped())
209+
.stderr(Stdio::piped())
210+
.spawn()
211+
.expect("Failed to spawn spacetime login");
212+
213+
// Run with timeout in case something goes wrong and it tries to open the browser for login.
214+
let timeout = Duration::from_secs(5);
215+
let Some(status) = try_until_timeout(timeout, || child.try_wait().expect("Failed to poll child")) else {
216+
child.kill().ok();
217+
panic!(
218+
"spacetime login --token hung for >{timeout:?} — \
219+
likely fell through to web login flow"
220+
);
221+
};
222+
let mut stdout = String::new();
223+
child.stdout.take().unwrap().read_to_string(&mut stdout).unwrap();
224+
assert!(
225+
status.success(),
226+
"spacetime login --token failed (exit {status}):\n{stdout}"
227+
);
228+
assert!(
229+
stdout.contains("Token saved."),
230+
"Expected 'Token saved.' in output, got: {stdout}"
231+
);
232+
}

0 commit comments

Comments
 (0)