Commit Graph

51 Commits

Author SHA1 Message Date
Edouard Vanbelle 5afb30ebfd feat(swimlane): add swimlane engine with first version on SharedWithMe section
added group by:

        - None (= ordered by folders/file name)
        - Type (Folder first, then Image, Vidao, Audio, Document, etc...)
        - Owner
        - Size (With logarithmic groups))
        - Shared date (with groups: today, last 7 days, last 30 days, then year)
2026-05-28 00:15:05 +02:00
Edouard Vanbelle 1cd934d594 refactor(resourceList): move grid/list view into a resourceList component, purpose normalize on all sections views 2026-05-28 00:15:04 +02:00
Edouard Vanbelle c65f2b5385 feat(api): cursor listing contract — PageCursor trait + resource field
- Add src/application/dtos/cursor.rs with three shared types:
  · PageCursor trait  — default base64url+JSON encode/decode; one bare
    impl line per cursor struct
  · CursorQuery struct — standard limit/cursor/sort_by query params with
    limit_clamped() and decode_cursor<C>() helpers; compose via flatten
  · CursorListResponse<T> — standard {items, next_cursor?} envelope with
    from_oversized() and with_cursor() builders

- Migrate GrantCursor to impl PageCursor (remove duplicate encode/decode)

- Update GET /api/grants/incoming/resources:
  · SharedWithMeQuery now embeds CursorQuery via #[serde(flatten)]
  · Replace file/folder nullable pair with ResourceContentDto (untagged
    enum) under a single always-present 'resource' field
  · SharedWithMeDto is now a type alias for CursorListResponse<SharedWithMeItemDto>
  · Handler uses q.paging.limit_clamped() and decode_cursor<GrantCursor>()

- Add docs/architecture/resource-listing.md — authoritative contract for
  all listing endpoints (cursor design, SQL keyset WHERE, sort_by naming,
  Rust + JS skeletons, compliance table, migration guide)

- Register doc in VitePress sidebar and architecture index

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 00:15:04 +02:00
Edouard Vanbelle b0c5e7827e feat(user-avatar): users can now edit there image (image is taken from OIDC picture) 2026-05-27 11:29:33 +02:00
Edouard Vanbelle 3e786daea5 fix(grants): correct the removal of a users from a grant 2026-05-25 23:24:04 +02:00
Edouard Vanbelle 8365608bd5 feat(list view): show the owner of the File or Folder in list view 2026-05-25 22:48:59 +02:00
Edouard Vanbelle 79c1a37931 feat(ui): 1 modal to manage shares (users & public share)
fix(share): ensure Authz parent is created/updated on publicShare create/update

fix(ShareModal): do not show Token (public) grants in People section
2026-05-25 22:47:36 +02:00
Edouard Vanbelle a88e4c2733 refactor: move modal into components (prepare a mode autonomous components) 2026-05-25 22:47:36 +02:00
Edouard Vanbelle d64beb43a7 feat(ui): add addressBook and systemUsers model + show person who shared an item with me in tooltip 2026-05-25 22:47:36 +02:00
Edouard Vanbelle 60d53ea779 feat(ui): add section 'Shared with me' 2026-05-25 22:47:32 +02:00
Eddie Yang 32ad2a4f0e refactor(i18n): rename safeT to t, drop export alias
Follow-up to PR #373 review feedback (thanks @EdouardVanbelle): with the
local t() removed in that PR, the safeT defensive name no longer earns
its purpose. There is no global t() left to shadow it, so the wrapper-
style name just creates confusion against callers writing i18n.t().

- function safeT -> function t
- export { t: safeT, ... } -> { t, ... }
- Remove stale comments in translateElement and above the definition
  that explained the safeT/admin.js shadowing history

No call-site changes - every external caller already uses i18n.t(...),
which now points directly at the function of the same name.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 21:17:58 +08:00
Edouard Vanbelle 126251a184 fix(ui/modal): ensure modal is reusable (confirm button was disabled on previous use) 2026-05-19 11:17:32 +02:00
Edouard Vanbelle 82561a2b90 fix(ui): add RecentItem type + ad protection while building items 2026-05-19 10:18:40 +02:00
Edouard Vanbelle fac184ccfe style(front/js): apply types on all objects
- reduce amount of warnings in IDE
    - maximize API type mapping with static/js/core/types.js
2026-05-19 10:18:33 +02:00
Edouard Vanbelle edbfe2848c fix(front): fix issue with already declared constants on release mode
- ensure not loading twice the same variables, namespace to ensure it in the future
 - end to end tests where successfull, need to check it is not reusing a previous release (in cache from build CI)
 - fix: #377 #378
2026-05-19 09:36:24 +02:00
tw199501 a142d52d05 feat(i18n): add Traditional Chinese (zh-TW) locale
Adds full Traditional Chinese translation (628 keys, 100% parity with
en.json) and the registration plumbing to make it pickable in the UI.

Registration spans three layers that all needed updating for the locale
to actually be selectable end-to-end:
- static/locales/zh-TW.json (new) — TW vocabulary (儲存/雲端/檔案/偵測),
  uses 「」 corner brackets for in-string quoting
- core/i18n.js: add 'zh-TW' to supportedLocales — without this,
  setLocale('zh-TW') was silently rejected by the whitelist and the
  previous locale stayed active (visible as the "picked 繁中 but the
  setup step still shows 簡中" bug)
- core/languageSelector.js: add 'zh-TW' to AVAILABLE_LOCALES + fallback
- features/auth/auth.js: add 'zh-TW' to ALL_LANGUAGES (🇹🇼 繁體中文)
  and LANGUAGE_TEXTS bootstrap table (used before i18n loads)

Browser detection rewrite (i18n.js + auth.js detectBrowserLanguage):
The previous navigator.language?.substring(0, 2) truncated zh-TW → zh
and routed Traditional Chinese browsers to Simplified. Replaced with
three-tier matching: exact full-tag > Chinese script/region heuristic
(zh-Hant*, zh-{TW,HK,MO}) > primary subtag fallback.

Disambiguates the existing zh entry: "Chinese / 中文" became
"Simplified Chinese / 简体中文".

Drive-by cleanups discovered while wiring up the above:
- Remove dead t() in i18n.js (export uses safeT, no callers of bare t)
- Remove dead fetchUserData() and logout() in auth.js (userMenu.js has
  its own local logout())
- Extract errMessage(unknown→string) and inputVal(id) helpers for the
  catch sites and getElementById('x').value sites that needed TS
  narrowing under checkJs
- Type-annotate module-scope let forms/errors/panels with
  HTMLFormElement and HTMLElement so .addEventListener and .reset()
  resolve under strict
- Drop navigator.userLanguage IE legacy fallback (DOM lib has no field)
- jsconfig.json: drop exactOptionalPropertyTypes (only valid with
  strictNullChecks, which the project deliberately disables)
- .gitignore: ignore docker-compose.override.yml for local bind-mount
  dev workflow

Verified clean before commit: biome ci, tsc --noEmit, i18n key parity
(628/628), HTTP smoke test against running container.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 23:37:13 +08:00
Edouard Vanbelle 7697f3d35b feat(ui): handle errors on folder creation or folder/file renaming
- protect file_management_service::rename_file with validate_storage_name
 - remove specific rename modal and use the generic modal class (less duplicate)
 - handle errors on modal action: do not close the modal on error and display this error
 - hide "Go to parent folder" contextMenu if section is files and folder is the same as current one
2026-05-09 00:06:36 +02:00
Dionisio Pozo 71fd84dd9d Merge pull request #350 from EdouardVanbelle/fix/blank-section-on-token-expired
fix(ui): handle any session expired and trigger transparently a refresh token
2026-05-08 01:21:42 +02:00
Edouard Vanbelle 93d9a21013 fix(ui): admin panel, profile: restore missing icons library 2026-05-07 22:43:02 +02:00
Edouard Vanbelle a69dde35ce fix(ui): handle any session expired and trigger transparently a refresh token
this change replace original window.fetch by a wrapper that check any 401 response, is so it will request a refresh token
this solve current issue with Favorites & Recent sections that give blank page when token is expired

- exclusion of requests to other domain (401 will not be handled here)
- security with shares /api/s is not handled

- check with CSRF, no risk
2026-05-07 00:55:21 +02:00
Dionisio Pozo c6b1b14444 Merge pull request #340 from abnvle/feat/polish-translation
add polish (pl) translation
2026-05-04 20:29:13 +02:00
abnvle e0a3578ee2 add polish (pl) translation 2026-05-04 00:20:41 +02:00
Edouard Vanbelle 3050556dc0 style(ui): request that all types defined
- check in more restrictive mode = request types
- define main types in static/js/core/types.js
2026-05-03 23:04:27 +02:00
Edouard Vanbelle 75d3984b8f refactor(ui): i18n: remove unnecessary wrappers 2026-04-26 00:13:12 +02:00
Edouard Vanbelle 4e2029969e refactor(ui): remove unnecessary checks (i18n is always defined) 2026-04-26 00:12:44 +02:00
Edouard Vanbelle fc8e529e7d refactor(ui): modal: use hidden class 2026-04-25 21:10:04 +02:00
Edouard Vanbelle 4c327b3fe1 fix(icons): add missing referenced icons
- icons added via tools/check-icons.py
2026-04-15 08:49:17 +02:00
Edouard Vanbelle 6f4abfcec4 refactor(js): avoid use of window.XXX and move to import/export
- change worker: do not cache html pages (not necessary)
- remove use of window.XXX and maximize import/export,
  this will provide more clarety,
  show circular dependencies + you will benefit IDE help
2026-04-14 19:05:01 +02:00
Andrey Tkachenko da066f47fa Music Player & Playlist Manager 2026-04-08 15:14:03 +03:00
Edouard Vanbelle a4266a6e93 style: apply linter suggestions 2026-04-08 00:09:27 +02:00
Edouard Vanbelle 1ce29c101d style: apply biome CSS/JS format 2026-04-08 00:09:27 +02:00
Edouard Vanbelle 72af70505d fix(icon): add missing menu bar icon, visible on small media screen 2026-04-07 00:53:46 +02:00
Edouard Vanbelle 534d4dc190 feat: improve drag & drop
* permits multiple drag & drop
 * synchronize grid & list view on selection
 * permits copy during ddrag & drop (use sift/alt key according your OS)
 * use batch move / copy on drag & drop
2026-04-03 15:06:09 +02:00
Dionisio Pozo 128dd8a76a Merge pull request #248 from EdouardVanbelle/chore/file-mode
chore: remove all executable attributes on non bash files
2026-04-01 23:42:12 +02:00
Edouard Vanbelle badf35f08f chore: remove all executable attributes on non bash files 2026-04-01 23:14:42 +02:00
Edouard Vanbelle d6c3ca3198 fix(notification): correct bell animation + automatically close notification zone on clear 2026-04-01 23:01:39 +02:00
Edouard Vanbelle 2a0a2e9c0c icons: add missing home icon (source: https://fontawesome.com/icons/house?f=classic&s=solid) 2026-03-25 16:28:06 +01:00
BillionClaw 0c812d9390 fix(i18n): use translation keys for upload notification titles
Replace hardcoded English/Spanish strings with proper i18n translations
for upload notification titles and file count labels.

- Add upload.files translation key to all locale files
- Update notifications.js to use window.i18n.t() for:
  - upload.uploading title
  - upload.files file count label
  - upload.complete completion message

Fixes #108
2026-03-17 14:17:39 +08:00
Diocrafts df336da679 feat(frontend): i18n expansion, admin/profile i18n, grid/list view fix, empty state
- Add 5 new locales (hi, ar, ru, ja, ko) — now 14 total
- Admin panel: 117 i18n keys, confirm modal, animated tabs, no inline handlers
- Profile page: 58 i18n keys with data-i18n attributes
- Fix i18n safeT() shadowing bug and translationsLoaded timing
- Fix grid/list view: list header no longer shows in grid mode on login
- Fix classList.toggle hidden sync for view switching across all nav functions
- Revert .hidden important that broke login page rendering
- Add files empty state (no_files + empty_hint) with translations
- Fix language selector dropdown scroll and styling
- Fix admin panel scroll with sticky tabs
2026-03-09 00:08:34 +01:00
Dionisio 9aa35aa0ea quick fix 2026-03-06 13:18:36 +01:00
Jared Wolff 6a84a5c44e fix(photos): fix SQL type mismatch, pagination panic, missing icons, and add day/month/year grouping
- Fix photos endpoint 500: remove ::uuid cast on user_id WHERE clause (VARCHAR column)
- Fix pagination underflow panic when total_pages is 0
- Add missing 'images' and 'play' icons to SVG icon registry
- Add day/month/year grouping toggle with localStorage persistence
- Improve grid spacing and group header styling per mode
- Add i18n translations for grouping labels (all 9 locales)
2026-03-05 17:32:28 -05:00
Jared Wolff 633c1bbe97 fix(admin): fix invisible modals and add missing button icons
- Add hidden class to quota, create-user, and reset-password modal divs
- Override opacity:0 from modals.css with opacity:1 in admin.css
- Add crown and ban SVG icons to icon registry for toggle-role and
  deactivate buttons
2026-03-05 17:20:07 -05:00
Jared Wolff c08926b817 fix(csp): remove all inline styles, scripts, and event handlers for strict CSP compliance
Replace ~50 inline style="" attributes with CSS classes, move 3 inline
<script> blocks to external JS files, replace all inline event handlers
(onclick, onerror) with addEventListener, and remove createElement('style')
from icons.js. All changes support the strict CSP policy (style-src 'self';
script-src 'self') without weakening it.
2026-03-05 16:28:28 -05:00
Dionisio f2d35ca792 feat: auto-persist JWT secret, remove setup token requirement
- JWT secret auto-generates and persists to <STORAGE_PATH>/.jwt_secret
- Remove setup token: first admin setup is open until system initialized
- Fix schema.sql: move CREATE EXTENSION pg_trgm/ltree to top
- Update login UI and auth.js to remove setup token fields
2026-03-05 22:12:53 +01:00
zjean 40b269c4eb fix: schema init, duplicate routes, and image preview bugs
- Move pg_trgm extension creation before CalDAV indexes that depend on it
- Remove duplicate app-password route registration that caused panic
- Fix missing comma in language selector array (Dutch entry)
- Await async canEdit() in file click handler (Promise was always truthy)
- Detect images by extension fallback when mime_type is octet-stream
  (files uploaded via Nextcloud WebDAV API lack correct mime types)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 20:46:28 +01:00
Dionisio b503e08384 security: fix vulnerabilities 1-7 from security audit
- Fix #1: Share handler IDOR - enforce owner check on share operations
- Fix #2: list_files_query IDOR - bind folder queries to authenticated user
- Fix #3: Dedup handler IDOR - restrict dedup operations to file owner
- Fix #4: Trash handler OptionalAuthUser - require full AuthUser
- Fix #5: Error info leakage - sanitize 500 error responses
- Fix #6: Chunked upload IDOR - bind upload sessions to user_id,
  add verify_session_owner() check on all session operations
- Fix #7: CSP unsafe-inline removal - migrate all inline scripts,
  styles and event handlers to external files, tighten CSP to
  script-src 'self'; style-src 'self'

New files:
  - static/js/core/theme-init.js (render-blocking theme init)
  - static/js/core/sw-register.js (service worker registration)
  - static/css/views/device-verify.css (extracted inline styles)
  - static/js/views/device-verify/device-verify.js (extracted inline script)
2026-03-05 13:15:34 +01:00
Dionisio d2c08d31ba feat(security): HttpOnly cookies + CSP headers + CSRF double-submit protection
- Migrate auth tokens from localStorage to HttpOnly SameSite=Lax cookies
- Add cookie_auth.rs: helpers for setting/clearing auth + CSRF cookies
- Update auth middleware: 3-method auth (Bearer → Basic → Cookie)
- Add 5 security headers: CSP, X-Content-Type-Options, X-Frame-Options,
  Referrer-Policy, Permissions-Policy
- Implement CSRF double-submit cookie pattern (csrf.rs middleware)
- Set CSRF cookie on login/refresh/oidc-exchange, clear on logout
- CookieAuthenticated marker skips CSRF for Bearer/Basic clients
- Frontend: strip all localStorage token refs from 14 JS files
- Frontend: csrf.js utility + all 52 mutating fetch/XHR calls protected
- 121 tests passing, 0 warnings
2026-03-03 01:10:50 +01:00
zjean 1cf69d439d fix dutch language selection 2026-02-21 20:44:05 +00:00
George Wu 283a80a302 fix: display unlimited quota (∞) when storage_quota_bytes = 0
- Added formatQuotaSize() function to display ∞ for unlimited (0) quota
- Added format_quota_size() Rust function matching JavaScript behavior
- Updated quota defaulting logic from '||' to '== null' check
- This allows 0 (unlimited) to pass through while defaulting to 10 GB
  only when the value is null/undefined
- Call sites now use dedicated formatQuotaSize() or format_quota_size()
  instead of options parameter for cleaner API
2026-02-20 19:23:44 -08:00
Diocrafts 269a5fe940 feat: implement full breadcrumb path navigation in Files tab
- Add breadcrumbPath array to app state for tracking folder hierarchy
- Rewrite updateBreadcrumb() to render full path: Home > folder > subfolder
- Each breadcrumb segment is clickable to navigate back to that level
- Current folder shown in bold (non-clickable), parent folders as links
- Reset breadcrumb path on tab switch, home navigation, and initial load
- Update navigateFolder/selectFolder to push to breadcrumb path
- Enhanced breadcrumb CSS with hover effects and dark mode support
2026-02-21 00:19:04 +01:00