54eedf5483
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>
71 lines
3.0 KiB
HTML
71 lines
3.0 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Error - OxiCloud</title>
|
|
<link rel="stylesheet" href="/css/main.css">
|
|
<link rel="stylesheet" href="/css/views/auth.css">
|
|
</head>
|
|
<body>
|
|
<div class="auth-container">
|
|
<div class="auth-panel">
|
|
<div class="auth-logo">
|
|
<div class="auth-logo-icon">
|
|
<svg viewBox="0 0 500 500">
|
|
<path d="M345 310c32 0 58-26 58-58s-26-58-58-58c-6.2 0-12 0.9-17.5 2.7C318 166 289 143 255 143c-34.3 0-63.1 22.6-73 53.7C176.9 195.7 171 195 165 195c-32 0-58 26-58 58s26 58 58 58h180z" fill="#fff"/>
|
|
</svg>
|
|
</div>
|
|
<div class="auth-logo-text">OxiCloud</div>
|
|
</div>
|
|
|
|
<h2 class="auth-title" id="error-title">Error</h2>
|
|
<div class="auth-error">
|
|
<i class="fas fa-exclamation-circle"></i>
|
|
<span id="error-message">An error occurred. Please try again.</span>
|
|
</div>
|
|
|
|
<div style="margin-top: 20px;">
|
|
<button type="button" class="auth-button" id="error-action">Try Again</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Read error type from URL query parameter
|
|
const params = new URLSearchParams(window.location.search);
|
|
const errorType = params.get('type') || 'generic';
|
|
|
|
const errorTitle = document.getElementById('error-title');
|
|
const errorMessage = document.getElementById('error-message');
|
|
const errorAction = document.getElementById('error-action');
|
|
|
|
switch(errorType) {
|
|
case 'invalid-credentials':
|
|
errorTitle.textContent = 'Login Failed';
|
|
errorMessage.textContent = 'Invalid username or password. Please check your credentials and try again.';
|
|
errorAction.textContent = 'Try Again';
|
|
errorAction.onclick = () => history.back();
|
|
break;
|
|
case 'session-expired':
|
|
errorTitle.textContent = 'Session Expired';
|
|
errorMessage.textContent = 'Your session has expired. Please try again.';
|
|
errorAction.textContent = 'Close Window';
|
|
errorAction.onclick = () => window.close();
|
|
break;
|
|
case 'not-found':
|
|
errorTitle.textContent = 'Not Found';
|
|
errorMessage.textContent = 'The requested page was not found.';
|
|
errorAction.textContent = 'Close Window';
|
|
errorAction.onclick = () => window.close();
|
|
break;
|
|
default:
|
|
errorTitle.textContent = 'Error';
|
|
errorMessage.textContent = 'An unexpected error occurred. Please try again.';
|
|
errorAction.textContent = 'Close Window';
|
|
errorAction.onclick = () => window.close();
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|