diff --git a/src/many-web/src/error.rs b/src/many-web/src/error.rs index bd9af763..f1013fbe 100644 --- a/src/many-web/src/error.rs +++ b/src/many-web/src/error.rs @@ -22,6 +22,7 @@ define_attribute_many_error!( 17: pub fn site_name_too_long(site_name) => "Site name too long: {site_name}.", 18: pub fn invalid_domain(domain) => "Invalid domain: {domain}.", 19: pub fn page_size_too_large(size) => "Page size too large: {size}.", + 20: pub fn domain_already_in_use(domain) => "Domain already in use: {domain}.", } ); diff --git a/src/many-web/src/module.rs b/src/many-web/src/module.rs index 039f80e1..132a8c9d 100644 --- a/src/many-web/src/module.rs +++ b/src/many-web/src/module.rs @@ -274,6 +274,12 @@ impl WebCommandsModuleBackend for WebModuleImpl { return Err(error::existent_site(site_name)); } + if let Some(domain) = &domain { + if self.storage.has_domain(domain) { + return Err(error::domain_already_in_use(domain)); + } + } + let tmpdir = Builder::new() .prefix("dweb-") .tempdir() @@ -368,6 +374,12 @@ impl WebCommandsModuleBackend for WebModuleImpl { return Err(error::nonexistent_site(site_name)); } + if let Some(domain) = &domain { + if self.storage.has_domain(domain) { + return Err(error::domain_already_in_use(domain)); + } + } + let tmpdir = Builder::new() .prefix("dweb-") .tempdir() diff --git a/src/many-web/src/storage.rs b/src/many-web/src/storage.rs index 5b8e2c68..4f4907d0 100644 --- a/src/many-web/src/storage.rs +++ b/src/many-web/src/storage.rs @@ -460,6 +460,12 @@ impl WebStorage { .map_err(error::storage_get_failed) } + // Check all websites for a given domain + pub fn has_domain(&self, domain: &String) -> bool { + self.list(SortOrder::Descending, None) + .any(|(_, meta)| meta.domain.as_ref() == Some(domain)) + } + pub fn list( &self, order: SortOrder, diff --git a/tests/e2e/web/web.bats b/tests/e2e/web/web.bats index dc07f030..a8007517 100644 --- a/tests/e2e/web/web.bats +++ b/tests/e2e/web/web.bats @@ -60,6 +60,29 @@ function teardown() { assert_output --partial "Nonexistent site: test_dweb" } +@test "$SUITE dweb deploy fails if domain already in use" { + call_web --pem=1 --port=8000 deploy test_dweb test_dweb.zip --domain foobar.com + assert_output --partial "https://test_dweb-$(identity 1).ghostcloud.org" + assert_output --partial "foobar.com" + + # We check all websites, not just the ones owned by the sender + call_web --pem=2 --port=8000 deploy test_dweb2 test_dweb.zip --domain foobar.com + assert_output --partial "Domain already in use: foobar.com." +} + +@test "$SUITE dweb update fails if domain already in use" { + call_web --pem=1 --port=8000 deploy test_dweb test_dweb.zip --domain foobar.com + assert_output --partial "https://test_dweb-$(identity 1).ghostcloud.org" + assert_output --partial "foobar.com" + + call_web --pem=1 --port=8000 deploy test_dweb2 test_dweb.zip + assert_output --partial "https://test_dweb2-$(identity 1).ghostcloud.org" + refute_output --partial "foobar.com" + + call_web --pem=1 --port=8000 update test_dweb2 test_dweb.zip --domain foobar.com + assert_output --partial "Domain already in use: foobar.com." +} + @test "$SUITE: dweb website removal works" { call_web --pem=1 --port=8000 deploy test_dweb test_dweb.zip assert_output --partial "https://test_dweb-$(identity 1).ghostcloud.org"