Data room portal – access chain, sign-in and viewing

The portal's access chain checked on every request, sign-in, persistent session and invitation token, and the viewing, preview, search and quick link endpoints.

Overview

A separate password-protected portal page where documents of folders shared on the admin side can be viewed, searched and — if allowed — downloaded with a watermark. Sign-in uses the framework's admin user master. Store-dependent: folders and documents are visible only in the store (subdomain) they are assigned to.

Common access chain

  1. The user is active (isUserActive, on every request); session key docshare_user_id.
  2. The folder is accessible (accessibleWhere): doc_share.status = 1, date_start <= now < date_expire in Budapest time, the user's own assignment window, and store filtering (doc_share_to_store).
  3. Document: doc_share_item membership, doc.status = 1, content (company) scope from the company/company_id rules of permission_scope (user, else group; super admin unlimited; no rule means no restriction; an empty allow list means nothing), and document store filtering (doc_to_store).
  4. Every event is written to the audit log (channel document/portal) with IP address and user agent.

Endpoints

EndpointBehaviour
document/documentwithout sign-in only the login box; signed in: left navigation, labels, global search. Without doc_share_id the home page: folder cards, statistics, all accessible documents deduplicated by doc_id (the more favourable download right wins), external web links, total size; with doc_share_id the folder view. Per row type, can_view, can_download (folder AND document downloadable), only controller URLs. For a non-default store the store's name and logo.
.login, .logoutauthenticate(): active user, password_verify; with remember a 30-day persistent token (doc_portal_token, cookie dlbt_portal_remember: secure, httponly, SameSite=Lax). Failures are logged with the user name. Sign-out deletes token and cookie.
.setpassword, .setpasswordsaveverifyInviteToken() (SHA-256; active, unused, not expired, bound to an active user); nothing leaks for an invalid one. Save: at least 8 characters and match, setUserPassword(), markInviteUsed(), automatic sign-in, logged. Table: user_invite.
.viewfull chain; direct navigation blocked for embeddable types (Sec-Fetch-Dest: document); bytes from storage (local copy, for Drive and OneDrive the doc cache outside the web root); office files converted to PDF via Drive (cached); dynamic watermark for PDF (Dlbtwatermark::pdf: name, ID, date, time, warning text); Content-Disposition: inline; temporary files are deleted
.gviewfor a Drive file, after the chain, a link-based read permission (once per session) and a redirect to the Drive preview; this path does not watermark
.thumbimages only, w = 240, 480 or 960; ETag and 304; cache with LRU touch; 403 without permission
.sheetfor a downloadable folder and document a Google copy ("name (online)") with writer/anyone right, written to the doc record; the original does not change
.search, .searchallname filter within the folder; global search across all accessible folders, logged with the term and hit count
.t&t=quick link without sign-in: doc_token (SHA-256, active, not expired), optional password, dl=1 only for allow_download=1 tokens, proxied bytes, hit counter, logged; invalid → neutral 404; no watermark on this path

Known limitations

  • There is no sign-in attempt limit in the code.
  • The gview and quick link paths do not watermark.