docs: dbal,hpp,cpp (5 files)

This commit is contained in:
2025-12-26 01:26:35 +00:00
parent bbd8acb296
commit 44b9fbb098
5 changed files with 46 additions and 22 deletions

View File

@@ -21,13 +21,13 @@ namespace session {
inline Result<int> cleanExpired(InMemoryStore& store) {
auto now = std::chrono::system_clock::now();
std::vector<std::string> expired_ids;
for (const auto& [id, session] : store.sessions) {
if (session.expires_at < now) {
if (session.expires_at <= now) {
expired_ids.push_back(id);
}
}
for (const auto& id : expired_ids) {
auto it = store.sessions.find(id);
if (it != store.sessions.end()) {
@@ -35,7 +35,7 @@ inline Result<int> cleanExpired(InMemoryStore& store) {
store.sessions.erase(it);
}
}
return Result<int>(static_cast<int>(expired_ids.size()));
}

View File

@@ -1,6 +1,6 @@
/**
* @file list_sessions.hpp
* @brief List sessions with filtering
* @brief List sessions with filtering and pagination
*/
#ifndef DBAL_LIST_SESSIONS_HPP
#define DBAL_LIST_SESSIONS_HPP
@@ -8,6 +8,7 @@
#include "dbal/types.hpp"
#include "dbal/errors.hpp"
#include "../../store/in_memory_store.hpp"
#include "clean_expired.hpp"
#include <algorithm>
namespace dbal {
@@ -18,36 +19,43 @@ namespace session {
* List sessions with filtering and pagination
*/
inline Result<std::vector<Session>> list(InMemoryStore& store, const ListOptions& options) {
cleanExpired(store);
std::vector<Session> sessions;
auto now = std::chrono::system_clock::now();
for (const auto& [id, session] : store.sessions) {
bool matches = true;
if (options.filter.find("user_id") != options.filter.end()) {
if (session.user_id != options.filter.at("user_id")) matches = false;
}
if (options.filter.find("active_only") != options.filter.end()) {
if (options.filter.at("active_only") == "true" && session.expires_at < now) {
matches = false;
}
if (options.filter.find("token") != options.filter.end()) {
if (session.token != options.filter.at("token")) matches = false;
}
if (matches) {
sessions.push_back(session);
}
if (matches) sessions.push_back(session);
}
std::sort(sessions.begin(), sessions.end(), [](const Session& a, const Session& b) {
return a.created_at > b.created_at;
});
if (options.sort.find("created_at") != options.sort.end()) {
std::sort(sessions.begin(), sessions.end(), [](const Session& a, const Session& b) {
return a.created_at < b.created_at;
});
} else if (options.sort.find("expires_at") != options.sort.end()) {
std::sort(sessions.begin(), sessions.end(), [](const Session& a, const Session& b) {
return a.expires_at < b.expires_at;
});
}
int start = (options.page - 1) * options.limit;
int end = std::min(start + options.limit, static_cast<int>(sessions.size()));
if (start < static_cast<int>(sessions.size())) {
return Result<std::vector<Session>>(std::vector<Session>(sessions.begin() + start, sessions.begin() + end));
}
return Result<std::vector<Session>>(std::vector<Session>());
}

View File

@@ -12,6 +12,7 @@ describe('validateLuaScriptUpdate', () => {
it.each([
{ data: { timeoutMs: 10 }, message: 'timeoutMs must be an integer between 100 and 30000' },
{ data: { allowedGlobals: ['ok', 1 as unknown as string] }, message: 'allowedGlobals must contain non-empty strings' },
{ data: { allowedGlobals: ['os'] }, message: 'allowedGlobals contains forbidden globals: os' },
{ data: { isSandboxed: 'yes' as unknown as boolean }, message: 'isSandboxed must be a boolean' },
])('rejects invalid case', ({ data, message }) => {
expect(validateLuaScriptUpdate(data)).toContain(message)

View File

@@ -23,6 +23,7 @@ Visit `/levels` to step through each tier. The page renders a grid of cards, hig
- Provide `?cap=<term>` (comma-separated) to return only levels whose capability descriptions mention the given keywords.
- `POST /api/levels` accepts a `{ level, note }` payload for telemetry and responds with the matched landing tier.
- `GET /api/levels/metrics` returns totals and capability counts so dashboards can include quick diagnostics.
- `GET /api/health` reports service readiness plus the current number of defined levels.
## Tooling

View File

@@ -0,0 +1,14 @@
import { describe, expect, it } from 'vitest'
import { GET } from './route'
describe('GET /api/health', () => {
it('returns OK status and permission level count', async () => {
const response = await GET(new Request('http://example.com/api/health'))
const payload = await response.json()
expect(payload.status).toBe('ok')
expect(typeof payload.timestamp).toBe('string')
expect(payload.levelCount).toBeGreaterThan(0)
})
})