feat(authz): add atomic mobile knowledge writes
This commit is contained in:
parent
a3282f7fe1
commit
5e2ba5b006
6 changed files with 527 additions and 19 deletions
|
|
@ -437,6 +437,49 @@ function createApp(options = {}) {
|
|||
}
|
||||
}
|
||||
|
||||
if (
|
||||
req.method === "PUT"
|
||||
&& url.pathname === "/api/hololake/knowledge/page"
|
||||
) {
|
||||
const authenticated = authenticateHoloLake(req);
|
||||
if (!authenticated.ok) {
|
||||
return json(
|
||||
res,
|
||||
authenticated.status,
|
||||
failure(authenticated.error),
|
||||
);
|
||||
}
|
||||
if (!hololakeKnowledgeProvider) {
|
||||
return json(res, 503, failure("knowledge_repository_unavailable"));
|
||||
}
|
||||
const body = await readJson(req, 1024 * 1024 + 16 * 1024);
|
||||
if (!body || typeof body !== "object") {
|
||||
return json(res, 400, failure("knowledge_page_request_invalid"));
|
||||
}
|
||||
try {
|
||||
const receipt = hololakeKnowledgeProvider.writePage({
|
||||
path: body.path,
|
||||
content: body.content,
|
||||
baseCommit: body.base_commit,
|
||||
});
|
||||
return json(res, 200, receipt);
|
||||
} catch (error) {
|
||||
const code = String(error && error.message || "");
|
||||
if (code === "knowledge_commit_conflict") {
|
||||
return json(res, 409, failure(code));
|
||||
}
|
||||
if ([
|
||||
"knowledge_page_path_invalid",
|
||||
"knowledge_secret_page_forbidden",
|
||||
"knowledge_page_content_invalid",
|
||||
"knowledge_page_too_large",
|
||||
].includes(code)) {
|
||||
return json(res, 400, failure(code));
|
||||
}
|
||||
return json(res, 503, failure("knowledge_repository_unavailable"));
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
req.method === "GET"
|
||||
&& url.pathname === "/api/hololake/knowledge/archive"
|
||||
|
|
@ -1252,10 +1295,21 @@ function document(title, body) {
|
|||
</style></head><body><main class="shell">${body}</main></body></html>`;
|
||||
}
|
||||
|
||||
function readJson(req) {
|
||||
function readJson(req, maxBytes = 32 * 1024) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let raw = "";
|
||||
req.on("data", chunk => { raw += chunk; if (raw.length > 32 * 1024) { const error = new Error("body too large"); error.code = "BODY_TOO_LARGE"; reject(error); req.destroy(); } });
|
||||
let received = 0;
|
||||
req.on("data", chunk => {
|
||||
received += chunk.length;
|
||||
if (received > maxBytes) {
|
||||
const error = new Error("body too large");
|
||||
error.code = "BODY_TOO_LARGE";
|
||||
reject(error);
|
||||
req.destroy();
|
||||
return;
|
||||
}
|
||||
raw += chunk;
|
||||
});
|
||||
req.on("end", () => { try { resolve(JSON.parse(raw || "{}")); } catch { resolve(null); } });
|
||||
req.on("error", reject);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue