Check that sync.server.origin is a URL (#3361)

This commit is contained in:
Dustin J. Mitchell 2024-04-15 22:11:55 -04:00 committed by GitHub
parent 4d9bb20bdd
commit 10cec507cb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 18 additions and 3 deletions

1
Cargo.lock generated
View file

@ -2095,6 +2095,7 @@ dependencies = [
"thiserror",
"tokio",
"ureq",
"url",
"uuid",
]

View file

@ -45,3 +45,4 @@ tokio = { version = "1", features = ["rt-multi-thread"] }
thiserror = "1.0"
ureq = { version = "^2.9.0", features = ["tls"] }
uuid = { version = "^1.8.0", features = ["serde", "v4"] }
url = { version = "2" }

View file

@ -73,6 +73,8 @@ Configure Taskwarrior with these details:
$ task config sync.server.origin <origin>
$ task config sync.server.client_id <client_id>
Note that the origin must include the scheme, such as 'http://' or 'https://'.
.SS Google Cloud Platform
To synchronize your tasks to GCP, use the GCP Console to create a new project,

View file

@ -186,7 +186,7 @@ static void test_replica_sync_local(void) {
static void test_replica_remote_server(void) {
TCString err;
TCServer *server = tc_server_new_sync(
tc_string_borrow("tc.freecinc.com"),
tc_string_borrow("http://tc.freecinc.com"),
tc_uuid_new_v4(),
tc_string_borrow("\xf0\x28\x8c\x28"), // NOTE: not utf-8
&err);

View file

@ -15,7 +15,7 @@ rust-version = "1.70.0"
default = ["server-sync", "server-gcp"]
# Support for sync to a server
server-sync = ["encryption", "dep:ureq"]
server-sync = ["encryption", "dep:ureq", "dep:url"]
# Support for sync to GCP
server-gcp = ["cloud", "encryption", "dep:google-cloud-storage", "dep:tokio"]
# (private) Support for sync protocol encryption
@ -43,10 +43,12 @@ byteorder.workspace = true
ring.workspace = true
google-cloud-storage.workspace = true
tokio.workspace = true
url.workspace = true
google-cloud-storage.optional = true
tokio.optional = true
ureq.optional = true
url.optional = true
ring.optional = true
[dev-dependencies]

View file

@ -4,6 +4,7 @@ use crate::server::{
VersionId,
};
use std::time::Duration;
use url::Url;
use uuid::Uuid;
use super::encryption::{Cryptor, Sealed, Secret, Unsealed};
@ -28,8 +29,16 @@ impl SyncServer {
/// identify this client to the server. Multiple replicas synchronizing the same task history
/// should use the same client_id.
pub fn new(origin: String, client_id: Uuid, encryption_secret: Vec<u8>) -> Result<SyncServer> {
let origin = Url::parse(&origin)
.map_err(|_| Error::Server(format!("Could not parse {} as a URL", origin)))?;
if origin.path() != "/" {
return Err(Error::Server(format!(
"Server origin must have an empty path; got {}",
origin
)));
}
Ok(SyncServer {
origin,
origin: origin.to_string(),
client_id,
cryptor: Cryptor::new(client_id, &Secret(encryption_secret.to_vec()))?,
agent: ureq::AgentBuilder::new()