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.
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,
}
@ -65,12 +72,25 @@ impl AuthCommand {
crate::keys::LoginInfo::Application {
name: user,
token: key,
api_url: host_url.clone(),
},
);
} else {
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 => {
if keys.hosts.is_empty() {
println!("No logins.");
@ -173,6 +193,7 @@ async fn oauth_login(
token: response.access_token,
refresh_token: response.refresh_token,
expires_at,
api_url: host.clone(),
};
let domain = crate::host_with_port(&host);
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> {
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 {
name: String,
token: String,
api_url: Url,
},
OAuth {
name: String,
token: String,
refresh_token: String,
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 {
LoginInfo::Application { token, .. } => {
let api = forgejo_api::Forgejo::new(forgejo_api::Auth::Token(token), url.clone())?;
LoginInfo::Application { token, api_url, .. } => {
let api =
forgejo_api::Forgejo::new(forgejo_api::Auth::Token(token), api_url.clone())?;
Ok(api)
}
LoginInfo::OAuth {
token,
refresh_token,
expires_at,
api_url,
..
} => {
if time::OffsetDateTime::now_utc() >= *expires_at {
let api = forgejo_api::Forgejo::new(forgejo_api::Auth::None, url.clone())?;
let (client_id, client_secret) = crate::auth::get_client_info_for(url)
let api = forgejo_api::Forgejo::new(forgejo_api::Auth::None, api_url.clone())?;
let (client_id, client_secret) = crate::auth::get_client_info_for(api_url)
.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
.oauth_get_access_token(forgejo_api::structs::OAuthTokenRequest::Refresh {
@ -113,7 +117,8 @@ impl LoginInfo {
);
*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)
}
}