73 lines
2.8 KiB
C++
73 lines
2.8 KiB
C++
#pragma once
|
|
#include "storage.h"
|
|
#include <memory>
|
|
|
|
namespace ks
|
|
{
|
|
struct SyncConfig
|
|
{
|
|
bool enabled{};
|
|
bool keepLocalLayouts{};
|
|
std::wstring provider = L"openbao", server, mount = L"kswitcher",
|
|
path = L"personal/settings", authMount = L"userpass", username;
|
|
bool operator==(const SyncConfig &) const = default;
|
|
};
|
|
bool syncVisible(const std::filesystem::path &);
|
|
SyncConfig loadSyncConfig(const std::filesystem::path &);
|
|
void saveSyncConfig(const std::filesystem::path &, const SyncConfig &);
|
|
void validateSyncConfig(const SyncConfig &);
|
|
void saveSyncPassword(const SyncConfig &, const std::wstring &);
|
|
void forgetSyncPassword(const SyncConfig &);
|
|
struct SyncDocument { uint64_t revision{}; Bytes settings; };
|
|
class SyncProvider
|
|
{
|
|
public:
|
|
virtual ~SyncProvider() = default;
|
|
virtual SyncDocument read() = 0;
|
|
virtual uint64_t write(const Bytes &, uint64_t expectedRevision) = 0;
|
|
};
|
|
struct SyncHttpResponse { unsigned status{}; Bytes body; };
|
|
using SyncTransport = std::function<SyncHttpResponse(const std::wstring &method, const std::wstring &path,
|
|
const std::wstring &token, const Bytes &body)>;
|
|
// An injectable transport permits protocol regression tests without a live vault.
|
|
std::unique_ptr<SyncProvider> makeSyncProvider(const SyncConfig &, SyncTransport transport = {});
|
|
inline constexpr ULONGLONG SyncIntervalMs = 10 * 60 * 1000;
|
|
struct SyncConflict
|
|
{
|
|
std::string key;
|
|
std::wstring label;
|
|
Bytes local, remote;
|
|
};
|
|
struct SyncChoice { SyncConflict conflict; bool useLocal{}; };
|
|
Bytes encodeSyncConflicts(const std::vector<SyncConflict> &);
|
|
std::vector<SyncConflict> decodeSyncConflicts(const Bytes &);
|
|
Bytes encodeSyncChoices(const std::vector<SyncChoice> &);
|
|
std::vector<SyncChoice> decodeSyncChoices(const Bytes &);
|
|
std::wstring syncValueText(const Bytes &);
|
|
struct SyncMerge
|
|
{
|
|
Bytes local, remote, base;
|
|
std::vector<SyncConflict> conflicts;
|
|
};
|
|
SyncMerge mergeSyncProfile(const Bytes &base, const Bytes &local, const Bytes &remote,
|
|
const std::vector<SyncChoice> &choices = {});
|
|
Bytes mergeSyncSettings(const Bytes &base, const Bytes &local, const Bytes &remote);
|
|
Bytes sharedSyncSettings(const Settings &);
|
|
Settings restoreSyncSettings(const Bytes &, const Settings &, const std::vector<Layout> &, bool keepLocalLayouts = false);
|
|
enum class SyncAction { Automatic, Download, Upload };
|
|
struct SyncResult
|
|
{
|
|
bool success{};
|
|
Bytes settings;
|
|
uint64_t revision{};
|
|
std::wstring status;
|
|
Bytes base;
|
|
std::vector<SyncConflict> conflicts;
|
|
};
|
|
SyncResult synchronize(SyncProvider &, const Bytes &base, const Bytes &local, SyncAction,
|
|
const std::function<void(const Bytes &)> &validate = {}, const std::vector<SyncChoice> &choices = {},
|
|
bool keepLocalLayouts = false);
|
|
Bytes loadSyncBase(const std::filesystem::path &, const SyncConfig &);
|
|
void saveSyncBase(const std::filesystem::path &, const SyncConfig &, const Bytes &);
|
|
}
|