- Add checkboxes to list view items (grid view already had them)
- Add 'select all' checkbox in list view header
- Add batch action bar with Delete, Move, and Download buttons
- Batch delete: moves all selected items to trash in one operation
- Batch move: reuses existing move dialog in batch mode
- Batch download: downloads each selected item
- Keyboard shortcuts: Ctrl+A (select all), Escape (deselect), Delete key
- Shift+click for range selection in both grid and list views
- Selection state synced between grid and list views
- New multiSelect.js module manages selection state and batch operations
The clickable area now covers both the logo icon and the 'OxiCloud'
text on profile.html and admin.html. The page indicator (· Profile,
· Admin) remains outside the link as expected.
Add server-side routes for /profile, /admin, and /shared that
serve their respective HTML pages directly (same pattern already
used for /login). Updated all frontend references to use clean
URLs instead of .html extensions.
Fixes#99
Follow-up to ce9971b — the logo was only fixed in index.html.
Now profile.html, admin.html, and shared.html also wrap their
logo elements in <a href='/'> links.
Fixes#97
The profile page checked user.auth_provider to hide the password
form, but the backend doesn't return that field. Now also queries
/api/auth/oidc/providers and hides the password section when
password_login_enabled is false.
Fixes#96
Non-admin users were seeing all users' root folders, including the
admin's. Three root causes fixed:
1. Backend: list_root_folders now extracts AuthUser and filters
results so each user only sees their own home folder at the
root level (folders matching 'My Folder - {username}' or
'Mi Carpeta - {username}').
2. Frontend: findUserHomeFolder() searched only for the Spanish
pattern 'Mi Carpeta - {username}' but the backend creates
folders with the English pattern 'My Folder - {username}'.
Now checks both naming conventions.
3. Frontend: when the home folder was not found, the code fell
back to folderList[0] — which was usually the admin's folder.
Removed that dangerous fallback; now shows empty root instead.
Fixes#94
Wrap the logo-container div in an <a href='/'> so clicking the
OxiCloud logo navigates back to the root/home view, matching the
widely accepted web convention.
Fixes#97
Axum's default body limit for Multipart extraction is 2 MB.
OxiCloud never overrode this default, so any file upload larger
than ~2 MB was silently truncated.
Added DefaultBodyLimit::max(10 GB) both globally on the app
router and specifically on the file upload routes, matching the
chunked upload capability already in place for large files.
Replaced the hidden dropzone-only progress bar with a floating
upload toast that appears at the bottom-right corner whenever
files are being uploaded (button or drag-and-drop).
Features:
- Per-file progress bar with real byte-level tracking via XHR
- Spinning icon while uploading, green check on success, red on error
- Overall progress bar and file counter in the footer
- Auto-hides 4 seconds after all uploads complete
- Dismiss button to minimise the toast
- Works for both file and folder uploads
- i18n keys added to all 8 locale files
- Service worker cache bumped to v3
Previously the admin quota was hardcoded to 100 GB and the regular
user quota to 1 GB, regardless of actual disk capacity. On systems
with less than 100 GB free this produced misleading quota values.
Added the fs2 crate to query available disk space on the storage
filesystem. A new capped_quota() helper now returns
min(default_quota, available_disk_space) when assigning quotas
during user registration, admin setup, and OIDC provisioning.
checkAuthentication() used await for the OIDC exchange fetch but was
declared as a regular function, not async. This caused a JavaScript
syntax error that prevented the entire app.js file from parsing,
resulting in a completely non-interactive frontend after OIDC login.
Also bumped service worker cache version to v2 so browsers
discard stale cached JS files on the next load.
get_authorize_url() was synchronous and fell back to constructing
{issuer}/authorize when the discovery cache was empty. This produced
incorrect URLs for providers like Keycloak whose authorization
endpoint is {issuer}/protocol/openid-connect/auth.
Made get_authorize_url() async so it can call get_discovery() to
fetch the real authorization_endpoint from .well-known/openid-configuration
before the first redirect. The discovery document is cached after the
initial fetch.
The backend redirected to /?oidc_code=<code> after successful OIDC auth,
but the frontend never exchanged this code for JWT tokens. The user
was redirected back to the login page every time.
- app.js: Detect oidc_code in URL params before token check, call
POST /api/auth/oidc/exchange, store tokens, reload clean
- auth.js: Fallback handler if oidc_code lands on login page
Fixes#90
- Added SSO login button on login page that appears when OIDC is configured
- Button shows provider name (e.g. 'Sign in with Authentik')
- When 'Disable password login' is enabled, hides password form and
shows only the SSO button
- Added auth divider between password and SSO sections
- Added i18n keys (or, sso_login, sso_login_provider) for all 8 locales
- Fixed missing comma in it.json locale file
Fixes#88, Fixes#89
- Added directory name filtering in folder_fs_repository.rs
- Filters out directories starting with '.' in list_folders, list_folders_paginated, and count_directory_items
- Matches existing file listing behavior
- Also added Italian language to popular languages list
Fixes#87
Backend:
- POST /api/admin/users — admin-only user creation endpoint
- username & password required, email optional (auto-generated placeholder)
- role, quota_bytes, active all configurable
- creates personal folder automatically
- PUT /api/admin/users/{id}/password — admin password reset
- GET/PUT /api/admin/settings/registration — toggle public registration
- Supports env var OXICLOUD_DISABLE_REGISTRATION override
- Blocks POST /api/auth/register when disabled
- AdminCreateUserDto, AdminResetPasswordDto added to settings DTOs
- registration_enabled field added to DashboardStatsDto
Frontend (admin.html):
- 'Create User' button in Users tab with full modal form
(username, password, email, role, quota)
- 'Reset Password' button per user in actions column
- 'Allow public self-registration' toggle in Dashboard > System
with warning banner when disabled
Closes#85
When renaming a file (e.g. image.png), the input now selects only
'image' instead of 'image.png', preventing accidental extension changes.
Folders still select the full name. Uses setSelectionRange(0, lastDot)
to position cursor selection up to the last dot.
Closes suggestion from issue #83 feedback.
- Add missing .confirm-dialog.active { display: flex; opacity: 1 } CSS rule.
The confirm dialog was created with display:none and the .active class
was added, but no CSS rule changed it to visible — so the user never
saw the confirmation prompt and delete appeared to do nothing.
- Capture file/folder target before closeContextMenu in delete handlers
to prevent null reference race condition (same as rename/share fix).
- Fix showShareDialog: add try-catch, null checks, prevent textContent
from destroying header icon (use span child instead)
- Capture file/folder target before closeContextMenu to prevent race
- createSharedLink now calls real backend POST /api/shares instead of
localStorage-only mock (still caches locally for offline compat)
- Fix share_handler.rs: use OptionalAuthUser instead of AuthUser to
prevent 401 when auth is disabled (same pattern as delete/trash)
- Add null-safety to closeShareDialog
- Reset new-share-section on dialog open
- Add ?metadata=true support to GET /api/files/{id} to return JSON metadata
instead of binary content (was the root cause of favorites not loading)
- Fix favorites loadFileDetails to use metadata endpoint with auth headers
- Add star icon on favorited files/folders in grid view (top-left corner)
- Add star icon on favorited files/folders in list view (next to name)
- Refresh file view when toggling favorites so star appears/disappears
- Add CSS styles for .favorite-star and .favorite-star-inline
- Fix rename: context menu was nullifying target reference before rename dialog could use it
- Fix delete files/folders: auth extractors were mandatory, causing 401 when auth not configured
- Fix view-file: async fetch race condition with context menu cleanup
- Fix orphaned ID mappings on file deletion
- Fix Authorization: Bearer null headers sent without token
- Add OptionalUserId and OptionalAuthUser infallible extractors
Three bugs caused 403 errors when creating the first admin on fresh
Docker deployments (Unraid, Komodo):
1. db.rs: Schema application failures were silently swallowed. The app
started with no tables, causing all auth queries to fail. Now the
startup aborts if schema cannot be applied, with a fallback
statement-by-statement executor that handles dollar-quoted blocks.
Retries increased to 5 with 2s intervals.
2. auth_application_service.rs: count_admin_users() used fragile string
matching (contains "does not exist")) on multi-layer wrapped errors.
count_all_users() rejected admin creation on any DB error. Both now
allow admin creation on any error for bootstrap scenarios.
3. auth_handler.rs: Redundant 60-line handler-level admin detection
duplicated service-layer logic and generated noisy ERROR logs on
fresh installs. Removed entirely - service layer handles it all.
Closes#81
- Auto-apply schema.sql when database tables don't exist (embedded in binary)
- Handle missing tables gracefully during admin registration (treat as fresh install)
- Fix docker-compose depends_on to wait for postgres healthcheck
- Rename personal folder from 'Mi Carpeta' to 'My Folder' with backward compat
- Translate remaining Spanish messages to English
- Downgrade OXICLOUD_JWT_SECRET missing log from error to warn level,
since generating a random secret per session is valid behavior
- Remove unused import super::* in calendar_storage_adapter tests
- Remove unused import tokio_stream::StreamExt in compression_service tests
- Prefix unused validate_user_ownership with _ in trash_service
- Add nohup.out to .gitignore
The translation commit accidentally removed the match statement and
opening arms (match item_result, Ok(Some(item)), match item.item_type)
while keeping the body, causing a brace mismatch compilation error.
- Fix file viewer not sending JWT auth tokens when loading files
- inlineViewer.js: already used XHR with auth (images/PDFs worked)
- fileViewer.js: was setting img.src/iframe.src directly without auth headers,
now uses fetch with Bearer token and blob URLs
- ui.js/contextMenus.js/fileRenderer.js/recent.js/favorites.js: replaced all
window.location.href = /api/files/... (unauthenticated navigation) with
authenticated viewer or fileOps.downloadFile()
- Add text file viewing support (text/*, application/json, etc.)
- New createTextViewer() in inlineViewer.js with authenticated fetch
- New loadTextViewer() in fileViewer.js with authenticated fetch
- New isViewableFile() helper in ui.js used across all entry points
- CSS styles for .inline-viewer-text-content and .file-viewer-text-content
- Translate remaining Spanish strings to English in viewer files
Fixes: text files showing 'Token not provided', images failing to load,
and text files not being previewable at all.
Root cause: Docker named volumes are created as root, but the container
ran as the unprivileged 'oxicloud' user (UID 1001). Services like
thumbnail_service, image_transcode, and dedup_service call
create_dir_all under /app/storage during initialization, which fails
with 'Permission denied (os error 13)'.
Changes:
- Add entrypoint.sh that runs as root to chown /app/storage, then
drops privileges via su-exec before executing the application
- Update Dockerfile to install su-exec, copy entrypoint, and use
ENTRYPOINT instead of USER+CMD
- Downgrade id_mapping_service initial write failure from ERROR to WARN
(empty in-memory map is perfectly valid, will persist on next save)
- Improve panic message in main.rs to hint at Docker permission issue
Fixes #<issue>
rand_core 0.9.x changed OsRng API (no longer implements RngCore directly)
and is incompatible with argon2 0.5.x which depends on rand_core 0.6.x.
This caused compilation failures in CI.
GitHub Actions events created by GITHUB_TOKEN don't trigger other
workflows. Changed trigger from 'release: published' to 'push: tags'
so docker-publish runs directly from the tag push.