Relax sync.server.origin to allow paths (#3423)

This commit is contained in:
Hector Dearman 2024-07-05 00:17:52 +01:00 committed by GitHub
parent 85f52e3630
commit fa5604ea8d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 38 additions and 23 deletions

View file

@ -68,18 +68,22 @@ To synchronize your tasks to a sync server, you will need the following
information from the server administrator:
.br
- The server's URL ("origin", such as "https://tw.example.com")
- The server's URL (such as "https://tw.example.com/path")
.br
- A client ID ("client_id") identifying your tasks
Configure Taskwarrior with these details:
.nf
$ task config sync.server.origin <origin>
$ task config sync.server.url <url>
$ task config sync.server.client_id <client_id>
.fi
Note that the origin must include the scheme, such as 'http://' or 'https://'.
Note that the URL must include the scheme, such as 'http://' or 'https://'.
$ task config sync.server.origin <origin>
Is a deprecated synonym for "sync.server.url".
.SS Google Cloud Platform
@ -168,7 +172,7 @@ 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 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
URL, to the user for inclusion in their Taskwarrior config. The user should
invent their own "encryption_secret".
.SH AVOIDING DUPLICATE RECURRING TASKS

View file

@ -164,7 +164,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_id\|encryption_secret\)\|local.server_dir\)='he=e-1
syn match taskrcGoodKey '^\s*\Vsync.\(server.\(url\|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

View file

@ -281,9 +281,9 @@ std::string configurationDefaults =
"\n"
"#sync.encryption_secret # Encryption secret for sync to a server\n"
"#sync.server.client_id # Client ID for sync to a server\n"
"#sync.server.origin # Origin of the sync server\n"
"#sync.server.url # URL of the sync server\n"
"#sync.local.server_dir # Directory for local sync\n"
"#sync.gcp.credential_path # Path to JSON file containing credentials to authenticate GCP Sync\n"
"#sync.gcp.credential_path # Path to JSON file containing credentials to authenticate GCP Sync\n"
"#sync.gcp.bucket # Bucket for sync to GCP\n"
"\n"
"# Aliases - alternate names for commands\n"

View file

@ -197,6 +197,7 @@ int CmdShow::execute (std::string& output)
" sync.gcp.bucket"
" sync.server.client_id"
" sync.encryption_secret"
" sync.server.url"
" sync.server.origin"
" tag.indicator"
" undo.style"

View file

@ -63,10 +63,15 @@ 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 url = Context::getContext ().config.get ("sync.server.url");
std::string server_dir = Context::getContext ().config.get ("sync.local.server_dir");
std::string gcp_credential_path = Context::getContext ().config.get ("sync.gcp.credential_path");
std::string gcp_bucket = Context::getContext ().config.get ("sync.gcp.bucket");
std::string encryption_secret = Context::getContext ().config.get ("sync.encryption_secret");
// sync.server.origin is a deprecated synonym for sync.server.url
std::string server_url = url == "" ? origin : url;
if (server_dir != "") {
server = tc::Server::new_local (server_dir);
server_ident = server_dir;
@ -78,23 +83,28 @@ int CmdSync::execute (std::string& output)
std::ostringstream os;
os << "GCP bucket " << gcp_bucket;
server_ident = os.str();
} else if (origin != "") {
} else if (server_url != "") {
std::string client_id = Context::getContext ().config.get ("sync.server.client_id");
if (client_id == "" || encryption_secret == "") {
throw std::string ("sync.server.client_id and sync.encryption_secret are required");
}
server = tc::Server::new_sync (origin, client_id, encryption_secret);
server = tc::Server::new_sync (server_url, client_id, encryption_secret);
std::ostringstream os;
os << "Sync server at " << origin;
os << "Sync server at " << server_url;
server_ident = os.str();
} else {
throw std::string ("No sync.* settings are configured. See task-sync(5).");
}
std::stringstream out;
if (Context::getContext ().verbose ("sync"))
if (origin != "") {
out << "sync.server.origin is deprecated. Use sync.server.url instead.\n";
}
if (Context::getContext ().verbose ("sync")) {
out << format ("Syncing with {1}", server_ident)
<< '\n';
}
Context::getContext ().tdb2.sync(std::move(server), false);

View file

@ -51,24 +51,24 @@ tc::Server::new_local (const std::string &server_dir)
////////////////////////////////////////////////////////////////////////////////
tc::Server
tc::Server::new_sync (const std::string &origin, const std::string &client_id, const std::string &encryption_secret)
tc::Server::new_sync (const std::string &url, const std::string &client_id, const std::string &encryption_secret)
{
TCString tc_origin = tc_string_borrow (origin.c_str ());
TCString tc_url = tc_string_borrow (url.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_uuid;
if (tc_uuid_from_str(tc_client_id, &tc_client_uuid) != TC_RESULT_OK) {
tc_string_free(&tc_origin);
tc_string_free(&tc_url);
tc_string_free(&tc_encryption_secret);
throw format ("client_id '{1}' is not a valid UUID", client_id);
}
TCString error;
auto tcserver = tc_server_new_sync (tc_origin, tc_client_uuid, tc_encryption_secret, &error);
auto tcserver = tc_server_new_sync (tc_url, tc_client_uuid, tc_encryption_secret, &error);
if (!tcserver) {
std::string errmsg = format ("Could not configure connection to server at {1}: {2}",
origin, tc_string_content (&error));
url, tc_string_content (&error));
tc_string_free (&error);
throw errmsg;
}

View file

@ -54,7 +54,7 @@ namespace tc {
static Server new_local (const std::string& server_dir);
// Construct a remote server (tc_server_new_sync).
static Server new_sync (const std::string &origin, const std::string &client_id, const std::string &encryption_secret);
static Server new_sync (const std::string &url, const std::string &client_id, const std::string &encryption_secret);
// Construct a GCP server (tc_server_new_gcp).
static Server new_gcp (const std::string &bucket, const std::string &credential_path, const std::string &encryption_secret);

View file

@ -108,14 +108,14 @@ pub unsafe extern "C" fn tc_server_new_local(
/// The server must be freed after it is used - tc_replica_sync does not automatically free it.
///
/// ```c
/// EXTERN_C struct TCServer *tc_server_new_sync(struct TCString origin,
/// EXTERN_C struct TCServer *tc_server_new_sync(struct TCString url,
/// struct TCUuid client_id,
/// struct TCString encryption_secret,
/// struct TCString *error_out);
/// ```
#[no_mangle]
pub unsafe extern "C" fn tc_server_new_sync(
origin: TCString,
url: TCString,
client_id: TCUuid,
encryption_secret: TCString,
error_out: *mut TCString,
@ -123,9 +123,9 @@ pub unsafe extern "C" fn tc_server_new_sync(
wrap(
|| {
// SAFETY:
// - origin is valid (promised by caller)
// - origin ownership is transferred to this function
let url = unsafe { TCString::val_from_arg(origin) }.into_string()?;
// - url is valid (promised by caller)
// - url ownership is transferred to this function
let url = unsafe { TCString::val_from_arg(url) }.into_string()?;
// SAFETY:
// - client_id is a valid Uuid (any 8-byte sequence counts)

View file

@ -433,7 +433,7 @@ EXTERN_C struct TCServer *tc_server_new_local(struct TCString server_dir, struct
// returned. The caller must free this string.
//
// The server must be freed after it is used - tc_replica_sync does not automatically free it.
EXTERN_C struct TCServer *tc_server_new_sync(struct TCString origin,
EXTERN_C struct TCServer *tc_server_new_sync(struct TCString url,
struct TCUuid client_id,
struct TCString encryption_secret,
struct TCString *error_out);