Files
memind/page-data-policy-index.mjs

124 lines
3.8 KiB
JavaScript

import crypto from 'node:crypto';
export function buildPageDataPolicyScopeHash(policy) {
const payload = {
accessMode: policy?.accessMode ?? null,
datasets: Object.keys(policy?.datasets ?? {}).sort(),
};
return crypto.createHash('sha256').update(JSON.stringify(payload)).digest('hex').slice(0, 16);
}
export async function upsertPageDataPolicyIndex(pool, policy) {
if (!pool || !policy?.pageId || !policy?.ownerUserId) return null;
const datasetCount = Object.keys(policy.datasets ?? {}).length;
const now = Date.now();
await pool.query(
`INSERT INTO h5_page_data_policy_index
(page_id, owner_user_id, access_mode, dataset_count, scope_hash, updated_at)
VALUES (?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
owner_user_id = VALUES(owner_user_id),
access_mode = VALUES(access_mode),
dataset_count = VALUES(dataset_count),
scope_hash = VALUES(scope_hash),
updated_at = VALUES(updated_at)`,
[
policy.pageId,
policy.ownerUserId,
policy.accessMode,
datasetCount,
buildPageDataPolicyScopeHash(policy),
now,
],
);
return {
pageId: policy.pageId,
ownerUserId: policy.ownerUserId,
accessMode: policy.accessMode,
datasetCount,
scopeHash: buildPageDataPolicyScopeHash(policy),
updatedAt: now,
};
}
export async function getPageDataPolicyIndex(pool, pageId) {
if (!pool) return null;
const [rows] = await pool.query(
`SELECT page_id, owner_user_id, access_mode, dataset_count, scope_hash, updated_at
FROM h5_page_data_policy_index
WHERE page_id = ?
LIMIT 1`,
[pageId],
);
const row = rows[0];
if (!row) return null;
return {
pageId: row.page_id,
ownerUserId: row.owner_user_id,
accessMode: row.access_mode,
datasetCount: Number(row.dataset_count ?? 0),
scopeHash: row.scope_hash,
updatedAt: Number(row.updated_at ?? 0),
};
}
export async function getPageDataPolicyIndexByWorkspacePath(
pool,
ownerUserId,
workspaceRelativePath,
) {
if (!pool || !ownerUserId || !workspaceRelativePath) return null;
const [rows] = await pool.query(
`SELECT i.page_id, i.owner_user_id, i.access_mode, i.dataset_count,
i.scope_hash, i.updated_at, p.current_publish_id
FROM h5_page_data_policy_index i
JOIN h5_page_records p
ON p.id = i.page_id
AND p.user_id = i.owner_user_id
WHERE i.owner_user_id = ?
AND p.workspace_relative_path = ?
AND p.status <> 'deleted'
ORDER BY i.updated_at DESC
LIMIT 1`,
[ownerUserId, workspaceRelativePath],
);
const row = rows[0];
if (!row) return null;
return {
pageId: row.page_id,
ownerUserId: row.owner_user_id,
accessMode: row.access_mode,
datasetCount: Number(row.dataset_count ?? 0),
scopeHash: row.scope_hash,
updatedAt: Number(row.updated_at ?? 0),
publicationId: row.current_publish_id ?? null,
};
}
export async function listPageDataPolicyIndexByOwner(pool, ownerUserId, { limit = 50 } = {}) {
if (!pool) return [];
const safeLimit = Math.min(Math.max(1, Number(limit ?? 50)), 200);
const [rows] = await pool.query(
`SELECT page_id, owner_user_id, access_mode, dataset_count, scope_hash, updated_at
FROM h5_page_data_policy_index
WHERE owner_user_id = ?
ORDER BY updated_at DESC
LIMIT ?`,
[ownerUserId, safeLimit],
);
return rows.map((row) => ({
pageId: row.page_id,
ownerUserId: row.owner_user_id,
accessMode: row.access_mode,
datasetCount: Number(row.dataset_count ?? 0),
scopeHash: row.scope_hash,
updatedAt: Number(row.updated_at ?? 0),
}));
}
export async function deletePageDataPolicyIndex(pool, pageId) {
if (!pool || !pageId) return false;
const [result] = await pool.query(`DELETE FROM h5_page_data_policy_index WHERE page_id = ?`, [pageId]);
return Number(result?.affectedRows ?? 0) > 0;
}