From 7f68441916f9ce8ff5d01c9dea3b851de7a3a986 Mon Sep 17 00:00:00 2001 From: "Dustin J. Mitchell" Date: Tue, 11 Jul 2023 22:13:53 -0400 Subject: [PATCH] Change "client key" to "client id" (#3130) In #3118 @ryneeverett mentioned that "key" suggests that this is a secret, when in truth it's just a user identifier. So "ID" is a better word for it than "key". --- doc/man/task-sync.5.in | 14 +- scripts/vim/syntax/taskrc.vim | 2 +- src/Context.cpp | 2 +- src/commands/CmdShow.cpp | 2 +- src/commands/CmdSync.cpp | 6 +- src/tc/Server.cpp | 12 +- src/tc/Server.h | 2 +- taskchampion/docs/src/sync-protocol.md | 6 +- .../integration-tests/tests/cross-sync.rs | 4 +- .../integration-tests/tests/snapshots.rs | 4 +- taskchampion/lib/src/server.rs | 10 +- taskchampion/lib/taskchampion.h | 2 +- .../sync-server/src/api/add_snapshot.rs | 39 +-- .../sync-server/src/api/add_version.rs | 33 +-- .../sync-server/src/api/get_child_version.rs | 29 ++- .../sync-server/src/api/get_snapshot.rs | 23 +- taskchampion/sync-server/src/api/mod.rs | 18 +- taskchampion/sync-server/src/server.rs | 242 +++++++++--------- .../sync-server/src/storage/inmemory.rs | 97 ++++--- taskchampion/sync-server/src/storage/mod.rs | 19 +- .../sync-server/src/storage/sqlite.rs | 97 ++++--- .../taskchampion/src/server/config.rs | 8 +- .../taskchampion/src/server/crypto.rs | 58 ++--- .../src/server/generate-test-data.py | 12 +- .../taskchampion/src/server/remote/mod.rs | 20 +- .../src/server/test-bad-app-id.data | 4 +- .../src/server/test-bad-client-id.data | 1 + .../src/server/test-bad-client-key.data | 1 - .../src/server/test-bad-secret.data | 2 +- .../src/server/test-bad-version-id.data | 2 +- .../src/server/test-bad-version.data | 2 +- .../taskchampion/src/server/test-good.data | 2 +- 32 files changed, 387 insertions(+), 388 deletions(-) create mode 100644 taskchampion/taskchampion/src/server/test-bad-client-id.data delete mode 100644 taskchampion/taskchampion/src/server/test-bad-client-key.data diff --git a/doc/man/task-sync.5.in b/doc/man/task-sync.5.in index 5adda6ce1..de1f83823 100644 --- a/doc/man/task-sync.5.in +++ b/doc/man/task-sync.5.in @@ -29,9 +29,9 @@ information from the server administrator: .br - The server's URL ("origin", such as "https://tw.example.com") .br - - A client key ("client_key") identifying your tasks + - A client ID ("client_id") identifying your tasks .br - - An encryption secret ("encryption_secret") used to encrypt and decrypt your tasks. This can be any secret string, and must match for all replicas using the same client key. + - An encryption secret ("encryption_secret") used to encrypt and decrypt your tasks. This can be any secret string, and must match for all replicas using the same client ID. Tools such as .BR pwgen (1) @@ -40,7 +40,7 @@ can generate suitable secret values. Configure Taskwarrior with these details: $ task config sync.server.origin - $ task config sync.server.client_key + $ task config sync.server.client_id $ task config sync.server.encryption_secret .SS Adding a Replica @@ -74,7 +74,7 @@ The default configuration is to sync to a database in the task directory .SH RUNNING TASKCHAMPION-SYNC-SERVER The Taskchampion sync server is an HTTP server supporting multiple users. -Users are identified by a client key, and users with different client keys are +Users are identified by a client ID, and users with different client IDs are entirely independent. Task data is encrypted by Taskwarrior, and the sync server never sees un-encrypted data. @@ -91,10 +91,10 @@ For example: .SS Adding a New User -To add a new user to the server, invent a new client key with a tool like +To add a new user to the server, invent a new client ID with a tool like `uuidgen` or an online UUID generator. There is no need to configure the server -for this new client key: the sync server will automatically create a new user -whenever presented with a new client key. Supply the key, along with the +for this new client ID: the sync server will automatically create a new user +whenever presented with a new client ID. Supply the ID, along with the origin, to the user for inclusion in their Taskwarrior config. The user should invent their own "encryption_secret". diff --git a/scripts/vim/syntax/taskrc.vim b/scripts/vim/syntax/taskrc.vim index c65b463b0..62f9d993a 100644 --- a/scripts/vim/syntax/taskrc.vim +++ b/scripts/vim/syntax/taskrc.vim @@ -163,7 +163,7 @@ syn match taskrcGoodKey '^\s*\Vrule.precedence.color='he=e-1 syn match taskrcGoodKey '^\s*\Vsearch.case.sensitive='he=e-1 syn match taskrcGoodKey '^\s*\Vsummary.all.projects='he=e-1 syn match taskrcGoodKey '^\s*\Vsugar='he=e-1 -syn match taskrcGoodKey '^\s*\Vsync.\(server.\(origin\|client_key\|encryption_secret\)\|local.server_dir\)='he=e-1 +syn match taskrcGoodKey '^\s*\Vsync.\(server.\(origin\|client_id\|encryption_secret\)\|local.server_dir\)='he=e-1 syn match taskrcGoodKey '^\s*\Vtag.indicator='he=e-1 syn match taskrcGoodKey '^\s*\Vuda.\S\{-}.\(default\|type\|label\|values\|indicator\)='he=e-1 syn match taskrcGoodKey '^\s*\Vundo.style='he=e-1 diff --git a/src/Context.cpp b/src/Context.cpp index c9614e8f5..4d92564fc 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -279,7 +279,7 @@ std::string configurationDefaults = "# WARNING: Please read the documentation (man task-sync) before setting up\n" "# Taskwarrior for Taskserver synchronization.\n" "\n" - "#sync.server.client_key # Client key for sync to a server\n" + "#sync.server.client_id # Client ID for sync to a server\n" "#sync.server.encryption_secret # Encryption secret for sync to a server\n" "#sync.server.origin # Origin of the sync server\n" "#sync.local.server_dir # Directory for local sync\n" diff --git a/src/commands/CmdShow.cpp b/src/commands/CmdShow.cpp index 9625a5d68..94130172c 100644 --- a/src/commands/CmdShow.cpp +++ b/src/commands/CmdShow.cpp @@ -193,7 +193,7 @@ int CmdShow::execute (std::string& output) " sugar" " summary.all.projects" " sync.local.server_dir" - " sync.server.client_key" + " sync.server.client_id" " sync.server.encryption_secret" " sync.server.origin" " tag.indicator" diff --git a/src/commands/CmdSync.cpp b/src/commands/CmdSync.cpp index b72aae4d0..c886f975c 100644 --- a/src/commands/CmdSync.cpp +++ b/src/commands/CmdSync.cpp @@ -63,14 +63,14 @@ int CmdSync::execute (std::string& output) // If no server is set up, quit. std::string origin = Context::getContext ().config.get ("sync.server.origin"); - std::string client_key = Context::getContext ().config.get ("sync.server.client_key"); + std::string client_id = Context::getContext ().config.get ("sync.server.client_id"); std::string encryption_secret = Context::getContext ().config.get ("sync.server.encryption_secret"); std::string server_dir = Context::getContext ().config.get ("sync.local.server_dir"); if (server_dir != "") { server = tc::Server (server_dir); server_ident = server_dir; - } else if (origin != "" && client_key != "" && encryption_secret != "") { - server = tc::Server (origin, client_key, encryption_secret); + } else if (origin != "" && client_id != "" && encryption_secret != "") { + server = tc::Server (origin, client_id, encryption_secret); server_ident = origin; } else { throw std::string ("Neither sync.server nor sync.local are configured."); diff --git a/src/tc/Server.cpp b/src/tc/Server.cpp index 5b1346838..2f17f4318 100644 --- a/src/tc/Server.cpp +++ b/src/tc/Server.cpp @@ -49,23 +49,23 @@ tc::Server::Server (const std::string &server_dir) } //////////////////////////////////////////////////////////////////////////////// -tc::Server::Server (const std::string &origin, const std::string &client_key, const std::string &encryption_secret) +tc::Server::Server (const std::string &origin, const std::string &client_id, const std::string &encryption_secret) { TCString tc_origin = tc_string_borrow (origin.c_str ()); - TCString tc_client_key_str = tc_string_borrow (client_key.c_str ()); + TCString tc_client_id = tc_string_borrow (client_id.c_str ()); TCString tc_encryption_secret = tc_string_borrow (encryption_secret.c_str ()); - TCUuid tc_client_key; - if (tc_uuid_from_str(tc_client_key_str, &tc_client_key) != TC_RESULT_OK) { + TCUuid tc_client_uuid; + if (tc_uuid_from_str(tc_client_id, &tc_client_uuid) != TC_RESULT_OK) { tc_string_free(&tc_origin); tc_string_free(&tc_encryption_secret); - throw "client_key must be a valid UUID"; + throw "client_id must be a valid UUID"; } TCString error; - auto tcserver = tc_server_new_remote (tc_origin, tc_client_key, tc_encryption_secret, &error); + auto tcserver = tc_server_new_remote (tc_origin, tc_client_uuid, tc_encryption_secret, &error); if (!tcserver) { auto errmsg = format ("Could not configure connection to server at {1}: {2}", origin, tc_string_content (&error)); diff --git a/src/tc/Server.h b/src/tc/Server.h index a29f581a8..0d2ddf370 100644 --- a/src/tc/Server.h +++ b/src/tc/Server.h @@ -54,7 +54,7 @@ namespace tc { Server (const std::string& server_dir); // Construct a remote server (tc_server_new_remote). - Server (const std::string &origin, const std::string &client_key, const std::string &encryption_secret); + Server (const std::string &origin, const std::string &client_id, const std::string &encryption_secret); // This object "owns" inner, so copy is not allowed. Server (const Server &) = delete; diff --git a/taskchampion/docs/src/sync-protocol.md b/taskchampion/docs/src/sync-protocol.md index 0bb588383..a67cd66be 100644 --- a/taskchampion/docs/src/sync-protocol.md +++ b/taskchampion/docs/src/sync-protocol.md @@ -9,7 +9,7 @@ The protocol builds on the model presented in the previous chapter, and in parti From the server's perspective, replicas accessing the same task history are indistinguishable, so this protocol uses the term "client" to refer generically to all replicas replicating a single task history. -Each client is identified and authenticated with a "client key", known only to the server and to the replicas replicating the task history. +Each client is identified and authenticated with a "client_id key", known only to the server and to the replicas replicating the task history. ## Server @@ -48,7 +48,7 @@ This section describes how that information is used to encrypt and decrypt data #### Key Derivation The client derives the 32-byte encryption key from the configured encryption secret using PBKDF2 with HMAC-SHA256 and 100,000 iterations. -The salt is the SHA256 hash of the 16-byte form of the client key. +The salt is the SHA256 hash of the 16-byte form of the client ID. #### Encryption @@ -172,7 +172,7 @@ The response contains the snapshot version ID and the snapshot data, if those ex The transactions above are realized for an HTTP server at `` using the HTTP requests and responses described here. The `origin` *should* be an HTTPS endpoint on general principle, but nothing in the functonality or security of the protocol depends on connection encryption. -The replica identifies itself to the server using a `clientKey` in the form of a UUID. +The replica identifies itself to the server using a `client_id` in the form of a UUID. This value is passed with every request in the `X-Client-Id` header, in its dashed-hex format. ### AddVersion diff --git a/taskchampion/integration-tests/tests/cross-sync.rs b/taskchampion/integration-tests/tests/cross-sync.rs index b13fb5354..94b53558d 100644 --- a/taskchampion/integration-tests/tests/cross-sync.rs +++ b/taskchampion/integration-tests/tests/cross-sync.rs @@ -26,12 +26,12 @@ async fn cross_sync() -> anyhow::Result<()> { let mut rep1 = Replica::new(StorageConfig::InMemory.into_storage()?); let mut rep2 = Replica::new(StorageConfig::InMemory.into_storage()?); - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let encryption_secret = b"abc123".to_vec(); let make_server = || { ServerConfig::Remote { origin: format!("http://127.0.0.1:{}", port), - client_key, + client_id, encryption_secret: encryption_secret.clone(), } .into_server() diff --git a/taskchampion/integration-tests/tests/snapshots.rs b/taskchampion/integration-tests/tests/snapshots.rs index c21ba297d..004a57ecf 100644 --- a/taskchampion/integration-tests/tests/snapshots.rs +++ b/taskchampion/integration-tests/tests/snapshots.rs @@ -30,12 +30,12 @@ async fn sync_with_snapshots() -> anyhow::Result<()> { } fn client(port: u16) -> anyhow::Result<()> { - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let encryption_secret = b"abc123".to_vec(); let make_server = || { ServerConfig::Remote { origin: format!("http://127.0.0.1:{}", port), - client_key, + client_id, encryption_secret: encryption_secret.clone(), } .into_server() diff --git a/taskchampion/lib/src/server.rs b/taskchampion/lib/src/server.rs index 7c923a236..f8823ceac 100644 --- a/taskchampion/lib/src/server.rs +++ b/taskchampion/lib/src/server.rs @@ -109,14 +109,14 @@ pub unsafe extern "C" fn tc_server_new_local( /// /// ```c /// EXTERN_C struct TCServer *tc_server_new_remote(struct TCString origin, -/// struct TCUuid client_key, +/// struct TCUuid client_id, /// struct TCString encryption_secret, /// struct TCString *error_out); /// ``` #[no_mangle] pub unsafe extern "C" fn tc_server_new_remote( origin: TCString, - client_key: TCUuid, + client_id: TCUuid, encryption_secret: TCString, error_out: *mut TCString, ) -> *mut TCServer { @@ -128,9 +128,9 @@ pub unsafe extern "C" fn tc_server_new_remote( let origin = unsafe { TCString::val_from_arg(origin) }.into_string()?; // SAFETY: - // - client_key is a valid Uuid (any 8-byte sequence counts) + // - client_id is a valid Uuid (any 8-byte sequence counts) - let client_key = unsafe { TCUuid::val_from_arg(client_key) }; + let client_id = unsafe { TCUuid::val_from_arg(client_id) }; // SAFETY: // - encryption_secret is valid (promised by caller) // - encryption_secret ownership is transferred to this function @@ -140,7 +140,7 @@ pub unsafe extern "C" fn tc_server_new_remote( let server_config = ServerConfig::Remote { origin, - client_key, + client_id, encryption_secret, }; let server = server_config.into_server()?; diff --git a/taskchampion/lib/taskchampion.h b/taskchampion/lib/taskchampion.h index 3c3e73066..82cabdd8e 100644 --- a/taskchampion/lib/taskchampion.h +++ b/taskchampion/lib/taskchampion.h @@ -433,7 +433,7 @@ EXTERN_C struct TCServer *tc_server_new_local(struct TCString server_dir, struct // // The server must be freed after it is used - tc_replica_sync does not automatically free it. EXTERN_C struct TCServer *tc_server_new_remote(struct TCString origin, - struct TCUuid client_key, + struct TCUuid client_id, struct TCString encryption_secret, struct TCString *error_out); diff --git a/taskchampion/sync-server/src/api/add_snapshot.rs b/taskchampion/sync-server/src/api/add_snapshot.rs index da1443c73..d92174c7a 100644 --- a/taskchampion/sync-server/src/api/add_snapshot.rs +++ b/taskchampion/sync-server/src/api/add_snapshot.rs @@ -1,4 +1,4 @@ -use crate::api::{client_key_header, failure_to_ise, ServerState, SNAPSHOT_CONTENT_TYPE}; +use crate::api::{client_id_header, failure_to_ise, ServerState, SNAPSHOT_CONTENT_TYPE}; use crate::server::{add_snapshot, VersionId, NIL_VERSION_ID}; use actix_web::{error, post, web, HttpMessage, HttpRequest, HttpResponse, Result}; use futures::StreamExt; @@ -29,7 +29,7 @@ pub(crate) async fn service( return Err(error::ErrorBadRequest("Bad content-type")); } - let client_key = client_key_header(&req)?; + let client_id = client_id_header(&req)?; // read the body in its entirety let mut body = web::BytesMut::new(); @@ -52,19 +52,19 @@ pub(crate) async fn service( let mut txn = server_state.storage.txn().map_err(failure_to_ise)?; // get, or create, the client - let client = match txn.get_client(client_key).map_err(failure_to_ise)? { + let client = match txn.get_client(client_id).map_err(failure_to_ise)? { Some(client) => client, None => { - txn.new_client(client_key, NIL_VERSION_ID) + txn.new_client(client_id, NIL_VERSION_ID) .map_err(failure_to_ise)?; - txn.get_client(client_key).map_err(failure_to_ise)?.unwrap() + txn.get_client(client_id).map_err(failure_to_ise)?.unwrap() } }; add_snapshot( txn, &server_state.config, - client_key, + client_id, client, version_id, body.to_vec(), @@ -76,6 +76,7 @@ pub(crate) async fn service( #[cfg(test)] mod test { use super::*; + use crate::api::CLIENT_ID_HEADER; use crate::storage::{InMemoryStorage, Storage}; use crate::Server; use actix_web::{http::StatusCode, test, App}; @@ -84,15 +85,15 @@ mod test { #[actix_rt::test] async fn test_success() -> anyhow::Result<()> { - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let version_id = Uuid::new_v4(); let storage: Box = Box::new(InMemoryStorage::new()); // set up the storage contents.. { let mut txn = storage.txn().unwrap(); - txn.new_client(client_key, version_id).unwrap(); - txn.add_version(client_key, version_id, NIL_VERSION_ID, vec![])?; + txn.new_client(client_id, version_id).unwrap(); + txn.add_version(client_id, version_id, NIL_VERSION_ID, vec![])?; } let server = Server::new(Default::default(), storage); @@ -103,7 +104,7 @@ mod test { let req = test::TestRequest::post() .uri(&uri) .insert_header(("Content-Type", "application/vnd.taskchampion.snapshot")) - .insert_header(("X-Client-Key", client_key.to_string())) + .insert_header((CLIENT_ID_HEADER, client_id.to_string())) .set_payload(b"abcd".to_vec()) .to_request(); let resp = test::call_service(&mut app, req).await; @@ -113,7 +114,7 @@ mod test { let uri = "/v1/client/snapshot"; let req = test::TestRequest::get() .uri(uri) - .append_header(("X-Client-Key", client_key.to_string())) + .append_header((CLIENT_ID_HEADER, client_id.to_string())) .to_request(); let resp = test::call_service(&mut app, req).await; assert_eq!(resp.status(), StatusCode::OK); @@ -127,14 +128,14 @@ mod test { #[actix_rt::test] async fn test_not_added_200() { - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let version_id = Uuid::new_v4(); let storage: Box = Box::new(InMemoryStorage::new()); // set up the storage contents.. { let mut txn = storage.txn().unwrap(); - txn.new_client(client_key, NIL_VERSION_ID).unwrap(); + txn.new_client(client_id, NIL_VERSION_ID).unwrap(); } let server = Server::new(Default::default(), storage); @@ -146,7 +147,7 @@ mod test { let req = test::TestRequest::post() .uri(&uri) .append_header(("Content-Type", "application/vnd.taskchampion.snapshot")) - .append_header(("X-Client-Key", client_key.to_string())) + .append_header((CLIENT_ID_HEADER, client_id.to_string())) .set_payload(b"abcd".to_vec()) .to_request(); let resp = test::call_service(&mut app, req).await; @@ -156,7 +157,7 @@ mod test { let uri = "/v1/client/snapshot"; let req = test::TestRequest::get() .uri(uri) - .append_header(("X-Client-Key", client_key.to_string())) + .append_header((CLIENT_ID_HEADER, client_id.to_string())) .to_request(); let resp = test::call_service(&mut app, req).await; assert_eq!(resp.status(), StatusCode::NOT_FOUND); @@ -164,7 +165,7 @@ mod test { #[actix_rt::test] async fn test_bad_content_type() { - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let version_id = Uuid::new_v4(); let storage: Box = Box::new(InMemoryStorage::new()); let server = Server::new(Default::default(), storage); @@ -175,7 +176,7 @@ mod test { let req = test::TestRequest::post() .uri(&uri) .append_header(("Content-Type", "not/correct")) - .append_header(("X-Client-Key", client_key.to_string())) + .append_header((CLIENT_ID_HEADER, client_id.to_string())) .set_payload(b"abcd".to_vec()) .to_request(); let resp = test::call_service(&mut app, req).await; @@ -184,7 +185,7 @@ mod test { #[actix_rt::test] async fn test_empty_body() { - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let version_id = Uuid::new_v4(); let storage: Box = Box::new(InMemoryStorage::new()); let server = Server::new(Default::default(), storage); @@ -198,7 +199,7 @@ mod test { "Content-Type", "application/vnd.taskchampion.history-segment", )) - .append_header(("X-Client-Key", client_key.to_string())) + .append_header((CLIENT_ID_HEADER, client_id.to_string())) .to_request(); let resp = test::call_service(&mut app, req).await; assert_eq!(resp.status(), StatusCode::BAD_REQUEST); diff --git a/taskchampion/sync-server/src/api/add_version.rs b/taskchampion/sync-server/src/api/add_version.rs index 157fbd779..7428d94e0 100644 --- a/taskchampion/sync-server/src/api/add_version.rs +++ b/taskchampion/sync-server/src/api/add_version.rs @@ -1,5 +1,5 @@ use crate::api::{ - client_key_header, failure_to_ise, ServerState, HISTORY_SEGMENT_CONTENT_TYPE, + client_id_header, failure_to_ise, ServerState, HISTORY_SEGMENT_CONTENT_TYPE, PARENT_VERSION_ID_HEADER, SNAPSHOT_REQUEST_HEADER, VERSION_ID_HEADER, }; use crate::server::{add_version, AddVersionResult, SnapshotUrgency, VersionId, NIL_VERSION_ID}; @@ -37,7 +37,7 @@ pub(crate) async fn service( return Err(error::ErrorBadRequest("Bad content-type")); } - let client_key = client_key_header(&req)?; + let client_id = client_id_header(&req)?; // read the body in its entirety let mut body = web::BytesMut::new(); @@ -60,19 +60,19 @@ pub(crate) async fn service( let mut txn = server_state.storage.txn().map_err(failure_to_ise)?; // get, or create, the client - let client = match txn.get_client(client_key).map_err(failure_to_ise)? { + let client = match txn.get_client(client_id).map_err(failure_to_ise)? { Some(client) => client, None => { - txn.new_client(client_key, NIL_VERSION_ID) + txn.new_client(client_id, NIL_VERSION_ID) .map_err(failure_to_ise)?; - txn.get_client(client_key).map_err(failure_to_ise)?.unwrap() + txn.get_client(client_id).map_err(failure_to_ise)?.unwrap() } }; let (result, snap_urgency) = add_version( txn, &server_state.config, - client_key, + client_id, client, parent_version_id, body.to_vec(), @@ -104,6 +104,7 @@ pub(crate) async fn service( #[cfg(test)] mod test { + use crate::api::CLIENT_ID_HEADER; use crate::storage::{InMemoryStorage, Storage}; use crate::Server; use actix_web::{http::StatusCode, test, App}; @@ -112,7 +113,7 @@ mod test { #[actix_rt::test] async fn test_success() { - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let version_id = Uuid::new_v4(); let parent_version_id = Uuid::new_v4(); let storage: Box = Box::new(InMemoryStorage::new()); @@ -120,7 +121,7 @@ mod test { // set up the storage contents.. { let mut txn = storage.txn().unwrap(); - txn.new_client(client_key, Uuid::nil()).unwrap(); + txn.new_client(client_id, Uuid::nil()).unwrap(); } let server = Server::new(Default::default(), storage); @@ -134,7 +135,7 @@ mod test { "Content-Type", "application/vnd.taskchampion.history-segment", )) - .append_header(("X-Client-Key", client_key.to_string())) + .append_header((CLIENT_ID_HEADER, client_id.to_string())) .set_payload(b"abcd".to_vec()) .to_request(); let resp = test::call_service(&mut app, req).await; @@ -154,7 +155,7 @@ mod test { #[actix_rt::test] async fn test_conflict() { - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let version_id = Uuid::new_v4(); let parent_version_id = Uuid::new_v4(); let storage: Box = Box::new(InMemoryStorage::new()); @@ -162,7 +163,7 @@ mod test { // set up the storage contents.. { let mut txn = storage.txn().unwrap(); - txn.new_client(client_key, version_id).unwrap(); + txn.new_client(client_id, version_id).unwrap(); } let server = Server::new(Default::default(), storage); @@ -176,7 +177,7 @@ mod test { "Content-Type", "application/vnd.taskchampion.history-segment", )) - .append_header(("X-Client-Key", client_key.to_string())) + .append_header((CLIENT_ID_HEADER, client_id.to_string())) .set_payload(b"abcd".to_vec()) .to_request(); let resp = test::call_service(&mut app, req).await; @@ -190,7 +191,7 @@ mod test { #[actix_rt::test] async fn test_bad_content_type() { - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let parent_version_id = Uuid::new_v4(); let storage: Box = Box::new(InMemoryStorage::new()); let server = Server::new(Default::default(), storage); @@ -201,7 +202,7 @@ mod test { let req = test::TestRequest::post() .uri(&uri) .append_header(("Content-Type", "not/correct")) - .append_header(("X-Client-Key", client_key.to_string())) + .append_header((CLIENT_ID_HEADER, client_id.to_string())) .set_payload(b"abcd".to_vec()) .to_request(); let resp = test::call_service(&mut app, req).await; @@ -210,7 +211,7 @@ mod test { #[actix_rt::test] async fn test_empty_body() { - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let parent_version_id = Uuid::new_v4(); let storage: Box = Box::new(InMemoryStorage::new()); let server = Server::new(Default::default(), storage); @@ -224,7 +225,7 @@ mod test { "Content-Type", "application/vnd.taskchampion.history-segment", )) - .append_header(("X-Client-Key", client_key.to_string())) + .append_header((CLIENT_ID_HEADER, client_id.to_string())) .to_request(); let resp = test::call_service(&mut app, req).await; assert_eq!(resp.status(), StatusCode::BAD_REQUEST); diff --git a/taskchampion/sync-server/src/api/get_child_version.rs b/taskchampion/sync-server/src/api/get_child_version.rs index 2ec4399bf..cb0e74fd7 100644 --- a/taskchampion/sync-server/src/api/get_child_version.rs +++ b/taskchampion/sync-server/src/api/get_child_version.rs @@ -1,5 +1,5 @@ use crate::api::{ - client_key_header, failure_to_ise, ServerState, HISTORY_SEGMENT_CONTENT_TYPE, + client_id_header, failure_to_ise, ServerState, HISTORY_SEGMENT_CONTENT_TYPE, PARENT_VERSION_ID_HEADER, VERSION_ID_HEADER, }; use crate::server::{get_child_version, GetVersionResult, VersionId}; @@ -24,17 +24,17 @@ pub(crate) async fn service( let mut txn = server_state.storage.txn().map_err(failure_to_ise)?; - let client_key = client_key_header(&req)?; + let client_id = client_id_header(&req)?; let client = txn - .get_client(client_key) + .get_client(client_id) .map_err(failure_to_ise)? .ok_or_else(|| error::ErrorNotFound("no such client"))?; return match get_child_version( txn, &server_state.config, - client_key, + client_id, client, parent_version_id, ) @@ -56,6 +56,7 @@ pub(crate) async fn service( #[cfg(test)] mod test { + use crate::api::CLIENT_ID_HEADER; use crate::server::NIL_VERSION_ID; use crate::storage::{InMemoryStorage, Storage}; use crate::Server; @@ -65,7 +66,7 @@ mod test { #[actix_rt::test] async fn test_success() { - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let version_id = Uuid::new_v4(); let parent_version_id = Uuid::new_v4(); let storage: Box = Box::new(InMemoryStorage::new()); @@ -73,8 +74,8 @@ mod test { // set up the storage contents.. { let mut txn = storage.txn().unwrap(); - txn.new_client(client_key, Uuid::new_v4()).unwrap(); - txn.add_version(client_key, version_id, parent_version_id, b"abcd".to_vec()) + txn.new_client(client_id, Uuid::new_v4()).unwrap(); + txn.add_version(client_id, version_id, parent_version_id, b"abcd".to_vec()) .unwrap(); } @@ -85,7 +86,7 @@ mod test { let uri = format!("/v1/client/get-child-version/{}", parent_version_id); let req = test::TestRequest::get() .uri(&uri) - .append_header(("X-Client-Key", client_key.to_string())) + .append_header((CLIENT_ID_HEADER, client_id.to_string())) .to_request(); let resp = test::call_service(&mut app, req).await; assert_eq!(resp.status(), StatusCode::OK); @@ -109,7 +110,7 @@ mod test { #[actix_rt::test] async fn test_client_not_found() { - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let parent_version_id = Uuid::new_v4(); let storage: Box = Box::new(InMemoryStorage::new()); let server = Server::new(Default::default(), storage); @@ -119,7 +120,7 @@ mod test { let uri = format!("/v1/client/get-child-version/{}", parent_version_id); let req = test::TestRequest::get() .uri(&uri) - .append_header(("X-Client-Key", client_key.to_string())) + .append_header((CLIENT_ID_HEADER, client_id.to_string())) .to_request(); let resp = test::call_service(&mut app, req).await; assert_eq!(resp.status(), StatusCode::NOT_FOUND); @@ -129,14 +130,14 @@ mod test { #[actix_rt::test] async fn test_version_not_found_and_gone() { - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let parent_version_id = Uuid::new_v4(); let storage: Box = Box::new(InMemoryStorage::new()); // create the client, but not the version { let mut txn = storage.txn().unwrap(); - txn.new_client(client_key, Uuid::new_v4()).unwrap(); + txn.new_client(client_id, Uuid::new_v4()).unwrap(); } let server = Server::new(Default::default(), storage); let app = App::new().configure(|sc| server.config(sc)); @@ -146,7 +147,7 @@ mod test { let uri = format!("/v1/client/get-child-version/{}", parent_version_id); let req = test::TestRequest::get() .uri(&uri) - .append_header(("X-Client-Key", client_key.to_string())) + .append_header((CLIENT_ID_HEADER, client_id.to_string())) .to_request(); let resp = test::call_service(&mut app, req).await; assert_eq!(resp.status(), StatusCode::GONE); @@ -159,7 +160,7 @@ mod test { let uri = format!("/v1/client/get-child-version/{}", NIL_VERSION_ID); let req = test::TestRequest::get() .uri(&uri) - .append_header(("X-Client-Key", client_key.to_string())) + .append_header((CLIENT_ID_HEADER, client_id.to_string())) .to_request(); let resp = test::call_service(&mut app, req).await; assert_eq!(resp.status(), StatusCode::NOT_FOUND); diff --git a/taskchampion/sync-server/src/api/get_snapshot.rs b/taskchampion/sync-server/src/api/get_snapshot.rs index 633d499bd..4135257f4 100644 --- a/taskchampion/sync-server/src/api/get_snapshot.rs +++ b/taskchampion/sync-server/src/api/get_snapshot.rs @@ -1,5 +1,5 @@ use crate::api::{ - client_key_header, failure_to_ise, ServerState, SNAPSHOT_CONTENT_TYPE, VERSION_ID_HEADER, + client_id_header, failure_to_ise, ServerState, SNAPSHOT_CONTENT_TYPE, VERSION_ID_HEADER, }; use crate::server::get_snapshot; use actix_web::{error, get, web, HttpRequest, HttpResponse, Result}; @@ -20,15 +20,15 @@ pub(crate) async fn service( ) -> Result { let mut txn = server_state.storage.txn().map_err(failure_to_ise)?; - let client_key = client_key_header(&req)?; + let client_id = client_id_header(&req)?; let client = txn - .get_client(client_key) + .get_client(client_id) .map_err(failure_to_ise)? .ok_or_else(|| error::ErrorNotFound("no such client"))?; if let Some((version_id, data)) = - get_snapshot(txn, &server_state.config, client_key, client).map_err(failure_to_ise)? + get_snapshot(txn, &server_state.config, client_id, client).map_err(failure_to_ise)? { Ok(HttpResponse::Ok() .content_type(SNAPSHOT_CONTENT_TYPE) @@ -41,6 +41,7 @@ pub(crate) async fn service( #[cfg(test)] mod test { + use crate::api::CLIENT_ID_HEADER; use crate::storage::{InMemoryStorage, Snapshot, Storage}; use crate::Server; use actix_web::{http::StatusCode, test, App}; @@ -50,13 +51,13 @@ mod test { #[actix_rt::test] async fn test_not_found() { - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let storage: Box = Box::new(InMemoryStorage::new()); // set up the storage contents.. { let mut txn = storage.txn().unwrap(); - txn.new_client(client_key, Uuid::new_v4()).unwrap(); + txn.new_client(client_id, Uuid::new_v4()).unwrap(); } let server = Server::new(Default::default(), storage); @@ -66,7 +67,7 @@ mod test { let uri = "/v1/client/snapshot"; let req = test::TestRequest::get() .uri(uri) - .append_header(("X-Client-Key", client_key.to_string())) + .append_header((CLIENT_ID_HEADER, client_id.to_string())) .to_request(); let resp = test::call_service(&mut app, req).await; assert_eq!(resp.status(), StatusCode::NOT_FOUND); @@ -74,7 +75,7 @@ mod test { #[actix_rt::test] async fn test_success() { - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let version_id = Uuid::new_v4(); let snapshot_data = vec![1, 2, 3, 4]; let storage: Box = Box::new(InMemoryStorage::new()); @@ -82,9 +83,9 @@ mod test { // set up the storage contents.. { let mut txn = storage.txn().unwrap(); - txn.new_client(client_key, Uuid::new_v4()).unwrap(); + txn.new_client(client_id, Uuid::new_v4()).unwrap(); txn.set_snapshot( - client_key, + client_id, Snapshot { version_id, versions_since: 3, @@ -102,7 +103,7 @@ mod test { let uri = "/v1/client/snapshot"; let req = test::TestRequest::get() .uri(uri) - .append_header(("X-Client-Key", client_key.to_string())) + .append_header((CLIENT_ID_HEADER, client_id.to_string())) .to_request(); let resp = test::call_service(&mut app, req).await; assert_eq!(resp.status(), StatusCode::OK); diff --git a/taskchampion/sync-server/src/api/mod.rs b/taskchampion/sync-server/src/api/mod.rs index 1a12b2826..bb5001f3b 100644 --- a/taskchampion/sync-server/src/api/mod.rs +++ b/taskchampion/sync-server/src/api/mod.rs @@ -1,4 +1,4 @@ -use crate::server::ClientKey; +use crate::server::ClientId; use crate::storage::Storage; use crate::ServerConfig; use actix_web::{error, http::StatusCode, web, HttpRequest, Result, Scope}; @@ -18,8 +18,8 @@ pub(crate) const SNAPSHOT_CONTENT_TYPE: &str = "application/vnd.taskchampion.sna /// The header name for version ID pub(crate) const VERSION_ID_HEADER: &str = "X-Version-Id"; -/// The header name for client key -pub(crate) const CLIENT_KEY_HEADER: &str = "X-Client-Key"; +/// The header name for client id +pub(crate) const CLIENT_ID_HEADER: &str = "X-Client-Id"; /// The header name for parent version ID pub(crate) const PARENT_VERSION_ID_HEADER: &str = "X-Parent-Version-Id"; @@ -46,15 +46,15 @@ fn failure_to_ise(err: anyhow::Error) -> impl actix_web::ResponseError { error::InternalError::new(err, StatusCode::INTERNAL_SERVER_ERROR) } -/// Get the client key -fn client_key_header(req: &HttpRequest) -> Result { +/// Get the client id +fn client_id_header(req: &HttpRequest) -> Result { fn badrequest() -> error::Error { error::ErrorBadRequest("bad x-client-id") } - if let Some(client_key_hdr) = req.headers().get(CLIENT_KEY_HEADER) { - let client_key = client_key_hdr.to_str().map_err(|_| badrequest())?; - let client_key = ClientKey::parse_str(client_key).map_err(|_| badrequest())?; - Ok(client_key) + if let Some(client_id_hdr) = req.headers().get(CLIENT_ID_HEADER) { + let client_id = client_id_hdr.to_str().map_err(|_| badrequest())?; + let client_id = ClientId::parse_str(client_id).map_err(|_| badrequest())?; + Ok(client_id) } else { Err(badrequest()) } diff --git a/taskchampion/sync-server/src/server.rs b/taskchampion/sync-server/src/server.rs index 8dc2c8ab5..61e349e2c 100644 --- a/taskchampion/sync-server/src/server.rs +++ b/taskchampion/sync-server/src/server.rs @@ -14,7 +14,7 @@ pub const NIL_VERSION_ID: VersionId = Uuid::nil(); const SNAPSHOT_SEARCH_LEN: i32 = 5; pub(crate) type HistorySegment = Vec; -pub(crate) type ClientKey = Uuid; +pub(crate) type ClientId = Uuid; pub(crate) type VersionId = Uuid; /// ServerConfig contains configuration parameters for the server. @@ -60,12 +60,12 @@ pub(crate) enum GetVersionResult { pub(crate) fn get_child_version<'a>( mut txn: Box, _config: &ServerConfig, - client_key: ClientKey, + client_id: ClientId, client: Client, parent_version_id: VersionId, ) -> anyhow::Result { // If a version with parentVersionId equal to the requested parentVersionId exists, it is returned. - if let Some(version) = txn.get_version_by_parent(client_key, parent_version_id)? { + if let Some(version) = txn.get_version_by_parent(client_id, parent_version_id)? { return Ok(GetVersionResult::Success { version_id: version.version_id, parent_version_id: version.parent_version_id, @@ -86,7 +86,7 @@ pub(crate) fn get_child_version<'a>( } // If a version with versionId equal to the requested parentVersionId exists, the response is _not-found_ (the client is up-to-date) - if txn.get_version(client_key, parent_version_id)?.is_some() { + if txn.get_version(client_id, parent_version_id)?.is_some() { return Ok(GetVersionResult::NotFound); } @@ -144,14 +144,14 @@ impl SnapshotUrgency { pub(crate) fn add_version<'a>( mut txn: Box, config: &ServerConfig, - client_key: ClientKey, + client_id: ClientId, client: Client, parent_version_id: VersionId, history_segment: HistorySegment, ) -> anyhow::Result<(AddVersionResult, SnapshotUrgency)> { log::debug!( - "add_version(client_key: {}, parent_version_id: {})", - client_key, + "add_version(client_id: {}, parent_version_id: {})", + client_id, parent_version_id, ); @@ -172,7 +172,7 @@ pub(crate) fn add_version<'a>( ); // update the DB - txn.add_version(client_key, version_id, parent_version_id, history_segment)?; + txn.add_version(client_id, version_id, parent_version_id, history_segment)?; txn.commit()?; // calculate the urgency @@ -200,14 +200,14 @@ pub(crate) fn add_version<'a>( pub(crate) fn add_snapshot<'a>( mut txn: Box, _config: &ServerConfig, - client_key: ClientKey, + client_id: ClientId, client: Client, version_id: VersionId, data: Vec, ) -> anyhow::Result<()> { log::debug!( - "add_snapshot(client_key: {}, version_id: {})", - client_key, + "add_snapshot(client_id: {}, version_id: {})", + client_id, version_id, ); @@ -254,7 +254,7 @@ pub(crate) fn add_snapshot<'a>( } // get the parent version ID - if let Some(parent) = txn.get_version(client_key, vid)? { + if let Some(parent) = txn.get_version(client_id, vid)? { vid = parent.parent_version_id; } else { // this version does not exist; "this should not happen" but if it does, @@ -269,7 +269,7 @@ pub(crate) fn add_snapshot<'a>( log::warn!("accepting snapshot for version {}", version_id); txn.set_snapshot( - client_key, + client_id, Snapshot { version_id, timestamp: Utc::now(), @@ -285,11 +285,11 @@ pub(crate) fn add_snapshot<'a>( pub(crate) fn get_snapshot<'a>( mut txn: Box, _config: &ServerConfig, - client_key: ClientKey, + client_id: ClientId, client: Client, ) -> anyhow::Result)>> { Ok(if let Some(snap) = client.snapshot { - txn.get_snapshot_data(client_key, snap.version_id)? + txn.get_snapshot_data(client_id, snap.version_id)? .map(|data| (snap.version_id, data)) } else { None @@ -354,16 +354,16 @@ mod test { let storage = InMemoryStorage::new(); let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); - txn.new_client(client_key, NIL_VERSION_ID)?; + let client_id = Uuid::new_v4(); + txn.new_client(client_id, NIL_VERSION_ID)?; // when no snapshot exists, the first version is NotFound - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); assert_eq!( get_child_version( txn, &ServerConfig::default(), - client_key, + client_id, client, NIL_VERSION_ID )?, @@ -378,11 +378,11 @@ mod test { let storage = InMemoryStorage::new(); let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); - txn.new_client(client_key, Uuid::new_v4())?; + txn.new_client(client_id, Uuid::new_v4())?; txn.set_snapshot( - client_key, + client_id, Snapshot { version_id: Uuid::new_v4(), versions_since: 0, @@ -392,12 +392,12 @@ mod test { )?; // when a snapshot exists, the first version is GONE - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); assert_eq!( get_child_version( txn, &ServerConfig::default(), - client_key, + client_id, client, NIL_VERSION_ID )?, @@ -412,19 +412,19 @@ mod test { let storage = InMemoryStorage::new(); let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); // add a parent version, but not the requested child version let parent_version_id = Uuid::new_v4(); - txn.new_client(client_key, parent_version_id)?; - txn.add_version(client_key, parent_version_id, NIL_VERSION_ID, vec![])?; + txn.new_client(client_id, parent_version_id)?; + txn.add_version(client_id, parent_version_id, NIL_VERSION_ID, vec![])?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); assert_eq!( get_child_version( txn, &ServerConfig::default(), - client_key, + client_id, client, parent_version_id )?, @@ -439,19 +439,19 @@ mod test { let storage = InMemoryStorage::new(); let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); // make up a parent version id, but neither that version // nor its child exists (presumed to have been deleted) let parent_version_id = Uuid::new_v4(); - txn.new_client(client_key, Uuid::new_v4())?; + txn.new_client(client_id, Uuid::new_v4())?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); assert_eq!( get_child_version( txn, &ServerConfig::default(), - client_key, + client_id, client, parent_version_id )?, @@ -466,25 +466,25 @@ mod test { let storage = InMemoryStorage::new(); let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let version_id = Uuid::new_v4(); let parent_version_id = Uuid::new_v4(); let history_segment = b"abcd".to_vec(); - txn.new_client(client_key, version_id)?; + txn.new_client(client_id, version_id)?; txn.add_version( - client_key, + client_id, version_id, parent_version_id, history_segment.clone(), )?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); assert_eq!( get_child_version( txn, &ServerConfig::default(), - client_key, + client_id, client, parent_version_id )?, @@ -506,24 +506,24 @@ mod test { ) -> anyhow::Result<(Uuid, Vec)> { init_logging(); let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let mut versions = vec![]; let mut version_id = Uuid::nil(); - txn.new_client(client_key, Uuid::nil())?; + txn.new_client(client_id, Uuid::nil())?; for vnum in 0..num_versions { let parent_version_id = version_id; version_id = Uuid::new_v4(); versions.push(version_id); txn.add_version( - client_key, + client_id, version_id, parent_version_id, vec![0, 0, vnum as u8], )?; if Some(vnum) == snapshot_version { txn.set_snapshot( - client_key, + client_id, Snapshot { version_id, versions_since: 0, @@ -534,13 +534,13 @@ mod test { } } - Ok((client_key, versions)) + Ok((client_id, versions)) } /// Utility function to check the results of an add_version call fn av_success_check( storage: &InMemoryStorage, - client_key: Uuid, + client_id: Uuid, existing_versions: &[Uuid], result: (AddVersionResult, SnapshotUrgency), expected_history: Vec, @@ -554,11 +554,11 @@ mod test { // verify that the storage was updated let mut txn = storage.txn()?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); assert_eq!(client.latest_version_id, new_version_id); let parent_version_id = existing_versions.last().cloned().unwrap_or_else(Uuid::nil); - let version = txn.get_version(client_key, new_version_id)?.unwrap(); + let version = txn.get_version(client_id, new_version_id)?.unwrap(); assert_eq!(version.version_id, new_version_id); assert_eq!(version.parent_version_id, parent_version_id); assert_eq!(version.history_segment, expected_history); @@ -574,17 +574,17 @@ mod test { #[test] fn add_version_conflict() -> anyhow::Result<()> { let storage = InMemoryStorage::new(); - let (client_key, versions) = av_setup(&storage, 3, None, None)?; + let (client_id, versions) = av_setup(&storage, 3, None, None)?; let mut txn = storage.txn()?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); // try to add a child of a version other than the latest assert_eq!( add_version( txn, &ServerConfig::default(), - client_key, + client_id, client, versions[1], vec![3, 6, 9] @@ -596,10 +596,10 @@ mod test { // verify that the storage wasn't updated txn = storage.txn()?; assert_eq!( - txn.get_client(client_key)?.unwrap().latest_version_id, + txn.get_client(client_id)?.unwrap().latest_version_id, versions[2] ); - assert_eq!(txn.get_version_by_parent(client_key, versions[2])?, None); + assert_eq!(txn.get_version_by_parent(client_id, versions[2])?, None); Ok(()) } @@ -607,15 +607,15 @@ mod test { #[test] fn add_version_with_existing_history() -> anyhow::Result<()> { let storage = InMemoryStorage::new(); - let (client_key, versions) = av_setup(&storage, 1, None, None)?; + let (client_id, versions) = av_setup(&storage, 1, None, None)?; let mut txn = storage.txn()?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); let result = add_version( txn, &ServerConfig::default(), - client_key, + client_id, client, versions[0], vec![3, 6, 9], @@ -623,7 +623,7 @@ mod test { av_success_check( &storage, - client_key, + client_id, &versions, result, vec![3, 6, 9], @@ -637,16 +637,16 @@ mod test { #[test] fn add_version_with_no_history() -> anyhow::Result<()> { let storage = InMemoryStorage::new(); - let (client_key, versions) = av_setup(&storage, 0, None, None)?; + let (client_id, versions) = av_setup(&storage, 0, None, None)?; let mut txn = storage.txn()?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); let parent_version_id = Uuid::nil(); let result = add_version( txn, &ServerConfig::default(), - client_key, + client_id, client, parent_version_id, vec![3, 6, 9], @@ -654,7 +654,7 @@ mod test { av_success_check( &storage, - client_key, + client_id, &versions, result, vec![3, 6, 9], @@ -668,15 +668,15 @@ mod test { #[test] fn add_version_success_recent_snapshot() -> anyhow::Result<()> { let storage = InMemoryStorage::new(); - let (client_key, versions) = av_setup(&storage, 1, Some(0), None)?; + let (client_id, versions) = av_setup(&storage, 1, Some(0), None)?; let mut txn = storage.txn()?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); let result = add_version( txn, &ServerConfig::default(), - client_key, + client_id, client, versions[0], vec![1, 2, 3], @@ -684,7 +684,7 @@ mod test { av_success_check( &storage, - client_key, + client_id, &versions, result, vec![1, 2, 3], @@ -699,15 +699,15 @@ mod test { fn add_version_success_aged_snapshot() -> anyhow::Result<()> { let storage = InMemoryStorage::new(); // one snapshot, but it was 50 days ago - let (client_key, versions) = av_setup(&storage, 1, Some(0), Some(50))?; + let (client_id, versions) = av_setup(&storage, 1, Some(0), Some(50))?; let mut txn = storage.txn()?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); let result = add_version( txn, &ServerConfig::default(), - client_key, + client_id, client, versions[0], vec![1, 2, 3], @@ -715,7 +715,7 @@ mod test { av_success_check( &storage, - client_key, + client_id, &versions, result, vec![1, 2, 3], @@ -730,10 +730,10 @@ mod test { fn add_version_success_snapshot_many_versions_ago() -> anyhow::Result<()> { let storage = InMemoryStorage::new(); // one snapshot, but it was 50 versions ago - let (client_key, versions) = av_setup(&storage, 50, Some(0), None)?; + let (client_id, versions) = av_setup(&storage, 50, Some(0), None)?; let mut txn = storage.txn()?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); let result = add_version( txn, @@ -741,7 +741,7 @@ mod test { snapshot_versions: 30, ..ServerConfig::default() }, - client_key, + client_id, client, versions[49], vec![1, 2, 3], @@ -749,7 +749,7 @@ mod test { av_success_check( &storage, - client_key, + client_id, &versions, result, vec![1, 2, 3], @@ -766,19 +766,19 @@ mod test { let storage = InMemoryStorage::new(); let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let version_id = Uuid::new_v4(); // set up a task DB with one version in it - txn.new_client(client_key, version_id)?; - txn.add_version(client_key, version_id, NIL_VERSION_ID, vec![])?; + txn.new_client(client_id, version_id)?; + txn.add_version(client_id, version_id, NIL_VERSION_ID, vec![])?; // add a snapshot for that version - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); add_snapshot( txn, &ServerConfig::default(), - client_key, + client_id, client, version_id, vec![1, 2, 3], @@ -786,12 +786,12 @@ mod test { // verify the snapshot let mut txn = storage.txn()?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); let snapshot = client.snapshot.unwrap(); assert_eq!(snapshot.version_id, version_id); assert_eq!(snapshot.versions_since, 0); assert_eq!( - txn.get_snapshot_data(client_key, version_id).unwrap(), + txn.get_snapshot_data(client_id, version_id).unwrap(), Some(vec![1, 2, 3]) ); @@ -804,21 +804,21 @@ mod test { let storage = InMemoryStorage::new(); let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let version_id_1 = Uuid::new_v4(); let version_id_2 = Uuid::new_v4(); // set up a task DB with two versions in it - txn.new_client(client_key, version_id_2)?; - txn.add_version(client_key, version_id_1, NIL_VERSION_ID, vec![])?; - txn.add_version(client_key, version_id_2, version_id_1, vec![])?; + txn.new_client(client_id, version_id_2)?; + txn.add_version(client_id, version_id_1, NIL_VERSION_ID, vec![])?; + txn.add_version(client_id, version_id_2, version_id_1, vec![])?; // add a snapshot for version 1 - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); add_snapshot( txn, &ServerConfig::default(), - client_key, + client_id, client, version_id_1, vec![1, 2, 3], @@ -826,12 +826,12 @@ mod test { // verify the snapshot let mut txn = storage.txn()?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); let snapshot = client.snapshot.unwrap(); assert_eq!(snapshot.version_id, version_id_1); assert_eq!(snapshot.versions_since, 0); assert_eq!( - txn.get_snapshot_data(client_key, version_id_1).unwrap(), + txn.get_snapshot_data(client_id, version_id_1).unwrap(), Some(vec![1, 2, 3]) ); @@ -844,22 +844,22 @@ mod test { let storage = InMemoryStorage::new(); let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let version_id_1 = Uuid::new_v4(); let version_id_2 = Uuid::new_v4(); // set up a task DB with two versions in it - txn.new_client(client_key, version_id_2)?; - txn.add_version(client_key, version_id_1, NIL_VERSION_ID, vec![])?; - txn.add_version(client_key, version_id_2, version_id_1, vec![])?; + txn.new_client(client_id, version_id_2)?; + txn.add_version(client_id, version_id_1, NIL_VERSION_ID, vec![])?; + txn.add_version(client_id, version_id_2, version_id_1, vec![])?; // add a snapshot for unknown version - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); let version_id_unk = Uuid::new_v4(); add_snapshot( txn, &ServerConfig::default(), - client_key, + client_id, client, version_id_unk, vec![1, 2, 3], @@ -867,7 +867,7 @@ mod test { // verify the snapshot does not exist let mut txn = storage.txn()?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); assert!(client.snapshot.is_none()); Ok(()) @@ -879,26 +879,26 @@ mod test { let storage = InMemoryStorage::new(); let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let mut version_id = Uuid::new_v4(); let mut parent_version_id = Uuid::nil(); let mut version_ids = vec![]; // set up a task DB with 10 versions in it (oldest to newest) - txn.new_client(client_key, Uuid::nil())?; + txn.new_client(client_id, Uuid::nil())?; for _ in 0..10 { - txn.add_version(client_key, version_id, parent_version_id, vec![])?; + txn.add_version(client_id, version_id, parent_version_id, vec![])?; version_ids.push(version_id); parent_version_id = version_id; version_id = Uuid::new_v4(); } // add a snapshot for the earliest of those - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); add_snapshot( txn, &ServerConfig::default(), - client_key, + client_id, client, version_ids[0], vec![1, 2, 3], @@ -906,7 +906,7 @@ mod test { // verify the snapshot does not exist let mut txn = storage.txn()?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); assert!(client.snapshot.is_none()); Ok(()) @@ -918,22 +918,22 @@ mod test { let storage = InMemoryStorage::new(); let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let mut version_id = Uuid::new_v4(); let mut parent_version_id = Uuid::nil(); let mut version_ids = vec![]; // set up a task DB with 5 versions in it (oldest to newest) and a snapshot of the middle // one - txn.new_client(client_key, Uuid::nil())?; + txn.new_client(client_id, Uuid::nil())?; for _ in 0..5 { - txn.add_version(client_key, version_id, parent_version_id, vec![])?; + txn.add_version(client_id, version_id, parent_version_id, vec![])?; version_ids.push(version_id); parent_version_id = version_id; version_id = Uuid::new_v4(); } txn.set_snapshot( - client_key, + client_id, Snapshot { version_id: version_ids[2], versions_since: 2, @@ -943,11 +943,11 @@ mod test { )?; // add a snapshot for the earliest of those - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); add_snapshot( txn, &ServerConfig::default(), - client_key, + client_id, client, version_ids[0], vec![9, 9, 9], @@ -955,12 +955,12 @@ mod test { // verify the snapshot was not replaced let mut txn = storage.txn()?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); let snapshot = client.snapshot.unwrap(); assert_eq!(snapshot.version_id, version_ids[2]); assert_eq!(snapshot.versions_since, 2); assert_eq!( - txn.get_snapshot_data(client_key, version_ids[2]).unwrap(), + txn.get_snapshot_data(client_id, version_ids[2]).unwrap(), Some(vec![1, 2, 3]) ); @@ -973,17 +973,17 @@ mod test { let storage = InMemoryStorage::new(); let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); // just set up the client - txn.new_client(client_key, NIL_VERSION_ID)?; + txn.new_client(client_id, NIL_VERSION_ID)?; // add a snapshot for the nil version - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); add_snapshot( txn, &ServerConfig::default(), - client_key, + client_id, client, NIL_VERSION_ID, vec![9, 9, 9], @@ -991,7 +991,7 @@ mod test { // verify the snapshot does not exist let mut txn = storage.txn()?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); assert!(client.snapshot.is_none()); Ok(()) @@ -1003,13 +1003,13 @@ mod test { let storage = InMemoryStorage::new(); let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let data = vec![1, 2, 3]; let snapshot_version_id = Uuid::new_v4(); - txn.new_client(client_key, snapshot_version_id)?; + txn.new_client(client_id, snapshot_version_id)?; txn.set_snapshot( - client_key, + client_id, Snapshot { version_id: snapshot_version_id, versions_since: 3, @@ -1018,9 +1018,9 @@ mod test { data.clone(), )?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); assert_eq!( - get_snapshot(txn, &ServerConfig::default(), client_key, client)?, + get_snapshot(txn, &ServerConfig::default(), client_id, client)?, Some((snapshot_version_id, data)) ); @@ -1033,13 +1033,13 @@ mod test { let storage = InMemoryStorage::new(); let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); - txn.new_client(client_key, NIL_VERSION_ID)?; - let client = txn.get_client(client_key)?.unwrap(); + txn.new_client(client_id, NIL_VERSION_ID)?; + let client = txn.get_client(client_id)?.unwrap(); assert_eq!( - get_snapshot(txn, &ServerConfig::default(), client_key, client)?, + get_snapshot(txn, &ServerConfig::default(), client_id, client)?, None ); diff --git a/taskchampion/sync-server/src/storage/inmemory.rs b/taskchampion/sync-server/src/storage/inmemory.rs index 03b36c47a..9f2e1ec0d 100644 --- a/taskchampion/sync-server/src/storage/inmemory.rs +++ b/taskchampion/sync-server/src/storage/inmemory.rs @@ -3,16 +3,16 @@ use std::collections::HashMap; use std::sync::{Mutex, MutexGuard}; struct Inner { - /// Clients, indexed by client_key + /// Clients, indexed by client_id clients: HashMap, - /// Snapshot data, indexed by client key + /// Snapshot data, indexed by client id snapshots: HashMap>, - /// Versions, indexed by (client_key, version_id) + /// Versions, indexed by (client_id, version_id) versions: HashMap<(Uuid, Uuid), Version>, - /// Child versions, indexed by (client_key, parent_version_id) + /// Child versions, indexed by (client_id, parent_version_id) children: HashMap<(Uuid, Uuid), Uuid>, } @@ -42,16 +42,16 @@ impl Storage for InMemoryStorage { } impl<'a> StorageTxn for InnerTxn<'a> { - fn get_client(&mut self, client_key: Uuid) -> anyhow::Result> { - Ok(self.0.clients.get(&client_key).cloned()) + fn get_client(&mut self, client_id: Uuid) -> anyhow::Result> { + Ok(self.0.clients.get(&client_id).cloned()) } - fn new_client(&mut self, client_key: Uuid, latest_version_id: Uuid) -> anyhow::Result<()> { - if self.0.clients.get(&client_key).is_some() { - return Err(anyhow::anyhow!("Client {} already exists", client_key)); + fn new_client(&mut self, client_id: Uuid, latest_version_id: Uuid) -> anyhow::Result<()> { + if self.0.clients.get(&client_id).is_some() { + return Err(anyhow::anyhow!("Client {} already exists", client_id)); } self.0.clients.insert( - client_key, + client_id, Client { latest_version_id, snapshot: None, @@ -62,44 +62,44 @@ impl<'a> StorageTxn for InnerTxn<'a> { fn set_snapshot( &mut self, - client_key: Uuid, + client_id: Uuid, snapshot: Snapshot, data: Vec, ) -> anyhow::Result<()> { let mut client = self .0 .clients - .get_mut(&client_key) + .get_mut(&client_id) .ok_or_else(|| anyhow::anyhow!("no such client"))?; client.snapshot = Some(snapshot); - self.0.snapshots.insert(client_key, data); + self.0.snapshots.insert(client_id, data); Ok(()) } fn get_snapshot_data( &mut self, - client_key: Uuid, + client_id: Uuid, version_id: Uuid, ) -> anyhow::Result>> { // sanity check - let client = self.0.clients.get(&client_key); + let client = self.0.clients.get(&client_id); let client = client.ok_or_else(|| anyhow::anyhow!("no such client"))?; if Some(&version_id) != client.snapshot.as_ref().map(|snap| &snap.version_id) { return Err(anyhow::anyhow!("unexpected snapshot_version_id")); } - Ok(self.0.snapshots.get(&client_key).cloned()) + Ok(self.0.snapshots.get(&client_id).cloned()) } fn get_version_by_parent( &mut self, - client_key: Uuid, + client_id: Uuid, parent_version_id: Uuid, ) -> anyhow::Result> { - if let Some(parent_version_id) = self.0.children.get(&(client_key, parent_version_id)) { + if let Some(parent_version_id) = self.0.children.get(&(client_id, parent_version_id)) { Ok(self .0 .versions - .get(&(client_key, *parent_version_id)) + .get(&(client_id, *parent_version_id)) .cloned()) } else { Ok(None) @@ -108,15 +108,15 @@ impl<'a> StorageTxn for InnerTxn<'a> { fn get_version( &mut self, - client_key: Uuid, + client_id: Uuid, version_id: Uuid, ) -> anyhow::Result> { - Ok(self.0.versions.get(&(client_key, version_id)).cloned()) + Ok(self.0.versions.get(&(client_id, version_id)).cloned()) } fn add_version( &mut self, - client_key: Uuid, + client_id: Uuid, version_id: Uuid, parent_version_id: Uuid, history_segment: Vec, @@ -128,19 +128,19 @@ impl<'a> StorageTxn for InnerTxn<'a> { history_segment, }; - if let Some(client) = self.0.clients.get_mut(&client_key) { + if let Some(client) = self.0.clients.get_mut(&client_id) { client.latest_version_id = version_id; if let Some(ref mut snap) = client.snapshot { snap.versions_since += 1; } } else { - return Err(anyhow::anyhow!("Client {} does not exist", client_key)); + return Err(anyhow::anyhow!("Client {} does not exist", client_id)); } self.0 .children - .insert((client_key, parent_version_id), version_id); - self.0.versions.insert((client_key, version_id), version); + .insert((client_id, parent_version_id), version_id); + self.0.versions.insert((client_id, version_id), version); Ok(()) } @@ -169,18 +169,18 @@ mod test { let storage = InMemoryStorage::new(); let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let latest_version_id = Uuid::new_v4(); - txn.new_client(client_key, latest_version_id)?; + txn.new_client(client_id, latest_version_id)?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); assert_eq!(client.latest_version_id, latest_version_id); assert!(client.snapshot.is_none()); let latest_version_id = Uuid::new_v4(); - txn.add_version(client_key, latest_version_id, Uuid::new_v4(), vec![1, 1])?; + txn.add_version(client_id, latest_version_id, Uuid::new_v4(), vec![1, 1])?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); assert_eq!(client.latest_version_id, latest_version_id); assert!(client.snapshot.is_none()); @@ -189,9 +189,9 @@ mod test { timestamp: Utc::now(), versions_since: 4, }; - txn.set_snapshot(client_key, snap.clone(), vec![1, 2, 3])?; + txn.set_snapshot(client_id, snap.clone(), vec![1, 2, 3])?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); assert_eq!(client.latest_version_id, latest_version_id); assert_eq!(client.snapshot.unwrap(), snap); @@ -212,14 +212,14 @@ mod test { let storage = InMemoryStorage::new(); let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let version_id = Uuid::new_v4(); let parent_version_id = Uuid::new_v4(); let history_segment = b"abc".to_vec(); - txn.new_client(client_key, parent_version_id)?; + txn.new_client(client_id, parent_version_id)?; txn.add_version( - client_key, + client_id, version_id, parent_version_id, history_segment.clone(), @@ -232,11 +232,11 @@ mod test { }; let version = txn - .get_version_by_parent(client_key, parent_version_id)? + .get_version_by_parent(client_id, parent_version_id)? .unwrap(); assert_eq!(version, expected); - let version = txn.get_version(client_key, version_id)?.unwrap(); + let version = txn.get_version(client_id, version_id)?.unwrap(); assert_eq!(version, expected); Ok(()) @@ -247,40 +247,39 @@ mod test { let storage = InMemoryStorage::new(); let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); - txn.new_client(client_key, Uuid::new_v4())?; - assert!(txn.get_client(client_key)?.unwrap().snapshot.is_none()); + txn.new_client(client_id, Uuid::new_v4())?; + assert!(txn.get_client(client_id)?.unwrap().snapshot.is_none()); let snap = Snapshot { version_id: Uuid::new_v4(), timestamp: Utc::now(), versions_since: 3, }; - txn.set_snapshot(client_key, snap.clone(), vec![9, 8, 9])?; + txn.set_snapshot(client_id, snap.clone(), vec![9, 8, 9])?; assert_eq!( - txn.get_snapshot_data(client_key, snap.version_id)?.unwrap(), + txn.get_snapshot_data(client_id, snap.version_id)?.unwrap(), vec![9, 8, 9] ); - assert_eq!(txn.get_client(client_key)?.unwrap().snapshot, Some(snap)); + assert_eq!(txn.get_client(client_id)?.unwrap().snapshot, Some(snap)); let snap2 = Snapshot { version_id: Uuid::new_v4(), timestamp: Utc::now(), versions_since: 10, }; - txn.set_snapshot(client_key, snap2.clone(), vec![0, 2, 4, 6])?; + txn.set_snapshot(client_id, snap2.clone(), vec![0, 2, 4, 6])?; assert_eq!( - txn.get_snapshot_data(client_key, snap2.version_id)? - .unwrap(), + txn.get_snapshot_data(client_id, snap2.version_id)?.unwrap(), vec![0, 2, 4, 6] ); - assert_eq!(txn.get_client(client_key)?.unwrap().snapshot, Some(snap2)); + assert_eq!(txn.get_client(client_id)?.unwrap().snapshot, Some(snap2)); // check that mismatched version is detected - assert!(txn.get_snapshot_data(client_key, Uuid::new_v4()).is_err()); + assert!(txn.get_snapshot_data(client_id, Uuid::new_v4()).is_err()); Ok(()) } diff --git a/taskchampion/sync-server/src/storage/mod.rs b/taskchampion/sync-server/src/storage/mod.rs index 2a7711b7f..a2e468fbb 100644 --- a/taskchampion/sync-server/src/storage/mod.rs +++ b/taskchampion/sync-server/src/storage/mod.rs @@ -39,15 +39,15 @@ pub struct Version { pub trait StorageTxn { /// Get information about the given client - fn get_client(&mut self, client_key: Uuid) -> anyhow::Result>; + fn get_client(&mut self, client_id: Uuid) -> anyhow::Result>; /// Create a new client with the given latest_version_id - fn new_client(&mut self, client_key: Uuid, latest_version_id: Uuid) -> anyhow::Result<()>; + fn new_client(&mut self, client_id: Uuid, latest_version_id: Uuid) -> anyhow::Result<()>; /// Set the client's most recent snapshot. fn set_snapshot( &mut self, - client_key: Uuid, + client_id: Uuid, snapshot: Snapshot, data: Vec, ) -> anyhow::Result<()>; @@ -56,30 +56,27 @@ pub trait StorageTxn { /// is used to verify that the snapshot is for the correct version. fn get_snapshot_data( &mut self, - client_key: Uuid, + client_id: Uuid, version_id: Uuid, ) -> anyhow::Result>>; /// Get a version, indexed by parent version id fn get_version_by_parent( &mut self, - client_key: Uuid, + client_id: Uuid, parent_version_id: Uuid, ) -> anyhow::Result>; /// Get a version, indexed by its own version id - fn get_version( - &mut self, - client_key: Uuid, - version_id: Uuid, - ) -> anyhow::Result>; + fn get_version(&mut self, client_id: Uuid, version_id: Uuid) + -> anyhow::Result>; /// Add a version (that must not already exist), and /// - update latest_version_id /// - increment snapshot.versions_since fn add_version( &mut self, - client_key: Uuid, + client_id: Uuid, version_id: Uuid, parent_version_id: Uuid, history_segment: Vec, diff --git a/taskchampion/sync-server/src/storage/sqlite.rs b/taskchampion/sync-server/src/storage/sqlite.rs index b738a4008..a8571bb36 100644 --- a/taskchampion/sync-server/src/storage/sqlite.rs +++ b/taskchampion/sync-server/src/storage/sqlite.rs @@ -53,13 +53,13 @@ impl SqliteStorage { let queries = vec![ "CREATE TABLE IF NOT EXISTS clients ( - client_key STRING PRIMARY KEY, + client_id STRING PRIMARY KEY, latest_version_id STRING, snapshot_version_id STRING, versions_since_snapshot INTEGER, snapshot_timestamp INTEGER, snapshot BLOB);", - "CREATE TABLE IF NOT EXISTS versions (version_id STRING PRIMARY KEY, client_key STRING, parent_version_id STRING, history_segment BLOB);", + "CREATE TABLE IF NOT EXISTS versions (version_id STRING PRIMARY KEY, client_id STRING, parent_version_id STRING, history_segment BLOB);", "CREATE INDEX IF NOT EXISTS versions_by_parent ON versions (parent_version_id);", ]; for q in queries { @@ -96,14 +96,14 @@ impl Txn { fn get_version_impl( &mut self, query: &'static str, - client_key: Uuid, + client_id: Uuid, version_id_arg: Uuid, ) -> anyhow::Result> { let t = self.get_txn()?; let r = t .query_row( query, - params![&StoredUuid(version_id_arg), &StoredUuid(client_key)], + params![&StoredUuid(version_id_arg), &StoredUuid(client_id)], |r| { let version_id: StoredUuid = r.get("version_id")?; let parent_version_id: StoredUuid = r.get("parent_version_id")?; @@ -122,7 +122,7 @@ impl Txn { } impl StorageTxn for Txn { - fn get_client(&mut self, client_key: Uuid) -> anyhow::Result> { + fn get_client(&mut self, client_id: Uuid) -> anyhow::Result> { let t = self.get_txn()?; let result: Option = t .query_row( @@ -132,9 +132,9 @@ impl StorageTxn for Txn { versions_since_snapshot, snapshot_version_id FROM clients - WHERE client_key = ? + WHERE client_id = ? LIMIT 1", - [&StoredUuid(client_key)], + [&StoredUuid(client_id)], |r| { let latest_version_id: StoredUuid = r.get(0)?; let snapshot_timestamp: Option = r.get(1)?; @@ -166,12 +166,12 @@ impl StorageTxn for Txn { Ok(result) } - fn new_client(&mut self, client_key: Uuid, latest_version_id: Uuid) -> anyhow::Result<()> { + fn new_client(&mut self, client_id: Uuid, latest_version_id: Uuid) -> anyhow::Result<()> { let t = self.get_txn()?; t.execute( - "INSERT OR REPLACE INTO clients (client_key, latest_version_id) VALUES (?, ?)", - params![&StoredUuid(client_key), &StoredUuid(latest_version_id)], + "INSERT OR REPLACE INTO clients (client_id, latest_version_id) VALUES (?, ?)", + params![&StoredUuid(client_id), &StoredUuid(latest_version_id)], ) .context("Error creating/updating client")?; t.commit()?; @@ -180,7 +180,7 @@ impl StorageTxn for Txn { fn set_snapshot( &mut self, - client_key: Uuid, + client_id: Uuid, snapshot: Snapshot, data: Vec, ) -> anyhow::Result<()> { @@ -193,13 +193,13 @@ impl StorageTxn for Txn { snapshot_timestamp = ?, versions_since_snapshot = ?, snapshot = ? - WHERE client_key = ?", + WHERE client_id = ?", params![ &StoredUuid(snapshot.version_id), snapshot.timestamp.timestamp(), snapshot.versions_since, data, - &StoredUuid(client_key), + &StoredUuid(client_id), ], ) .context("Error creating/updating snapshot")?; @@ -209,14 +209,14 @@ impl StorageTxn for Txn { fn get_snapshot_data( &mut self, - client_key: Uuid, + client_id: Uuid, version_id: Uuid, ) -> anyhow::Result>> { let t = self.get_txn()?; let r = t .query_row( - "SELECT snapshot, snapshot_version_id FROM clients WHERE client_key = ?", - params![&StoredUuid(client_key)], + "SELECT snapshot, snapshot_version_id FROM clients WHERE client_id = ?", + params![&StoredUuid(client_id)], |r| { let v: StoredUuid = r.get("snapshot_version_id")?; let d: Vec = r.get("snapshot")?; @@ -237,29 +237,29 @@ impl StorageTxn for Txn { fn get_version_by_parent( &mut self, - client_key: Uuid, + client_id: Uuid, parent_version_id: Uuid, ) -> anyhow::Result> { self.get_version_impl( - "SELECT version_id, parent_version_id, history_segment FROM versions WHERE parent_version_id = ? AND client_key = ?", - client_key, + "SELECT version_id, parent_version_id, history_segment FROM versions WHERE parent_version_id = ? AND client_id = ?", + client_id, parent_version_id) } fn get_version( &mut self, - client_key: Uuid, + client_id: Uuid, version_id: Uuid, ) -> anyhow::Result> { self.get_version_impl( - "SELECT version_id, parent_version_id, history_segment FROM versions WHERE version_id = ? AND client_key = ?", - client_key, + "SELECT version_id, parent_version_id, history_segment FROM versions WHERE version_id = ? AND client_id = ?", + client_id, version_id) } fn add_version( &mut self, - client_key: Uuid, + client_id: Uuid, version_id: Uuid, parent_version_id: Uuid, history_segment: Vec, @@ -267,10 +267,10 @@ impl StorageTxn for Txn { let t = self.get_txn()?; t.execute( - "INSERT INTO versions (version_id, client_key, parent_version_id, history_segment) VALUES(?, ?, ?, ?)", + "INSERT INTO versions (version_id, client_id, parent_version_id, history_segment) VALUES(?, ?, ?, ?)", params![ StoredUuid(version_id), - StoredUuid(client_key), + StoredUuid(client_id), StoredUuid(parent_version_id), history_segment ] @@ -281,8 +281,8 @@ impl StorageTxn for Txn { SET latest_version_id = ?, versions_since_snapshot = versions_since_snapshot + 1 - WHERE client_key = ?", - params![StoredUuid(version_id), StoredUuid(client_key),], + WHERE client_id = ?", + params![StoredUuid(version_id), StoredUuid(client_id),], ) .context("Error updating client for new version")?; @@ -333,18 +333,18 @@ mod test { let storage = SqliteStorage::new(tmp_dir.path())?; let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let latest_version_id = Uuid::new_v4(); - txn.new_client(client_key, latest_version_id)?; + txn.new_client(client_id, latest_version_id)?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); assert_eq!(client.latest_version_id, latest_version_id); assert!(client.snapshot.is_none()); let latest_version_id = Uuid::new_v4(); - txn.add_version(client_key, latest_version_id, Uuid::new_v4(), vec![1, 1])?; + txn.add_version(client_id, latest_version_id, Uuid::new_v4(), vec![1, 1])?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); assert_eq!(client.latest_version_id, latest_version_id); assert!(client.snapshot.is_none()); @@ -353,9 +353,9 @@ mod test { timestamp: "2014-11-28T12:00:09Z".parse::>().unwrap(), versions_since: 4, }; - txn.set_snapshot(client_key, snap.clone(), vec![1, 2, 3])?; + txn.set_snapshot(client_id, snap.clone(), vec![1, 2, 3])?; - let client = txn.get_client(client_key)?.unwrap(); + let client = txn.get_client(client_id)?.unwrap(); assert_eq!(client.latest_version_id, latest_version_id); assert_eq!(client.snapshot.unwrap(), snap); @@ -378,12 +378,12 @@ mod test { let storage = SqliteStorage::new(tmp_dir.path())?; let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let version_id = Uuid::new_v4(); let parent_version_id = Uuid::new_v4(); let history_segment = b"abc".to_vec(); txn.add_version( - client_key, + client_id, version_id, parent_version_id, history_segment.clone(), @@ -396,11 +396,11 @@ mod test { }; let version = txn - .get_version_by_parent(client_key, parent_version_id)? + .get_version_by_parent(client_id, parent_version_id)? .unwrap(); assert_eq!(version, expected); - let version = txn.get_version(client_key, version_id)?.unwrap(); + let version = txn.get_version(client_id, version_id)?.unwrap(); assert_eq!(version, expected); Ok(()) @@ -412,40 +412,39 @@ mod test { let storage = SqliteStorage::new(tmp_dir.path())?; let mut txn = storage.txn()?; - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); - txn.new_client(client_key, Uuid::new_v4())?; - assert!(txn.get_client(client_key)?.unwrap().snapshot.is_none()); + txn.new_client(client_id, Uuid::new_v4())?; + assert!(txn.get_client(client_id)?.unwrap().snapshot.is_none()); let snap = Snapshot { version_id: Uuid::new_v4(), timestamp: "2013-10-08T12:00:09Z".parse::>().unwrap(), versions_since: 3, }; - txn.set_snapshot(client_key, snap.clone(), vec![9, 8, 9])?; + txn.set_snapshot(client_id, snap.clone(), vec![9, 8, 9])?; assert_eq!( - txn.get_snapshot_data(client_key, snap.version_id)?.unwrap(), + txn.get_snapshot_data(client_id, snap.version_id)?.unwrap(), vec![9, 8, 9] ); - assert_eq!(txn.get_client(client_key)?.unwrap().snapshot, Some(snap)); + assert_eq!(txn.get_client(client_id)?.unwrap().snapshot, Some(snap)); let snap2 = Snapshot { version_id: Uuid::new_v4(), timestamp: "2014-11-28T12:00:09Z".parse::>().unwrap(), versions_since: 10, }; - txn.set_snapshot(client_key, snap2.clone(), vec![0, 2, 4, 6])?; + txn.set_snapshot(client_id, snap2.clone(), vec![0, 2, 4, 6])?; assert_eq!( - txn.get_snapshot_data(client_key, snap2.version_id)? - .unwrap(), + txn.get_snapshot_data(client_id, snap2.version_id)?.unwrap(), vec![0, 2, 4, 6] ); - assert_eq!(txn.get_client(client_key)?.unwrap().snapshot, Some(snap2)); + assert_eq!(txn.get_client(client_id)?.unwrap().snapshot, Some(snap2)); // check that mismatched version is detected - assert!(txn.get_snapshot_data(client_key, Uuid::new_v4()).is_err()); + assert!(txn.get_snapshot_data(client_id, Uuid::new_v4()).is_err()); Ok(()) } diff --git a/taskchampion/taskchampion/src/server/config.rs b/taskchampion/taskchampion/src/server/config.rs index 6360ac8fe..5b15a6d63 100644 --- a/taskchampion/taskchampion/src/server/config.rs +++ b/taskchampion/taskchampion/src/server/config.rs @@ -16,8 +16,8 @@ pub enum ServerConfig { /// Sync server "origin"; a URL with schema and hostname but no path or trailing `/` origin: String, - /// Client Key to identify and authenticate this replica to the server - client_key: Uuid, + /// Client ID to identify and authenticate this replica to the server + client_id: Uuid, /// Private encryption secret used to encrypt all data sent to the server. This can /// be any suitably un-guessable string of bytes. @@ -32,9 +32,9 @@ impl ServerConfig { ServerConfig::Local { server_dir } => Box::new(LocalServer::new(server_dir)?), ServerConfig::Remote { origin, - client_key, + client_id, encryption_secret, - } => Box::new(RemoteServer::new(origin, client_key, encryption_secret)?), + } => Box::new(RemoteServer::new(origin, client_id, encryption_secret)?), }) } } diff --git a/taskchampion/taskchampion/src/server/crypto.rs b/taskchampion/taskchampion/src/server/crypto.rs index 2e10a96fc..5d8a0e328 100644 --- a/taskchampion/taskchampion/src/server/crypto.rs +++ b/taskchampion/taskchampion/src/server/crypto.rs @@ -12,23 +12,23 @@ const TASK_APP_ID: u8 = 1; /// An Cryptor stores a secret and allows sealing and unsealing. It derives a key from the secret, /// which takes a nontrivial amount of time, so it should be created once and re-used for the given -/// client_key. +/// client_id. pub(super) struct Cryptor { key: aead::LessSafeKey, rng: rand::SystemRandom, } impl Cryptor { - pub(super) fn new(client_key: Uuid, secret: &Secret) -> Result { + pub(super) fn new(client_id: Uuid, secret: &Secret) -> Result { Ok(Cryptor { - key: Self::derive_key(client_key, secret)?, + key: Self::derive_key(client_id, secret)?, rng: rand::SystemRandom::new(), }) } /// Derive a key as specified for version 1. Note that this may take 10s of ms. - fn derive_key(client_key: Uuid, secret: &Secret) -> Result { - let salt = digest::digest(&digest::SHA256, client_key.as_bytes()); + fn derive_key(client_id: Uuid, secret: &Secret) -> Result { + let salt = digest::digest(&digest::SHA256, client_id.as_bytes()); let mut key_bytes = vec![0u8; aead::CHACHA20_POLY1305.key_len()]; pbkdf2::derive( @@ -268,10 +268,10 @@ mod test { fn round_trip_bad_key() { let version_id = Uuid::new_v4(); let payload = b"HISTORY REPEATS ITSELF".to_vec(); - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let secret = Secret(b"SEKRIT".to_vec()); - let cryptor = Cryptor::new(client_key, &secret).unwrap(); + let cryptor = Cryptor::new(client_id, &secret).unwrap(); let unsealed = Unsealed { version_id, @@ -280,7 +280,7 @@ mod test { let sealed = cryptor.seal(unsealed).unwrap(); let secret = Secret(b"DIFFERENT_SECRET".to_vec()); - let cryptor = Cryptor::new(client_key, &secret).unwrap(); + let cryptor = Cryptor::new(client_id, &secret).unwrap(); assert!(cryptor.unseal(sealed).is_err()); } @@ -288,10 +288,10 @@ mod test { fn round_trip_bad_version() { let version_id = Uuid::new_v4(); let payload = b"HISTORY REPEATS ITSELF".to_vec(); - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let secret = Secret(b"SEKRIT".to_vec()); - let cryptor = Cryptor::new(client_key, &secret).unwrap(); + let cryptor = Cryptor::new(client_id, &secret).unwrap(); let unsealed = Unsealed { version_id, @@ -303,13 +303,13 @@ mod test { } #[test] - fn round_trip_bad_client_key() { + fn round_trip_bad_client_id() { let version_id = Uuid::new_v4(); let payload = b"HISTORY REPEATS ITSELF".to_vec(); - let client_key = Uuid::new_v4(); + let client_id = Uuid::new_v4(); let secret = Secret(b"SEKRIT".to_vec()); - let cryptor = Cryptor::new(client_key, &secret).unwrap(); + let cryptor = Cryptor::new(client_id, &secret).unwrap(); let unsealed = Unsealed { version_id, @@ -317,8 +317,8 @@ mod test { }; let sealed = cryptor.seal(unsealed).unwrap(); - let client_key = Uuid::new_v4(); - let cryptor = Cryptor::new(client_key, &secret).unwrap(); + let client_id = Uuid::new_v4(); + let cryptor = Cryptor::new(client_id, &secret).unwrap(); assert!(cryptor.unseal(sealed).is_err()); } @@ -340,13 +340,13 @@ mod test { #[test] fn good() { - let (version_id, client_key, encryption_secret) = defaults(); + let (version_id, client_id, encryption_secret) = defaults(); let sealed = Sealed { version_id, payload: include_bytes!("test-good.data").to_vec(), }; - let cryptor = Cryptor::new(client_key, &Secret(encryption_secret)).unwrap(); + let cryptor = Cryptor::new(client_id, &Secret(encryption_secret)).unwrap(); let unsealed = cryptor.unseal(sealed).unwrap(); assert_eq!(unsealed.payload, b"SUCCESS"); @@ -355,61 +355,61 @@ mod test { #[test] fn bad_version_id() { - let (version_id, client_key, encryption_secret) = defaults(); + let (version_id, client_id, encryption_secret) = defaults(); let sealed = Sealed { version_id, payload: include_bytes!("test-bad-version-id.data").to_vec(), }; - let cryptor = Cryptor::new(client_key, &Secret(encryption_secret)).unwrap(); + let cryptor = Cryptor::new(client_id, &Secret(encryption_secret)).unwrap(); assert!(cryptor.unseal(sealed).is_err()); } #[test] - fn bad_client_key() { - let (version_id, client_key, encryption_secret) = defaults(); + fn bad_client_id() { + let (version_id, client_id, encryption_secret) = defaults(); let sealed = Sealed { version_id, - payload: include_bytes!("test-bad-client-key.data").to_vec(), + payload: include_bytes!("test-bad-client-id.data").to_vec(), }; - let cryptor = Cryptor::new(client_key, &Secret(encryption_secret)).unwrap(); + let cryptor = Cryptor::new(client_id, &Secret(encryption_secret)).unwrap(); assert!(cryptor.unseal(sealed).is_err()); } #[test] fn bad_secret() { - let (version_id, client_key, encryption_secret) = defaults(); + let (version_id, client_id, encryption_secret) = defaults(); let sealed = Sealed { version_id, payload: include_bytes!("test-bad-secret.data").to_vec(), }; - let cryptor = Cryptor::new(client_key, &Secret(encryption_secret)).unwrap(); + let cryptor = Cryptor::new(client_id, &Secret(encryption_secret)).unwrap(); assert!(cryptor.unseal(sealed).is_err()); } #[test] fn bad_version() { - let (version_id, client_key, encryption_secret) = defaults(); + let (version_id, client_id, encryption_secret) = defaults(); let sealed = Sealed { version_id, payload: include_bytes!("test-bad-version.data").to_vec(), }; - let cryptor = Cryptor::new(client_key, &Secret(encryption_secret)).unwrap(); + let cryptor = Cryptor::new(client_id, &Secret(encryption_secret)).unwrap(); assert!(cryptor.unseal(sealed).is_err()); } #[test] fn bad_app_id() { - let (version_id, client_key, encryption_secret) = defaults(); + let (version_id, client_id, encryption_secret) = defaults(); let sealed = Sealed { version_id, payload: include_bytes!("test-bad-app-id.data").to_vec(), }; - let cryptor = Cryptor::new(client_key, &Secret(encryption_secret)).unwrap(); + let cryptor = Cryptor::new(client_id, &Secret(encryption_secret)).unwrap(); assert!(cryptor.unseal(sealed).is_err()); } } diff --git a/taskchampion/taskchampion/src/server/generate-test-data.py b/taskchampion/taskchampion/src/server/generate-test-data.py index 366597813..e89fe3dcc 100644 --- a/taskchampion/taskchampion/src/server/generate-test-data.py +++ b/taskchampion/taskchampion/src/server/generate-test-data.py @@ -1,6 +1,6 @@ # This file generates test-encrypted.data. To run it: # - pip install cryptography pbkdf2 -# - python taskchampion/src/server/generate-test-data.py taskchampion/src/server/ +# - python taskchampion/taskchampion/src/server/generate-test-data.py taskchampion/taskchampion/src/server/ import os import hashlib @@ -12,15 +12,15 @@ import uuid from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 # these values match values used in the rust tests -client_key = "0666d464-418a-4a08-ad53-6f15c78270cd" +client_id = "0666d464-418a-4a08-ad53-6f15c78270cd" encryption_secret = b"b4a4e6b7b811eda1dc1a2693ded" version_id = "b0517957-f912-4d49-8330-f612e73030c4" def gen( - version_id=version_id, client_key=client_key, encryption_secret=encryption_secret, + version_id=version_id, client_id=client_id, encryption_secret=encryption_secret, app_id=1, version=1): # first, generate the encryption key - salt = hashlib.sha256(uuid.UUID(client_key).bytes).digest() + salt = hashlib.sha256(uuid.UUID(client_id).bytes).digest() key = pbkdf2.PBKDF2( encryption_secret, salt, @@ -61,8 +61,8 @@ def main(): with open(os.path.join(dir, 'test-bad-version-id.data'), "wb") as f: f.write(gen(version_id=uuid.uuid4().hex)) - with open(os.path.join(dir, 'test-bad-client-key.data'), "wb") as f: - f.write(gen(client_key=uuid.uuid4().hex)) + with open(os.path.join(dir, 'test-bad-client-id.data'), "wb") as f: + f.write(gen(client_id=uuid.uuid4().hex)) with open(os.path.join(dir, 'test-bad-secret.data'), "wb") as f: f.write(gen(encryption_secret=b"xxxxxxxxxxxxxxxxxxxxx")) diff --git a/taskchampion/taskchampion/src/server/remote/mod.rs b/taskchampion/taskchampion/src/server/remote/mod.rs index 13b6fb96c..6b168ab32 100644 --- a/taskchampion/taskchampion/src/server/remote/mod.rs +++ b/taskchampion/taskchampion/src/server/remote/mod.rs @@ -10,7 +10,7 @@ use super::crypto::{Cryptor, Sealed, Secret, Unsealed}; pub struct RemoteServer { origin: String, - client_key: Uuid, + client_id: Uuid, cryptor: Cryptor, agent: ureq::Agent, } @@ -25,18 +25,18 @@ const SNAPSHOT_CONTENT_TYPE: &str = "application/vnd.taskchampion.snapshot"; /// taskchampion-sync-server). impl RemoteServer { /// Construct a new RemoteServer. The `origin` is the sync server's protocol and hostname - /// without a trailing slash, such as `https://tcsync.example.com`. Pass a client_key to + /// without a trailing slash, such as `https://tcsync.example.com`. Pass a client_id to /// identify this client to the server. Multiple replicas synchronizing the same task history - /// should use the same client_key. + /// should use the same client_id. pub fn new( origin: String, - client_key: Uuid, + client_id: Uuid, encryption_secret: Vec, ) -> Result { Ok(RemoteServer { origin, - client_key, - cryptor: Cryptor::new(client_key, &Secret(encryption_secret.to_vec()))?, + client_id, + cryptor: Cryptor::new(client_id, &Secret(encryption_secret.to_vec()))?, agent: ureq::AgentBuilder::new() .timeout_connect(Duration::from_secs(10)) .timeout_read(Duration::from_secs(60)) @@ -86,7 +86,7 @@ impl Server for RemoteServer { .agent .post(&url) .set("Content-Type", HISTORY_SEGMENT_CONTENT_TYPE) - .set("X-Client-Key", &self.client_key.to_string()) + .set("X-Client-Id", &self.client_id.to_string()) .send_bytes(sealed.as_ref()) { Ok(resp) => { @@ -115,7 +115,7 @@ impl Server for RemoteServer { match self .agent .get(&url) - .set("X-Client-Key", &self.client_key.to_string()) + .set("X-Client-Id", &self.client_id.to_string()) .call() { Ok(resp) => { @@ -148,7 +148,7 @@ impl Server for RemoteServer { .agent .post(&url) .set("Content-Type", SNAPSHOT_CONTENT_TYPE) - .set("X-Client-Key", &self.client_key.to_string()) + .set("X-Client-Id", &self.client_id.to_string()) .send_bytes(sealed.as_ref()) .map(|_| ())?) } @@ -158,7 +158,7 @@ impl Server for RemoteServer { match self .agent .get(&url) - .set("X-Client-Key", &self.client_key.to_string()) + .set("X-Client-Id", &self.client_id.to_string()) .call() { Ok(resp) => { diff --git a/taskchampion/taskchampion/src/server/test-bad-app-id.data b/taskchampion/taskchampion/src/server/test-bad-app-id.data index a1c6832a6..311a7390e 100644 --- a/taskchampion/taskchampion/src/server/test-bad-app-id.data +++ b/taskchampion/taskchampion/src/server/test-bad-app-id.data @@ -1,2 +1,2 @@ -#$ -^~B>n)ji19|~ \ No newline at end of file + +Ko]ʶMc\QL)cH;-: \ No newline at end of file diff --git a/taskchampion/taskchampion/src/server/test-bad-client-id.data b/taskchampion/taskchampion/src/server/test-bad-client-id.data new file mode 100644 index 000000000..2bfcfde74 --- /dev/null +++ b/taskchampion/taskchampion/src/server/test-bad-client-id.data @@ -0,0 +1 @@ +%ۇ ko¹{hكb ˁLqU \ No newline at end of file diff --git a/taskchampion/taskchampion/src/server/test-bad-client-key.data b/taskchampion/taskchampion/src/server/test-bad-client-key.data deleted file mode 100644 index bfdd9635e..000000000 --- a/taskchampion/taskchampion/src/server/test-bad-client-key.data +++ /dev/null @@ -1 +0,0 @@ -A4 t; pϦx^reJԤ \ No newline at end of file diff --git a/taskchampion/taskchampion/src/server/test-bad-secret.data b/taskchampion/taskchampion/src/server/test-bad-secret.data index 696da066f..b5c1b6f0c 100644 --- a/taskchampion/taskchampion/src/server/test-bad-secret.data +++ b/taskchampion/taskchampion/src/server/test-bad-secret.data @@ -1 +1 @@ -/}d EdIcX-!V%4d]} \ No newline at end of file +sqnk,\ ;W< ' ;{А \ No newline at end of file diff --git a/taskchampion/taskchampion/src/server/test-bad-version-id.data b/taskchampion/taskchampion/src/server/test-bad-version-id.data index 2ccd8c638..415f8706b 100644 --- a/taskchampion/taskchampion/src/server/test-bad-version-id.data +++ b/taskchampion/taskchampion/src/server/test-bad-version-id.data @@ -1 +1 @@ -la|@ύS_zV9qх)+ \ No newline at end of file + ajJշq\IF4Y ӣ $9W \ No newline at end of file diff --git a/taskchampion/taskchampion/src/server/test-bad-version.data b/taskchampion/taskchampion/src/server/test-bad-version.data index 20fed792e..8de898f54 100644 --- a/taskchampion/taskchampion/src/server/test-bad-version.data +++ b/taskchampion/taskchampion/src/server/test-bad-version.data @@ -1 +1 @@ -cTHp>溦m4~10PIW \ No newline at end of file +cR||iKo+tU|љ& BI3 \ No newline at end of file diff --git a/taskchampion/taskchampion/src/server/test-good.data b/taskchampion/taskchampion/src/server/test-good.data index 9efec7577..1f0880a08 100644 --- a/taskchampion/taskchampion/src/server/test-good.data +++ b/taskchampion/taskchampion/src/server/test-good.data @@ -1 +1 @@ -pѿҟVTo"}cTY7 @dLT` \ No newline at end of file +PRojǗgs&vMYn?c~: \ No newline at end of file