# Changelog
## 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 `