feat: add api_url field to keys file

This commit is contained in:
Cyborus 2024-08-30 12:46:02 -04:00
parent f8650ab284
commit 555d237a47
No known key found for this signature in database
2 changed files with 34 additions and 8 deletions

View file

@ -18,6 +18,13 @@ pub enum AuthCommand {
/// The key to add. If not present, the key will be read in from stdin. /// The key to add. If not present, the key will be read in from stdin.
key: Option<String>, key: Option<String>,
}, },
SetApiUrl {
/// Sets the URL to access for API calls for this host.
///
/// This can be useful if the api is hosted on a subdomain, or if the
/// ssh and http access are on different domains.
url: url::Url,
},
/// List all instances you're currently logged into /// List all instances you're currently logged into
List, List,
} }
@ -65,12 +72,25 @@ impl AuthCommand {
crate::keys::LoginInfo::Application { crate::keys::LoginInfo::Application {
name: user, name: user,
token: key, token: key,
api_url: host_url.clone(),
}, },
); );
} else { } else {
println!("key for {host} already exists"); println!("key for {host} already exists");
} }
} }
AuthCommand::SetApiUrl { url } => {
let repo_info = crate::repo::RepoInfo::get_current(host_name, None, None)?;
let host_url = repo_info.host_url();
let host = crate::host_with_port(&host_url);
match keys.hosts.get_mut(host) {
Some(key_info) => match key_info {
crate::LoginInfo::OAuth { api_url, .. } => *api_url = url,
crate::LoginInfo::Application { api_url, .. } => *api_url = url,
},
None => println!("Not signed in to {host}"),
}
}
AuthCommand::List => { AuthCommand::List => {
if keys.hosts.is_empty() { if keys.hosts.is_empty() {
println!("No logins."); println!("No logins.");
@ -173,6 +193,7 @@ async fn oauth_login(
token: response.access_token, token: response.access_token,
refresh_token: response.refresh_token, refresh_token: response.refresh_token,
expires_at, expires_at,
api_url: host.clone(),
}; };
let domain = crate::host_with_port(&host); let domain = crate::host_with_port(&host);
keys.hosts.insert(domain.to_owned(), login_info); keys.hosts.insert(domain.to_owned(), login_info);

View file

@ -52,7 +52,7 @@ impl KeyInfo {
} }
pub async fn get_api(&mut self, url: &Url) -> eyre::Result<forgejo_api::Forgejo> { pub async fn get_api(&mut self, url: &Url) -> eyre::Result<forgejo_api::Forgejo> {
self.get_login(url)?.api_for(url).await.map_err(Into::into) self.get_login(url)?.api_for().await.map_err(Into::into)
} }
} }
@ -62,12 +62,14 @@ pub enum LoginInfo {
Application { Application {
name: String, name: String,
token: String, token: String,
api_url: Url,
}, },
OAuth { OAuth {
name: String, name: String,
token: String, token: String,
refresh_token: String, refresh_token: String,
expires_at: time::OffsetDateTime, expires_at: time::OffsetDateTime,
api_url: Url,
}, },
} }
@ -79,23 +81,25 @@ impl LoginInfo {
} }
} }
pub async fn api_for(&mut self, url: &Url) -> eyre::Result<forgejo_api::Forgejo> { pub async fn api_for(&mut self) -> eyre::Result<forgejo_api::Forgejo> {
match self { match self {
LoginInfo::Application { token, .. } => { LoginInfo::Application { token, api_url, .. } => {
let api = forgejo_api::Forgejo::new(forgejo_api::Auth::Token(token), url.clone())?; let api =
forgejo_api::Forgejo::new(forgejo_api::Auth::Token(token), api_url.clone())?;
Ok(api) Ok(api)
} }
LoginInfo::OAuth { LoginInfo::OAuth {
token, token,
refresh_token, refresh_token,
expires_at, expires_at,
api_url,
.. ..
} => { } => {
if time::OffsetDateTime::now_utc() >= *expires_at { if time::OffsetDateTime::now_utc() >= *expires_at {
let api = forgejo_api::Forgejo::new(forgejo_api::Auth::None, url.clone())?; let api = forgejo_api::Forgejo::new(forgejo_api::Auth::None, api_url.clone())?;
let (client_id, client_secret) = crate::auth::get_client_info_for(url) let (client_id, client_secret) = crate::auth::get_client_info_for(api_url)
.ok_or_else(|| { .ok_or_else(|| {
eyre::eyre!("Can't refresh token; no client info for {url}. How did this happen?") eyre::eyre!("Can't refresh token; no client info for {api_url}. How did this happen?")
})?; })?;
let response = api let response = api
.oauth_get_access_token(forgejo_api::structs::OAuthTokenRequest::Refresh { .oauth_get_access_token(forgejo_api::structs::OAuthTokenRequest::Refresh {
@ -113,7 +117,8 @@ impl LoginInfo {
); );
*expires_at = time::OffsetDateTime::now_utc() + expires_in; *expires_at = time::OffsetDateTime::now_utc() + expires_in;
} }
let api = forgejo_api::Forgejo::new(forgejo_api::Auth::Token(token), url.clone())?; let api =
forgejo_api::Forgejo::new(forgejo_api::Auth::Token(token), api_url.clone())?;
Ok(api) Ok(api)
} }
} }