mirror of
https://github.com/luxfi/license.git
synced 2026-10-30 16:21:14 +00:00
- Stdlib-only deterministic binary token format (no JWT / CBOR dep). - Go API: VerifyToken, LoadFromEnv, HasFeature, HasFeatureOrDie. - Stable C ABI + C++17 RAII wrapper for non-Go commercial binaries (luxcpp/cevm). - cmd/lux-license: keygen / issue / inspect / verify. - Embedded development key; warns once at runtime until production key swap. - 22 Go tests + 1 cgo round-trip test, all passing.
113 lines
3.0 KiB
C++
113 lines
3.0 KiB
C++
/*
|
|
* Copyright (C) 2020-2026, Lux Industries Inc. All rights reserved.
|
|
* See the file LICENSE for licensing terms.
|
|
*
|
|
* lux_license.hpp — thin RAII wrapper around lux_license.h for C++17+.
|
|
*/
|
|
|
|
#ifndef LUX_LICENSE_HPP
|
|
#define LUX_LICENSE_HPP
|
|
|
|
#include "lux_license.h"
|
|
|
|
#include <cstdint>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
namespace lux {
|
|
|
|
class license_error : public std::runtime_error {
|
|
public:
|
|
using std::runtime_error::runtime_error;
|
|
};
|
|
|
|
class License {
|
|
public:
|
|
/* Load and verify a license from the environment. Throws license_error
|
|
* on failure; check::has_feature is the non-throwing alternative. */
|
|
static License load_from_env() {
|
|
auto* c = lux_license_load_from_env();
|
|
if (c == nullptr) {
|
|
throw license_error(lux_license_last_error());
|
|
}
|
|
return License(c);
|
|
}
|
|
|
|
/* Verify a base64-encoded token directly. */
|
|
static License verify_base64(std::string_view token) {
|
|
std::string s(token); // NUL-terminate
|
|
auto* c = lux_license_verify_base64(s.c_str());
|
|
if (c == nullptr) {
|
|
throw license_error(lux_license_last_error());
|
|
}
|
|
return License(c);
|
|
}
|
|
|
|
/* Abort the process if the named feature is not licensed. Mirrors
|
|
* Go's HasFeatureOrDie. */
|
|
static void require_feature_or_die(std::string_view scope) {
|
|
std::string s(scope);
|
|
lux_license_require_feature_or_die(s.c_str());
|
|
}
|
|
|
|
License(const License&) = delete;
|
|
License& operator=(const License&) = delete;
|
|
|
|
License(License&& other) noexcept : claims_(other.claims_) {
|
|
other.claims_ = nullptr;
|
|
}
|
|
|
|
License& operator=(License&& other) noexcept {
|
|
if (this != &other) {
|
|
reset();
|
|
claims_ = other.claims_;
|
|
other.claims_ = nullptr;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
~License() { reset(); }
|
|
|
|
bool has_feature(std::string_view scope) const {
|
|
std::string s(scope);
|
|
return lux_license_has_feature(claims_, s.c_str()) != 0;
|
|
}
|
|
|
|
std::string customer_id() const {
|
|
const char* p = lux_license_customer_id(claims_);
|
|
return p == nullptr ? std::string{} : std::string(p);
|
|
}
|
|
|
|
std::string license_id() const {
|
|
const char* p = lux_license_license_id(claims_);
|
|
return p == nullptr ? std::string{} : std::string(p);
|
|
}
|
|
|
|
int64_t issued_at_unix() const { return lux_license_issued_at_unix(claims_); }
|
|
int64_t expiry_unix() const { return lux_license_expiry_unix(claims_); }
|
|
|
|
int scope_count() const { return lux_license_scope_count(claims_); }
|
|
|
|
std::string scope(int i) const {
|
|
const char* p = lux_license_scope(claims_, i);
|
|
return p == nullptr ? std::string{} : std::string(p);
|
|
}
|
|
|
|
private:
|
|
explicit License(LuxLicenseClaims* c) : claims_(c) {}
|
|
|
|
void reset() {
|
|
if (claims_ != nullptr) {
|
|
lux_license_free(claims_);
|
|
claims_ = nullptr;
|
|
}
|
|
}
|
|
|
|
LuxLicenseClaims* claims_;
|
|
};
|
|
|
|
} /* namespace lux */
|
|
|
|
#endif /* LUX_LICENSE_HPP */
|