mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-24 22:04:56 +00:00
code: cpp,dbal,hpp (7 files)
This commit is contained in:
43
dbal/cpp/src/security/nonce_check_and_store.hpp
Normal file
43
dbal/cpp/src/security/nonce_check_and_store.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
/**
|
||||
* @file nonce_check_and_store.hpp
|
||||
* @brief Nonce validation and storage
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <chrono>
|
||||
|
||||
namespace dbal::security {
|
||||
|
||||
/**
|
||||
* Nonce storage state
|
||||
*/
|
||||
struct NonceStorage {
|
||||
std::unordered_map<std::string, std::chrono::steady_clock::time_point> nonces;
|
||||
std::chrono::steady_clock::time_point last_cleanup{};
|
||||
int expiry_seconds = 300;
|
||||
int cleanup_interval_seconds = 60;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if nonce is fresh and store it
|
||||
* @param storage The nonce storage state
|
||||
* @param nonce The nonce to check
|
||||
* @return true if fresh (not seen before), false if replay
|
||||
*/
|
||||
inline bool nonce_check_and_store(NonceStorage& storage, const std::string& nonce) {
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
|
||||
// Check if already exists
|
||||
auto it = storage.nonces.find(nonce);
|
||||
if (it != storage.nonces.end()) {
|
||||
return false; // Replay detected
|
||||
}
|
||||
|
||||
// Store new nonce
|
||||
storage.nonces[nonce] = now;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dbal::security
|
||||
30
dbal/cpp/src/security/nonce_cleanup.hpp
Normal file
30
dbal/cpp/src/security/nonce_cleanup.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
/**
|
||||
* @file nonce_cleanup.hpp
|
||||
* @brief Expired nonce cleanup
|
||||
*/
|
||||
|
||||
#include "nonce_check_and_store.hpp"
|
||||
|
||||
namespace dbal::security {
|
||||
|
||||
/**
|
||||
* Remove expired nonces from storage
|
||||
* @param storage The nonce storage state
|
||||
*/
|
||||
inline void nonce_cleanup(NonceStorage& storage) {
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
auto cutoff = now - std::chrono::seconds(storage.expiry_seconds);
|
||||
|
||||
for (auto it = storage.nonces.begin(); it != storage.nonces.end(); ) {
|
||||
if (it->second < cutoff) {
|
||||
it = storage.nonces.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
storage.last_cleanup = now;
|
||||
}
|
||||
|
||||
} // namespace dbal::security
|
||||
26
dbal/cpp/src/security/nonce_maybe_cleanup.hpp
Normal file
26
dbal/cpp/src/security/nonce_maybe_cleanup.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
/**
|
||||
* @file nonce_maybe_cleanup.hpp
|
||||
* @brief Conditional nonce cleanup based on interval
|
||||
*/
|
||||
|
||||
#include "nonce_cleanup.hpp"
|
||||
|
||||
namespace dbal::security {
|
||||
|
||||
/**
|
||||
* Cleanup expired nonces if interval has passed
|
||||
* @param storage The nonce storage state
|
||||
*/
|
||||
inline void nonce_maybe_cleanup(NonceStorage& storage) {
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(
|
||||
now - storage.last_cleanup
|
||||
).count();
|
||||
|
||||
if (elapsed >= storage.cleanup_interval_seconds) {
|
||||
nonce_cleanup(storage);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dbal::security
|
||||
20
dbal/cpp/src/security/nonce_size.hpp
Normal file
20
dbal/cpp/src/security/nonce_size.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
/**
|
||||
* @file nonce_size.hpp
|
||||
* @brief Get nonce storage size
|
||||
*/
|
||||
|
||||
#include "nonce_check_and_store.hpp"
|
||||
|
||||
namespace dbal::security {
|
||||
|
||||
/**
|
||||
* Get number of stored nonces
|
||||
* @param storage The nonce storage state
|
||||
* @return Count of stored nonces
|
||||
*/
|
||||
inline size_t nonce_size(const NonceStorage& storage) {
|
||||
return storage.nonces.size();
|
||||
}
|
||||
|
||||
} // namespace dbal::security
|
||||
24
dbal/cpp/src/security/rate_limit_remaining.hpp
Normal file
24
dbal/cpp/src/security/rate_limit_remaining.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
/**
|
||||
* @file rate_limit_remaining.hpp
|
||||
* @brief Get remaining tokens in bucket
|
||||
*/
|
||||
|
||||
#include "rate_limit_try_acquire.hpp"
|
||||
|
||||
namespace dbal::security {
|
||||
|
||||
/**
|
||||
* Get remaining tokens in a bucket
|
||||
* @param bucket The token bucket
|
||||
* @param max_tokens Default if bucket uninitialized
|
||||
* @return Number of remaining tokens
|
||||
*/
|
||||
inline double rate_limit_remaining(const TokenBucket& bucket, double max_tokens) {
|
||||
if (bucket.last_update.time_since_epoch().count() == 0) {
|
||||
return max_tokens;
|
||||
}
|
||||
return bucket.tokens;
|
||||
}
|
||||
|
||||
} // namespace dbal::security
|
||||
54
dbal/cpp/src/security/rate_limit_try_acquire.hpp
Normal file
54
dbal/cpp/src/security/rate_limit_try_acquire.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
/**
|
||||
* @file rate_limit_try_acquire.hpp
|
||||
* @brief Token bucket acquire logic
|
||||
*/
|
||||
|
||||
#include <chrono>
|
||||
#include <algorithm>
|
||||
|
||||
namespace dbal::security {
|
||||
|
||||
/**
|
||||
* Token bucket state
|
||||
*/
|
||||
struct TokenBucket {
|
||||
double tokens = 0;
|
||||
std::chrono::steady_clock::time_point last_update{};
|
||||
};
|
||||
|
||||
/**
|
||||
* Try to acquire a token from bucket, refilling based on elapsed time
|
||||
* @param bucket The token bucket state
|
||||
* @param tokens_per_second Refill rate
|
||||
* @param max_tokens Maximum bucket capacity
|
||||
* @return true if token acquired, false if rate limited
|
||||
*/
|
||||
inline bool rate_limit_try_acquire(
|
||||
TokenBucket& bucket,
|
||||
double tokens_per_second,
|
||||
double max_tokens
|
||||
) {
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
|
||||
// Initialize new buckets
|
||||
if (bucket.tokens == 0 && bucket.last_update.time_since_epoch().count() == 0) {
|
||||
bucket.tokens = max_tokens;
|
||||
bucket.last_update = now;
|
||||
}
|
||||
|
||||
// Refill tokens based on elapsed time
|
||||
auto elapsed = std::chrono::duration<double>(now - bucket.last_update).count();
|
||||
bucket.tokens = std::min(max_tokens, bucket.tokens + elapsed * tokens_per_second);
|
||||
bucket.last_update = now;
|
||||
|
||||
// Try to consume
|
||||
if (bucket.tokens >= 1.0) {
|
||||
bucket.tokens -= 1.0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace dbal::security
|
||||
@@ -696,6 +696,15 @@ void test_lua_script_validation() {
|
||||
assert(resultGlobals.error().code() == dbal::ErrorCode::ValidationError);
|
||||
std::cout << " ✓ Empty allowed_globals rejected" << std::endl;
|
||||
|
||||
dbal::CreateLuaScriptInput inputForbiddenGlobals = input1;
|
||||
inputForbiddenGlobals.name = "forbidden-globals";
|
||||
inputForbiddenGlobals.timeout_ms = 1000;
|
||||
inputForbiddenGlobals.allowed_globals = {"os"};
|
||||
auto resultForbiddenGlobals = client.createLuaScript(inputForbiddenGlobals);
|
||||
assert(resultForbiddenGlobals.isError());
|
||||
assert(resultForbiddenGlobals.error().code() == dbal::ErrorCode::ValidationError);
|
||||
std::cout << " ✓ Forbidden globals rejected" << std::endl;
|
||||
|
||||
dbal::CreateLuaScriptInput input2;
|
||||
input2.name = "duplicate-script";
|
||||
input2.code = "return true";
|
||||
@@ -711,6 +720,14 @@ void test_lua_script_validation() {
|
||||
assert(result3.isError());
|
||||
assert(result3.error().code() == dbal::ErrorCode::Conflict);
|
||||
std::cout << " ✓ Duplicate script name rejected" << std::endl;
|
||||
|
||||
dbal::CreateLuaScriptInput input4 = input2;
|
||||
input4.name = "dedupe-globals";
|
||||
input4.allowed_globals = {"math", "math", "print"};
|
||||
auto result4 = client.createLuaScript(input4);
|
||||
assert(result4.isOk());
|
||||
assert(result4.value().allowed_globals.size() == 2);
|
||||
std::cout << " ✓ Allowed globals deduped" << std::endl;
|
||||
}
|
||||
|
||||
void test_package_crud() {
|
||||
|
||||
Reference in New Issue
Block a user