feat(nextcloud): add Nextcloud-compatible API layer
Implement a complete Nextcloud client compatibility layer so that Nextcloud desktop/mobile sync clients can connect to OxiCloud. Key additions: - Login Flow v2 (device auth) with OIDC bridge support - WebDAV handler compatible with Nextcloud clients (PROPFIND, GET, PUT, DELETE, MKCOL, MOVE, COPY, HEAD, PROPPATCH) - OCS API endpoints (user info, capabilities, notifications stubs, sharees, unified search) - Basic Auth middleware with app password verification, account lockout integration, and blake3-keyed auth cache - App password management: create, list, revoke via both native API (JWT-authenticated profile page) and Nextcloud OCS endpoints - Nextcloud file ID mapping (oc:fileid) with persistent DB storage - Chunked upload support (Nextcloud v2 chunking protocol) - Trashbin WebDAV interface - Avatar (SVG placeholder) and preview (redirect) handlers - User profile page with app password management UI - URL user validation on all DAV routes (403 on mismatch) - Database schema for app_passwords and nextcloud_object_ids tables All services are behind a `nextcloud.enabled` config flag and cleanly separated under src/interfaces/nextcloud/. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -120,6 +120,62 @@ pub enum LockType {
|
||||
Write,
|
||||
}
|
||||
|
||||
/// Extra property context for Nextcloud/ownCloud WebDAV extensions.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct NextcloudPropContext {
|
||||
pub file_id: Option<i64>,
|
||||
pub oc_id: Option<String>,
|
||||
pub owner_id: Option<String>,
|
||||
pub owner_display_name: Option<String>,
|
||||
pub permissions: String,
|
||||
pub size: u64,
|
||||
pub has_preview: bool,
|
||||
pub is_encrypted: bool,
|
||||
pub mount_type: String,
|
||||
pub contained_file_count: u64,
|
||||
pub contained_folder_count: u64,
|
||||
}
|
||||
|
||||
impl NextcloudPropContext {
|
||||
pub fn for_folder(
|
||||
file_id: Option<i64>,
|
||||
oc_id: Option<String>,
|
||||
owner: &str,
|
||||
contained_files: u64,
|
||||
contained_folders: u64,
|
||||
) -> Self {
|
||||
Self {
|
||||
file_id,
|
||||
oc_id,
|
||||
owner_id: Some(owner.to_string()),
|
||||
owner_display_name: Some(owner.to_string()),
|
||||
permissions: "RGDNVCK".to_string(),
|
||||
size: 0,
|
||||
has_preview: false,
|
||||
is_encrypted: false,
|
||||
mount_type: "dir".to_string(),
|
||||
contained_file_count: contained_files,
|
||||
contained_folder_count: contained_folders,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_file(file_id: Option<i64>, oc_id: Option<String>, owner: &str, size: u64) -> Self {
|
||||
Self {
|
||||
file_id,
|
||||
oc_id,
|
||||
owner_id: Some(owner.to_string()),
|
||||
owner_display_name: Some(owner.to_string()),
|
||||
permissions: "RGDNVW".to_string(),
|
||||
size,
|
||||
has_preview: false,
|
||||
is_encrypted: false,
|
||||
mount_type: "file".to_string(),
|
||||
contained_file_count: 0,
|
||||
contained_folder_count: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// WebDAV adapter for converting between XML and domain objects
|
||||
pub struct WebDavAdapter;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user