Adds local System Name persistence (trimmed, 1-40) in system_kv, an
injectable sync module with conflict/invalid revert and a pending-sync
flag, a background SystemNameSync worker (retries on boot and on a timer),
and api_client support for PUT /licenses/{key}/system-name plus the
additive systemName field/systemNameStatus on license validation. The
license service sends the stored name and applies the status. Covers
validation, pending retry, and conflict revert with a faked HTTP layer.
54 lines
2.5 KiB
C++
54 lines
2.5 KiB
C++
#pragma once
|
|
|
|
#include "db/database_manager.h"
|
|
#include "network/api_client.h"
|
|
#include <functional>
|
|
#include <string>
|
|
|
|
namespace radiantwave::license {
|
|
|
|
enum class Result {
|
|
Ok, // license valid; subscription active
|
|
NotConfigured, // email and/or license key missing from the DB
|
|
Invalid, // API rejected the pair (bad key, wrong user, inactive, ...)
|
|
NetworkError, // the request never completed
|
|
};
|
|
|
|
// How long a previously-validated license stays valid without a successful
|
|
// re-validation (7 days). Network failures within this window after the last
|
|
// successful check do not invalidate the license; the user has the whole
|
|
// window to reconnect so the "last verified" stamp can be refreshed.
|
|
constexpr long long GRACE_PERIOD_SECONDS = 7LL * 24 * 60 * 60;
|
|
|
|
// Validates the stored license key against the stored email address via the
|
|
// portal API. A successful validation is the device's "subscribed" flag — no
|
|
// separate subscription state is tracked. On failure nothing is written, so a
|
|
// previous good value survives a transient outage. Returns NotConfigured
|
|
// without touching the network when either value is missing. Never throws.
|
|
//
|
|
// `outErrorMessage` is an optional out-param.
|
|
Result validateStoredLicense(radiantwave::db::DatabaseManager& db,
|
|
std::string* outErrorMessage = nullptr);
|
|
|
|
// Injectable core of validateStoredLicense: performs the given validation call
|
|
// instead of the live portal. On success it stamps "last verified" and applies
|
|
// any advisory `systemNameStatus` to the local System Name state.
|
|
using ValidateFn = std::function<api::LicenseResult(
|
|
const std::string& key, const std::string& email, const std::string& systemName)>;
|
|
|
|
Result validateStoredLicenseWith(radiantwave::db::DatabaseManager& db,
|
|
const ValidateFn& validate,
|
|
std::string* outErrorMessage = nullptr);
|
|
|
|
// Records the current time as the "last verified" stamp of the license. Called
|
|
// after every successful server validation so the offline grace window starts
|
|
// (or is extended) from the most recent confirmation.
|
|
void markLicenseVerified(radiantwave::db::DatabaseManager& db);
|
|
|
|
// True when a prior successful validation happened within
|
|
// GRACE_PERIOD_SECONDS of now. Returns false when no stamp is stored or the
|
|
// stamp is corrupted or older than the grace window.
|
|
bool isLicenseWithinGracePeriod(const radiantwave::db::DatabaseManager& db);
|
|
|
|
} // namespace radiantwave::license
|