mirror of
https://codeberg.org/Cyborus/forgejo-cli.git
synced 2024-11-23 18:31:46 +01:00
implement fj auth login
This commit is contained in:
parent
c47a24ad22
commit
3ff6a86e8e
4 changed files with 396 additions and 16 deletions
237
Cargo.lock
generated
237
Cargo.lock
generated
|
@ -65,6 +65,23 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-waker"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||
|
||||
[[package]]
|
||||
name = "auth-git2"
|
||||
version = "0.5.4"
|
||||
|
@ -121,6 +138,15 @@ version = "2.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.16.0"
|
||||
|
@ -212,6 +238,25 @@ version = "0.8.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
|
@ -222,6 +267,16 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "directories"
|
||||
version = "5.0.1"
|
||||
|
@ -298,15 +353,20 @@ name = "fj"
|
|||
version = "0.0.4"
|
||||
dependencies = [
|
||||
"auth-git2",
|
||||
"base64ct",
|
||||
"clap",
|
||||
"directories",
|
||||
"eyre",
|
||||
"forgejo-api",
|
||||
"futures",
|
||||
"git2",
|
||||
"hyper 1.3.1",
|
||||
"hyper-util",
|
||||
"open",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha256",
|
||||
"soft_assert",
|
||||
"time",
|
||||
"tokio",
|
||||
|
@ -452,6 +512,16 @@ dependencies = [
|
|||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.14"
|
||||
|
@ -495,7 +565,26 @@ dependencies = [
|
|||
"futures-core",
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http 0.2.12",
|
||||
"indexmap",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab"
|
||||
dependencies = [
|
||||
"atomic-waker",
|
||||
"bytes",
|
||||
"fnv",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"http 1.1.0",
|
||||
"indexmap",
|
||||
"slab",
|
||||
"tokio",
|
||||
|
@ -521,6 +610,12 @@ version = "0.3.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.12"
|
||||
|
@ -532,6 +627,17 @@ dependencies = [
|
|||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "0.4.6"
|
||||
|
@ -539,10 +645,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http",
|
||||
"http 0.2.12",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.8.0"
|
||||
|
@ -565,9 +681,9 @@ dependencies = [
|
|||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"h2 0.3.26",
|
||||
"http 0.2.12",
|
||||
"http-body 0.4.6",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
|
@ -579,6 +695,26 @@ dependencies = [
|
|||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "1.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"h2 0.4.5",
|
||||
"http 1.1.0",
|
||||
"http-body 1.0.0",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"smallvec",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-tls"
|
||||
version = "0.5.0"
|
||||
|
@ -586,12 +722,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"hyper",
|
||||
"hyper 0.14.28",
|
||||
"native-tls",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http 1.1.0",
|
||||
"http-body 1.0.0",
|
||||
"hyper 1.3.1",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.5.0"
|
||||
|
@ -962,6 +1113,12 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.81"
|
||||
|
@ -980,6 +1137,36 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.1"
|
||||
|
@ -1011,10 +1198,10 @@ dependencies = [
|
|||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"hyper",
|
||||
"h2 0.3.26",
|
||||
"http 0.2.12",
|
||||
"http-body 0.4.6",
|
||||
"hyper 0.14.28",
|
||||
"hyper-tls",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
|
@ -1156,6 +1343,30 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha256"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18278f6a914fa3070aa316493f7d2ddfb9ac86ebc06fa3b83bffda487e9065b0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"hex",
|
||||
"sha2",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.2"
|
||||
|
@ -1413,6 +1624,12 @@ version = "0.2.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.7.0"
|
||||
|
|
|
@ -7,15 +7,20 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
auth-git2 = "0.5.3"
|
||||
base64ct = { version = "1.6.0", features = ["std"] }
|
||||
clap = { version = "4.3.11", features = ["derive"] }
|
||||
directories = "5.0.1"
|
||||
eyre = "0.6.8"
|
||||
forgejo-api = "0.3.0"
|
||||
futures = "0.3.28"
|
||||
git2 = "0.17.2"
|
||||
hyper = "1.3.1"
|
||||
hyper-util = { version = "0.1.5", features = ["tokio", "server", "http1", "http2"] }
|
||||
open = "5.0.0"
|
||||
rand = "0.8.5"
|
||||
serde = { version = "1.0.170", features = ["derive"] }
|
||||
serde_json = "1.0.100"
|
||||
sha256 = "1.5.0"
|
||||
soft_assert = "0.1.1"
|
||||
time = { version = "0.3.30", features = ["formatting", "macros"] }
|
||||
tokio = { version = "1.29.1", features = ["full"] }
|
||||
|
|
168
src/auth.rs
168
src/auth.rs
|
@ -1,4 +1,5 @@
|
|||
use clap::Subcommand;
|
||||
use eyre::OptionExt;
|
||||
|
||||
#[derive(Subcommand, Clone, Debug)]
|
||||
pub enum AuthCommand {
|
||||
|
@ -18,12 +19,28 @@ pub enum AuthCommand {
|
|||
}
|
||||
|
||||
impl AuthCommand {
|
||||
pub async fn run(self, keys: &mut crate::KeyInfo) -> eyre::Result<()> {
|
||||
pub async fn run(self, keys: &mut crate::KeyInfo, host_name: Option<&str>) -> eyre::Result<()> {
|
||||
match self {
|
||||
AuthCommand::Login => {
|
||||
todo!();
|
||||
// let user = readline("username: ").await?;
|
||||
// let pass = readline("password: ").await?;
|
||||
let repo_info = crate::repo::RepoInfo::get_current(host_name, None, None)?;
|
||||
let host_url = repo_info.host_url();
|
||||
let client_info = get_client_info_for(host_url);
|
||||
if let Some((client_id, _)) = client_info {
|
||||
oauth_login(keys, host_url, client_id).await?;
|
||||
} else {
|
||||
let host_domain = host_url.host_str().ok_or_eyre("invalid host")?;
|
||||
let host_path = host_url.path();
|
||||
let mut applications_url = host_url.clone();
|
||||
applications_url
|
||||
.path_segments_mut()
|
||||
.map_err(|_| eyre::eyre!("invalid url"))?
|
||||
.extend(["user", "settings", "applications"]);
|
||||
|
||||
println!("{host_domain}{host_path} doesn't support easy login");
|
||||
println!();
|
||||
println!("Please visit {applications_url}");
|
||||
println!("to create a token, and use it to log in with `fj auth add-token`");
|
||||
}
|
||||
}
|
||||
AuthCommand::Logout { host } => {
|
||||
let info_opt = keys.hosts.remove(&host);
|
||||
|
@ -64,10 +81,151 @@ impl AuthCommand {
|
|||
}
|
||||
|
||||
pub fn get_client_info_for(url: &url::Url) -> Option<(&'static str, &'static str)> {
|
||||
let host = url.host_str()?;
|
||||
let client_info = match (url.host_str()?, url.path()) {
|
||||
("codeberg.org", "/") => option_env!("CLIENT_INFO_CODEBERG"),
|
||||
_ => None,
|
||||
};
|
||||
client_info.and_then(|info| info.split_once(":"))
|
||||
}
|
||||
|
||||
async fn oauth_login(
|
||||
keys: &mut crate::KeyInfo,
|
||||
host: &url::Url,
|
||||
client_id: &'static str,
|
||||
) -> eyre::Result<()> {
|
||||
use base64ct::Encoding;
|
||||
use rand::{distributions::Alphanumeric, prelude::*};
|
||||
|
||||
let mut rng = thread_rng();
|
||||
|
||||
let state = (0..32)
|
||||
.map(|_| rng.sample(Alphanumeric) as char)
|
||||
.collect::<String>();
|
||||
let code_verifier = (0..43)
|
||||
.map(|_| rng.sample(Alphanumeric) as char)
|
||||
.collect::<String>();
|
||||
let code_challenge =
|
||||
base64ct::Base64Url::encode_string(sha256::digest(&code_verifier).as_bytes());
|
||||
|
||||
let mut auth_url = host.clone();
|
||||
auth_url
|
||||
.path_segments_mut()
|
||||
.map_err(|_| eyre::eyre!("invalid url"))?
|
||||
.extend(["login", "oauth", "authorize"]);
|
||||
auth_url.query_pairs_mut().extend_pairs([
|
||||
("client_id", client_id),
|
||||
("redirect_uri", "http://127.0.0.1:26218/"),
|
||||
("response_type", "code"),
|
||||
("code_challenge_method", "S256"),
|
||||
("code_challenge", &code_challenge),
|
||||
("state", &state),
|
||||
]);
|
||||
open::that(auth_url.as_str()).unwrap();
|
||||
|
||||
let (handle, mut rx) = auth_server();
|
||||
let res = rx.recv().await.unwrap();
|
||||
handle.abort();
|
||||
let code = match res {
|
||||
Ok(Some((code, returned_state))) => {
|
||||
if returned_state == state {
|
||||
code
|
||||
} else {
|
||||
eyre::bail!("returned with invalid state");
|
||||
}
|
||||
}
|
||||
Ok(None) => {
|
||||
println!("Login canceled");
|
||||
return Ok(());
|
||||
}
|
||||
Err(e) => {
|
||||
eyre::bail!("Failed to authenticate: {e}");
|
||||
}
|
||||
};
|
||||
|
||||
let api = forgejo_api::Forgejo::new(forgejo_api::Auth::None, host.clone())?;
|
||||
let request = forgejo_api::structs::OAuthTokenRequest::Public {
|
||||
client_id,
|
||||
code_verifier: &code_verifier,
|
||||
code: &code,
|
||||
redirect_uri: url::Url::parse("http://127.0.0.1:26218/").unwrap(),
|
||||
};
|
||||
let response = api.oauth_get_access_token(request).await?;
|
||||
|
||||
let api = forgejo_api::Forgejo::new(
|
||||
forgejo_api::Auth::OAuth2(&response.access_token),
|
||||
host.clone(),
|
||||
)?;
|
||||
let current_user = api.user_get_current().await?;
|
||||
let name = current_user
|
||||
.login
|
||||
.ok_or_eyre("user does not have login name")?;
|
||||
|
||||
// A minute less, in case any weirdness happens at the exact moment it
|
||||
// expires. Better to refresh slightly too soon than slightly too late.
|
||||
let expires_in = std::time::Duration::from_secs(response.expires_in.saturating_sub(60) as u64);
|
||||
let expires_at = time::OffsetDateTime::now_utc() + expires_in;
|
||||
let login_info = crate::keys::LoginInfo::OAuth {
|
||||
name,
|
||||
token: response.access_token,
|
||||
refresh_token: response.refresh_token,
|
||||
expires_at,
|
||||
};
|
||||
keys.hosts
|
||||
.insert(host.host_str().unwrap().to_string(), login_info);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
use tokio::{sync::mpsc::Receiver, task::JoinHandle};
|
||||
|
||||
fn auth_server() -> (
|
||||
JoinHandle<eyre::Result<()>>,
|
||||
Receiver<Result<Option<(String, String)>, String>>,
|
||||
) {
|
||||
let addr: std::net::SocketAddr = ([127, 0, 0, 1], 26218).into();
|
||||
let (tx, rx) = tokio::sync::mpsc::channel(1);
|
||||
let tx = std::sync::Arc::new(tx);
|
||||
let handle = tokio::spawn(async move {
|
||||
let listener = tokio::net::TcpListener::bind(addr).await?;
|
||||
let server =
|
||||
hyper_util::server::conn::auto::Builder::new(hyper_util::rt::TokioExecutor::new());
|
||||
let svc = hyper::service::service_fn(|req: hyper::Request<hyper::body::Incoming>| {
|
||||
let tx = std::sync::Arc::clone(&tx);
|
||||
async move {
|
||||
let mut code = None;
|
||||
let mut state = None;
|
||||
let mut error_description = None;
|
||||
if let Some(query) = req.uri().query() {
|
||||
for item in query.split("&") {
|
||||
let (key, value) = item.split_once("=").unwrap_or((item, ""));
|
||||
match key {
|
||||
"code" => code = Some(value),
|
||||
"state" => state = Some(value),
|
||||
"error_description" => error_description = Some(value),
|
||||
_ => eprintln!("unknown key {key} {value}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
let (response, message) = match (code, state, error_description) {
|
||||
(_, _, Some(error)) => (Err(error.to_owned()), "Failed to authenticate"),
|
||||
(Some(code), Some(state), None) => (
|
||||
Ok(Some((code.to_owned(), state.to_owned()))),
|
||||
"Authenticated! Close this tab and head back to your terminal",
|
||||
),
|
||||
_ => (Ok(None), "Canceled"),
|
||||
};
|
||||
tx.send(response).await.unwrap();
|
||||
Ok::<_, hyper::Error>(hyper::Response::new(message.to_owned()))
|
||||
}
|
||||
});
|
||||
loop {
|
||||
let (connection, _addr) = listener.accept().await.unwrap();
|
||||
server
|
||||
.serve_connection(hyper_util::rt::TokioIo::new(connection), svc)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
(handle, rx)
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ async fn main() -> eyre::Result<()> {
|
|||
println!("currently signed in to {name}@{host}{}", url.path());
|
||||
}
|
||||
}
|
||||
Command::Auth(subcommand) => subcommand.run(&mut keys).await?,
|
||||
Command::Auth(subcommand) => subcommand.run(&mut keys, host_name).await?,
|
||||
Command::Release(subcommand) => subcommand.run(&mut keys, host_name).await?,
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue