# Changelog ## Changes 12/6/2025 (v2.3.6) release(v2.3.6): add non-zip multi-download, richer hover preview/peak, modified sort default - download: add "Download (no ZIP)" bulk action - New context-menu action to download multiple selected files individually without creating a ZIP. - Shows a centered stepper panel with "Download next" / "Cancel" while walking the queue. - Limits plain multi-downloads (default 20) and nudges user to ZIP for larger batches. - Uses existing /api/file/download.php URLs and respects current folder + selection. - hover preview/peak: richer folder/file details and safer snippets - Folder hover now shows: - Icon + path - Owner (from folder caps, when available) - "Your access" summary (Upload / Move / Rename / Share / Delete) based on capabilities. - Created / Modified timestamps derived from folder stats. - Peek into child items (📁 / 📄) with trimmed labels and a clean "…" when truncated. - File hover now adds: - Tags/metadata line (tag names + MIME, duration, resolution when present). - Text snippets are now capped per-line and by total characters to avoid huge blocks and keep previews/peak tidy. - sorting: modified-desc default and folder stats for created/modified - Default sort for the file list is now `Modified ↓` (newest first), matching typical Explorer-style views. - Folders respect Created/Uploaded and Modified sort using folder stats: - Created/Uploaded uses `earliest_uploaded`. - Modified uses `latest_mtime`. - Added a shared compareFilesForSort() so table view and gallery view use the same sort pipeline. - Inline folders still render A>Z by name, so tree/folder strip remain predictable. - UX / plumbing - Added i18n strings for the new download queue labels and permission names ("Your access", Upload/Move/Rename/Share/Delete). - Reset hover snippet styling per-row so folder previews and file previews each get the right wrapping behavior. - Exported downloadSelectedFilesIndividually on window for file context menu integration and optional debugging helpers. - Changed default file list row height from 48px to 44px. --- ## Changese 12/6/2025 (v2.3.5) release(v2.3.5): make client portals ACL-aware and improve admin UX - Wire PortalController into ACL.php and expose canUpload/canDownload flags - Gate portal uploads/downloads on both portal flags and folder ACL for logged-in users - Normalize legacy portal JSON (uploadOnly) with new allowDownload checkbox semantics - Disable portal upload UI when uploads are turned off; hide refresh when downloads are disabled - Improve portal subtitles (“Upload & download”, “Upload only”, etc.) and status messaging - Add quick-access buttons in Client Portals modal for Add user, Folder access, and User groups - Enforce slug + folder as required on both frontend and backend, with inline hints and scroll-to-first-error - Auto-focus newly created portals’ folder input for faster setup - Raise user permissions modal z-index so it appears above the portals modal - Enhance portal form submission logging with better client IP detection (X-Forwarded-For / X-Real-IP aware) --- ## Changes 12/5/2025 (v2.3.4) release(v2.3.4): fix(admin): use textContent for footer preview to satisfy CodeQL --- ## Changes 12/5/2025 (v2.3.3) release(v2.3.3): footer branding, Pro bundle UX + file list polish **Branding & footer** - Added **Pro-only footer branding** (`branding.footerHtml`) stored in `adminConfig.json` and exposed via the Admin API. - Footer is now rendered from config; if no Pro footer is set, FileRise shows: `© YEAR FileRise` with a link to **filerise.net**. - New **“Header & Footer settings”** section in the Admin Panel, with a textarea for footer HTML (simple HTML + links allowed for Pro users). **FileRise Pro & license UX** - Bumped UI hint to `PRO_LATEST_BUNDLE_VERSION = v1.2.1`. - Pro bundle install now: - Parses the version from the uploaded ZIP basename (works with `C:\fakepath\FileRisePro-v1.2.1.zip`). - Invalidates OPcache for updated Pro files so new code is active immediately. - Re-fetches admin config after a successful install and displays the actual active Pro bundle version in the status line. - Admin config now exposes richer Pro metadata (plan, expiresAt, maxMajor), and the Admin Panel shows: - License type + email, - Friendly **plan** description (early supporter vs personal/business), - **Lifetime** vs **Valid until …** wording instead of a scary raw timestamp. **Upload UX** - Upload button is now only visible/enabled when there are files queued (regular or resumable): - Hidden when the list is empty or after clearing uploads. - Shown again when user picks or drags in files. - Adjusted Upload / Choose Files button sizing and spacing for a cleaner upload card, especially on smaller screens. **File list & hover preview polish** - Inline folders now respect the current sort mode: - **Name** sort: A–Z / Z–A. - **Size** sort: uses folder stats (bytes) and sorts accordingly. - Size and meta columns: - Right-aligned **size**, **uploaded/created**, **modified**, and **owner/uploader** columns. - Use tabular numerals for nicer numeric alignment. - Hover preview: - Skips “fake” rows (e.g. “No files found”) and rows that don’t resolve to a real file. - Uses `sizeBytes` + `formatSize()` for a consistent, human-readable size. - `formatSize()` now uses 1 decimal place (KB/MB/GB) and short `B` label for bytes. - File metadata normalization: - Every file gets a `sizeBytes`, normalized display `size`, and a `cacheKey` derived from modified/uploaded/size, used for stable cache-busting. - Gallery / preview URLs now use `apiFileUrl()` with a stable `t` parameter instead of `Date.now()`, improving browser caching behavior. **Layout & animation tweaks** - Slightly reduced default upload card padding and button sizes to make the homepage cards feel less “tall”. - New **site footer** styling (subtle border, centered text) added below the main layout. - Drag-and-drop card (upload/folder cards to header dock) animations: - Crisper ghost cards with better text opacity and anti-jank tweaks. - Longer, smoother easing and more readable motion (both collapse-to-header and expand-from-header). --- ## Changes 12/3/2025 (v2.3.2) release(v2.3.2): fix media preview URLs and tighten hover card layout - Reuse the working preview URL as a base when stepping between images/videos so next/prev navigation keeps using the same inline/download endpoint - Preserve video progress tracking and watched badges while fixing black-screen playback issues across browsers - Slightly shrink the file hover preview card (width/height, grid columns, gaps, snippet/props heights) for a more compact, less intrusive peek --- ## Changes 12/3/2025 (v2.3.1) release(v2.3.1): polish file list actions & hover preview peak - Replace per-row action button stack with compact 3-dot “More actions” menu in file list and folder tree - Add desktop hover preview peak card for files & folders (image thumb, text snippet, quick metadata) - Add per-user toggle to disable file hover preview (stored in localStorage) - Improve preview overlay: add Download button, Zoom/Rotate labels, keep download target in sync when navigating images/videos - Fix mobile table layout so Size column is visible for files & folders - Tweak dark/light glassmorphism styles for hover card and action buttons - Clean up size parsing and editable flag logic for big/unknown files --- ## Changes 12/2/2025 (v2.3.0) release(v2.3.0): feat(portals): branding, intake presets, limits & CSV export **v2.3.0 – Portal branding, intake presets & upload limits** **Client portals (Pro)** - Added **per-portal branding**: - Custom accent color and footer text, applied to both the portal page and the login card. - Optional **portal logo** stored under `uploads/profile_pics`, with a simple upload flow from the Client Portals modal. - Upgraded the **intake form**: - Per-field labels, defaults, visibility, and "required" switches for Name, Email, Reference, and Notes. - New presets for common workflows: **Legal intake**, **Tax client**, and **Order / RMA** that pre-fill labels and hints. - New **thank-you screen**: - Optional “Thank you” message shown after successful uploads, configurable per portal. - New **upload rules per portal**: - Max file size (MB) override. - Allowed extensions whitelist (comma-separated). - Simple per-browser daily upload limit, enforced in the portal UI with clear messaging. - Improved **portal description**: - Portal page now shows active rules (max size, allowed types, daily limit) so clients know what’s allowed. - **Submissions block** in the Client Portals modal: - Inline list of portal submissions with timestamps, folder, submitter and IP. - “Load submissions” button with paging-style UI and improved styling in both light and dark mode. - (New) **Export to CSV** action from the submissions block for easier reporting and audits. **Portal login** - Portal login screen now respects **per-portal branding**: - Uses the portal’s logo (or falls back to the default FileRise logo). - Reuses accent color and footer text from portal metadata so login matches the portal look. **Admin panel** - Added dedicated **Client Portals** editor section with: - Portal slug / label, folder picker, expiry, upload/download options. - Branding, logo upload, intake presets, upload limits, thank-you message, and live submissions preview. - Wired up new **ONLYOFFICE** admin section: - Toggle, document server origin, JWT secret management, plus built-in connection tests and CSP helper. - Wired up **Sponsor** section helper with copy-to-clipboard convenience for support links. - Moved a bunch of admin-panel specific styles into `styles.css` for better maintainability (modal sizing, section headers, dark-mode tweaks). **File Preview** - Remember the user’s volume (and mute state) in localStorage and re-apply it for every video preview in browser. **Security / hardening** - New `public/api/pro/portals/uploadLogo.php` endpoint for portal logos: - Pro-only, admin-only, CSRF-protected. - Accepts JPEG/PNG/GIF up to 2MB and stores them under `UPLOAD_DIR/profile_pics` with randomised names. _No breaking changes expected; existing portals continue to work with default settings._ --- ## Changes 11/30/2025 (v2.2.4) release(v2.2.4): fix(admin): ONLYOFFICE JWT save crash and respect replace/locked flags - Prevented a JS crash when the ONLYOFFICE JWT field isn’t present by always initializing payload.onlyoffice before touching jwtSecret. - Tightened ONLYOFFICE JWT handling so the secret is only sent when config isn’t locked by PHP and the admin explicitly chooses Replace (or is setting it for the first time), instead of always pushing whatever is in the field. --- ## Changes 11/29/2025 (v2.2.3) fix(preview): harden SVG handling and normalize mime type release(v2.2.3): round gallery card corners in file grid - Stop treating SVGs as inline-previewable images in file list and preview modal - Show a clear “SVG preview disabled for security reasons” message instead - Keep SVGs downloadable via /api/file/download.php with proper image/svg+xml MIME - Add i18n key for svg_preview_disabled --- ## Changes 11/29/2025 (v2.2.2) release(v2.2.2): feat(folders): show inline folder stats & dates - Extend FolderModel::countVisible() to track earliest and latest file mtimes - Format folder created/modified timestamps via DATE_TIME_FORMAT on the backend - Add a small folder stats cache in fileListView.js to reuse isEmpty.php responses - Use shared fetchFolderStats() for both folder strip icons and inline folder rows - Show per-folder item counts, total size, and created/modified dates in inline rows - Make size parsing more robust by accepting multiple backend size keys (bytes/sizeBytes/size/totalBytes) --- ## Changes 11/28/2025 (v2.2.1) release(v2.2.1): fix(storage-explorer): DOM-safe rendering + docs for disk usage - Refactor adminStorage breadcrumb builder to construct DOM nodes instead of using innerHTML. - Rework Storage explorer folder view to render rows via createElement/textContent, avoiding DOM text reinterpreted as HTML. - Keep deep-delete and pagination behavior unchanged while tightening up XSS/CodeQL concerns. - Update README feature list to mention disk usage summary and Pro storage explorer (ncdu-style) alongside user groups and client portals. --- ## Changes 11/28/2025 (v2.2.0) release(v2.2.0): add storage explorer + disk usage scanner - New **Storage / Disk Usage** admin section with snapshot-based totals and "Top folders by size". - Disk usage CLI scanner (`src/cli/disk_usage_scan.php`) and background rescan endpoint. - New **Storage Explorer** (drilldown, top files view, deep-delete actions) available in FileRise Pro v1.2.0. - Non-Pro installsshow a blurred preview of the explorer with upgrade prompts. Features - Add new "Storage / Disk Usage" section to the Admin Panel with a summary card and "Top folders by size" table. - Introduce CLI disk usage scanner (src/cli/disk_usage_scan.php) that walks UPLOAD_DIR, applies FS::IGNORE()/SKIP(), and persists a structured snapshot to META_DIR/disk_usage.json. - Add /api/admin/diskUsageSummary.php and /api/admin/diskUsageTriggerScan.php endpoints to expose the snapshot and trigger background rescans from the UI. - Wire the new storage section into adminPanel.js with a Rescan button that launches the CLI worker and polls for a fresh snapshot. Improvements - Storage summary now shows total files, folders, scan duration, and last scan time, plus grouped volume usage across Uploads / Users / Metadata when available. - "Top folders by size" table supports a Pro-only "show more" interaction, but still provides a clean preview in the core edition. - Slight spacing / layout tweaks so the Storage card doesn’t sit flush against the Admin Panel header. Pro integration - Keep the full ncdu-style "Storage explorer" (per-folder drilldown + global Top files, deep delete toggle, size filters, etc.) behind FR_PRO_ACTIVE via /api/pro/diskUsageChildren.php and /api/pro/diskUsageTopFiles.php. - Pro-only delete-from-explorer actions are exposed via /api/pro/diskUsageDeleteFilePermanent.php and /api/pro/diskUsageDeleteFolderRecursive.php, reusing FileModel and FolderModel admin helpers. - Non-Pro instances still see the explorer teaser, but the table body is blurred and padded with "Pro" badges, clearly advertising the upgrade path without exposing the Pro internals. DX / internals - Centralize disk usage logic in DiskUsageModel: snapshot builder, summary (including volumes), per-folder children view, and global Top N file listing. - Ensure adminStorage.js is idempotent and safe to re-init when the Admin Panel is reopened (guards on data-* flags, re-wires only once). - Add robust PHP-CLI discovery and log output for the disk usage worker, mirroring the existing zip worker pattern. --- ## Changes 11/27/2025 (v2.1.0) 🦃🍂 Happy Thanksgiving. 🥧🍁🍽️ release(v2.1.0): add header zoom controls, preview tags & modal/dock polish - **feat(ux): header zoom controls with persisted app zoom** - Add `zoom.js` with percent-based zoom API (`window.fileriseZoom`) and `--app-zoom` CSS variable. - Wrap the main app in `#appZoomShell` and scale via `transform: scale(var(--app-zoom))` so the whole UI zooms uniformly. - Add header zoom UI (+ / − / 100% reset) and wire it via `data-zoom` buttons. - Persist zoom level in `localStorage` and restore on load. - **feat(prefs): user toggle to hide header zoom controls** - Add `hide_header_zoom_controls` i18n key. - Extend the Settings → Display fieldset with “Hide header zoom controls”. - Store preference in `localStorage('hideZoomControls')` and respect it from `appCore.js` when initializing header zoom UI. - **feat(preview): show file tags next to preview title** - Add `.title-tags` container in the media viewer header. - When opening a file, look up its `tags` from `fileData` and render them as pill badges beside the filename in the modal top bar. - **fix(modals): folder modals always centered above header cards** - Introduce `detachFolderModalsToBody()` in `folderManager.js` and call it on init + before opening create/rename/move/delete modals. - Move those modals under `document.body` with a stable high `z-index`, so they’re not clipped/hidden when the cards live in the header dock. - **fix(dnd): header dock & hidden cards container** - Change `#hiddenCardsContainer` from `display:none` to an off-screen absolutely positioned container so card internals (modals/layout) still work while represented as header icons. - Ensure sidebar is always visible as a drop target while dragging (even when panels are collapsed), plus improved highlight & placeholder behavior. - **feat(ux): header dock hover/lock polish** - Make header icon buttons share the same hover style as other header buttons. - Add `.is-locked` state so a pinned header icon stays visually “pressed” while its card modal is locked open. - **feat(ux): header drop zone and zoom bar layout** - Rework `.header-right` to neatly align zoom controls, header dock, and user buttons. - Add a more flexible `.header-drop-zone` with smooth width/padding transitions and a centered `"Drop Zone"` label when active and empty. - Adjust responsive spacing around zoom controls on smaller screens. - **tweak(prefs-modal): improve settings modal sizing** - Increase auth/settings modal `max-height` from 500px to 600px to fit the extra display options without excessive scrolling. --- ## Changes 11/26/2025 (v2.0.4) release(v2.0.4): harden sessions and align Pro paths with USERS_DIR - Enable strict_types in config.php and AdminController - Decouple PHP session lifetime from "remember me" window - Regenerate session ID on persistent token auto-login - Point Pro license / bundle paths at USERS_DIR instead of hardcoded /users - Tweak folder management card drag offset for better alignment --- ## Changes 11/26/2025 (v2.0.3) release(v2.0.3): polish uploads, header dock, and panel fly animations - Rework upload drop area markup to be rebuild-safe and wire a guarded "Choose files" button so only one OS file-picker dialog can open at a time. - Centralize file input change handling and reset selectedFiles/_currentResumableIds per batch to avoid duplicate resumable entries and keep the progress list/drafts in sync. - Ensure drag-and-drop uploads still support folder drops while file-picker is files-only. - Add ghost-based animations when collapsing panels into the header dock and expanding them back to sidebar/top zones, inheriting card background/border/shadow for smooth visuals. - Offset sidebar ghosts so upload and folder cards don't stack directly on top of each other. - Respect header-pinned cards: cards saved to HEADER stay as icons and no longer fly out on expand. - Slightly tighten file summary margin in the file list header for better alignment with actions. --- ## Changes 11/23/2025 (v2.0.2) release(v2.0.2): add config-driven demo mode and lock demo account changes - Wire FR_DEMO_MODE through AdminModel/siteConfig and admin getConfig (demoMode flag) - Drive demo detection in JS from __FR_SITE_CFG__.demoMode instead of hostname - Show consistent login tip + toasts for demo using shared __FR_DEMO__ flag - Block password changes for the demo user and profile picture uploads when in demo mode - Keep normal user dropdown/admin UI visible even on the demo, while still protecting the demo account --- ## Changes 11/23/2025 (v2.0.0) ### FileRise Core v2.0.0 & FileRise Pro v1.1.0 ```text release(v2.0.0): feat(pro): client portals + portal login flow release(v2.0.1): fix: harden portal + core login redirects for codeql ``` ### Core v2.0.0 - **Portal plumbing in core** - New public pages: `portal.html` and `portal-login.html` for client-facing views. - New portal controller + API endpoints that read portal definitions from the Pro bundle, enforce expiry, and expose safe public metadata. - Login flow now respects a `?redirect=` parameter so portals can bounce through login cleanly and land back on the right slug. - **Admin UX + styling** - Admin panel CSS pulled into a dedicated `adminPanelStyles.js` helper instead of inline styles. - User Groups and Client Portals modals use the new shared styling and dark-mode tweaks so they match the rest of the UI. - **Breadcrumb root fix** - Breadcrumbs now always show **root** explicitly and behave correctly when you’re at top level vs nested folders. - **Routing** - Apache rewrite added for pretty portal URLs: `https://host/portal/` → `portal.html?slug=` without affecting other routes. ### Pro v1.1.0 – Client Portals - **Client portal definitions (Admin → FileRise Pro → Client Portals)** - Create multiple portals, each with: - Slug + display name - Target folder - Optional client email - Upload-only / allow-download flags - Per-portal expiry date - Portal-level copy and branding: - Optional title + instructions - Accent color used throughout the portal UI - Footer text at bottom of the portal page - **Optional intake form before uploads** - Enable a form per portal with fields: name, email, reference, notes. - Per-field “default value” and “required” toggles. - Form must be completed before uploads when enabled. - **Submissions log** - Each portal keeps a submissions list showing: - Date/time, folder, submitting user, IP address - The intake form values (name, email, reference, notes). - **Client-facing experience** - New portal UI with: - Branded header (title + accent color) - Optional intake form - Drag-and-drop upload dropzone - If downloads are enabled, a clean list/grid of files already in that portal’s folder with download buttons. - **Portal login page** - Minimal login screen that pulls title/accent/footer from portal metadata. - After successful login, user is redirected back to the original portal URL. --- ## Changes 11/21/2025 (v1.9.14) release(v1.9.14): inline folder rows, synced folder icons, and compact theme polish - Add ACL-aware folder stats and byte counts in FolderModel::countVisible() - Show subfolders inline as rows above files in table view (Explorer-style) - Page folders + files together and wire folder rows into existing DnD and context menu flows - Add folder action buttons (move/rename/color/share) with capability checks from /api/folder/capabilities.php - Cache folder capabilities and owners to avoid repeat calls per row - Add user settings to toggle folder strip and inline folder rows (stored in localStorage) - Default itemsPerPage to 50 and remember current page across renders - Sync inline folder icon size to file row height and tweak vertical alignment for different row heights - Update table headers + i18n keys to use Name / Size / Modified / Created / Owner labels - Compact and consolidate light/dark theme CSS, search pill, pagination, and font-size controls - Tighten file action button hit areas and add specific styles for folder move/rename buttons --- ## Changes 11/20/2025 (v1.9.13) release(v1.9.13): style(ui): compact dual-theme polish for lists, inputs, search & modals - Added compact, unified light/dark theme for core surfaces (file list, upload, folder manager, admin panel). - Updated modals, dropdown menus, and editor header to use the same modern panel styling in both themes. - Restyled search bar into a pill-shaped control with a dedicated icon chip and better hover states. - Refined pagination (Prev/Next) and font size (A-/A+) buttons to be smaller, rounded, and more consistent. - Normalized input fields so borders render cleanly and focus states are consistent across the app. - Tweaked button shadows so primary actions (Create/Upload) pop without feeling heavy in light mode. - Polished dark-mode colors for tables, rows, toasts, and meta text for a more “app-like” feel. --- ## Changes 11/19/2025 (v1.9.12) release(v1.9.12): feat(pro-acl): add user groups and group-aware ACL - Add Pro user groups as a first-class ACL source: - Load group grants from FR_PRO_BUNDLE_DIR/groups.json in ACL::hasGrant(). - Treat group grants as additive only; they can never remove access. - Introduce AclAdminController: - Move getGrants/saveGrants logic into a dedicated controller. - Keep existing ACL normalization and business rules (shareFolder ⇒ view, shareFile ⇒ at least viewOwn). - Refactor public/api/admin/acl/getGrants.php and saveGrants.php to use the controller. - Implement Pro user group storage and APIs: - Add ProGroups store class under FR_PRO_BUNDLE_DIR (groups.json with {name,label,members,grants}). - Add /api/pro/groups/list.php and /api/pro/groups/save.php, guarded by AdminController::requireAuth/requireAdmin/requireCsrf(). - Keep groups and bundle code behind FR_PRO_ACTIVE/FR_PRO_BUNDLE_DIR checks. - Ship Pro-only endpoints from core instead of the bundle: - Move public/api/pro/uploadBrandLogo.php into core and gate it on FR_PRO_ACTIVE. - Remove start.sh logic that copied public/api/pro from the Pro bundle into the container image. - Extend admin UI for user groups: - Turn “User groups” into a real Pro-only modal with add/delete groups, multi-select members, and member chips. - Add “Edit folder access” for each group, reusing the existing folder grants grid. - Overlay group grants when editing a user’s ACL: - Show which caps are coming from groups, lock those checkboxes, and update tooltips. - Show group membership badges in the user permissions list. - Add a collapsed “Groups” section at the top of the permissions screen to preview group ACLs (read-only). - Misc: - Bump PRO_LATEST_BUNDLE_VERSION hint in adminPanel.js to v1.0.1. - Tweak modal border-radius styling to include the new userGroups and groupAcl modals. --- ## Changes 11/18/2025 (v1.9.11) release(v1.9.11): fix(media): HTTP Range streaming; feat(ui): paged folder strip (closes #68) - media: add proper HTTP Range support to /api/file/download.php so HTML5 video/audio can seek correctly across all browsers (Brave/Chrome/Android/Windows). - media: avoid buffering the entire file in memory; stream from disk with 200/206 responses and Accept-Ranges for smoother playback and faster start times. - media: keep video progress tracking, watched badges, and status chip behavior unchanged but now compatible with the new streaming endpoint. - ui: update the folder strip to be responsive: - desktop: keep the existing "chip" layout with icon above name. - mobile: switch to inline rows `[icon] [name]` with reduced whitespace. - ui: add simple lazy-loading for the folder strip so only the first batch of folders is rendered initially, with a "Load more…" button to append chunks for very large folder sets (stays friendly with 100k+ folders). - misc: small CSS tidy-up around the folder strip classes to remove duplicates and keep mobile/desktop behavior clearly separated. --- ## Changes 11/18/2025 (v1.9.10) release(v1.9.10): add Pro bundle installer and admin panel polish - Add FileRise Pro section in admin panel with license management and bundle upload - Persist Pro bundle under users/pro and sync public/api/pro endpoints on container startup - Improve admin config API: Pro metadata, license file handling, hardened auth/CSRF helpers - Update Pro badge/version UI with “update available” hint and link to filerise.net - Change Pro bundle installer to always overwrite existing bundle files for clean upgrades --- ## Changes 11/16/2025 (v1.9.9) release(v1.9.9): fix(branding): sanitize custom logo URL preview - Sanitize branding.customLogoUrl on the server before writing siteConfig.json - Allow only http/https or site-relative paths; strip invalid/sneaky values - Update adminPanel.js live logo preview to set img src/alt safely - Addresses CodeQL XSS warning while keeping Pro branding logo overrides working --- ## Changes 11/16/2025 (v1.9.8) release(v1.9.8): feat(pro): wire core to Pro licensing + branding hooks - Add Pro feature flags + bootstrap wiring - Define FR_PRO_ACTIVE/FR_PRO_TYPE/FR_PRO_EMAIL/FR_PRO_VERSION/FR_PRO_LICENSE_FILE in config.php and optionally require src/pro/bootstrap_pro.php. - Expose a `pro` block from AdminController::getConfig() so the UI can show license status, type, email, and bundle version without leaking the raw key. - Implement license save endpoint - Add AdminController::setLicense() and /api/admin/setLicense.php to accept a FRP1 license string via JSON, validate basic shape, and persist it to FR_PRO_LICENSE_FILE with strict 0600 permissions. - Return structured JSON success/error responses for the admin UI. - Extend admin config model with branding + safer validation - Add `branding.customLogoUrl`, `branding.headerBgLight`, and `branding.headerBgDark` fields to AdminModel defaults and updateConfig(). - Introduce AdminModel::sanitizeLogoUrl() to allow only site-relative /uploads paths or http(s) URLs; reject absolute filesystem paths, data: URLs, and javascript: URLs. - Continue to validate ONLYOFFICE docsOrigin as http(s) only, keeping core config hardening intact. - New Pro-aware Admin Panel UI - Rework User Management section to group: - Add user / Remove user - Folder Access (per-folder ACL) - User Permissions (account-level flags) - Add Pro-only actions with clear gating: - “User groups” button (Pro) - “Client upload portal” button with “Pro · Coming soon” pill - Add “FileRise Pro” section: - Show current Pro status (Free vs Active) + license metadata. - Textarea for pasting license key, file upload helper, and “Save license” action wired to /api/admin/setLicense.php. - Optional “Copy current license” button when a license is present. - Add “Sponsor / Donations” section with fixed GitHub Sponsors and Ko-fi URLs and one-click copy/open buttons. - Header branding controls (Pro) - Add Header Logo + Header Colors controls under Header Settings, gated by `config.pro.active`. - Allow uploading a logo via /api/pro/uploadBrandLogo.php and auto-filling the normalized /uploads path. - Add live-preview helpers to update the header logo and header background colors in the running UI after saving. - Apply branding on app boot - Update main.js to read branding config on load and apply: - Custom header logo (or fallback to /assets/logo.svg). - Light/dark header background colors via CSS variables. - Keeps header consistent with saved branding across reloads and before opening the admin panel. - Styling + UX polish - Add styles for new admin sections: collapsible headers, dark-mode aware modal content, and refined folder access grid. - Introduce .btn-pro-admin and .btn-pro-pill classes to render “Pro” and “Pro · Coming soon” pills overlayed on buttons, matching the existing header “Core/Pro” badge treatment. - Minor spacing/typography tweaks in admin panel and ACL UI. Note: Core code remains MIT-licensed; Pro functionality is enabled via optional runtime hooks and separate closed-source bundle, without changing the core license text. --- ## Changes 11/14/2025 (v1.9.7) release(v1.9.7): harden client path guard and refine header/folder strip CSS - Tighten isSafeFolderPath() to reject dot-prefixed/invalid segments (client-side defense-in-depth on folder paths). - Rework header layout: consistent logo sizing, centered title, cleaner button alignment, and better small-screen stacking. - Polish user dropdown and icon buttons: improved hover/focus states, dark-mode colors, and rounded menu corners. - Update folder strip tiles: cap tile width, allow long folder names to wrap neatly, and fine-tune text/icon alignment. - Tweak folder tree rows: better label wrapping, vertical alignment, and consistent SVG folder icon rendering. - Small CSS cleanup and normalization (body, main wrapper, media modal/progress styles) without changing behavior. --- ## Changes 11/14/2025 (v1.9.6) release(v1.9.6): hardened resumable uploads, menu/tag UI polish and hidden temp folders (closes #67) - Resumable uploads - Normalize resumable GET “test chunk” handling in `UploadModel` using `resumableChunkNumber` + `resumableIdentifier`, returning explicit `status: "found"|"not found"`. - Skip CSRF checks for resumable GET tests in `UploadController`, but keep strict CSRF validation for real POST uploads with soft-fail `csrf_expired` responses. - Refactor `UploadModel::handleUpload()` for chunked uploads: strict filename validation, safe folder normalization, reliable temp chunk directory creation, and robust merge with clear errors if any chunk is missing. - Add `UploadModel::removeChunks()` + internal `rrmdir()` to safely clean up `resumable_…` temp folders via a dedicated controller endpoint. - Frontend resumable UX & persistence - Enable `testChunks: true` for Resumable.js and wire GET checks to the new backend status logic. - Track in-progress resumable files per user in `localStorage` (identifier, filename, folder, size, lastPercent, updatedAt) and show a resumable hint banner inside the Upload card with a dismiss button that clears the hints for that folder. - Clamp client-side progress to max `99%` until the server confirms success, so aborted tabs still show resumable state instead of “100% done”. - Improve progress UI: show upload speed, spinner while finalizing, and ensure progress elements exist even for non-standard flows (e.g., submit without prior list build). - On complete success, clear the progress UI, reset the file input, cancel Resumable’s internal queue, clear draft records for the folder, and re-show the resumable banner only when appropriate. - Hiding resumable temp folders - Hide `resumable_…` folders alongside `trash` and `profile_pics` in: - Folder tree BFS traversal (child discovery / recursion). - `listChildren.php` results and child-cache hydration. - The inline folder strip above the file list (also filtered in `fileListView.js`). - Folder manager context menu upgrade - Replace the old ad-hoc folder context menu with a unified `filr-menu` implementation that mirrors the file context menu styling. - Add Material icon mapping per action (`create_folder`, `move_folder`, `rename_folder`, `color_folder`, `folder_share`, `delete_folder`) and clamp the menu to viewport with escape/outside-click close behavior. - Wire the new menu from both tree nodes and breadcrumb links, respecting locked folders and current folder capabilities. - File context menu & selection logic - Define a semantic file context menu in `index.html` (`#fileContextMenu` with `.filr-menu` buttons, icons, `data-action`, and `data-when` visibility flags). - Rebuild `fileMenu.js` to: - Derive the current selection from file checkboxes and map back to real `fileData` entries, handling the encoded row IDs. - Toggle menu items based on selection state (`any`, `one`, `many`, `zip`, `can-edit`) and hide redundant separators. - Position the menu within the viewport, add ESC/outside-click dismissal, and delegate click handling to call the existing file actions (preview, edit, rename, copy/move/delete/download/extract, tag single/multiple). - Tagging system robustness - Refactor `fileTags.js` to enforce single-instance modals for both single-file and multi-file tagging, preventing duplicate DOM nodes and double bindings. - Centralize global tag storage (`window.globalTags` + `localStorage`) with shared dropdowns for both modals, including “×” removal for global tags that syncs back to the server. - Make the tag modals safer and more idempotent (re-usable DOM, Esc and backdrop-to-close, defensive checks on elements) while keeping the existing file row badge rendering and tag-based filtering behavior. - Localize various tag-related strings where possible and ensure gallery + table views stay in sync after tag changes. - Visual polish & theming - Introduce a shared `--menu-radius` token and apply it across login form, file list container, restore modal, preview modals, OnlyOffice modal, user dropdown menus, and the Upload / Folder Management cards for consistent rounded corners. - Update header button hover to use the same soft blue hover as other interactive elements and tune card shadows for light vs dark mode. - Adjust media preview modal background to a darker neutral and tweak `filePreview` panel background fallback (`--panel-bg` / `--bg-color`) for better dark mode contrast. - Style `.filr-menu` for both file + folder menus with max-height, scrolling, proper separators, and Material icons inheriting text color in light and dark themes. - Align the user dropdown menu hover/active styles with the new menu hover tokens (`--filr-row-hover-bg`, `--filr-row-outline-hover`) for a consistent interaction feel. --- ## Changes 11/13/2025 (v1.9.5) release(v1.9.5): harden folder tree DOM, add a11y to “Load more”, and guard folder paths - Replace innerHTML-based row construction in folderManager.js with safe DOM APIs (createElement, textContent, dataset). All user-derived strings now use textContent; only locally-generated SVG remains via innerHTML. - Add isSafeFolderPath() client-side guard; fail closed on suspicious paths before rendering clickable nodes. - “Load more” button rebuilt with proper a11y: - aria-label, optional aria-controls to the UL - aria-busy + disabled during fetch; restore state only if the node is still present (Node.isConnected). - Keep lazy tree + cursor pagination behavior intact; chevrons/icons continue to hydrate from server hints (hasSubfolders/nonEmpty) once available. - Addresses CodeQL XSS findings by removing unsafe HTML interpolation and avoiding HTML interpretation of extracted text. No breaking changes; security + UX polish on top of v1.9.4. --- ## Changes 11/13/2025 (v1.9.4) release(v1.9.4): lazy folder tree, cursor pagination, ACL-safe chevrons, and “Load more” (closes #66) **Big focus on folder management performance & UX for large libraries.** feat(folder-tree): - Lazy-load children on demand with cursor-based pagination (`nextCursor` + `limit`), including inline “Load more” row. - BFS-based initial selection: if user can’t view requested/default folder, auto-pick the first accessible folder (but stick to (Root) when user can view it). - Persisted expansion state across reloads; restore saved path and last opened folder; prevent navigation into locked folders (shows i18n toast instead). - Breadcrumb now respects ACL: clicking a locked crumb toggles expansion only (no navigation). - Live chevrons from server truth: `hasSubfolders` is computed server-side to avoid file count probes and show correct expanders (even when a direct child is unreadable). - Capabilities-driven toolbar enable/disable for create/move/rename/color/delete/share. - Color-carry on move/rename + expansion state migration so moved/renamed nodes keep colors and stay visible. - Root DnD honored only when viewable; structural locks disable dragging. perf(core): - New `FS.php` helpers: safe path resolution (`safeReal`), segment sanitization, symlink defense, ignore/skip lists, bounded child counting, `hasSubfolders`, and `hasReadableDescendant` (depth-limited). - Thin caching for child lists and counts, with targeted cache invalidation on move/rename/create/delete. - Bounded concurrency for folder count requests; short timeouts to keep UI snappy. api/model: - `FolderModel::listChildren(...)` now returns items shaped like: `{ name, locked, hasSubfolders, nonEmpty? }` - `nonEmpty` included only for unlocked nodes (prevents side-channel leakage). - Locked nodes are only returned when `hasReadableDescendant(...)` is true (preserves legacy “structural visibility without listing the entire tree” behavior). - `public/api/folder/listChildren.php` delegates to controller/model; `isEmpty.php` hardened; `capabilities.php` exposes `canView` (or derived) for fast checks. - Folder color endpoints gate results by ACL so users only see colors for folders they can at least “own-view”. ui/ux: - New “Load more” row (`
  • `) with dark-mode friendly ghost button styling; consistent padding, focus ring, hover state. - Locked folders render with padlock overlay and no DnD; improved contrast/spacing; icons/chevrons update live as children load. - i18n additions: `no_access`, `load_more`, `color_folder(_saved|_cleared)`, `please_select_valid_folder`, etc. - When a user has zero access anywhere, tree selects (Root) but shows `no_access` instead of “No files found”. security: - Stronger path traversal + symlink protections across folder APIs (all joins normalized, base-anchored). - Reduced metadata leakage by omitting `nonEmpty` for locked nodes and depth-limiting descendant checks. fixes: - Chevron visibility for unreadable intermediate nodes (e.g., “Files” shows a chevron when it contains a readable “Resources” descendant). - Refresh now honors the actively viewed folder (session/localStorage), not the first globally readable folder. chore: - CSS additions for locked state, tree rows, and dark-mode ghost buttons. - Minor code cleanups and comments across controller/model and JS tree logic. --- ## Changes 11/11/2025 (v1.9.3) release(v1.9.3): unify folder icons across tree & strip, add “paper” lines, live color sync, and vendor-aware release - UI / Icons - Replace Material icon in folder strip with shared `folderSVG()` and export it for reuse. Adds clipPaths, subtle gradients, and `shape-rendering: geometricPrecision` to eliminate the tiny seam. - Add ruled “paper” lines and blue handwriting dashes; CSS for `.paper-line` and `.paper-ink` included. - Match strokes between tree (24px) and strip (48px) so both look identical; round joins/caps to avoid nicks. - Polish folder strip layout & hover: tighter spacing, centered icon+label, improved wrapping. - Folder color & non-empty detection - Live color sync: after saving a color we dispatch `folderColorChanged`; strip repaints and tree refreshes. - Async strip icon: paint immediately, then flip to “paper” if the folder has contents. HSL helpers compute front/back/stroke shades. - FileList strip - Render subfolders with `` + name, wire context menu actions (move, color, share, etc.), and attach icons for each tile. - Exports & helpers - Export `openColorFolderModal(...)` and `openMoveFolderUI(...)` for the strip and toolbar; use `refreshFolderIcon(...)` after ops to keep icons current. - AppCore - Update file upload DnD relay hook to `#fileList` (id rename). - CSS tweaks - Bring tree icon stroke/paint rules in line with the strip, add scribble styles, and adjust margins/spacing. - CI/CD (release) - Build PHP dependencies during release: setup PHP 8.3 + Composer, cache downloads, install into `staging/vendor/`, exclude `vendor/` from placeholder checks, and ship artifact including `vendor/`. - Changelog highlights - Sharper, seam-free folder SVGs shared across tree & strip, with paper lines + handwriting accents. - Real-time folder color propagation between views. - Folder strip switched to SVG tiles with better layout + context actions. - Release pipeline now produces a ready-to-run zip that includes `vendor/`. --- ## Changes 11/10/2025 (v1.9.2) release(v1.9.2): Upload modal + DnD relay from file list (with robust synthetic-drop fallback) - New “Upload file(s)” action in Create menu: - Adds `
  • ` to the dropdown. - Opens a reusable Upload modal that *moves* the existing #uploadCard into the modal (no cloning = no lost listeners). - ESC / backdrop / “×” close support; focus jumps to “Choose Files” for fast keyboard flow. - Drag & Drop from file list → Upload: - Drag-over on #fileListContainer shows drop-hover and auto-opens the Upload modal after a short hover. - On drop, waits until the modal’s #uploadDropArea exists, then relays the drop to it. - Uses a resilient relay: attempts to attach DataTransfer to a synthetic event; falls back to a stash. - Synthetic drop fallback: - Introduces window.__pendingDropData (cleared after use). - upload.js now reads e.dataTransfer || window.__pendingDropData to accept relayed drops across browsers. - Implementation details: - fileActions.js: adds openUploadModal()/closeUploadModal() with a hidden sentinel to return #uploadCard to its original place on close. - appCore.js: imports openUploadModal, adds waitFor() helper, and wires dragover/leave/drop logic for the relay. - index.html: adds Upload option to the Create menu and the #uploadModal scaffold. - UX/Safety: - Defensive checks if modal/card isn’t present. - No backend/API changes; CSRF/auth unchanged. Files touched: public/js/upload.js, public/js/fileActions.js, public/js/appCore.js, public/index.html --- ## Changes 11/9/2025 (v1.9.1) release(v1.9.1): customizable folder colors + live preview; improved tree persistence; accent button; manual sync script ### Highlights v1.9.1 - 🎨 Per-folder colors with live SVG preview and consistent styling in light/dark modes. - 📄 Folder icons auto-refresh when contents change (no full page reload). - 🧭 Drag-and-drop breadcrumb fallback for folder→folder moves. - 🛠️ Safer upgrade helper script to rsync app files without touching data. - feat(colors): add per-folder color customization - New endpoints: GET /api/folder/getFolderColors.php and POST /api/folder/saveFolderColor.php - AuthZ: reuse canRename for “customize folder”, validate hex, and write atomically to metadata/folder_colors.json. - Read endpoint filters map by ACL::canRead before returning to the user. - Frontend: load/apply colors to tree rows; persist on move/rename; API helpers saveFolderColor/getFolderColors. - feat(ui): color-picker modal with live SVG folder preview - Shows preview that updates as you pick; supports Save/Reset; protects against accidental toggle clicks. - feat(controls): “Color folder” button in Folder Management card - New `.btn-color-folder` with accent palette (#008CB4), hover/active/focus states, dark-mode tuning; event wiring gated by caps. - i18n: add strings for color UI (color_folder, choose_color, reset_default, save_color, folder_color_saved, folder_color_cleared). - ux(tree): make expansion state more predictable across refreshes - `expandTreePath(path, {force,persist,includeLeaf})` with persistence; keep ancestors expanded; add click-suppression guard. - ux(layout): center the folder-actions toolbar; remove left padding hacks; normalize icon sizing. - chore(ops): add scripts/manual-sync.sh (safe rsync update path, preserves data dirs and public/.htaccess). --- ## Changes 11/9/2025 (v1.9.0) release(v1.9.0): folder tree UX overhaul, fast ACL-aware counts, and .htaccess hardening feat(ui): modern folder tree - New crisp folder SVG with clear paper insert; unified yellow/orange palette for light & dark - Proper ARIA tree semantics (role=treeitem, aria-expanded), cleaner chevrons, better alignment - Breadcrumb tweaks (› separators), hover/selected polish - Prime icons locally, then confirm via counts for accurate “empty vs non-empty” feat(api): add /api/folder/isEmpty.php via controller/model - public/api/folder/isEmpty.php delegates to FolderController::stats() - FolderModel::countVisible() enforces ACL, path safety, and short-circuits after first entry - Releases PHP session lock early to avoid parallel-request pileups perf: cap concurrent “isEmpty” requests + timeouts - Small concurrency limiter + fetch timeouts - In-memory result & inflight caches for fewer network hits fix(state): preserve user expand/collapse choices - Respect saved folderTreeState; don’t auto-expand unopened nodes - Only show ancestors for visibility when navigating (no unwanted persists) security: tighten .htaccess while enabling WebDAV - Deny direct PHP except /api/*.php, /api.php, and /webdav.php - AcceptPathInfo On; keep path-aware dotfile denial refactor: move count logic to model; thin controller action chore(css): add unified “folder tree” block with variables (sizes, gaps, colors) Files touched: FolderModel.php, FolderController.php, public/js/folderManager.js, public/css/styles.css, public/api/folder/isEmpty.php (new), public/.htaccess --- ## Changes 11/8/2025 (v1.8.13) release(v1.8.13): ui(dnd): stabilize zones, lock sidebar width, and keep header dock in sync - dnd: fix disappearing/overlapping cards when moving between sidebar/top; return to origin on failed drop - layout: placeCardInZone now live-updates top layout, sidebar visibility, and toggle icon - toggle/collapse: move ALL cards to header on collapse, restore saved layout on expand; keep icon state synced; add body.sidebar-hidden for proper file list expansion; emit `zones:collapsed-changed` - header dock: show dock whenever icons exist (and on collapse); hide when empty - responsive: enforceResponsiveZones also updates toggle icon; stash/restore behavior unchanged - sidebar: hard-lock width to 350px (CSS) and remove runtime 280px minWidth; add placeholder when empty to make dropping back easy - CSS: right-align header dock buttons, centered “Drop Zone” label, sensible min-height; dark-mode safe - refactor: small renames/ordering; remove redundant z-index on toggle; minor formatting --- ## Changes 11/8/2025 (v1.8.12) release(v1.8.12): auth UI & DnD polish — show OIDC, auto-SSO, right-aligned header icons - auth (public/js/main.js) - Robust login options: tolerate key variants (disableFormLogin/disable_form_login, etc.). - Correctly show/hide wrapper + individual methods (form/OIDC/basic). - Auto-SSO when OIDC is the only enabled method; add opt-out with `?noauto=1`. - Minor cleanup (SW register catch spacing). - drag & drop (public/js/dragAndDrop.js) - Reworked zones model: Sidebar / Top (left/right) / Header (icon+modal). - Persist user layout with `userZonesSnapshot.v2` and responsive stash for small screens. - Live UI sync: toggle icon (`material-icons`) updates immediately after moves. - Smarter small-screen behavior: lift sidebar cards ephemerally; restore only what belonged to sidebar. - Cleaner header icon modal plumbing; remove legacy/dead code. - styles (public/css/styles.css) - Header drop zone fills remaining space and right-aligns its icons. UX: - OIDC button reliably appears when form/basic are disabled. - If OIDC is the sole method, users are taken straight to the provider (unless `?noauto=1`). - Header icons sit with the other header actions (right-aligned), and the toggle icon reflects layout changes instantly. --- ## Changes 11/8/2025 (v1.8.11) release(v1.8.11): fix(oidc): always send PKCE (S256) and treat empty secret as public client - Force PKCE via setCodeChallengeMethod('S256') so Authelia’s public-client policy is satisfied. - Convert empty OIDC client secret to null to correctly signal a public client. - Optional commented hook to switch token endpoint auth to client_secret_post if desired. - OIDC_TOKEN_ENDPOINT_AUTH_METHOD added to config.php --- ## Changes 11/8/2025 (v1.8.10) release(v1.8.10): theme-aware media modal, stronger file drag-and-drop, unified progress color, and favicon overhaul UI/UX — Media modal - Add fixed top bar to avoid filename/controls overlapping native media chrome; keep hover-on-stage look. - Show a Material icon by file type next to the filename (image/video/pdf/code/arch/txt, with fallback). - Restore “X” behavior and make hover theme-aware (red pill + white ‘X’ in light, red pill + black ‘X’ in dark). Video/Image controls - Top-right action icons use theme-aware styles and align with the filename row. - Prev/Next paddles remain high-contrast and vertically centered within the stage. Progress badges (list & modal) - Standardize “in-progress” to darker orange (#ea580c) for better contrast in light/dark; update CSS and list badge rendering. Drag & drop - Support multi-select drags with a clean JSON payload + text fallback; nicer drag ghost. - More resilient drops: accept data-dest-folder, safer JSON parse, early guards, and better toasts. - POST move now sends Accept header, uses global CSRF, and refreshes the active view on success. Editor & ONLYOFFICE - Full-screen OO modal with preconnect, optional hidden warm-up to reduce first-open latency, and live theme sync. - CodeMirror path: fix theme/mode setters (use `cm`) and tighten dynamic mode loading. Assets & polish - Swap in full favicon stack (SVG + PNG 512/32/16 + ICO) and set theme-color; cache-busted via `{{APP_QVER}}`. - Refresh `logo.svg` (accessibility, cleaner handles/gradients). Also added: refreshed resource images and new logo sizes (logo-16, logo-32, logo-64, etc.) for crisper favicons and embeds. --- ## Changes 11/7/2025 (v1.8.9) release(v1.8.9): fix(oidc, admin): first-save Client ID/Secret (closes #64) - adminPanel.js: - Masked inputs without a saved value now start with data-replace="1". - handleSave() now sends oidc.clientId / oidc.clientSecret on first save (no longer requires clicking “Replace” first). --- ## Changes 11/7/2025 (v1.8.8) release(v1.8.8): background ZIP jobs w/ tokenized download + in‑modal progress bar; robust finalize; janitor cleanup — closes #60 **Summary** This release moves ZIP creation off the request thread into a **background worker** and switches the client to a **queue > poll > tokenized GET** download flow. It fixes large multi‑GB ZIP failures caused by request timeouts or cross‑device renames, and provides a resilient in‑modal progress experience. It also adds a 6‑hour janitor for temporary tokens/logs. **Backend** changes: - Add **zip status** endpoint that returns progress and readiness, and **tokenized download** endpoint for one‑shot downloads. - Update `FileController::downloadZip()` to enqueue a job and return `{ token, statusUrl, downloadUrl }` instead of streaming a blob in the POST response. - Implement `spawnZipWorker()` to find a working PHP CLI, set `TMPDIR` on the same filesystem as the final ZIP, spawn with `nohup`, and persist PID/log metadata for diagnostics. - Serve finished ZIPs via `downloadZipFile()` with strict token/user checks and streaming headers; unlink the ZIP after successful read. New **Worker**: - New `src/cli/zip_worker.php` builds the archive in the background. - Writes progress fields (`pct`, `filesDone`, `filesTotal`, `bytesDone`, `bytesTotal`, `current`, `phase`, `startedAt`, `finalizeAt`) to the per‑token JSON. - During **finalizing**, publishes `selectedFiles`/`selectedBytes` and clears incremental counters to avoid the confusing “N/N files” display before `close()` returns. - Adds a **janitor**: purge `.tokens/*.json` and `.logs/WORKER-*.log` older than **6 hours** on each run. New **API/Status Payload**: - `zipStatus()` exposes `ready` (derived from `status=done` + existing `zipPath`), and includes `startedAt`/`finalizeAt` for UI timers. - Returns a prebuilt `downloadUrl` for a direct handoff once the ZIP is ready. **Frontend (UX)** changes: - Replace blob POST download with **enqueue → poll → tokenized GET** flow. - Native `` bar now renders **inside the modal** (no overflow/jitter). - Shows determinate **0–98%** during enumeration, then **locks at 100%** with **“Finalizing… mm:ss — N files, ~Size”** until the download starts. - Modal closes just before download; UI resets for the next operation. Added **CSS**: - Ensure the progress modal has a minimum height and hidden overflow; ellipsize the status line to prevent scrollbars. **Why this closes #60**? - ZIP creation no longer depends on the request lifetime (avoids proxy/Apache timeouts). - Temporary files and final ZIP are created on the **same filesystem** (prevents “rename temp file failed” during `ZipArchive::close()`). - Users get continuous, truthful feedback for large multi‑GB archives. Additional **Notes** - Download tokens are **one‑shot** and are deleted after the GET completes. - Temporary artifacts (`META_DIR/ziptmp/.tokens`, `.logs`, and old ZIPs) are cleaned up automatically (≥6h). --- ## Changes 11/5/2025 (v1.8.7) release(v1.8.7): fix(zip-download): stream clean ZIP response and purge stale temp archives - FileController::downloadZip - Remove _jsonStart/_jsonEnd and JSON wrappers; send a pure binary ZIP - Close session locks, disable gzip/output buffering, set Content-Length when known - Stream in 1MiB chunks; proper HTTP codes/messages on errors - Unlink the temp ZIP after successful send - Preserves all auth/ACL/ownership checks - FileModel::createZipArchive - Purge META_DIR/ziptmp/download-*.zip older than 6h before creating a new ZIP Result: fixes “failed to fetch / load failed” with fetch>blob flow and reduces leftover tmp ZIPs. --- ## Changes 11/4/2025 (v1.8.6) release(v1.8.6): fix large ZIP downloads + safer extract; close #60 - Zip creation - Write archives to META_DIR/ziptmp (on large/writable disk) instead of system tmp. - Auto-create ziptmp (0775) and verify writability. - Free-space sanity check (~files total +5% +20MB); clearer error on low space. - Normalize/validate folder segments; include only regular files. - set_time_limit(0); use CREATE|OVERWRITE; improved error handling. - Zip extraction - New: stamp metadata for files in nested subfolders (per-folder metadata.json). - Skip hidden “dot” paths (files/dirs with any segment starting with “.”) by default via SKIP_DOTFILES_ON_EXTRACT=true; only extract allow-listed entries. - Hardenings: zip-slip guard, reject symlinks (external_attributes), zip-bomb limits (MAX_UNZIP_BYTES default 200GiB, MAX_UNZIP_FILES default 20k). - Persist metadata for all touched folders; keep extractedFiles list for top-level names. Ops note: ensure /var/www/metadata/ziptmp exists & is writable (or mount META_DIR to a large volume). Closes #60. --- ## Changes 11/4/2025 (v1.8.5) release(v1.8.5): ci: reduce pre-run delay to 2-min and add missing `needs: delay`, final test - No change release just testing --- ## Changes 11/4/2025 (v1.8.4) release(v1.8.4): ci: add 3-min pre-run delay to avoid workflow_run races - No change release just testing --- ## Changes 11/4/2025 (v1.8.3) release(v1.8.3): feat(mobile+ci): harden Capacitor switcher & make release-on-version robust - switcher.js: allow running inside Capacitor; remove innerHTML usage; build nodes safely; normalize/strip creds from URLs; add withParam() for ?frapp=1; drop inline handlers; clamp rename length; minor UX polish. - CI: cancel superseded runs per ref; checkout triggering commit (workflow_run head_sha); improve APP_VERSION parsing; point tag to checked-out commit; add recent-tag debug. --- ## Changes 11/4/2025 (v1.8.2) release(v1.8.2): media progress tracking + watched badges; PWA scaffolding; mobile switcher (closes #37) - **Highlights** - Video: auto-save playback progress and mark “Watched”, with resume-on-open and inline status chips on list/gallery. - Mobile: introduced FileRise Mobile (Capacitor) companion repo + in-app server switcher and PWA bits. - **Details** - API (new): - POST /api/media/updateProgress.php — persist per-user progress (seconds/duration/completed). - GET /api/media/getProgress.php — fetch per-file progress. - GET /api/media/getViewedMap.php — folder map for badges. - **Frontend (media):** - Video previews now resume from last position, periodically save progress, and mark completed on end, with toasts. - Added status badges (“Watched” / %-complete) in table & gallery; CSS polish for badges. - Badges render during list/gallery refresh; safer filename wrapping for badge injection. - **Mobile & PWA:** - New in-app server switcher (Capacitor-aware) loaded only in app/standalone contexts. - Service Worker + manifest added (root scope via /public/sw.js; worker body in /js/pwa/sw.js; manifest icons). - main.js conditionally imports the mobile switcher and registers the SW on web origins only. - **Notes** - Companion repo: **filerise-mobile** (Capacitor app shell) created for iOS/Android distribution. - No breaking changes expected; endpoints are additive. Closes #37. --- ## Changes 11/3/2025 (V1.8.1) release(v1.8.1): fix(security,onlyoffice): sanitize DS origin; safe api.js/iframe probes; better UX placeholder - Add ONLYOFFICE URL sanitizers: - getTrustedDocsOrigin(): enforce http/https, strip creds, normalize to origin - buildOnlyOfficeApiUrl(): construct fixed /web-apps/.../api.js via URL() - Probe hardening (addresses CodeQL js/xss-through-dom): - ooProbeScript/ooProbeFrame now use sanitized origins and fixed paths - optional CSP nonce support for injected script - optional iframe sandbox; robust cleanup/timeout handling - CSP helper now renders lines based on validated origin (fallback to raw for visibility) - Admin UI UX: placeholder switched to HTTPS example (`https://docs.example.com`) - Comments added to justify safety to static analyzers Files: public/js/adminPanel.js Refs: #37 --- ## Changes 11/3/2025 (v1.8.0) release(v1.8.0): feat(onlyoffice): first-class ONLYOFFICE integration (view/edit), admin UI, API, CSP helpers Refs #37 — implements ONLYOFFICE integration suggested in the discussion; video progress saving will be tracked separately. Adds secure, ACL-aware ONLYOFFICE support throughout FileRise: - **Backend / API** - New OnlyOfficeController with supported extensions (doc/xls/ppt/pdf etc.), status/config endpoints, and signed download flow. - New endpoints: - GET /api/onlyoffice/status.php — reports availability + supported exts. - GET /api/onlyoffice/config.php — returns DocEditor config (signed URLs, callback). - GET /api/onlyoffice/signed-download.php — serves signed blobs to DS. - Effective config/overrides: env/constant wins; supports docsOrigin, publicOrigin, and jwtSecret; status gated on presence of origin+secret. - Public origin resolution (BASE_URL/proxy aware) for absolute URLs. - **Admin config / UI** - AdminPanel gets a new “ONLYOFFICE” section with Enable toggle, Document Server Origin, masked JWT Secret, and “Replace” control. - Built-in connection tester (status, secret presence, callback ping, api.js load, iframe embed) + CSP helper (Apache & Nginx snippets) - **Frontend integration** - fileEditor detects OO capability via /api/onlyoffice/status and routes supported types to the DocEditor; loads DocsAPI dynamically. - editFile() short-circuits to openOnlyOffice when applicable; includes live dark/light theme sync where supported. - fileListView pulls status once on load to drive UI decisions (e.g., editing affordances). - **AdminModel / config** - Adds onlyoffice {enabled, docsOrigin, publicOrigin} defaults and update path, with jwtSecret persisted (kept unless explicitly replaced). - Optional constants in config.php to override and debug. - **Security & UX notes** - Editor access remains ACL-checked (read/edit) and uses absolute, signed URLs surfaced via controller. - Admin UI never echoes secrets; “Replace” toggles explicit updates only. - CSP helper makes it straightforward to permit api.js + iframe + XHR to your DS. - **Docs/Styling** - Minor CSS touch-ups around hover states and modal layout. --- ## Changes 11/2/2025 (v1.7.5) release(v1.7.5): CSP hardening, API-backed previews, flicker-free theming, cache tuning & deploy script (closes #50) release(v1.7.5): retrigger CI bump (no code changes) release(v1.7.5): retrigger CI bump ensure up to date ### Security/headers - Tighten CSP: pin the inline pre-theme snippet with a script-src SHA-256 and keep everything else on 'self'. - Improve cache policy for versioned assets: force 1y + immutable and add s-maxage for CDNs; also avoid HSTS redirects on local/dev hosts. ### Previews & editor - Remove hardcoded `/uploads/` paths; always build preview URLs via the API (respects UPLOAD_DIR/ACL). - Use the API URL for gallery prev/next and file-menu “Preview” to fix 404s on custom storage roots. - Editor now probes size safely (HEAD → Range 0-0 fallback) before fetching, then fetches with credentials. ### Login, theming & UX polish - Pre-theme inline boot sets `dark-mode` + background early; swap to `[hidden]`/`unhide()` instead of inline `display:none`. - Add full-screen loading overlay with quick fade and proper color-scheme; prevent white/black flash on theme flips. - Refactor app/login reveal flow in `main.js` (`revealAppAndHideOverlay`, `authed` path, setup wizard). ### HTML/CSS & perf - Make Bootstrap/Styles/Roboto critical (plain ``); keep fonts as true preloads; modulepreload app entry. - Export a `__CSS_PROMISE__` from `defer-css.js` for sites that still promote preloads. - Header logo marked `fetchpriority="high"` for faster first paint. - Normalize dark-mode selectors to `.dark-mode` scope (admin panel, etc.). ### Manual Deploy script - Add `scripts/filerise-deploy.sh`: idempotent rsync-based deploy with writable dirs preserved, optional Composer install, and PHP-FPM/Apache reloads. ### Notes - If you change the inline pre-theme snippet, update the CSP hash accordingly. --- ## Changes 10/31/2025 (v1.7.4) release(v1.7.4): login hint replace toast + fix unauth boot main.js - Added isDemoHost() and showLoginTip(message). - In the unauth branch, call showLoginTip('Please log in to continue'). - Removed ensureToastReady() + showToast('please_log_in_to_continue') in the unauth path to avoid loading toast/DOM utils before auth. --- ## Changes 10/31/2025 (v1.7.3) release(v1.7.3): lightweight boot pipeline, dramatically faster first paint, deduped /api writes, sturdier uploads/auth ### 🎃 Highlights (advantages) 👻 🦇 - ⚡ Faster, cleaner boot: a lightweight **main.js** decides auth/setup before painting, avoids flicker, and wires modules exactly once. - ♻️ Fewer duplicate actions: **request coalescer** dedupes POST/PUT/PATCH/DELETE to /api/* . - ✅ Truthy UX: global **toast bridge** queues early toasts and normalizes misleading “not found/already exists” messages after success. - 🔐 Smoother auth: CSRF priming/rotation + **TOTP step-up detection** across JSON & redirect paths; “Welcome back, `user`” toast once per tab. - 🌓 Polished UI: **dark-mode persistence with system fallback**, live siteConfig title application, higher-z modals, drag auto-scroll. - 🚀 Faster first paint & interactions: defer CodeMirror/Fuse/Resumable, promote preloaded CSS, and coalesce duplicate requests → snappier UI. - 🧭 Admin polish: live header title preview, masked OIDC fields with **Replace** flow, and a **read-only Sponsors/Donations** section. - 🧱 Safer & cache-smarter: opinionated .htaccess (CSP/HSTS/MIME/compression) + `?v={{APP_QVER}}` for versioned immutable assets. ### Core bootstrap (main.js) overhaul - Early **toast bridge** (queues until domUtils is ready); expose `window.__FR_TOAST_FILTER__` for centralized rewrites/suppression. - **Result guard + request coalescer** wrapping `fetch`: - Dedupes same-origin `/api/*` mutating requests for ~800ms using a stable key (method + path + normalized body). - Tracks “last OK” JSON (`success|status|result=ok`) to suppress false-negative error toasts after success. - **Boot orchestrator** with hard guards: - `__FR_FLAGS` (`booted`, `initialized`, `wired.*`, `bootPromise`, `entryStarted`) to prevent double init/leaks. - **No-flicker login**: resolve `checkAuth()` + `setup` before showing UI; show login only when truly unauthenticated. - **Heavy boot** for authed users: load i18n, `appCore.loadCsrfToken/initializeApp`, first file list, then light UI wiring. - **Auth flow**: - `primeCsrf()` + `` management; persist token in localStorage. - **TOTP** detection via header (`X-TOTP-Required`) & JSON (`totp_required` / `TOTP_REQUIRED`); calls `openTOTPLoginModal()`. - **Welcome toast** once per tab via `sessionStorage.__fr_welcomed`. - **UI/UX niceties**: - `applySiteConfig()` updates header title & login method visibility on both login & authed screens. - Dark-mode persistence with system fallback, proper a11y labels/icons. - Create dropdown/menu wiring with capture-phase outside-click + ESC close; modal cancel safeties. - Lift modals above cards (z-index), **drag auto-scroll** near viewport edges. - Dispatch legacy `DOMContentLoaded`/`load` **once** (supports older inline handlers). - Username label refresh for existing `.user-name-label` without injecting new DOM. ### Performance & UX changes - CSS/first paint: - Preload Bootstrap & app CSS; promote at DOMContentLoaded; keep inline CSS minimal. - Add `width/height/decoding/fetchpriority` to logo to reduce layout shift. - Search/editor/uploads: - **fileListView.js**: lazy-load Fuse with instant substring fallback; `warmUpSearch()` hook. - **fileEditor.js**: lazy-load CodeMirror core/theme/modes; start plain then upgrade; guard very large files gracefully. - **upload.js**: lazy-load Resumable; resilient init; background warm-up; smarter addFile/submit; clearer toasts. - Toast/UX: - Install early toast bridge; queue & normalize messages; neutral “Done.” when server returns misleading errors after success. ### Correctness: uploads, paths, ACLs - **UploadController/UploadModel**: normalize folders via `ACL::normalizeFolder(rawurldecode())`; stricter segment checks; consistent base paths; safer metadata writes; proper chunk presence/merge & temp cleanup. ### Auth hardening & resilience - **auth.js/main.js/appCore.js**: CSRF rotate/retry (JSON then x-www-form-urlencoded fallback); robust login handling; fewer misleading error toasts. - **AuthController**: OIDC username fallback to `email` or `sub` when `preferred_username` missing. ### Admin panel - **adminPanel.js**: - Live header title preview (instant update without reload). - Masked OIDC client fields with **Replace** button; saved-value hints; only send secrets when replacing. - **New “Sponsor / Donations” section (read-only)**: - GitHub Sponsors → `https://github.com/sponsors/error311` - Ko-fi → `https://ko-fi.com/error311` - Includes **Copy** and **Open** buttons; values are fixed. - **AdminController**: boolean for `oidc.hasClientId/hasClientSecret` to drive masked inputs. ### Security & caching (.htaccess) - Consolidated security headers (CSP, CORP, HSTS on HTTPS), MIME types, compression (Brotli/Deflate), TRACE disable. - Caching rules: - HTML/version.js: no-cache; unversioned JS/CSS: 1h; unversioned static: 7d; **versioned assets `?v=`: 1y `immutable`**. - **config.php**: remove duplicate runtime headers (now via Apache) to avoid proxy/CDN conflicts. ### Upgrade notes - No schema changes. - Ensure Apache modules (`headers`, `rewrite`, `brotli`/`deflate`) are available for the new .htaccess rules (fallbacks included). - Versioned assets mean users shouldn’t need a hard refresh; `?v={{APP_QVER}}` busts caches automatically. --- ## Changes 10/29/2025 (v1.7.0 & v1.7.1 & v1.7.2) release(v1.7.0): asset cache-busting pipeline, public siteConfig cache, JS core split, and caching/security polish ### ✨ Features - Public, non-sensitive site config cache: - Add `AdminModel::buildPublicSubset()` and `writeSiteConfig()` to write `USERS_DIR/siteConfig.json`. - New endpoint `public/api/siteConfig.php` + `UserController::siteConfig()` to serve the public subset (regenerates if stale). - Frontend now reads `/api/siteConfig.php` (safe subset) instead of `/api/admin/getConfig.php`. - Frontend module versioning: - Replace all module imports with `?v={{APP_QVER}}` query param so the release/Docker stamper can pin exact versions. - Add `scripts/stamp-assets.sh` to stamp `?v=` and `{{APP_VER}}/{{APP_QVER}}` in **staging** for ZIP/Docker builds. ### 🧩 Refactors - Extract shared boot/bootstrap logic into `public/js/appCore.js`: - CSRF helpers (`setCsrfToken`, `getCsrfToken`, `loadCsrfToken`) - `initializeApp()`, `triggerLogout()` - Keep `main.js` lean; wrap global `fetch` once to append/rotate CSRF. - Update imports across JS modules to use versioned module URLs. ### 🚀 Performance - Aggressive, safe caching for versioned assets: - `.htaccess`: `?v=…` ⇒ `Cache-Control: max-age=31536000, immutable`. - Unversioned JS/CSS short cache (1h), other static (7d). - Eliminate duplicate `main.js` loads and tighten CodeMirror mode loading. ### 🔒 Security / Hardening - `.htaccess`: - Conditional HSTS only when HTTPS, add CORP and X-Permitted-Cross-Domain-Policies. - CSP kept strict for modules, workers, blobs. - Admin config exposure reduced to a curated subset in `siteConfig.json`. ### 🧪 CI/CD / Release - **FileRise repo** - `sync-changelog.yml`: keep `public/js/version.js` as source-of-truth only (no repo-wide stamping). - `release-on-version.yml`: build **stamped** ZIP from a staging copy via `scripts/stamp-assets.sh`, verify placeholders removed, attach checksum. - **filerise-docker repo** - Read `VERSION`, checkout app to `app/`, run stamper inside build context before `docker buildx`, tag `latest` and `:${VERSION}`. ### 🔧 Defaults - Sample/admin config defaults now set `disableBasicAuth: true` (safer default). Existing installations keep their current setting. ### 📂 Notable file changes - `src/models/AdminModel.php` (+public subset +atomic write) - `src/controllers/UserController.php` (+siteConfig action) - `public/api/siteConfig.php` (new) - `public/js/appCore.js` (new), `public/js/main.js` (slim, uses appCore) - Many `public/js/*.js` import paths updated to `?v={{APP_QVER}}` - `public/.htaccess` (caching & headers) - `scripts/stamp-assets.sh` (new) ### ⚠️ Upgrade notes - Ensure `USERS_DIR` is writable by web server for `siteConfig.json`. - Proxies/edge caches: the new `?v=` scheme enables long-lived immutable caching; purge is automatic on version bump. - If you previously read admin config directly on the client, it now reads `/api/siteConfig.php`. ### Additional changes/fixes for release - `release-on-version.yml` - normalize line endings (strip CRLF) - stamp-assets.sh don’t rely on the exec; invoke via bash release(v1.7.2): harden asset stamping & CI verification ### build(stamper) - Rewrite scripts/stamp-assets.sh to be repo-agnostic and macOS/Windows friendly: - Drop reliance on git ls-files/mapfile; use find + null-delimited loops - Normalize CRLF to LF for all web assets before stamping - Stamp ?v= in HTML/CSS/PHP and {{APP_VER}} everywhere - Normalize any ".mjs|.js?v=..." occurrences inside JS (ESM imports/strings) - Force-write public/js/version.js from VER (source of truth in stamped output) - Print touched counts and fail fast if any {{APP_QVER}}|{{APP_VER}} remain --- ## Changes 10/28/2025 (v1.6.11) release(v1.6.11) fix(ui/dragAndDrop) restore floating zones toggle click action Re-add the click handler to toggle `zonesCollapsed` so the header “sidebarToggleFloating” button actually expands/collapses the zones again. This regressed in v1.6.10 during auth-gating refactor. Refs: #regression #ux chore(codeql): move config to repo root for default setup - Relocate .github/codeql/codeql-config.yml to codeql-config.yml so GitHub default code scanning picks it up - Keep paths: public/js, api - Keep ignores: public/vendor/**, public/css/vendor/**, public/fonts/**, public/**/*.min.{js,css}, public/**/*.map --- ## Changes 10/28/2025 (v1.6.10) release(v1.6.10): self-host ReDoc, gate sidebar toggle on auth, and enrich release workflow - Vendor ReDoc and add MIT license file under public/vendor/redoc/; switch api.php to local bundle to satisfy CSP (script-src 'self'). - main.js: add/remove body.authenticated on login/logout so UI can reflect auth state. - dragAndDrop.js: only render sidebarToggleFloating when authenticated; stop event bubbling, keep dark-mode styles. - sync-changelog.yml: also stamp ?v= in PHP templates (public/**/*.php). - release-on-version.yml: build zip first, compute SHA-256, assemble release body with latest CHANGELOG snippet, “Full Changelog” compare link, and attach .sha256 alongside the zip. - THIRD_PARTY.md: document ReDoc vendoring and rationale. Refs: #security #csp #release --- ## Changes 10/27/2025 (v1.6.9) release(v1.6.9): feat(core) localize assets, harden headers, and speed up load - index.html: drop all CDNs in favor of local /vendor assets - add versioned cache-busting query (?v=…) on CSS/JS - wire version.js for APP_VERSION and numeric cache key - public/vendor/: add pinned copies of: - bootstrap 4.5.2, codemirror 5.65.5 (+ themes/modes), dompurify 2.4.0, fuse.js 6.6.2, resumable.js 1.1.0 - fonts: add self-hosted Material Icons + Roboto (latin + latin-ext) with vendor CSS (material-icons.css, roboto.css) - fileEditor.js: load CodeMirror modes from local vendor with ?v=APP_VERSION_NUM, keep timeout/plain-text fallback, no SRI (same-origin) - dragAndDrop.js: nudge zonesToggle 65px left to sit tighter to the logo - styles.css: prune/organize rules and add small utility classes; move 3P font CSS to /css/vendor/ - .htaccess: security + performance overhaul - Content-Security-Policy: default-src 'self'; img-src include data: and blob: - version-aware caching: HTML/version.js = no-cache; assets with ?v= = 1y immutable - correct MIME for fonts/SVG; enable Brotli/Gzip (if available) - X-Frame-Options, X-Content-Type-Options, Referrer-Policy, HSTS, Permissions-Policy - disable TRACE; deny dotfiles; prevent directory listing - .gitattributes: mark vendor/minified as linguist-vendored, treat assets as binary in diffs, exclude CI/resources from source archives - docs/licensing: - add licenses/ and THIRD_PARTY.md with upstream licenses/attribution - README: add “License & Credits” section with components and licenses - CI: (sync-changelog) stamp asset cache-busters to the numeric release (e.g. ?v=1.6.9) and write window.APP_VERSION in version.js before Docker build perf: site loads significantly faster with local assets + compression + long-lived caching security: CSP, strict headers, and same-origin assets reduce XSS/SRI/CORS risk Refs: #performance #security --- ## Changes 10/25/2025 (v1.6.8) release(v1.6.8): fix(ui) prevent Extract/Create flash on refresh; remember last folder - Seed `currentFolder` from `localStorage.lastOpenedFolder` (fallback to "root") - Stop eager `loadFileList('root')` on boot; defer initial load to resolved folder - Hide capability-gated actions by default (`#extractZipBtn`, `#createBtn`) to avoid pre-auth flash - Eliminates transient root state when reloading inside a subfolder User-visible: refreshing a non-root folder no longer flashes Root items or privileged buttons; app resumes in the last opened folder. --- ## Changes 10/25/2025 (v1.6.7) release(v1.6.7): Folder Move feature, stable DnD persistence, safer uploads, and ACL/UI polish ### 📂 Folder Move (new major feature) **Drag & Drop to move folder, use context menu or Move Folder button** - Added **Move Folder** support across backend and UI. - New API endpoint: `public/api/folder/moveFolder.php` - Controller and ACL updates to validate scope, ownership, and permissions. - Non-admins can only move within folders they own. - `ACL::renameTree()` re-keys all subtree ACLs on folder rename/move. - Introduced new capabilities: - `canMoveFolder` - `canMove` (UI alias for backward compatibility) - New “Move Folder” button + modal in the UI with full i18n strings (`i18n.js`). - Action button styling and tooltip consistency for all folder actions. ### 🧱 Drag & Drop / Layout Improvements - Fixed **random sidebar → top zone jumps** on refresh. - Cards/panels now **persist exactly where you placed them** (`userZonesSnapshot`) — no unwanted repositioning unless the window is resized below the small-screen threshold. - Added hysteresis around the 1205 px breakpoint to prevent flicker when resizing. - Eliminated the 50 px “ghost” gutter with `clampSidebarWhenEmpty()`: - Sidebar no longer reserves space when collapsed or empty. - Temporarily “unclamps” during drag so drop targets remain accurate and full-width. - Removed forced 800 px height on drag highlight; uses natural flex layout now. - General layout polish — smoother transitions when toggling *Hide/Show Panels*. ### ☁️ Uploads & UX - Stronger folder sanitization and safer base-path handling. - Fixed subfolder creation when uploading directories (now builds under correct parent). - Improved chunk error handling and metadata key correctness. - Clearer success/failure toasts and accurate filename display from server responses. ### 🔐 Permissions / ACL - Simplified file rename checks — now rely solely on granular `ACL::canRename()`. - Updated capability lists to include move/rename operations consistently. ### 🌐 UI / i18n Enhancements - Added i18n strings for new “Move Folder” prompts, modals, and tooltips. - Minor UI consistency tweaks: button alignment, focus states, reduced-motion support. --- ## Changes 10/24/2025 (v1.6.6) release(v1.6.6): header-mounted toggle, dark-mode polish, persistent layout, and ACL fix - dragAndDrop: mount zones toggle beside header logo (absolute, non-scrolling); stop click propagation so it doesn’t trigger the logo link; theme-aware styling - live updates via MutationObserver; snapshot card locations on drop and restore on load (prevents sidebar reset); guard first-run defaults with `layoutDefaultApplied_v1`; small/medium layout tweaks & refactors. - CSS: switch toggle icon to CSS variable (`--toggle-icon-color`) with dark-mode override; remove hardcoded `!important`. - API (capabilities.php): remove unused `disableUpload` flag from `canUpload` and flags payload to resolve undefined variable warning. --- ## Changes 10/24/2025 (v1.6.5) release(v1.6.5): fix PHP warning and upload-flag check in capabilities.php - Fix undefined variable: use $disableUpload consistently - Harden flag read: (bool)($perms['disableUpload'] ?? false) - Prevents warning and ensures Upload capability is computed correctly --- ## Changes 10/24/2025 (v1.6.4) release(v1.6.4): runtime version injection + CI bump/sync; caching tweaks - Add public/js/version.js (default "dev") and load it before main.js. - adminPanel.js: replace hard-coded string with `window.APP_VERSION || "dev"`. - public/.htaccess: add no-cache for js/version.js - GitHub Actions: replace sync job with “Bump version and sync Changelog to Docker Repo”. - Parse commit msg `release(vX.Y.Z)` -> set step output `version`. - Write `public/js/version.js` with `window.APP_VERSION = ''`. - Commit/push version.js if changed. - Mirror CHANGELOG.md to filerise-docker and write a VERSION file with ``. - Guard all steps with `if: steps.ver.outputs.version != ''` to no-op on non-release commits. This wires the UI version label to CI, keeps dev builds showing “dev”, and feeds the Docker repo with CHANGELOG + VERSION for builds. --- ## Changes 10/24/2025 (v1.6.3) release(v1.6.3): drag/drop card persistence, admin UX fixes, and docs (closes #58) Drag & Drop - Upload/Folder Management Cards layout - Persist panel locations across refresh; snapshot + restore when collapsing/expanding. - Unified “zones” toggle; header-icon mode no longer loses card state. - Responsive: auto-move sidebar cards to top on small screens; restore on resize. - Better top-zone placeholder/cleanup during drag; tighter header modal sizing. - Safer order saving + deterministic placement for upload/folder cards. Admin Panel – Folder Access - Fix: newly created folders now appear without a full page refresh (cache-busted `getFolderList`). - Show admin users in the list with full access pre-applied and inputs disabled (read-only). - Skip sending updates for admins when saving grants. - “Folder” column now has its own horizontal scrollbar so long names / “Inherited from …” are never cut off. Admin Panel – User Permissions (flags) - Show admins (marked as Admin) with all switches disabled; exclude from save payload. - Clarified helper text (account-level vs per-folder). UI/Styling - Added `.folder-cell` scroller in ACL table; improved dark-mode scrollbar/thumb. Docs - README edits: - Clarified PUID/PGID mapping and host/NAS ownership requirements for mounted volumes. - Environment variables section added - CHOWN_ON_START additional details - Admin details - Upgrade section added - 💖 Sponsor FileRise section added --- ## Changes 10/23/2025 (v1.6.2) feat(i18n,auth): add Simplified Chinese (zh-CN) and expose in User Panel - Add zh-CN locale to i18n.js with full key set. - Introduce chinese_simplified label key across locales. - Added some missing labels - Update language selector mapping to include zh-CN (English/Spanish/French/German/简体中文). - Wire zh-CN into Auth/User Panel (authModals) language dropdown. - Fallback-safe rendering for language names when a key is missing. ui: fix “Change Password” button sizing in User Panel - Keep consistent padding and font size for cleaner layout --- ## Changes 10/23/2025 (v1.6.1) feat(ui): unified zone toggle + polished interactions for sidebar/top cards - Add floating toggle button styling (hover lift, press, focus ring, ripple) for #zonesToggleFloating and #sidebarToggleFloating (CSS). - Ensure icons are visible and centered; enforce consistent sizing/color. - Introduce unified “zones collapsed” state persisted via `localStorage.zonesCollapsed`. - Update dragAndDrop.js to: - manage a single floating toggle for both Sidebar and Top Zone - keep toggle visible when cards are in Top Zone; hide only when both cards are in Header - rotate icon 90° when both cards are in Top Zone and panels are open - respect collapsed state during DnD flows and on load - preserve original DnD behaviors and saved orders (sidebar/header) - Minor layout/visibility fixes during drag (clear temp heights; honor collapsed). Notes: - No breaking API changes; existing `sidebarOrder` / `headerOrder` continue to work. - New key: `zonesCollapsed` (string '0'/'1') controls visibility of Sidebar + Top Zone. UX: - Floating toggle feels more “material”: subtle hover elevation, press feedback, focus ring, and click ripple to restore the prior interactive feel. - Icons remain legible on white (explicit color set), centered in the circular button. --- ## Changes 10/22/2025 (v1.6.0) feat(acl): granular per-folder permissions + stricter gates; WebDAV & UI aligned - Add granular ACL buckets: create, upload, edit, rename, copy, move, delete, extract, share_file, share_folder - Implement ACL::canX helpers and expand upsert/explicit APIs (preserve read_own) - Enforce “write no longer implies read” in canRead; use granular gates for write-ish ops - WebDAV: use canDelete for DELETE, canUpload/canEdit + disableUpload for PUT; enforce ownership on overwrite - Folder create: require Manage/Owner on parent; normalize paths; seed ACL; rollback on failure - FileController: refactor copy/move/rename/delete/extract to granular gates + folder-scope checks + own-only ownership enforcement - Capabilities API: compute effective actions with scope + readOnly/disableUpload; protect root - Admin Panel (v1.6.0): new Folder Access editor with granular caps, inheritance hints, bulk toggles, and UX validations - getFileList: keep root visible but inert for users without visibility; apply own-only filtering server-side - Bump version to v1.6.0 --- ## Changes 10/20/2025 (v1.5.3) security(acl): enforce folder-scope & own-only; fix file list “Select All”; harden ops ### fileListView.js (v1.5.3) - Restore master “Select All” checkbox behavior and row highlighting. - Keep selection working with own-only filtered lists. - Build preview/thumb URLs via secure API endpoints; avoid direct /uploads. - Minor UI polish: slider wiring and pagination focus handling. ### FileController.php (v1.5.3) - Add enforceFolderScope($folder, $user, $perms, $need) and apply across actions. - Copy/Move: require read on source, write on destination; apply scope on both. - When user only has read_own, enforce per-file ownership (uploader==user). - Extract ZIP: require write + scope; consistent 403 messages. - Save/Rename/Delete/Create: tighten ACL checks; block dangerous extensions; consistent CSRF/Auth handling and error codes. - Download/ZIP: honor read vs read_own; own-only gates by uploader; safer headers. ### FolderController.php (v1.5.3) - Align with ACL: enforce folder-scope for non-admins; require owner or bypass for destructive ops. - Create/Rename/Delete: gate by write on parent/target + ownership when needed. - Share folder link: require share capability; forbid root sharing for non-admins; validate expiry; optional password. - Folder listing: return only folders user can fully view or has read_own. - Shared downloads/uploads: stricter validation, headers, and error handling. This commits a consistent, least-privilege ACL model (owners/read/write/share/read_own), fixes bulk-select in the UI, and closes scope/ownership gaps across file & folder actions. feat(dnd): default cards to sidebar on medium screens when no saved layout - Adds one-time responsive default in loadSidebarOrder() (uses layoutDefaultApplied_v1) - Preserves existing sidebarOrder/headerOrder and small-screen behavior - Keeps user changes persistent; no override once a layout exists feat(editor): make modal non-blocking; add SRI + timeout for CodeMirror mode loads - Build the editor modal immediately and wire close (✖, Close button, and Esc) before any async work, so the UI is always dismissible. - Restore MODE_URL and add normalizeModeName() to resolve aliases (text/html → htmlmixed, php → application/x-httpd-php). - Add SRI for each lazily loaded mode (MODE_SRI) and apply integrity/crossOrigin on script tags; switch to async and improved error messages. - Introduce MODE_LOAD_TIMEOUT_MS=2500 and Promise.race() to init in text/plain if a mode is slow; auto-upgrade to the real mode once it arrives. - Graceful fallback: if CodeMirror core isn’t present, keep textarea, enable Save, and proceed. - Minor UX: disable Save until the editor is ready, support theme toggling, better resize handling, and font size controls without blocking. Security: Locks CDN mode scripts with SRI. --- ## Changes 10/19/2025 (v1.5.2) fix(admin): modal bugs; chore(api): update ReDoc SRI; docs(openapi): add annotations + spec - adminPanel.js - Fix modal open/close reliability and stacking order - Prevent background scroll while modal is open - Tidy focus/keyboard handling for better UX - style.css - Polish styles for Folder Access + Users views (spacing, tables, badges) - Improve responsiveness and visual consistency - api.php - Update Redoc SRI hash and pin to the current bundle URL - OpenAPI - Add/refresh inline @OA annotations across endpoints - Introduce src/openapi/Components.php with base Info/Server, common responses, and shared components - Regenerate and commit openapi.json.dist - public/js/adminPanel.js - public/css/style.css - public/api.php - src/openapi/Components.php - openapi.json.dist - public/api/** (annotated endpoints) --- ## Changes 10/19/2025 (v1.5.1) fix(config/ui): serve safe public config to non-admins; init early; gate trash UI to admins; dynamic title; demo toast (closes #56) Regular users were getting 403s from `/api/admin/getConfig.php`, breaking header title and login option rendering. Issue #56 tracks this. ### What changed - **AdminController::getConfig** - Return a **public, non-sensitive subset** of config for everyone (incl. unauthenticated and non-admin users): `header_title`, minimal `loginOptions` (disable* flags only), `globalOtpauthUrl`, `enableWebDAV`, `sharedMaxUploadSize`, and OIDC `providerUrl`/`redirectUri`. - For **admins**, merge in admin-only fields (`authBypass`, `authHeaderName`). - Never expose secrets or client IDs. - **auth.js** - `loadAdminConfigFunc()` now robustly handles empty/204 responses, writes sane defaults, and sets `document.title` from `header_title`. - `showToast()` override: on `demo.filerise.net` shows a longer demo-creds toast; keeps TOTP “don’t nag” behavior. - **main.js** - Call `loadAdminConfigFunc()` early during app init. - Run `setupTrashRestoreDelete()` **only for admins** (based on `localStorage.isAdmin`). - **adminPanel.js** - Bump visible version to **v1.5.1**. - **index.html** - Keep `FileRise` static; runtime title now driven by `loadAdminConfigFunc()`. ### Security v1.5.1 - Prevents info disclosure by strictly limiting non-admin fields. - Avoids noisy 403 for regular users while keeping admin-only data protected. ### QA - As a non-admin: - Opening the app no longer triggers a 403 on `getConfig.php`. - Header title and login options render; document tab title updates to configured `header_title`. - Trash/restore UI is not initialized. - As an admin: - Admin Panel loads extra fields; trash/restore UI initializes. - Title updates correctly. - On `demo.filerise.net`: - Pre-login toast shows demo credentials for ~12s. Closes #56. --- ## Changes 10/17/2025 (v1.5.0) Security and permission model overhaul. Tightens access controls with explicit, server‑side ACL checks across controllers and WebDAV. Introduces `read_own` for own‑only visibility and separates view from write so uploaders can’t automatically see others’ files. Fixes session warnings and aligns the admin UI with the new capabilities. > **Security note** > This release contains security hardening based on a private report (tracked via a GitHub Security Advisory, CVE pending). For responsible disclosure, details will be published alongside the advisory once available. Users should upgrade promptly. ### Highlights - **ACL** - New `read_own` bucket (own‑only visibility) alongside `owners`, `read`, `write`, `share`. - **Semantic change:** `write` no longer implies `read`. - `ACL::applyUserGrantsAtomic()` to atomically set per‑folder grants (`view`, `viewOwn`, `upload`, `manage`, `share`). - `ACL::purgeUser($username)` to remove a user from all buckets (used when deleting a user). - Auto‑heal `folder_acl.json` (ensure `root` exists; add missing buckets; de‑dupe; normalize types). - More robust admin detection (role flag or session/admin user). - **Controllers** - `FileController`: ACL + ownership enforcement for list, download, zip download, extract, move, copy, rename, create, save, tag edit, and share‑link creation. `getFileList()` now filters to the caller’s uploads when they only have `read_own` (no `read`). - `UploadController`: requires `ACL::canWrite()` for the target folder; CSRF refresh path improved; admin bypass intact. - `FolderController`: listing filtered by `ACL::canRead()`; optional parent filter preserved; removed name‑based ownership assumptions. - **Admin UI** - Folder Access grid now includes **View (own)**; bulk toolbar actions; column alignment fixes; more space for folder names; dark‑mode polish. - **WebDAV** - WebDAV now enforces ACL consistently: listing requires `read` (or `read_own` ⇒ shows only caller’s files); writes require `write`. - Removed legacy “folderOnly” behavior — ACL is the single source of truth. - Metadata/uploader is preserved through existing models. ### Behavior changes (⚠️ Breaking) - **`write` no longer implies `read`.** - If you want uploaders to see all files in a folder, also grant **View (all)** (`read`). - If you want uploaders to see only their own files, grant **View (own)** (`read_own`). - **Removed:** legacy `folderOnly` view logic in favor of ACL‑based access. ### Upgrade checklist 1. Review **Folder Access** in the admin UI and grant **View (all)** or **View (own)** where appropriate. 2. For users who previously had “upload but not view,” confirm they now have **Upload** + **View (own)** (or add **View (all)** if intended). 3. Verify WebDAV behavior for representative users: - `read` shows full listings; `read_own` lists only the caller’s files. - Writes only succeed where `write` is granted. 4. Confirm admin can upload/move/zip across all folders (regression tested). ### Affected areas - `config/config.php` — session/cookie initialization ordering; proxy header handling. - `src/lib/ACL.php` — new bucket, semantics, healing, purge, admin detection. - `src/controllers/FileController.php` — ACL + ownership gates across operations. - `src/controllers/UploadController.php` — write checks + CSRF refresh handling. - `src/controllers/FolderController.php` — ACL‑filtered listing and parent scoping. - `public/api/admin/acl/*.php` — includes `viewOwn` round‑trip and sanitization. - `public/js/*` & CSS — folder access grid alignment and layout fixes. - `src/webdav/*` & `public/webdav.php` — ACL‑aware WebDAV server. ### Credits - Security report acknowledged privately and will be credited in the published advisory. ### Fix - fix(folder-model): resolve syntax error, unexpected token - Deleted accidental second `5 MB; lighter CM settings for big files. - fileListView.js: latest-call-wins; compute editable via ext + sizeBytes (no blink). - FileModel.php: add sizeBytes; cap inline content to ≤5 MB (INDEX_TEXT_BYTES_MAX). - HTML: load extra CM modes: htmlmixed, php, clike, python, yaml, markdown, shell, sql, vb, ruby, perl, properties, nginx. --- ## Changes 10/5/2025 v1.3.14 fix(admin): OIDC optional by default; validate only when enabled (fixes #44) - AdminModel::updateConfig now enforces OIDC fields only if disableOIDCLogin=false - AdminModel::getConfig defaults disableOIDCLogin=true and guarantees OIDC keys - AdminController default loginOptions sets disableOIDCLogin=true; CSRF via header or body - Normalize file perms to 0664 after write --- ## Changes 10/4/2025 v1.3.13 fix(scanner): resolve dirs via CLI/env/constants; write per-item JSON; skip trash fix(scanner): rebuild per-folder metadata to match File/Folder models chore(scanner): skip profile_pics subtree during scans - scan_uploads.php now falls back to UPLOAD_DIR/META_DIR from config.php - prevents double slashes in metadata paths; respects app timezone - unblocks SCAN_ON_START so externally added files are indexed at boot - Writes per-folder metadata files (root_metadata.json / folder_metadata.json) using the same naming rule as the models - Adds missing entries for files (uploaded, modified using DATE_TIME_FORMAT, uploader=Imported) - Prunes stale entries for files that no longer exist - Skips uploads/trash and symlinks - Resolves paths from CLI flags, env vars, or config constants (UPLOAD_DIR/META_DIR) - Idempotent; safe to run at startup via SCAN_ON_START - Avoids indexing internal avatar images (folder already hidden in UI) - Reduces scan noise and metadata churn; keeps firmware/other content indexed --- ## Changes 10/4/2025 v1.3.12 Fix: robust PUID/PGID handling; optional ownership normalization (closes #43) - Remap www-data to PUID/PGID when running as root; skip with helpful log if non-root - Added CHOWN_ON_START env to control recursive chown (default true; turn off after first run) - SCAN_ON_START unchanged, with non-root fallback --- ## Changes 10/4/2025 v1.3.11 Chore: keep BASE_URL fallback, prefer env SHARE_URL; fix HTTPS auto-detect - Remove no-op sed of SHARE_URL from start.sh (env already used) - Build default share link with correct scheme (http/https, proxy-aware) --- ## Changes 10/4/2025 v1.3.10 Fix: index externally added files on startup; harden start.sh (#46) - Run metadata scan before Apache when SCAN_ON_START=true (was unreachable after exec) - Execute scan as www-data; continue on failure so startup isn’t blocked - Guard env reads for set -u; add umask 002 for consistent 775/664 - Make ServerName idempotent; avoid duplicate entries - Ensure sessions/metadata/log dirs exist with correct ownership and perms No behavior change unless SCAN_ON_START=true. --- ## Changes 5/27/2025 v1.3.9 - Support for mounting CIFS (SMB) network shares via Docker volumes - New `scripts/scan_uploads.php` script to generate metadata for imported files and folders - `SCAN_ON_START` environment variable to trigger automatic scanning on container startup - Documentation for configuring CIFS share mounting and scanning - Clipboard Paste Upload Support (single image): - Users can now paste images directly into the FileRise web interface. - Pasted images are renamed to `image.png` and added to the upload queue using the existing drag-and-drop logic. - Implemented using a `.isClipboard` flag and a delayed UI cleanup inside `xhr.addEventListener("load", ...)`. --- ## Changes 5/26/2025 - Updated `REGEX_FOLDER_NAME` in `config.php` to forbids < > : " | ? * characters in folder names. - Ensures the whole name can’t end in a space or period. - Blocks Windows device names. - Updated `FolderController.php` when `createFolder` issues invalid folder name to return `http_response_code(400);` --- ## Changes 5/23/2025 v1.3.8 - **Folder-strip context menu** - Enabled right-click on items in the new folder strip (above file list) to open the same “Create / Rename / Share / Delete Folder” menu as in the main folder tree. - Bound `contextmenu` event on each `.folder-item` in `loadFileList` to: - Prevent the default browser menu - Highlight the clicked folder-strip item - Invoke `showFolderManagerContextMenu` with menu entries: - Create Folder - Rename Folder - Share Folder (passes the strip’s `data-folder` value) - Delete Folder - Ensured menu actions are wrapped in arrow functions (`() => …`) so they fire only on menu-item click, not on render. - Refactored folder-strip injection in `fileListView.js` to: - Mark each strip item as `draggable="true"` (for drag-and-drop) - Add `el.addEventListener("contextmenu", …)` alongside existing click/drag handlers - Clean up global click listener for hiding the context menu - Prevented premature invocation of `openFolderShareModal` by switching to `action: () => openFolderShareModal(dest)` instead of calling it directly. - **Create File/Folder dropdown** - Replaced standalone “Create File” button with a combined dropdown button in the actions toolbar. - New markup - Wired up JS handlers in `fileActions.js`: - `#createFileOption` → `openCreateFileModal()` - `#createFolderOption` → `document.getElementById('createFolderModal').style.display = 'block'` - Toggled `.dropdown-menu` visibility on button click, and closed on outside click. - Applied dark-mode support: dropdown background and text colors switch with `.dark-mode` class. --- ## Changes 5/22/2025 v1.3.7 - `.folder-strip-container .folder-name` css added to center text below folder material icon. - Override file share_url to always use current origin - Update `fileList` css to keep file name wrapping tight. --- ## Changes 5/21/2025 - **Drag & Drop to Folder Strip** - Enabled dragging files from the file list directly onto the folder-strip items. - Hooked up `folderDragOverHandler`, `folderDragLeaveHandler`, and `folderDropHandler` to `.folder-strip-container .folder-item`. - On drop, files are moved via `/api/file/moveFiles.php` and the file list is refreshed. - **Restore files from trash Toast Message** - Changed the restore handlers so that the toast always reports the actual file(s) restored (e.g. “Restored file: foo.txt”) instead of “No trash record found.” - Removed reliance on backend message payload and now generate the confirmation text client-side based on selected items. --- ## Changes 5/20/2025 v1.3.6 - **domUtils.js** - `updateFileActionButtons` - Hide selection buttons (`Delete Files`, `Copy Files`, `Move Files` & `Download ZIP`) until file is selected. - Hide `Extract ZIP` until selecting zip files - Hide `Create File` button when file list items are selected. --- ## Changes 5/19/2025 v1.3.5 ### Added Folder strip & Create File - **Folder strip in file list** - `loadFileList` now fetches sub-folders in parallel from `/api/folder/getFolderList.php`. - Filters to only direct children of the current folder, hiding `profile_pics` and `trash`. - Injects a new `.folder-strip-container` just below the Files In above (summary + slider). - Clicking a folder in the strip updates: - the breadcrumb (via `updateBreadcrumbTitle`) - the tree selection highlight - reloads `loadFileList` for the chosen folder. - **Create File feature** - New “Create New File” button added to the file-actions toolbar and context menu. - New endpoint `public/api/file/createFile.php` (handled by `FileController`/`FileModel`): - Creates an empty file if it doesn’t already exist. - Appends an entry to `_metadata.json` with `uploaded` timestamp and `uploader`. - `fileActions.js`: - Implemented `handleCreateFile()` to show a modal, POST to the new endpoint, and refresh the list. - Added translations for `create_new_file` and `newfile_placeholder`. --- ## Changees 5/15/2025 ### Drag‐and‐Drop Upload extended to File List - **Forward file‐list drops** Dropping files onto the file‐list area (`#fileListContainer`) now re‐dispatches the same `drop` event to the upload card’s drop zone (`#uploadDropArea`) - **Visual feedback** Added a `.drop-hover` class on `#fileListContainer` during drag‐over for a dashed‐border + light‐background hover state to indicate it accepts file drops. --- ## Changes 5/14/2025 v1.3.4 ### 1. Button Grouping (Bootstrap) - Converted individual action buttons (`download`, `edit`, `rename`, `share`) in both **table view** and **gallery view** into a single Bootstrap button group for a cleaner, more compact UI. - Applied `btn-group` and `btn-sm` classes for consistent sizing and spacing. ### 2. Header Dropdown Replacement - Replaced the standalone “User Panel” icon button with a **dropdown wrapper** (`.user-dropdown`) in the header. - Dropdown toggle now shows: - **Profile picture** (if set) or the Material “account_circle” icon - **Username** text (between avatar and caret) - Down-arrow caret span. ### 3. Menu Items Moved to Dropdown - Moved previously standalone header buttons into the dropdown menu: - **User Panel** opens the modal - **Admin Panel** only shown when `data.isAdmin` and on `demo.filerise.net` - **API Docs** calls `openApiModal()` - **Logout** calls `triggerLogout()` - Each menu item now has a matching Material icon (e.g. `person`, `admin_panel_settings`, `description`, `logout`). ### 4. Profile Picture Support - Added a new `/api/profile/uploadPicture.php` endpoint + `UserController::uploadPicture()` + corresponding `UserModel::setProfilePicture()`. - On **Open User Panel**, display: - Default avatar if none set - Current profile picture if available - In the **User Panel** modal: - Stylish “edit” overlay icon on the avatar to launch file picker - Auto-upload on file selection (no “Save” button click needed) - Preview updates immediately and header avatar refreshes live - Persisted in `users.txt` and re-fetched via `getCurrentUser.php` ### 5. API Docs & Logout Relocation - Removed API Docs from User Panel - Removed “Logout” buttons from the header toolbar. - Both are now menu entries in the **User Dropdown**. ### 6. Admin Panel Conditional - The **Admin Panel** button was: - Kept in the dropdown only when `data.isAdmin` - Removed entirely elsewhere. ### 7. Utility & Styling Tweaks - Introduced a small `normalizePicUrl()` helper to strip stray colons and ensure a leading slash. - Hidden the scrollbar in the User Panel modal via: - Inline CSS (`scrollbar-width: none; -ms-overflow-style: none;`) - Global/WebKit rule for `::-webkit-scrollbar { display: none; }` - Made the User Panel modal fully responsive and vertically centered, with smooth dark-mode support. ### 8. File/List View & Gallery View Sliders - **Unified “View‐Mode” Slider** Added a single slider panel (`#viewSliderContainer`) in the file‐list actions toolbar that switches behavior based on the current view mode: - **Table View**: shows a **Row Height** slider (min 31px, max 60px). - Adjusts the CSS variable `--file-row-height` to resize all `` heights. - Persists the chosen height in `localStorage`. - **Gallery View**: shows a **Columns** slider (min 1, max 6). - Updates the grid’s `grid-template-columns: repeat(N, 1fr)`. - Persists the chosen column count in `localStorage`. - **Injection Point** The slider container is dynamically inserted (or updated) just before the folder summary (`#fileSummary`) in `loadFileList()`, ensuring a consistent position across both view modes. - **Live Updates** Moving the slider thumb immediately updates the visible table row heights or gallery column layout without a full re‐render. - **Styling & Alignment** - `#viewSliderContainer` uses `inline-flex` and `align-items: center` so that label, slider, and value text are vertically aligned with the other toolbar elements. - Reset margins/padding on the label and value span within `#viewSliderContainer` to eliminate any vertical misalignment. ### 9. Fixed new issues with Undefined username in header on profile pic change & TOTP Enabled not checked **openUserPanel** - **Rewritten entirely with DOM APIs** instead of `innerHTML` for any user-supplied text to eliminates “DOM text reinterpreted as HTML” warnings. - **Default avatar fallback**: now uses `'/assets/default-avatar.png'` whenever `profile_picture` is empty. - **TOTP checkbox initial state** is now set from the `totp_enabled` value returned by the server. - **Modal title sync** on reopen now updates the `(username)` correctly (no more “undefined” until refresh). - **Re-sync on reopen**: background color, avatar, TOTP checkbox and language selector all update when reopen the panel. **updateAuthenticatedUI** - **Username fix**: dropdown toggle now always uses `data.username` so the name never becomes `undefined` after uploading a picture. - **Profile URL update** via `fetchProfilePicture()` always writes into `localStorage` before rebuilding the header, ensuring avatar+name stay in sync instantly. - **Dropdown rebuild logic** tweaked to update the toggle’s innerHTML with both avatar and username on every call. **UserModel::getUser** - Switched to `explode(':', $line, 4)` to the fourth “profile_picture” field without clobbering the TOTP secret. - **Strip trailing colons** from the stored URL (`rtrim($parts[3], ':')`) so we never send `…png:` back to the client. - Returns an array with both `'username'` and `'profile_picture'`, matching what `getCurrentUser.php` needs. ### 10. setAttribute + encodeURI to avoid “DOM text reinterpreted as HTML” alerts ### 11. Fix duplicated Upload & Folder cards if they were added to header and page was refreshed --- ## Changes 5/8/2025 ### Docker 🐳 - Ensure `/var/www/config` exists and is owned by `www-data` (chmod 750) so that `start.sh`’s `sed -i` updates to `config.php` work reliably --- ## Changes 5/8/2025 v1.3.3 ### Enhancements - **Admin API** (`updateConfig.php`): - Now merges incoming payload onto existing on-disk settings instead of overwriting blanks. - Preserves `clientId`, `clientSecret`, `providerUrl` and `redirectUri` when those fields are omitted or empty in the request. - **Admin API** (`getConfig.php`): - Returns only a safe subset of admin settings (omits `clientSecret`) to prevent accidental exposure of sensitive data. - **Frontend** (`auth.js`): - Update UI based on merged loginOptions from the server, ensuring blank or missing fields no longer revert your existing config. - **Auth API** (`auth.php`): - Added `$oidc->addScope(['openid','profile','email']);` to OIDC flow. (This should resolve authentik issue) --- ## Changes 5/8/2025 v1.3.2 ### config/config.php - Added a default `define('AUTH_BYPASS', false)` at the top so the constant always exists. - Removed the static `AUTH_HEADER` fallback; instead read the adminConfig.json at the end of the file and: - Overwrote `AUTH_BYPASS` with the `loginOptions.authBypass` setting from disk. - Defined `AUTH_HEADER` (normalized, e.g. `"X_REMOTE_USER"`) based on `loginOptions.authHeaderName`. - Inserted a **proxy-only auto-login** block before the usual session/auth checks: If `AUTH_BYPASS` is true and the trusted header (`$_SERVER['HTTP_' . AUTH_HEADER]`) is present, bump the session, mark the user authenticated/admin, load their permissions, and skip straight to JSON output. - Relax filename validation regex to allow broader Unicode and special chars ### src/controllers/AdminController.php - Ensured the returned `loginOptions` object always contains: - `authBypass` (boolean, default false) - `authHeaderName` (string, default `"X-Remote-User"`) - Read `authBypass` and `authHeaderName` from the nested `loginOptions` in the request payload. - Validated them (`authBypass` → bool; `authHeaderName` → non-empty string, fallback to `"X-Remote-User"`). - Included them when building the `$configUpdate` array to pass to the model. ### src/models/AdminModel.php - Normalized `loginOptions.authBypass` to a boolean (default false). - Validated/truncated `loginOptions.authHeaderName` to a non-empty trimmed string (default `"X-Remote-User"`). - JSON-encoded and encrypted the full config, now including the two new fields. - After decrypting & decoding, normalized the loaded `loginOptions` to always include: - `authBypass` (bool) - `authHeaderName` (string, default `"X-Remote-User"`) - Left all existing defaults & validations for the original flags intact. ### public/js/adminPanel.js - **Login Options** section: - Added a checkbox for **Disable All Built-in Logins (proxy only)** (`authBypass`). - Added a text input for **Auth Header Name** (`authHeaderName`). - In `handleSave()`: - Included the new `authBypass` and `authHeaderName` values in the payload sent to `updateConfig.php`. - In `openAdminPanel()`: - Initialized those inputs from `config.loginOptions.authBypass` and `config.loginOptions.authHeaderName`. ### public/js/auth.js - In `loadAdminConfigFunc()`: - Stored `authBypass` and `authHeaderName` in `localStorage`. - In `checkAuthentication()`: - After a successful login check, called a new helper (`applyProxyBypassUI()`) which reads `localStorage.authBypass` and conditionally hides the entire login form/UI. - In the “not authenticated” branch, only shows the login form if `authBypass` is false. - No other core fetch/token logic changed; all existing flows remain intact. ### Security old - **Admin API**: `getConfig.php` now returns only a safe subset of admin settings (omits `clientSecret`) to prevent accidental exposure of sensitive data. --- ## Changes 5/4/2025 v1.3.1 ### Modals - **Added** a shared `.editor-close-btn` component for all modals: - File Tags - User Panel - TOTP Login & Setup - Change Password - **Truncated** long filenames in the File Tags modal header using CSS `text-overflow: ellipsis`. - **Resized** File Tags modal from 400px to 450px wide (with `max-width: 90vw` fallback). - **Capped** User Panel height at 381px and hidden scrollbars to eliminate layout jumps on hover. ### HTML - **Moved** `
    …
    ` out of `.main-wrapper` so the login form can show independently of the app shell. - **Added** `
    ` immediately inside `` to cover the UI during auth checks. - **Inserted** inline `