LZOGKBJXRQJKXHYNNENJFGNLP5SHIXGSV6HDB7UVOP7FSA5EUNCQC X2MMGGXQEXJQKXV77LMQWY2BLMLOD6WRDGS3ZX3Z4NUDRAI5IDCAC 2MLOE3FPVT4ZXC4L74VC7GV2IXATZQNFLJECDPZZ7MTSW4A6XT5QC 44RUBHREQUNI4B36WSV7CUK5CVVIKG2AQOQJQZ7HU3BHY6W6AUEQC MEK57BADGFCCZDNPUPUZGOJGNNS5R7UWRWCNJELKONGKOLLAQDDAC M37JTFEIT6NHRDJOE7K6JWKFJF7327JMZDMX7GC2DQNECZKODBXQC 4HTHYIA3GLMUBUMAI7CQMZA4KE47EUXOP24XLUEYFRMOG57CJLMAC UMF6N7CZA4CTSPKQFZSZXA3VRHWQAKEA5GUNIEAAVRWC7FUSSKAAC SXEYMYF7P4RZMZ46WPL4IZUTSQ2ATBWYZX7QNVMS3SGOYXYOHAGQC ZDK3GNDBWXJ2OXFDYB72ZCEBGLBF4MKE5K3PVHDZATHJ7HJIDPRQC DO2Y5TY5JQISUHCVNPI2FXO7WWZVJQ3LGPWF4DNADMGZRIO6PT2QC IQ4FCHPZYGTZHCQHUIRCMUI5LCHIDSJCM2AZXGRJARWLCPPLXZOQC FBXYP7QM7SG6P2JDJVQPPCRKJE3GVYXNQ5GVV4GRDUNG6Q4ZRDJQC OIOMXESDNMLOTMNYCZZBYSBAQTYPAXXMUHTLA2AYCMNHZMPSLX2AC H4AU6QRPRDRFW3V7NN5CJ6DHLEUBYGNLRZ5GYV6ULBGRMOPCJQXQC MU5GSJAW65PEG3BRYUKZ7O37BPHW3MOX3S5E2RFOXKGUOJEEDQ5AC A3RM526Y7LUXNYW4TL56YKQ5GVOK2R5D7JJVTSQ6TT5MEXIR6YAAC 4OJWMSOWWNT5N4W4FDMKBZB5UARCLGV3SRZVKGR4EFAYFUMUHM7AC TI7PCK7JLPU4KYE65XIMBUPPY7DRPVDAETPDFMG3VAQGGDRGQHPQC SNZ3OAMCPUGFYON5SZHQQQK46ZZMVMJECJYEUCMG657UVLY2PNBQC 4KJ45IJLTIE35KQZUSFMFS67RNENG4P2FZMKMULJLGGYMKJUVRSQC EEBKW7VTILH6AGGV57ZIJ3DJGYHDSYBWGU3C7Q4WWAKSVNUGIYMQC I24UEJQLCH2SOXA4UHIYWTRDCHSOPU7AFTRUOTX7HZIAV4AZKYEQC IIV3EL2XYI2X7HZWKXEXQFAE3R3KC2Q7SGOT3Q332HSENMYVF32QC TEDGMEHFZK6QKSXVOHM3Z4MYZC26EDCWRURHWKOU2JLETWJIJPLQC TPEH2XNBS5RO4IEVKENVF6P65AH7IX64KK2JAYMSJT3J5GXO67EAC GYXIF25T2BCTCWCQI5DQOF3F4HBWDJUDJUMZ2WLHVBIOYATJTFAQC VAPBIG46QVLGCASUE2QLISQ6657CZRAMNEG2PRK7FKEKAYM7FS3QC LYTVEPH3W5UHF7MAYFWBT6NVNC42HEVKJGGMFDKUDZDNDOI33YJQC SN7AGY6SLIWVKLBHQQ2MZ7VYY4BBFKROC5F3M6FVVFIGT25QNX7AC 2K7JLB4Z7BS5VFNWD4DO3MKYU7VNPA5MTVHVSDI3FQZ5ICM6XM6QC std::fs::create_dir_all(&path)?;for id in resp.id.iter() {path.push(&id.public_key.key);debug!("recv identity: {:?} {:?}", id, path);let mut id_file = std::fs::File::create(&path)?;serde_json::to_writer_pretty(&mut id_file, &id.as_portable())?;path.pop();
if let Some(resp) = resp {std::fs::create_dir_all(&path)?;for id in resp.id.iter() {path.push(&id.public_key.key);debug!("recv identity: {:?} {:?}", id, path);let mut id_file = std::fs::File::create(&path)?;serde_json::to_writer_pretty(&mut id_file, &id.as_portable())?;path.pop();}Ok(resp.rev)} else {Ok(0)
Ok(resp.rev)
}pub async fn prove(&mut self,key: libpijul::key::SKey,) -> Result<(), anyhow::Error> {debug!("prove {:?}", self.url);let url = format!("{}/{}", self.url, super::DOT_DIR);let q = [("challenge", key.public_key().key)];let mut req = self.client.get(&url).query(&q).header(reqwest::header::USER_AGENT, USER_AGENT);for (k, v) in self.headers.iter() {debug!("kv = {:?} {:?}", k, v);req = req.header(k.as_str(), v.as_str());}let res = req.send().await?;if !res.status().is_success() {bail!("HTTP error {:?}", res.status())}let resp = res.bytes().await?;debug!("resp = {:?}", resp);let sig = key.sign_raw(&resp)?;debug!("sig = {:?}", sig);let q = [("prove", &sig)];let mut req = self.client.get(&url).query(&q).header(reqwest::header::USER_AGENT, USER_AGENT);for (k, v) in self.headers.iter() {debug!("kv = {:?} {:?}", k, v);req = req.header(k.as_str(), v.as_str());}let res = req.send().await?;if !res.status().is_success() {bail!("HTTP error {:?}", res.status())}Ok(())
use crate::remote::RemoteRepo;if let RemoteRepo::Ssh(ssh) = repo.remote(None,Some(&self.config.author.username),&remote,crate::DEFAULT_CHANNEL,no_cert_check,false,).await?{ssh} else {bail!("No such remote: {}", remote)}} else if let Some(mut ssh) = crate::remote::ssh::ssh_remote(Some(&self.config.author.username), &remote, false) {if let Some(c) = ssh.connect(&remote, crate::DEFAULT_CHANNEL).await? {c} else {bail!("No such remote: {}", remote)}
repo.remote(None,Some(&self.config.author.username),&remote,crate::DEFAULT_CHANNEL,no_cert_check,false,).await?
use clap::Parser;use std::convert::Infallible;use std::net::SocketAddr;use hyper::{Body, Request, Response, Server};use hyper::service::{make_service_fn, service_fn};use tokio::sync::mpsc::channel;use tokio::select;use crate::config::global_config_dir;#[derive(Parser, Debug)]pub struct Client {/// Url to authenticate to.#[clap(value_name = "URL")]url: String,}impl Client {pub async fn run(self) -> Result<(), anyhow::Error> {let url = url::Url::parse(&self.url)?;let mut cache_path = None;if let Some(mut cached) = global_config_dir() {cached.push("cache");if let Some(host) = url.host_str() {std::fs::create_dir_all(&cached)?;cached.push(host);if let Ok(token) = std::fs::read_to_string(&cached) {println!("Bearer {}", token);return Ok(())} else {cache_path = Some(cached);}}}let (tx, mut rx) = channel::<String>(1);let make_service = make_service_fn(|_conn| {let tx = tx.clone();async move {let handle = move |req: Request<_>| {let qq: Option<String> = if let Some(q) = req.uri().query() {let eq = "token=";if q.starts_with(eq) {Some(q.split_at(eq.len()).1.to_string())} else {None}} else {None};let tx = tx.clone();async move {if let Some(qq) = qq {tx.send(qq).await.unwrap();let resp = Response::builder().header("Content-Type", "text/html").body(Body::from(include_str!("client.html"))).unwrap();Ok::<_, Infallible>(resp)} else {Ok::<_, Infallible>(Response::builder().status(404).body("Not found".into()).unwrap())}}};Ok::<_, Infallible>(service_fn(handle))}});let mut port = 3000;loop {let addr = SocketAddr::from(([127, 0, 0, 1], port));if let Ok(server) = Server::try_bind(&addr) {let mut url = url::Url::parse(&self.url)?;url.query_pairs_mut().append_pair("port", &port.to_string());open::that(&url.to_string())?;let server = server.serve(make_service);select!{x = server => {if let Err(e) = x {eprintln!("server error: {}", e);}break}x = rx.recv() => {if let Some(x) = x {if let Some(cache_path) = cache_path {std::fs::write(&cache_path, &x)?;}println!("Bearer {}", x);}break}}}if port < u16::MAX {port += 1} else {break}}Ok(())}}