feat: support specifying allowed external registries in config

This commit is contained in:
daimond113 2024-11-28 18:18:40 +01:00
parent cb17c419d0
commit b475ff40e5
No known key found for this signature in database
GPG key ID: 3A8ECE51328B513C
4 changed files with 51 additions and 23 deletions

View file

@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Make `includes` use glob patterns by @daimond113 - Make `includes` use glob patterns by @daimond113
- Use symlinks for workspace dependencies to not require reinstalling by @daimond113 - Use symlinks for workspace dependencies to not require reinstalling by @daimond113
- Add `auth token` command to print the auth token for the index by @daimond113 - Add `auth token` command to print the auth token for the index by @daimond113
- Support specifying which external registries are allowed on registries by @daimond113
### Fixed ### Fixed
- Install dependencies of packages in `x` command - Install dependencies of packages in `x` command

View file

@ -66,25 +66,6 @@ struct DocEntryInfo {
collapsed: bool, collapsed: bool,
} }
fn compare_repo_urls(this: &gix::Url, external: &gix::Url) -> bool {
let this = this.to_bstring().to_string().to_lowercase();
let external = external.to_bstring().to_string().to_lowercase();
let this = if this.ends_with(".git") {
&this[..this.len() - 4]
} else {
&this
};
let external = if external.ends_with(".git") {
&external[..external.len() - 4]
} else {
&external
};
this == external
}
pub async fn publish_package( pub async fn publish_package(
app_state: web::Data<AppState>, app_state: web::Data<AppState>,
bytes: Bytes, bytes: Bytes,
@ -321,8 +302,9 @@ pub async fn publish_package(
.index .index
.as_deref() .as_deref()
.filter(|index| match gix::Url::try_from(*index) { .filter(|index| match gix::Url::try_from(*index) {
Ok(_) if config.other_registries_allowed => true, Ok(url) => config
Ok(url) => compare_repo_urls(source.repo_url(), &url), .other_registries_allowed
.is_allowed(source.repo_url().clone(), url),
Err(_) => false, Err(_) => false,
}) })
.is_none() .is_none()

View file

@ -265,6 +265,42 @@ fn default_archive_size() -> usize {
4 * 1024 * 1024 4 * 1024 * 1024
} }
/// The allowed registries for a package
#[derive(Deserialize, Debug, Clone)]
#[serde(untagged)]
pub enum AllowedRegistries {
/// All registries are allowed
All(bool),
/// Only specific registries are allowed
#[serde(deserialize_with = "crate::util::deserialize_gix_url_hashset")]
Specific(HashSet<Url>),
}
impl Default for AllowedRegistries {
fn default() -> Self {
Self::All(false)
}
}
impl AllowedRegistries {
/// Whether the given URL is allowed
pub fn is_allowed(&self, mut this: Url, mut external: Url) -> bool {
// strip .git suffix to allow for more flexible matching
this.path = this.path.strip_suffix(b".git").unwrap_or(&this.path).into();
external.path = external
.path
.strip_suffix(b".git")
.unwrap_or(&external.path)
.into();
this == external
|| (match self {
Self::All(all) => *all,
Self::Specific(urls) => urls.contains(&this) || urls.contains(&external),
})
}
}
/// The configuration for the pesde index /// The configuration for the pesde index
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
@ -278,7 +314,7 @@ pub struct IndexConfig {
pub git_allowed: bool, pub git_allowed: bool,
/// Whether other registries are allowed as a source for publishing packages /// Whether other registries are allowed as a source for publishing packages
#[serde(default)] #[serde(default)]
pub other_registries_allowed: bool, pub other_registries_allowed: AllowedRegistries,
/// Whether Wally is allowed as a source for publishing packages /// Whether Wally is allowed as a source for publishing packages
#[serde(default)] #[serde(default)]
pub wally_allowed: bool, pub wally_allowed: bool,

View file

@ -2,7 +2,7 @@ use crate::AuthConfig;
use gix::bstr::BStr; use gix::bstr::BStr;
use serde::{Deserialize, Deserializer, Serializer}; use serde::{Deserialize, Deserializer, Serializer};
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use std::collections::BTreeMap; use std::collections::{BTreeMap, HashSet};
pub fn authenticate_conn( pub fn authenticate_conn(
conn: &mut gix::remote::Connection< conn: &mut gix::remote::Connection<
@ -59,6 +59,15 @@ pub fn deserialize_gix_url_vec<'de, D: Deserializer<'de>>(
.collect() .collect()
} }
pub fn deserialize_gix_url_hashset<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<HashSet<gix::Url>, D::Error> {
HashSet::<String>::deserialize(deserializer)?
.into_iter()
.map(|v| gix::Url::from_bytes(BStr::new(&v)).map_err(serde::de::Error::custom))
.collect()
}
pub fn deserialize_git_like_url<'de, D: Deserializer<'de>>( pub fn deserialize_git_like_url<'de, D: Deserializer<'de>>(
deserializer: D, deserializer: D,
) -> Result<gix::Url, D::Error> { ) -> Result<gix::Url, D::Error> {