diff --git a/Cargo.lock b/Cargo.lock index 7d17cb9..2c3b879 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -356,9 +356,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.17" +version = "1.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" +checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c" dependencies = [ "jobserver", "libc", @@ -501,9 +501,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.4.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cfac68e08048ae1883171632c2aef3ebc555621ae56fbccce1cbf22dd7f058" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", ] @@ -580,9 +580,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", "windows-sys 0.59.0", @@ -613,9 +613,9 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "flate2" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" +checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" dependencies = [ "crc32fast", "miniz_oxide", @@ -1027,9 +1027,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" dependencies = [ "bytes", "futures-channel", @@ -1037,6 +1037,7 @@ dependencies = [ "http 1.3.1", "http-body 1.0.1", "hyper", + "libc", "pin-project-lite", "socket2", "tokio", @@ -1046,9 +1047,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.62" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2fd658b06e56721792c5df4475705b6cda790e9298d19d2f8af083457bcd127" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1209,9 +1210,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -1307,9 +1308,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "litemap" @@ -1415,9 +1416,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", ] @@ -1594,9 +1595,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "openssl" -version = "0.10.71" +version = "0.10.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" +checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" dependencies = [ "bitflags", "cfg-if", @@ -1625,13 +1626,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] -name = "openssl-sys" -version = "0.9.106" +name = "openssl-src" +version = "300.5.0+3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" +checksum = "e8ce546f549326b0e6052b649198487d91320875da901e7bd11a06d1ee3f9c2f" +dependencies = [ + "cc", +] + +[[package]] +name = "openssl-sys" +version = "0.9.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" dependencies = [ "cc", "libc", + "openssl-src", "pkg-config", "vcpkg", ] @@ -1662,6 +1673,7 @@ dependencies = [ "jsonwebtoken", "mime_guess", "mockall", + "openssl", "pin-project-lite", "quick-xml", "rand", @@ -1925,9 +1937,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" dependencies = [ "bitflags", ] @@ -2063,9 +2075,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e56a18552996ac8d29ecc3b190b4fdbb2d91ca4ec396de7bbffaf43f3d637e96" +checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" dependencies = [ "bitflags", "errno", @@ -2342,9 +2354,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" [[package]] name = "socket2" @@ -2803,9 +2815,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.44.1" +version = "1.44.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" +checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" dependencies = [ "backtrace", "bytes", @@ -3278,11 +3290,37 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.52.0" +version = "0.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" dependencies = [ - "windows-targets 0.52.6", + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings 0.4.0", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", ] [[package]] @@ -3298,7 +3336,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" dependencies = [ "windows-result", - "windows-strings", + "windows-strings 0.3.1", "windows-targets 0.53.0", ] @@ -3320,6 +3358,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-strings" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -3691,9 +3738,9 @@ dependencies = [ [[package]] name = "zip" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27c03817464f64e23f6f37574b4fdc8cf65925b5bfd2b0f2aedf959791941f88" +checksum = "1dcb24d0152526ae49b9b96c1dcf71850ca1e0b882e4e28ed898a93c41334744" dependencies = [ "aes", "arbitrary", diff --git a/Cargo.toml b/Cargo.toml index 31e5bb4..8df90f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,16 +5,16 @@ edition = "2021" [dependencies] -axum = { version = "0.8.1", features = ["multipart", "http1", "tokio", "macros"] } -tokio = { version = "1.44.1", features = ["full"] } +axum = { version = "0.8.3", features = ["multipart", "http1", "tokio", "macros"] } +tokio = { version = "1.44.2", features = ["full"] } tokio-util = { version = "0.7.14", features = ["io", "codec"] } tokio-stream = { version = "0.1.17", features = ["fs"] } bytes = "1.10.1" tempfile = "3.19.1" tower = "0.5.2" tower-http = { version = "0.6.2", features = ["fs", "compression-gzip", "trace", "cors", "add-extension", "request-id"] } -flate2 = "1.1.0" -zip = "2.5.0" +flate2 = "1.1.1" +zip = "2.6.1" tracing = "0.1.41" tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } chrono = { version = "0.4.40", features = ["serde"] } @@ -39,9 +39,10 @@ rand_core = { version = "0.6.4", features = ["std"] } time = "0.3.41" axum-server = "0.6.0" hyper = { version = "1.6.0", features = ["full"] } -url = "2.5.0" +url = "2.5.4" quick-xml = "0.30.0" http-body-util = "0.1.3" +openssl = { version = "0.10.72", features = ["vendored"] } [features] default = [] diff --git a/Dockerfile b/Dockerfile index b4e6a9b..68bbe5d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM rust:1.85-alpine AS cacher WORKDIR /app RUN apk --no-cache upgrade && \ - apk add --no-cache musl-dev openssl-dev pkgconfig postgresql-dev + apk add --no-cache musl-dev pkgconfig postgresql-dev gcc perl make COPY Cargo.toml Cargo.lock ./ # Create a minimal project to download and cache dependencies RUN mkdir -p src && \ @@ -14,7 +14,7 @@ RUN mkdir -p src && \ FROM rust:1.85-alpine AS builder WORKDIR /app RUN apk --no-cache upgrade && \ - apk add --no-cache musl-dev openssl-dev pkgconfig postgresql-dev + apk add --no-cache musl-dev pkgconfig postgresql-dev gcc perl make # Copy cached dependencies COPY --from=cacher /app/target target COPY --from=cacher /usr/local/cargo /usr/local/cargo @@ -30,7 +30,7 @@ RUN cargo build --release FROM alpine:3.21.3 # Install only necessary runtime dependencies and update packages RUN apk --no-cache upgrade && \ - apk add --no-cache libgcc openssl ca-certificates libpq tzdata + apk add --no-cache libgcc ca-certificates libpq tzdata # Copy only the compiled binary COPY --from=builder /app/target/release/oxicloud /usr/local/bin/ diff --git a/ISSUE_45_SOLUTION.md b/ISSUE_45_SOLUTION.md new file mode 100644 index 0000000..a24c02f --- /dev/null +++ b/ISSUE_45_SOLUTION.md @@ -0,0 +1,89 @@ +# Solución para el issue #45: [BUG] Admin already exists? + +## Descripción del problema + +Al intentar configurar un usuario administrador, algunos usuarios reciben el error: + +``` +2025-04-09T14:01:26.733566Z ERROR oxicloud::interfaces::api::handlers::auth_handler: Registration failed for user admin: Already Exists: El usuario 'admin' ya existe +``` + +## Causa raíz + +Este problema ocurre debido a cómo está implementada la migración de datos inicial. En el archivo `migrations/20250408000001_default_users.sql`, el sistema intenta crear un usuario admin por defecto durante la migración inicial, pero: + +1. Si luego el usuario intenta crear manualmente otro usuario con nombre "admin", el sistema detecta el conflicto. +2. La cláusula `ON CONFLICT (id) DO NOTHING` solo previene conflictos en el ID, no en el nombre de usuario. + +## Solución implementada + +Hemos realizado los siguientes cambios: + +1. Modificado `migrations/20250408000001_default_users.sql` para comprobar primero si el usuario "admin" ya existe: + +```sql +-- Check if admin user already exists before creating it +DO $$$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM auth.users WHERE username = 'admin') THEN + -- Create admin user (password: Admin123!) + INSERT INTO auth.users ( + id, + username, + ... + ) VALUES (...); + END IF; +END; +$$$; +``` + +2. Creado un script `scripts/reset_admin.sql` que puede ejecutarse para eliminar el usuario admin existente: + +```sql +-- Set the correct schema +SET search_path TO auth; + +-- Delete the admin user if it exists +DELETE FROM auth.users WHERE username = 'admin'; + +-- Output remaining users for verification +SELECT username, email, role FROM auth.users ORDER BY role, username; +``` + +3. Actualizado la documentación en `doc/DATABASE-MIGRATIONS.md` con instrucciones detalladas para resolver este problema. + +## Instrucciones para usuarios afectados + +Si encuentras el error "Admin already exists", tienes dos opciones: + +### Opción 1: Usar el script proporcionado +```bash +cat scripts/reset_admin.sql | docker exec -i oxicloud-postgres-1 psql -U postgres -d oxicloud +``` + +### Opción 2: Hacerlo manualmente +1. Conéctate al contenedor de PostgreSQL: +```bash +# Encuentra el contenedor +docker ps +# Ejemplo: oxicloud-postgres-1 +docker exec -it oxicloud-postgres-1 bash +``` + +2. Conéctate a la base de datos: +```bash +psql -U postgres -d oxicloud +``` + +3. Borra el usuario admin existente: +```sql +SET search_path TO auth; +DELETE FROM auth.users WHERE username = 'admin'; +``` + +4. Verifica que se eliminó correctamente: +```sql +SELECT username, email, role FROM auth.users; +``` + +5. Sal y registra un nuevo usuario admin a través de la interfaz web. diff --git a/TODO-LIST.md b/TODO-LIST.md index bb8ed7c..8d9867a 100644 --- a/TODO-LIST.md +++ b/TODO-LIST.md @@ -104,6 +104,8 @@ This document contains the task list for the development of OxiCloud, a minimali - [ ] Add support for locking - [ ] Test compatibility with standard clients - [ ] Optimize WebDAV performance +- [ ] Implement Range Requests (RFC 7233) for resumable transfers +- [ ] Support partial file updates with HTTP PATCH for bandwidth efficiency ### Sync Client - [ ] Design client architecture in Rust @@ -112,6 +114,9 @@ This document contains the task list for the development of OxiCloud, a minimali - [ ] Implement conflict detection - [ ] Add configuration options - [ ] Create minimal client version for Windows/macOS/Linux +- [ ] Implement bandwidth throttling controls +- [ ] Add delta synchronization for large files +- [ ] Support synchronization pausing and resuming ## Phase 5: Advanced Features @@ -146,6 +151,9 @@ This document contains the task list for the development of OxiCloud, a minimali - [x] Implement asynchronous processing for heavy tasks - [ ] Optimize database queries - [ ] Implement scaling strategies +- [ ] Implement transfer acceleration with multipart chunking +- [ ] Implement differential sync algorithm (similar to rsync) +- [ ] Add strong ETag support for more efficient caching ### Frontend - [ ] Optimize initial asset loading @@ -154,6 +162,9 @@ This document contains the task list for the development of OxiCloud, a minimali - [ ] Optimize UI rendering - [ ] Implement intelligent prefetching - [ ] Add basic offline support +- [ ] Implement client-side image resizing before upload +- [ ] Add HTTP/2 support for multiplexing requests +- [ ] Implement progressive image loading ### Storage - [ ] Research deduplication options @@ -162,6 +173,9 @@ This document contains the task list for the development of OxiCloud, a minimali - [ ] Implement log rotation and archiving - [ ] Create automated backup system - [ ] Add support for distributed storage +- [ ] Implement media transcoding for optimized delivery +- [ ] Add content-aware compression by file format +- [ ] Implement dynamic thumbnail resizing based on viewport ## Infrastructure and Deployment diff --git a/doc/DATABASE-MIGRATIONS.md b/doc/DATABASE-MIGRATIONS.md index 9f93c3a..d656604 100644 --- a/doc/DATABASE-MIGRATIONS.md +++ b/doc/DATABASE-MIGRATIONS.md @@ -136,6 +136,45 @@ match migration_check { 3. **Permisos insuficientes**: Asegúrate de que el usuario de la base de datos tenga permisos suficientes para crear esquemas, tablas e índices. +4. **Error "Admin already exists"**: Si al intentar registrar un usuario admin recibes el error "El usuario 'admin' ya existe", sigue estos pasos: + + a. Conéctate al contenedor de PostgreSQL: + ```bash + # Encuentra el contenedor + docker ps + # Ejemplo: oxicloud-postgres-1 + docker exec -it oxicloud-postgres-1 bash + ``` + + b. Conéctate a la base de datos: + ```bash + psql -U postgres -d oxicloud + ``` + + c. Establece el esquema y borra el usuario admin existente: + ```sql + SET search_path TO auth; + DELETE FROM auth.users WHERE username = 'admin'; + ``` + + d. Verifica la eliminación: + ```sql + SELECT username, email, role FROM auth.users; + ``` + + e. Sal de PostgreSQL: + ```sql + \q + exit + ``` + + f. Ahora puedes registrar un nuevo usuario admin a través de la interfaz de OxiCloud. + + Alternativamente, utiliza el script proporcionado: + ```bash + cat scripts/reset_admin.sql | docker exec -i oxicloud-postgres-1 psql -U postgres -d oxicloud + ``` + ## Beneficios del Enfoque Basado en Migraciones - **Separación de Responsabilidades**: Las migraciones están separadas del código de la aplicación. diff --git a/migrations/20250408000001_default_users.sql b/migrations/20250408000001_default_users.sql index 5daac3a..ccd520e 100644 --- a/migrations/20250408000001_default_users.sql +++ b/migrations/20250408000001_default_users.sql @@ -1,35 +1,49 @@ -- Migration 002: Default Users --- Create admin user (password: Admin123!) -INSERT INTO auth.users ( - id, - username, - email, - password_hash, - role, - storage_quota_bytes -) VALUES ( - '00000000-0000-0000-0000-000000000000', - 'admin', - 'admin@oxicloud.local', - '$argon2id$v=19$m=65536,t=3,p=4$c2FsdHNhbHRzYWx0c2FsdA$H3VxE8LL2qPT31DM3loTg6D+O4MSc2sD7GjlQ5h7Jkw', -- Admin123! - 'admin', - 107374182400 -- 100GB for admin -) ON CONFLICT (id) DO NOTHING; +-- Check if admin user already exists before creating it +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM auth.users WHERE username = 'admin') THEN + -- Create admin user (password: Admin123!) + INSERT INTO auth.users ( + id, + username, + email, + password_hash, + role, + storage_quota_bytes + ) VALUES ( + '00000000-0000-0000-0000-000000000000', + 'admin', + 'admin@oxicloud.local', + '$argon2id$v=19$m=65536,t=3,p=4$c2FsdHNhbHRzYWx0c2FsdA$H3VxE8LL2qPT31DM3loTg6D+O4MSc2sD7GjlQ5h7Jkw', -- Admin123! + 'admin', + 107374182400 -- 100GB for admin + ); + END IF; +END; +$$; --- Create test user (password: test123) -INSERT INTO auth.users ( - id, - username, - email, - password_hash, - role, - storage_quota_bytes -) VALUES ( - '11111111-1111-1111-1111-111111111111', - 'test', - 'test@oxicloud.local', - '$argon2id$v=19$m=65536,t=3,p=4$c2FsdHNhbHRzYWx0c2FsdA$ZG17Z7SFKhs9zWYbuk08CkHpyiznnZapYnxN5Vi62R4', -- test123 - 'user', - 10737418240 -- 10GB for test user -) ON CONFLICT (id) DO NOTHING; \ No newline at end of file +-- Check if test user already exists before creating it +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM auth.users WHERE username = 'test') THEN + -- Create test user (password: test123) + INSERT INTO auth.users ( + id, + username, + email, + password_hash, + role, + storage_quota_bytes + ) VALUES ( + '11111111-1111-1111-1111-111111111111', + 'test', + 'test@oxicloud.local', + '$argon2id$v=19$m=65536,t=3,p=4$c2FsdHNhbHRzYWx0c2FsdA$ZG17Z7SFKhs9zWYbuk08CkHpyiznnZapYnxN5Vi62R4', -- test123 + 'user', + 10737418240 -- 10GB for test user + ); + END IF; +END; +$$; \ No newline at end of file diff --git a/scripts/reset_admin.sql b/scripts/reset_admin.sql new file mode 100644 index 0000000..1d795cb --- /dev/null +++ b/scripts/reset_admin.sql @@ -0,0 +1,19 @@ +-- Script to safely reset the admin user in OxiCloud +-- Run this script to delete the existing admin user if you're having issues creating one + +-- Set the correct schema +SET search_path TO auth; + +-- Delete the admin user if it exists +DELETE FROM auth.users WHERE username = 'admin'; + +-- Check if the user was deleted +SELECT 'Admin user has been removed successfully. You can now create a new admin user.' AS message +WHERE NOT EXISTS (SELECT 1 FROM auth.users WHERE username = 'admin'); + +-- Check if there are still users in the system +SELECT 'Warning: No users remain in the system. You should register a new admin user.' AS warning +WHERE NOT EXISTS (SELECT 1 FROM auth.users LIMIT 1); + +-- Output remaining users for verification +SELECT username, email, role FROM auth.users ORDER BY role, username; \ No newline at end of file diff --git a/src/application/adapters/webdav_adapter.rs b/src/application/adapters/webdav_adapter.rs index 8794792..47a7ef2 100644 --- a/src/application/adapters/webdav_adapter.rs +++ b/src/application/adapters/webdav_adapter.rs @@ -210,7 +210,7 @@ impl WebDavAdapter { files: &[FileDto], subfolders: &[FolderDto], request: &PropFindRequest, - depth: &str, + _depth: &str, base_href: &str, ) -> Result<()> { let mut xml_writer = Writer::new(writer); @@ -226,7 +226,7 @@ impl WebDavAdapter { } // If depth allows, add responses for files and subfolders - if depth != "0" { + if _depth != "0" { // Add responses for files for file in files { Self::write_file_response(&mut xml_writer, file, request, &format!("{}{}", base_href, file.name))?; @@ -249,7 +249,7 @@ impl WebDavAdapter { writer: W, file: &FileDto, request: &PropFindRequest, - depth: &str, + _depth: &str, href: &str, ) -> Result<()> { let mut xml_writer = Writer::new(writer); diff --git a/src/application/services/favorites_service.rs b/src/application/services/favorites_service.rs index 1f5b671..9b1e203 100644 --- a/src/application/services/favorites_service.rs +++ b/src/application/services/favorites_service.rs @@ -38,7 +38,7 @@ impl FavoritesUseCase for FavoritesService { item_type as "item_type", created_at as "created_at" FROM auth.user_favorites - WHERE user_id = $1 + WHERE user_id = $1::TEXT ORDER BY created_at DESC "# ) @@ -90,7 +90,7 @@ impl FavoritesUseCase for FavoritesService { sqlx::query( r#" INSERT INTO auth.user_favorites (user_id, item_id, item_type) - VALUES ($1, $2, $3) + VALUES ($1::TEXT, $2, $3) ON CONFLICT (user_id, item_id, item_type) DO NOTHING "# ) @@ -123,7 +123,7 @@ impl FavoritesUseCase for FavoritesService { let result = sqlx::query( r#" DELETE FROM auth.user_favorites - WHERE user_id = $1 AND item_id = $2 AND item_type = $3 + WHERE user_id = $1::TEXT AND item_id = $2 AND item_type = $3 "# ) .bind(user_uuid) @@ -164,7 +164,7 @@ impl FavoritesUseCase for FavoritesService { r#" SELECT EXISTS ( SELECT 1 FROM auth.user_favorites - WHERE user_id = $1 AND item_id = $2 AND item_type = $3 + WHERE user_id = $1::TEXT AND item_id = $2 AND item_type = $3 ) AS "is_favorite" "# ) diff --git a/src/application/services/recent_service.rs b/src/application/services/recent_service.rs index ed61f3d..dda0585 100644 --- a/src/application/services/recent_service.rs +++ b/src/application/services/recent_service.rs @@ -45,7 +45,7 @@ impl RecentItemsUseCase for RecentService { item_type as "item_type", accessed_at as "accessed_at" FROM auth.user_recent_files - WHERE user_id = $1 + WHERE user_id = $1::TEXT ORDER BY accessed_at DESC LIMIT $2 "# @@ -99,7 +99,7 @@ impl RecentItemsUseCase for RecentService { sqlx::query( r#" INSERT INTO auth.user_recent_files (user_id, item_id, item_type, accessed_at) - VALUES ($1, $2, $3, CURRENT_TIMESTAMP) + VALUES ($1::TEXT, $2, $3, CURRENT_TIMESTAMP) ON CONFLICT (user_id, item_id, item_type) DO UPDATE SET accessed_at = CURRENT_TIMESTAMP "# @@ -136,7 +136,7 @@ impl RecentItemsUseCase for RecentService { let result = sqlx::query( r#" DELETE FROM auth.user_recent_files - WHERE user_id = $1 AND item_id = $2 AND item_type = $3 + WHERE user_id = $1::TEXT AND item_id = $2 AND item_type = $3 "# ) .bind(user_uuid) @@ -176,7 +176,7 @@ impl RecentItemsUseCase for RecentService { sqlx::query( r#" DELETE FROM auth.user_recent_files - WHERE user_id = $1 + WHERE user_id = $1::TEXT "# ) .bind(user_uuid) @@ -208,7 +208,7 @@ impl RecentService { DELETE FROM auth.user_recent_files WHERE id IN ( SELECT id FROM auth.user_recent_files - WHERE user_id = $1 + WHERE user_id = $1::TEXT ORDER BY accessed_at DESC OFFSET $2 ) diff --git a/src/infrastructure/repositories/file_fs_repository.rs b/src/infrastructure/repositories/file_fs_repository.rs index ae8838e..f0539d7 100644 --- a/src/infrastructure/repositories/file_fs_repository.rs +++ b/src/infrastructure/repositories/file_fs_repository.rs @@ -19,7 +19,7 @@ use crate::domain::repositories::file_repository::{ FileRepository, FileRepositoryError, FileRepositoryResult }; use crate::application::services::storage_mediator::StorageMediator; -use crate::application::ports::outbound::IdMappingPort; +// use crate::application::ports::outbound::IdMappingPort; use crate::infrastructure::services::id_mapping_service::IdMappingError; use crate::infrastructure::services::file_metadata_cache::{FileMetadataCache, CacheEntryType}; use crate::domain::services::path_service::{StoragePath, PathService}; diff --git a/src/infrastructure/repositories/file_path_resolver.rs b/src/infrastructure/repositories/file_path_resolver.rs index 24b783b..c55bb12 100644 --- a/src/infrastructure/repositories/file_path_resolver.rs +++ b/src/infrastructure/repositories/file_path_resolver.rs @@ -4,7 +4,7 @@ use async_trait::async_trait; use crate::domain::services::path_service::{PathService, StoragePath}; use crate::application::services::storage_mediator::StorageMediator; -use crate::application::ports::outbound::IdMappingPort; +// use crate::application::ports::outbound::IdMappingPort; use crate::domain::repositories::file_repository::FileRepositoryError; use crate::common::errors::DomainError; use crate::application::ports::storage_ports::FilePathResolutionPort; diff --git a/src/infrastructure/repositories/folder_fs_repository.rs b/src/infrastructure/repositories/folder_fs_repository.rs index 5ae1e31..ba61a68 100644 --- a/src/infrastructure/repositories/folder_fs_repository.rs +++ b/src/infrastructure/repositories/folder_fs_repository.rs @@ -11,7 +11,7 @@ use crate::domain::repositories::folder_repository::{ FolderRepository, FolderRepositoryError, FolderRepositoryResult }; use crate::domain::services::path_service::{StoragePath, PathService}; -use crate::application::ports::outbound::IdMappingPort; +// use crate::application::ports::outbound::IdMappingPort; use crate::infrastructure::services::id_mapping_service::{IdMappingService, IdMappingError}; use crate::application::services::storage_mediator::StorageMediator; use crate::application::ports::outbound::FolderStoragePort; diff --git a/src/infrastructure/repositories/pg/session_pg_repository.rs b/src/infrastructure/repositories/pg/session_pg_repository.rs index becb4cc..78f564c 100644 --- a/src/infrastructure/repositories/pg/session_pg_repository.rs +++ b/src/infrastructure/repositories/pg/session_pg_repository.rs @@ -1,5 +1,5 @@ use async_trait::async_trait; -use sqlx::{PgPool, Row, Executor}; +use sqlx::{PgPool, Row}; use std::sync::Arc; use chrono::Utc; use futures::future::BoxFuture; diff --git a/src/infrastructure/repositories/pg/user_pg_repository.rs b/src/infrastructure/repositories/pg/user_pg_repository.rs index 6257166..de322f4 100644 --- a/src/infrastructure/repositories/pg/user_pg_repository.rs +++ b/src/infrastructure/repositories/pg/user_pg_repository.rs @@ -1,5 +1,5 @@ use async_trait::async_trait; -use sqlx::{PgPool, Row, Executor}; +use sqlx::{PgPool, Row}; use std::sync::Arc; use futures::future::BoxFuture; diff --git a/src/interfaces/api/handlers/file_handler.rs b/src/interfaces/api/handlers/file_handler.rs index 4cfda62..47ce98d 100644 --- a/src/interfaces/api/handlers/file_handler.rs +++ b/src/interfaces/api/handlers/file_handler.rs @@ -8,7 +8,7 @@ use axum::{ use serde::Deserialize; use std::collections::HashMap; use futures::Stream; -use futures::StreamExt; +// use futures::StreamExt; use std::task::{Context, Poll}; use std::pin::Pin; diff --git a/src/interfaces/api/handlers/trash_handler.rs b/src/interfaces/api/handlers/trash_handler.rs index 1b52f90..a685168 100644 --- a/src/interfaces/api/handlers/trash_handler.rs +++ b/src/interfaces/api/handlers/trash_handler.rs @@ -4,7 +4,7 @@ use axum::Json; use serde_json::json; use tracing::{debug, error, instrument}; -use crate::application::ports::trash_ports::TrashUseCase; +// use crate::application::ports::trash_ports::TrashUseCase; use crate::common::di::AppState; use crate::interfaces::middleware::auth::AuthUser; diff --git a/src/interfaces/api/handlers/webdav_handler.rs b/src/interfaces/api/handlers/webdav_handler.rs index f7f68d6..98bf8bf 100644 --- a/src/interfaces/api/handlers/webdav_handler.rs +++ b/src/interfaces/api/handlers/webdav_handler.rs @@ -15,7 +15,6 @@ use axum::{ }; use std::sync::Arc; use uuid::Uuid; -use http_body_util::BodyExt; use chrono::Utc; use bytes::Buf; @@ -28,7 +27,7 @@ use crate::common::errors::AppError; // Create a custom DAV header since it's not in the standard headers const HEADER_DAV: HeaderName = HeaderName::from_static("dav"); const HEADER_LOCK_TOKEN: HeaderName = HeaderName::from_static("lock-token"); -const HEADER_IF: HeaderName = HeaderName::from_static("if"); +// const HEADER_IF: HeaderName = HeaderName::from_static("if"); /** * Creates and returns the WebDAV router with all required endpoints. @@ -81,7 +80,7 @@ async fn handle_options( ) -> Result, AppError> { // Extract State and Path from request let parts = req.uri().path().split('/').collect::>(); - let path = if parts.len() > 2 { + let _path = if parts.len() > 2 { parts[2..].join("/") } else { "".to_string() @@ -313,10 +312,10 @@ async fn handle_proppatch( "".to_string() }; - let state = req.extensions().get::>().ok_or_else(|| { + let _state = req.extensions().get::>().ok_or_else(|| { AppError::internal_error("Missing AppState extension") })?; - let user = req.extensions().get::().ok_or_else(|| { + let _user = req.extensions().get::().ok_or_else(|| { AppError::unauthorized("Authentication required") })?; @@ -391,7 +390,7 @@ async fn handle_get( let state = req.extensions().get::>().ok_or_else(|| { AppError::internal_error("Missing AppState extension") })?; - let user = req.extensions().get::().ok_or_else(|| { + let _user = req.extensions().get::().ok_or_else(|| { AppError::unauthorized("Authentication required") })?; @@ -405,7 +404,7 @@ async fn handle_get( } // Get file metadata - let file = file_service.get_file_by_path(&path).await.map_err(|e| { + let file = file_service.get_file_by_path(&path).await.map_err(|_e| { AppError::not_found(format!("File not found: {}", path)) })?; @@ -654,7 +653,7 @@ async fn handle_delete( let state = req.extensions().get::>().ok_or_else(|| { AppError::internal_error("Missing AppState extension") })?; - let user = req.extensions().get::().ok_or_else(|| { + let _user = req.extensions().get::().ok_or_else(|| { AppError::unauthorized("Authentication required") })?; @@ -677,7 +676,7 @@ async fn handle_delete( })?; } else { // Try to delete file - let file = file_service.get_file_by_path(&path).await.map_err(|e| { + let file = file_service.get_file_by_path(&path).await.map_err(|_e| { AppError::not_found(format!("Resource not found: {}", path)) })?; @@ -718,7 +717,7 @@ async fn handle_move( let state = req.extensions().get::>().ok_or_else(|| { AppError::internal_error("Missing AppState extension") })?; - let user = req.extensions().get::().ok_or_else(|| { + let _user = req.extensions().get::().ok_or_else(|| { AppError::unauthorized("Authentication required") })?; @@ -779,7 +778,7 @@ async fn handle_move( } } else { // Try to move file - let file = file_service.get_file_by_path(&source_path).await.map_err(|e| { + let file = file_service.get_file_by_path(&source_path).await.map_err(|_e| { AppError::not_found(format!("Resource not found: {}", source_path)) })?; @@ -826,7 +825,7 @@ async fn handle_copy( let state = req.extensions().get::>().ok_or_else(|| { AppError::internal_error("Missing AppState extension") })?; - let user = req.extensions().get::().ok_or_else(|| { + let _user = req.extensions().get::().ok_or_else(|| { AppError::unauthorized("Authentication required") })?; @@ -884,7 +883,7 @@ async fn handle_copy( } }; - let new_folder = folder_service.create_folder(create_dto).await.map_err(|e| { + let _new_folder = folder_service.create_folder(create_dto).await.map_err(|e| { AppError::internal_error(format!("Failed to create destination folder: {}", e)) })?; @@ -908,7 +907,7 @@ async fn handle_copy( } } else { // Try to copy file - let file = file_service.get_file_by_path(&source_path).await.map_err(|e| { + let file = file_service.get_file_by_path(&source_path).await.map_err(|_e| { AppError::not_found(format!("Resource not found: {}", source_path)) })?; @@ -964,7 +963,7 @@ async fn handle_lock( }; // Get the state and user in a way that doesn't keep req borrowed - let state = { + let _state = { let state_ref = req.extensions().get::>().ok_or_else(|| { AppError::internal_error("Missing AppState extension") })?; @@ -1104,7 +1103,7 @@ async fn handle_unlock( ) -> Result, AppError> { // Clone all necessary data first to avoid borrow issues let uri = req.uri().clone(); - let path = { + let _path = { let parts = uri.path().split('/').collect::>(); if parts.len() > 2 { parts[2..].join("/") @@ -1135,7 +1134,7 @@ async fn handle_unlock( .ok_or_else(|| AppError::bad_request("Lock-Token header required"))?; // Extract token from header value (format: ) - let token = lock_token + let _token = lock_token .trim() .trim_start_matches('<') .trim_end_matches('>')