mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-24 13:54:57 +00:00
docs: dbal,hpp,cpp (5 files)
This commit is contained in:
@@ -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()));
|
||||
}
|
||||
|
||||
|
||||
@@ -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>());
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
14
frontends/nextjs/src/app/api/health/route.test.tsx
Normal file
14
frontends/nextjs/src/app/api/health/route.test.tsx
Normal 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)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user