use anyhow::{anyhow, ensure, Result};
use clap::Parser;
use serde_json::Value;
use crate::state::http::HttpClient;
use crate::state::State;
use crate::store::context::Context;
use crate::store::Store;
#[derive(Debug, Parser)]
#[clap(about = "Logout the current user")]
#[group(skip)]
pub struct Options {}
pub async fn handle(_options: Options, mut state: State) -> Result<()> {
let user_id = state.ctx.default_user;
ensure!(user_id.is_some(), "You are not logged in.");
invalidate_token(
&state.http,
state
.auth
.authorized
.get(user_id.as_ref().unwrap())
.unwrap(),
)
.await?;
state.ctx = Context::default();
state.ctx.save().await?;
state.auth.authorized.remove(user_id.as_ref().unwrap());
state.auth.save().await?;
log::info!("You have been logged out");
Ok(())
}
async fn invalidate_token(http: &HttpClient, token: &str) -> Result<()> {
match token.split('_').next() {
Some("bearer") => {
http.request::<Value>("POST", "/auth/logout", None).await?;
}
Some("pat") => {
http.request::<Value>("DELETE", &format!("/users/@me/pats/{token}"), None)
.await?;
}
Some("ptk") => {
log::warn!(
"Project tokens are not invalidated on logout, please revoke them manually."
);
}
_ => {
return Err(anyhow!("Unknown token type"));
}
}
Ok(())
}