feat: finalize mindspace service extraction phase a

This commit is contained in:
john
2026-07-03 08:40:28 +08:00
parent 506a551438
commit ec5b1a6e3f
32 changed files with 2834 additions and 490 deletions
+40
View File
@@ -0,0 +1,40 @@
import crypto from 'node:crypto';
function normalizeSecret(secret) {
return String(secret ?? '');
}
export function publicAssetToken(assetId, secret) {
const normalizedAssetId = String(assetId ?? '').trim();
if (!normalizedAssetId) return '';
return crypto
.createHmac('sha256', normalizeSecret(secret))
.update(`mindspace-public-asset:v1:${normalizedAssetId}`)
.digest('base64url');
}
export function verifyPublicAssetToken(assetId, token, secret) {
const value = Array.isArray(token) ? token[0] : token;
const provided = String(value ?? '').trim();
if (!provided) return false;
const expected = publicAssetToken(assetId, secret);
const providedBuffer = Buffer.from(provided);
const expectedBuffer = Buffer.from(expected);
return (
providedBuffer.length === expectedBuffer.length &&
crypto.timingSafeEqual(providedBuffer, expectedBuffer)
);
}
export function appendPublicAssetTokens(html, secret) {
const source = String(html ?? '');
if (!source || !source.includes('/api/mindspace/v1/assets/')) return source;
return source.replace(
/((?:https?:\/\/[^"'<>\\\s]+)?\/api\/mindspace\/v1\/assets\/([a-z0-9-]+)\/download)(\?[^"'<>\\\s)]*)?/gi,
(value, base, assetId, query = '') => {
if (/(?:\?|&|&amp;)public_token=/.test(query)) return value;
const separator = query ? (query.includes('&amp;') ? '&amp;' : '&') : '?';
return `${base}${query}${separator}public_token=${publicAssetToken(assetId, secret)}`;
},
);
}