Files
memind/page-data-policy-store.mjs
john 8d01553469 feat(page-data): add private and public dataset API (phase 1-3)
Extract UserDataSpaceService for shared SQLite access, wire logged-in Page
Data routes, and add public insert plus password-token read/update/delete with
policy storage, rate limits, and regression tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-08 12:44:23 +08:00

53 lines
2.0 KiB
JavaScript

import fs from 'node:fs';
import path from 'node:path';
import { normalizePageAccessPolicy } from './page-access-policy.mjs';
export function resolvePageDataPolicyDir(workspaceRoot) {
return path.join(workspaceRoot, '.mindspace', 'page-data-policies');
}
export function resolvePageDataPolicyPath(workspaceRoot, pageId) {
const safePageId = String(pageId ?? '').trim();
if (!safePageId || /[\\/]/.test(safePageId)) {
throw Object.assign(new Error('pageId 无效'), { code: 'invalid_page_id' });
}
return path.join(resolvePageDataPolicyDir(workspaceRoot), `${safePageId}.json`);
}
export function readPageAccessPolicy(workspaceRoot, pageId) {
const policyPath = resolvePageDataPolicyPath(workspaceRoot, pageId);
if (!fs.existsSync(policyPath)) return null;
const raw = JSON.parse(fs.readFileSync(policyPath, 'utf8'));
return normalizePageAccessPolicy(raw, { fallbackPageId: pageId });
}
export function writePageAccessPolicy(workspaceRoot, policyInput) {
const policy = normalizePageAccessPolicy(policyInput);
const policyDir = resolvePageDataPolicyDir(workspaceRoot);
fs.mkdirSync(policyDir, { recursive: true });
const policyPath = resolvePageDataPolicyPath(workspaceRoot, policy.pageId);
fs.writeFileSync(
policyPath,
`${JSON.stringify({ ...policy, updatedAt: new Date().toISOString() }, null, 2)}\n`,
'utf8',
);
return readPageAccessPolicy(workspaceRoot, policy.pageId);
}
export function deletePageAccessPolicy(workspaceRoot, pageId) {
const policyPath = resolvePageDataPolicyPath(workspaceRoot, pageId);
if (!fs.existsSync(policyPath)) return false;
fs.unlinkSync(policyPath);
return true;
}
export function listPageAccessPolicies(workspaceRoot) {
const policyDir = resolvePageDataPolicyDir(workspaceRoot);
if (!fs.existsSync(policyDir)) return [];
return fs
.readdirSync(policyDir)
.filter((name) => name.endsWith('.json'))
.map((name) => readPageAccessPolicy(workspaceRoot, name.replace(/\.json$/, '')))
.filter(Boolean);
}