fix: preview PDFs via blob URL instead of a remote iframe - #2
Conversation
|
|
||
| // rekoni vendors an older pdfjs-dist server-side for PDF text extraction, | ||
| // while packages/ui uses a modern build for browser canvas rendering. | ||
| "pdfjs-dist": ["2.12.313", "4.10.38"] |
There was a problem hiding this comment.
It was not updated for a while yep.
|
Actually self hosted versions are path based and use same origin, it was a Huly global deployment used separate services. Also datalake in case of path based hosting support cookie based auth, so potentially token will not be required. @aonnikov may comment. |
|
btw, I am running this on prem right now. |
Backend blockers found during review of the office/video port: - rpc.ts (#1 broken access control, #2 modifiedBy spoofing): the six direct /api/v1/{create,addCollection,update,createMixin,updateMixin, remove} endpoints build their client via wrapPipeline(...,true), which runs as the system account and bypasses space/role/read-only checks. Gate them to system/service accounts (the only legitimate caller, e.g. the love service which connects with a system token). Regular clients must use the permission-checked /api/v1/tx path. This also stops non-system callers from spoofing modifiedBy. - guests.ts (#3 guest-token secret): sign/verify the guest platform token with the platform SECRET instead of the LiveKit API secret, so it validates against the transactor without conflating the two secrets. - transient.ts (#4 TransientMiddleware): clear the ttlChecker interval in a new close() override (timer leak); detect removes via tx._class (was tx.objectClass, never TxRemoveDoc, so removes re-added the object with a fresh TTL); delete expired entries from ttlObjectMap in checkTTL (map grew unbounded and re-broadcast every second). - FloorPreview.svelte (#9 committed debug scaffolding): remove the dev-only Debug/Clear-AI-Bot/Search-Accounts menu actions and their functions, which hardcoded personal emails and logged PII. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BZnVtCWH1hTH7EisaBdT7T
Backend blockers found during review of the office/video port: - rpc.ts (#1 broken access control, #2 modifiedBy spoofing): the six direct /api/v1/{create,addCollection,update,createMixin,updateMixin, remove} endpoints build their client via wrapPipeline(...,true), which runs as the system account and bypasses space/role/read-only checks. Gate them to system/service accounts (the only legitimate caller, e.g. the love service which connects with a system token). Regular clients must use the permission-checked /api/v1/tx path. This also stops non-system callers from spoofing modifiedBy. - guests.ts (#3 guest-token secret): sign/verify the guest platform token with the platform SECRET instead of the LiveKit API secret, so it validates against the transactor without conflating the two secrets. - transient.ts (#4 TransientMiddleware): clear the ttlChecker interval in a new close() override (timer leak); detect removes via tx._class (was tx.objectClass, never TxRemoveDoc, so removes re-added the object with a fresh TTL); delete expired entries from ttlObjectMap in checkTTL (map grew unbounded and re-broadcast every second). - FloorPreview.svelte (#9 committed debug scaffolding): remove the dev-only Debug/Clear-AI-Bot/Search-Accounts menu actions and their functions, which hardcoded personal emails and logged PII. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BZnVtCWH1hTH7EisaBdT7T Signed-off-by: Artem Savchenko <armisav@gmail.com>
Backend blockers found during review of the office/video port: - rpc.ts (#1 broken access control, #2 modifiedBy spoofing): the six direct /api/v1/{create,addCollection,update,createMixin,updateMixin, remove} endpoints build their client via wrapPipeline(...,true), which runs as the system account and bypasses space/role/read-only checks. Gate them to system/service accounts (the only legitimate caller, e.g. the love service which connects with a system token). Regular clients must use the permission-checked /api/v1/tx path. This also stops non-system callers from spoofing modifiedBy. - guests.ts (#3 guest-token secret): sign/verify the guest platform token with the platform SECRET instead of the LiveKit API secret, so it validates against the transactor without conflating the two secrets. - transient.ts (#4 TransientMiddleware): clear the ttlChecker interval in a new close() override (timer leak); detect removes via tx._class (was tx.objectClass, never TxRemoveDoc, so removes re-added the object with a fresh TTL); delete expired entries from ttlObjectMap in checkTTL (map grew unbounded and re-broadcast every second). - FloorPreview.svelte (#9 committed debug scaffolding): remove the dev-only Debug/Clear-AI-Bot/Search-Accounts menu actions and their functions, which hardcoded personal emails and logged PII. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BZnVtCWH1hTH7EisaBdT7T Signed-off-by: Artem Savchenko <armisav@gmail.com>
|
@haiodo you are right about the browser case, and I should have said so in July instead of the one-liner I left. Apologies for the long silence on my own PR. Path-based self-hosting is same-origin, and if datalake accepts the session cookie there, the The case it does not cover is the desktop app. The desktop front is loaded from disk — Proposal, if agreeable: derive the file URL's origin and only append the token when it differs from Two corrections to my own PR description while I am here, because both were stated more strongly than what I actually verified:
Still current as of today: the branch is @aonnikov you were tagged on 2026-07-10 and I do not think this reached you. The one question that decides the shape: does pod-datalake accept cookie auth for a path-based self-host today, or is that a "should work" rather than a "does work"? Tell me whether you want the origin-gated token or the token removed outright and I will turn it around this week. |
|
@shanzez I somehow overlooked this question. For files preview there was a workaround implemented, instead of embedding PDF documents via URL we download them and embed via blob URL. |
Iframing getFileUrl fails when the file server is cross-origin (desktop loadFile, cloud dl.huly.app vs huly.app): cookies are not sent, and X-Frame-Options: SAMEORIGIN blanks the frame. Download the file with Authorization: Bearer (datalake already accepts this; default cors() allows the preflight) and iframe a blob: URL — the same workaround already used for HTML preview. Same-origin self-host still works via cookies on the fetch. Tokens stay out of the URL. pdf.js is not required. Fixes Platform-Collective#1
2f6d7e4 to
c1c28a8
Compare
|
@aonnikov thanks — that last sentence was the steer. We dropped pdf.js and Pushed over this PR. |
Summary
Fixes #1.
EmbeddedPDFiframesgetFileUrl(...). That is blank when the file server is cross-origin (desktoploadFileorigin, clouddl.huly.appvshuly.app): the session cookie is not sent, andX-Frame-Options: SAMEORIGIN(or our nginx equivalent) refuses the frame.This follows the existing files-preview workaround: download the file with
Authorization: Bearer(datalake already accepts it;cors()default allows the preflight) and iframe a same-originblob:URL. Tokens stay out of the URL. pdf.js is not required.Same-origin self-host still works: the fetch is same-origin, so cookies go with it.
What changed
EmbeddedPDF.svelte— fetch the remote file (Bearer token when the caller has one),createObjectURL, iframe that.blob:/data:srcs are used as-is so HTML preview does not re-download. Aborts and revokes onsrcchange / unmount.presentation.metadata.Token.EmbeddedHTML/ DOCX preview — same path, so converted HTML also authenticates when the file is on datalake.Why not
?token=or pdf.jsAuthorizationand cookies (extractToken). Putting the token in the URL is worse and unnecessary.Set-Cookieon the datalake domain was never implemented; JSdocument.cookiecannot set it cross-origin.Credit: Exaviz team.