diff --git a/src/registry.rs b/src/registry.rs index 4dd5d12..cc2fead 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -24,17 +24,14 @@ pub struct RegistryTagsFetcher {} impl DockerTags for RegistryTagsFetcher { fn get_tags(&self, args: &QueryArgs) -> Vec { + let repository = args.repository.clone().unwrap(); let mut namespace = "library"; - let repository = match &args.repository { - Some(s) => { - let vec = s.split('/') - .into_iter() - .collect::>(); - namespace = vec[0]; - vec[1] - } - None => { "" } - }; + let mut repository = repository.as_str(); + let option = repository.find('/'); + if option.is_some() { + namespace = &repository[0..option.unwrap()]; + repository = &repository[(option.unwrap() + 1)..]; + } let token = get_token(namespace, repository).unwrap(); let url = format!("https://registry-1.docker.io/v2/{namespace}/{repository}/tags/list"); @@ -51,26 +48,25 @@ impl DockerTags for RegistryTagsFetcher { } } +/// get the access token for tags request fn get_token(namespace: &str, repository: &str) -> Option { - let config = read_config(); - match config { - Some(s) => { - let service = "registry.docker.io"; - let scope = format!("repository:{namespace}/{repository}:pull"); - let auth = format!("https://auth.docker.io/token?service={service}&scope={scope}"); - let client = reqwest::blocking::Client::new(); - let response = client.get(auth) - .basic_auth(s.username, Some(s.password)) - .send(); - match response { - Ok(r) => { - let json: RegistryTokenResponse = serde_json::from_str(r.text().unwrap().as_str()).unwrap(); - Some(json.token.unwrap()) - } - Err(_) => { None } - } + let config = match read_config() { + None => { return None; } + Some(x) => { x } + }; + let service = "registry.docker.io"; + let scope = format!("repository:{namespace}/{repository}:pull"); + let auth = format!("https://auth.docker.io/token?service={service}&scope={scope}"); + let client = reqwest::blocking::Client::new(); + let response = client.get(auth) + .basic_auth(config.username, Some(config.password)) + .send(); + match response { + Ok(r) => { + let json: RegistryTokenResponse = serde_json::from_str(r.text().unwrap().as_str()).unwrap(); + Some(json.token.unwrap()) } - _ => { None } + Err(_) => { None } } } @@ -86,34 +82,32 @@ struct DockerAuth { use base64::{Engine as _, engine::general_purpose}; +/// read authentication info from local docker config file fn read_config() -> Option { let user_dirs = UserDirs::new().unwrap(); let home_dir = user_dirs.home_dir(); let config_path = home_dir.join(".docker").join("config.json"); - let config = fs::read_to_string(config_path); - let json: DockerConfig = serde_json::from_str(config.unwrap().as_str()).unwrap(); - let auths = json.auths; - // let auth = auths.get("https://hub.docker.com/v2/"); - let auth = auths.get("https://index.docker.io/v1/"); - match auth { - Some(a) => { - let auth = a.auth.clone().unwrap(); - - let mut buffer = Vec::::new(); - let result = general_purpose::URL_SAFE_NO_PAD.decode_vec(auth.as_bytes(), &mut buffer); - let decoded = match std::str::from_utf8(&buffer) { - Ok(v) => v, - Err(e) => panic!("Invalid UTF-8 sequence: {}", e), - }; - let vec = decoded.split(":").collect::>(); - println!("{:?}", decoded); - Some(DockerPassword { - username: vec[0].parse().unwrap(), - password: vec[1].parse().unwrap(), - }) - } - _ => { None } - } + let config_context = fs::read_to_string(config_path); + let docker_config: DockerConfig = serde_json::from_str(config_context.unwrap().as_str()).unwrap(); + let auths = docker_config.auths; + let auth = match auths.get("https://index.docker.io/v1/") { + None => { return None; } + Some(docker_auth) => { docker_auth.auth.clone().unwrap() } + }; + let mut buffer = Vec::::new(); + let _result = general_purpose::URL_SAFE_NO_PAD.decode_vec(auth.as_bytes(), &mut buffer); + let decoded = match std::str::from_utf8(&buffer) { + Ok(v) => v, + Err(e) => panic!("Invalid UTF-8 sequence: {}", e), + }; + let idx = match decoded.find(':') { + None => { panic!("Invalid authentication: {}", decoded) } + Some(i) => { i } + }; + return Some(DockerPassword { + username: String::from(&decoded[0..idx]), + password: String::from(&decoded[(idx + 1)..]), + }); } #[derive(Serialize, Deserialize)]