Commit Graph

160 Commits

Author SHA1 Message Date
Dionisio e2297d276a fix: resolve admin registration failure on fresh Docker installs (#81)
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
2026-02-12 23:20:46 +01:00
Dionisio 8123406ab9 fixing db error and upgrading technical documentation 2026-02-12 22:29:35 +01:00
Dionisio ab8f3191cb refactor: remove legacy 'Mi Carpeta' references, use 'My Folder' only 2026-02-12 15:31:39 +01:00
Dionisio ad07a5abda fix: auto-apply DB schema on fresh install and fix admin registration (#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
2026-02-12 14:45:52 +01:00
Dionisio 321fae7dcb chore: bump version to 0.3.1 2026-02-12 12:33:45 +01:00
Dionisio 76d9038e5b fix: resolve compiler warnings and downgrade JWT secret log to warn
- 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
2026-02-12 12:29:12 +01:00
Dionisio 59af22390d fix: restore missing match arms in trash_service restore_item
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.
2026-02-12 11:26:23 +01:00
Dionisio 3c03caaf60 fix: resolve file viewer auth issues and add text file viewing support
- 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.
2026-02-12 11:16:58 +01:00
Dionisio 6ca1ac4294 fix: resolve Docker volume permission denied on startup
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>
2026-02-12 09:57:33 +01:00
Dionisio d31a413e57 chore: translate all Spanish comments and log messages to English 2026-02-12 09:41:25 +01:00
Dionisio bc169de8f6 docs: add Star History chart to README 2026-02-11 21:27:25 +01:00
Dionisio a52d221c07 ci: increase docker build timeout to 2 hours for arm64 emulation 2026-02-11 18:56:39 +01:00
Dionisio f675606422 fix(docker): restore COPY static in builder stage for include_str!
login.html is embedded at compile-time via include_str! macro,
so static/ must be present during cargo build.
2026-02-11 18:12:17 +01:00
Dionisio 95e2f9acc8 ci: remove dependabot configuration 2026-02-11 18:00:38 +01:00
Dionisio d448e632ed fix: downgrade rand_core to 0.6 for argon2 compatibility
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.
2026-02-11 17:59:18 +01:00
Dionisio 0f1dc0031e fix(ci): trigger docker publish on tag push instead of release event
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.
2026-02-11 14:16:02 +01:00
Dionisio ee131abeee ci: add release workflow for automated GitHub releases 2026-02-11 14:11:16 +01:00
Dionisio 1e8a7dd5bb feat: redesign admin panel & profile page, optimize Dockerfile, remove rootless
- Completely redesign admin.html matching OxiCloud design system
- Create standalone profile.html page with avatar, details & password change
- Optimize Dockerfile: 3-stage build, non-root user, OCI labels, layer cache
- Add .dockerignore to reduce build context
- Remove redundant Dockerfile.rootless & rootless-compose.yml
- Redesign login language selector as compact dropdown with search
- Fix CI/CD workflows (ci.yml, docker-build.yml, docker-publish.yml)
- Update app.js to navigate to profile page instead of modal
2026-02-11 14:09:40 +01:00
Dionisio 3050955f9c feat: add admin/profile UI, i18n (fr/de/pt), fix CI pipelines
- Add admin panel link and profile modal in user menu dropdown
- Add French, German and Portuguese locale support (full translations)
- Register new locales across JS frontend and Rust backend
- Create CI pipeline (fmt, clippy, test, audit, build)
- Fix docker-build.yml (cache, real tests, reduced timeout)
- Fix docker-publish.yml (multi-arch via QEMU, latest tag, pre-publish tests)
- Add dependabot.yml for automated dependency updates
2026-02-11 12:37:03 +01:00
Dionisio Pozo 6b55cdf3c4 Merge pull request #71 from roswitina/main
feat(i18n): add Deutsch(de) to language list
2026-02-11 12:27:52 +01:00
roswitina f02a9c6d95 Merge pull request #1 from roswitina/dev
feat(i18n): add Deutsch(de) to language list
2026-02-11 09:25:09 +01:00
roswitina d1acb9677a feat(i18n): add Deutsch(de) to language list --> de.json 2026-02-11 09:22:12 +01:00
roswitina 6c900c51a3 feat(i18n): add Deutsch(de) to language list --> sw.js 2026-02-11 09:11:00 +01:00
roswitina d66af34beb feat(i18n): add Deutsch(de) to language list 2026-02-11 08:56:01 +01:00
Dionisio ccd071911d feat(admin): add user management, quotas, and stats dashboard to admin panel
- Dashboard tab: total users, active users, admins, storage usage, quota warnings
- User management tab: list, edit role, activate/deactivate, update quota, delete
- Self-protection: cannot delete/deactivate/demote yourself
- Paginated user listing (default 50 per page)
- Efficient single-query dashboard stats with direct SQL aggregation
- Quota modal with GB/MB/TB unit selector
- Backend: added methods to UserStoragePort, UserRepository, PgRepository
- Backend: added 7 admin methods to AuthApplicationService
- Backend: added 5 new DTOs for admin operations
- Backend: 7 new endpoints under /api/admin/

Files modified:
- src/application/ports/auth_ports.rs (4 new UserStoragePort methods)
- src/domain/repositories/user_repository.rs (StorageStats + 3 methods)
- src/infrastructure/repositories/pg/user_pg_repository.rs (implementations)
- src/application/services/auth_application_service.rs (admin methods)
- src/application/dtos/settings_dto.rs (5 new DTOs)
- src/interfaces/api/handlers/admin_handler.rs (7 new endpoints)
- static/admin.html (complete UI with 3 tabs: Dashboard, Users, OIDC)
2026-02-11 01:08:00 +01:00
Dionisio 1a1dee9179 fix(oidc): add CSRF state validation, PKCE S256, nonce, secure token delivery, registration guard
Security fixes for OIDC authentication flow:

1. CSRF state validation (High): State nonce is now stored server-side
   and validated on callback (single-use, 600s TTL)

2. PKCE S256 (Medium): code_challenge/code_verifier pair generated per
   RFC 9126, sent in authorize URL and token exchange

3. Nonce in ID token (Medium): Random nonce included in authorize URL,
   verified against ID token claims to prevent token replay

4. Secure token delivery (Medium): Tokens no longer in URL fragments.
   One-time exchange code redirected to frontend, tokens retrieved via
   POST /api/auth/oidc/exchange endpoint (60s TTL, single-use)

5. Registration guard (Low): POST /api/auth/register returns 403 when
   disable_password_login is active in OIDC-only mode
2026-02-11 00:37:47 +01:00
Dionisio f60c0df9f9 feat(admin): add admin settings panel for OIDC configuration
- Admin UI at /admin.html with settings management interface
- REST API: GET/PUT /api/admin/settings/oidc, POST .../test, GET .../general
- DB-backed settings in auth.admin_settings table (PostgreSQL)
- OIDC auto-discovery from issuer URL (.well-known/openid-configuration)
- Hot-reload: OIDC config changes apply without server restart
- Role-based access: admin-only endpoints with 403 for regular users
- Client secret stored securely, never exposed in GET responses
- Env var override detection shown in admin UI
- Clean architecture: repository trait, PG implementation, service, handler
2026-02-11 00:15:26 +01:00
Dionisio 8ef62109a3 feat(auth): add OpenID Connect (OIDC) authentication support
Implements OIDC Authorization Code Flow for external identity providers
(Authentik, Keycloak, etc.) with JIT user provisioning.

New features:
- OidcService with OpenID Discovery, JWKS caching, RS256 ID token validation
- Authorization Code Flow: /api/auth/oidc/authorize -> IdP -> /api/auth/oidc/callback
- JIT user provisioning from OIDC claims (sub, email, name, groups)
- OIDC group-to-role mapping (admin_groups config)
- Provider info endpoint: GET /api/auth/oidc/providers
- Option to disable password login entirely (OXICLOUD_OIDC_DISABLE_PASSWORD_LOGIN)
- Auto-provision toggle (OXICLOUD_OIDC_AUTO_PROVISION)
- Email collision detection (security: prevents account takeover)

Configuration (env vars):
- OXICLOUD_OIDC_ENABLED, OXICLOUD_OIDC_ISSUER_URL
- OXICLOUD_OIDC_CLIENT_ID, OXICLOUD_OIDC_CLIENT_SECRET
- OXICLOUD_OIDC_REDIRECT_URI, OXICLOUD_OIDC_SCOPES
- OXICLOUD_OIDC_FRONTEND_URL, OXICLOUD_OIDC_PROVIDER_NAME
- OXICLOUD_OIDC_AUTO_PROVISION, OXICLOUD_OIDC_ADMIN_GROUPS
- OXICLOUD_OIDC_DISABLE_PASSWORD_LOGIN

DB migration:
- ALTER TABLE auth.users ADD oidc_provider, oidc_subject columns
- UNIQUE index on (oidc_provider, oidc_subject)

Files changed: 14 files, ~1400 lines added
Dependencies: reqwest 0.12 (rustls-tls-webpki-roots), base64 0.22
2026-02-10 20:32:32 +01:00
Dionisio 65f4e10236 fix(webdav): fully working WebDAV RFC 4918 implementation
- Move WebDAV routes to top-level (out of /api nest) for proper path handling
- Add trailing slash routes and HEAD method support
- Refactor all 12 handlers to use Axum State extractor instead of req.extensions()
- Fix MOVE handler to support rename (same-folder move) via rename_file service
- Add Overwrite header support in MOVE/COPY operations
- Add extract_webdav_path() helper for consistent path parsing
- Add precondition_failed variant to AppError
- All 17 integration tests passing: OPTIONS, PROPFIND, MKCOL, PUT, GET, HEAD,
  PROPPATCH, COPY, MOVE, LOCK, DELETE (files and folders)
2026-02-10 19:26:28 +01:00
Dionisio ef9ed2cc31 feat: complete CalDAV (RFC 4791) and CardDAV (RFC 6352) implementation
- CalDAV: MKCALENDAR, PROPFIND, PUT/GET/DELETE events, REPORT calendar-query
- CardDAV: MKCOL, PROPFIND, PUT/GET/DELETE vCards, REPORT addressbook-query
- Fix routing: move CalDAV/CardDAV to top-level merge() with explicit routes
- Fix DB schema: VARCHAR(36) -> UUID for entity IDs, vcard_data -> vcard
- Fix 15 repository stub methods that returned empty results
- Fix vCard parser in ContactStorageAdapter (was hardcoded stub)
- All operations tested end-to-end in Docker (201/207/200/204 as expected)
2026-02-10 18:46:59 +01:00
Diocrafts 5bd505ccd7 modernizing frontend 2026-02-08 22:44:42 +01:00
Dionisio Pozo 03b409bbbc Merge pull request #70 from Goudarz/feature/bidirectional-support
Add RTL Support with Automatic HTML Attributes
2026-02-08 13:42:47 +01:00
Diocrafts a82faa5eaf refactoring hexagonal and clean architecture 2026-02-08 13:40:23 +01:00
Goudarz Jafari 67ade90d95 feat: add RTL-specific CSS for bidirectional layout 2026-02-08 10:05:04 +03:30
Goudarz Jafari 449ac7a981 feat: add RTL-specific CSS for bidirectional layout 2026-02-08 10:04:58 +03:30
Goudarz Jafari d05485c459 feat: add RTL-specific CSS for bidirectional layout 2026-02-08 10:04:49 +03:30
Goudarz Jafari 0096d2ee95 feat: add RTL-specific CSS for bidirectional layout 2026-02-08 10:04:37 +03:30
Goudarz Jafari 31ad2f878a feat(i18n): add Persian(fa) to language list 2026-02-08 09:57:55 +03:30
Goudarz Jafari 00a8e0c361 feat(i18n): add Persian(fa) to language list 2026-02-08 09:57:38 +03:30
Goudarz Jafari a3b2192b0e feat(i18n): add Persian(fa) to language list 2026-02-08 09:57:11 +03:30
Goudarz Jafari ad48b865f2 feat: add automatic HTML lang and dir attributes
- Add updateHtmlAttributes() function to set lang attribute on HTML element
- Automatically add dir=rtl for RTL languages (fa, ar) and remove for LTR
- Initialize attributes on component load with current locale
- Listen for locale changes to update attributes dynamically
- Add rtlLanguages configuration array for maintainability
2026-02-08 09:56:11 +03:30
Dionisio Pozo 3e4fb67c19 Delete src/domain/services/auth_service.rs 2026-02-07 10:42:39 +01:00
Dionisio b9d10c7b5c fix 2026-02-07 04:02:38 +01:00
Dionisio Pozo dad185a8d5 Merge pull request #69 from DioCrafts/dev
refactoring hexagonal architecture
2026-02-06 20:58:27 +01:00
Dionisio c952e82b27 refactoring hexagonal architecture 2026-02-06 20:57:00 +01:00
Dionisio Pozo 4ac141fe36 Merge pull request #68 from Goudarz/fa-translation
Add Persian translation
2026-02-06 08:38:04 +01:00
Goudarz Jafari f9cac2037d docs(i18n): document Persian(fa) language support 2026-02-06 10:31:48 +03:30
Goudarz Jafari 2c5c67311e feat(i18n): add Persian(fa) to language list 2026-02-06 10:30:26 +03:30
Goudarz Jafari fac45c4d44 feat(i18n): add Persian(fa) to language list 2026-02-06 10:29:19 +03:30
Goudarz Jafari 7008c22c12 feat(i18n): add Persian(fa) to language list 2026-02-06 10:29:13 +03:30