From e0de36e734333f80fb128f7865e1bd8f71c4918c Mon Sep 17 00:00:00 2001 From: Joachim Hummel Date: Sun, 7 Dec 2025 01:17:05 +0000 Subject: [PATCH] Add CLAUDE.md with comprehensive codebase documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added detailed guidance for Claude Code including: - Project overview and tech stack - Development setup instructions - Architecture and directory structure - ACL system and metadata patterns - Common development tasks - Code conventions and security requirements 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- CLAUDE.md | 288 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..2f1df6f --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,288 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +FileRise is a self-hosted web file manager / WebDAV server built with PHP 8.3+. It provides drag-and-drop uploads, granular ACL-based permissions, ONLYOFFICE integration, WebDAV support, and OIDC authentication. No external database is required - all data is stored in JSON files. + +**Tech Stack:** +- Backend: PHP 8.3+ (no framework) +- Frontend: Vanilla JavaScript, Bootstrap 4.5.2 +- WebDAV: sabre/dav +- Dependencies: Composer (see composer.json) + +## Development Setup + +### Running Locally (Docker - Recommended) + +```bash +docker compose up -d +``` + +The docker-compose.yml file is configured for development. FileRise will be available at http://localhost:8080. + +### Running with PHP Built-in Server + +1. Install dependencies: +```bash +composer install +``` + +2. Create required directories: +```bash +mkdir -p uploads users metadata +chmod -R 775 uploads users metadata +``` + +3. Set environment variables and start: +```bash +export TIMEZONE="America/New_York" +export TOTAL_UPLOAD_SIZE="10G" +export SECURE="false" +export PERSISTENT_TOKENS_KEY="dev_key_please_change" +php -S localhost:8080 -t public/ +``` + +## Architecture + +### Directory Structure + +``` +FileRise/ +├── config/ +│ └── config.php # Global configuration, session handling, encryption +├── src/ +│ ├── controllers/ # Business logic for each feature area +│ │ ├── FileController.php # File operations (download, preview, share) +│ │ ├── FolderController.php # Folder operations (create, move, copy, delete) +│ │ ├── UserController.php # User management +│ │ ├── AuthController.php # Authentication (login, OIDC, TOTP) +│ │ ├── AdminController.php # Admin panel operations +│ │ ├── AclAdminController.php # ACL management +│ │ ├── UploadController.php # File upload handling +│ │ ├── MediaController.php # Media preview/streaming +│ │ ├── OnlyOfficeController.php # ONLYOFFICE document editing +│ │ └── PortalController.php # Client portal (Pro feature) +│ ├── models/ # Data access layer +│ │ ├── UserModel.php +│ │ ├── FolderModel.php +│ │ ├── FolderMeta.php +│ │ ├── MediaModel.php +│ │ └── AdminModel.php +│ ├── lib/ # Core libraries +│ │ ├── ACL.php # Central ACL enforcement (read, write, upload, share, etc.) +│ │ └── FS.php # Filesystem utilities and safety checks +│ ├── webdav/ # WebDAV implementation (using sabre/dav) +│ │ ├── FileRiseFile.php +│ │ ├── FileRiseDirectory.php +│ │ └── CurrentUser.php +│ ├── cli/ # CLI utilities +│ └── openapi/ # OpenAPI spec generation +├── public/ # Web root (served by Apache/Nginx) +│ ├── index.html # Main SPA entry point +│ ├── api.php # API documentation viewer +│ ├── webdav.php # WebDAV endpoint +│ ├── api/ # API endpoints (called by frontend) +│ │ ├── *.php # Individual API endpoints +│ │ └── pro/ # Pro-only API endpoints +│ ├── js/ # Frontend JavaScript +│ ├── css/ # Stylesheets +│ ├── vendor/ # Client-side libraries (Bootstrap, CodeMirror, etc.) +│ └── .htaccess # Apache rewrite rules +├── scripts/ +│ └── scan_uploads.php # CLI tool to rebuild metadata from filesystem +├── uploads/ # User file storage (created at runtime) +├── users/ # User data, permissions, tokens (created at runtime) +└── metadata/ # File metadata, tags, shares, ACLs (created at runtime) +``` + +### Key Architectural Patterns + +#### 1. ACL System (src/lib/ACL.php) + +The ACL class is the **single source of truth** for all permission checks. It manages folder-level permissions with inheritance: + +- **Buckets**: owners, read, write, share, read_own, create, upload, edit, rename, copy, move, delete, extract, share_file, share_folder +- **Enforcement**: All controllers MUST call ACL methods (e.g., `ACL::canRead()`, `ACL::canWrite()`) before performing operations +- **Storage**: Permissions stored in `metadata/folder_acl.json` +- **Inheritance**: When a user is granted permissions on a folder, they typically have access to subfolders unless explicitly restricted + +#### 2. Metadata System + +FileRise stores metadata in JSON files rather than a database: + +- **Per-folder metadata**: `metadata/{folder_key}_metadata.json` + - Root folder: `root_metadata.json` + - Subfolder "invoices/2025": `invoices-2025_metadata.json` (slashes/spaces replaced with hyphens) +- **Global metadata**: + - `users/users.txt` - User credentials (bcrypt hashed) + - `users/userPermissions.json` - Per-user settings (encrypted) + - `users/persistent_tokens.json` - "Remember me" tokens (encrypted) + - `users/adminConfig.json` - Admin settings (encrypted) + - `metadata/folder_acl.json` - All ACL rules + - `metadata/folder_owners.json` - Folder ownership tracking + +#### 3. Encryption + +Sensitive data is encrypted using AES-256-CBC with the `PERSISTENT_TOKENS_KEY` environment variable: +- Functions: `encryptData()` and `decryptData()` in config/config.php +- Encrypted files: userPermissions.json, persistent_tokens.json, adminConfig.json, proLicense.json + +#### 4. Session Management + +- PHP sessions with configurable lifetime (default: 2 hours) +- "Remember me" tokens stored separately with 30-day expiry +- Session regeneration on login to prevent fixation attacks +- Proxy authentication bypass mode (AUTH_BYPASS) for SSO integration + +#### 5. WebDAV Integration + +The WebDAV endpoint (`public/webdav.php`) uses sabre/dav with custom node classes: +- `FileRiseFile` and `FileRiseDirectory` in `src/webdav/` +- **All WebDAV operations respect ACL rules** via the same ACL class +- Authentication via HTTP Basic Auth or proxy headers + +#### 6. Pro Features + +FileRise has a Pro version with additional features loaded dynamically: +- Pro bundle located in `users/pro/` (configurable via FR_PRO_BUNDLE_DIR) +- Bootstrap file: `users/pro/bootstrap_pro.php` +- License validation sets FR_PRO_ACTIVE constant +- Pro endpoints in `public/api/pro/` + +## Common Development Tasks + +### Testing ACL Changes + +When modifying ACL logic: + +1. Test with multiple user roles (admin, regular user, restricted user) +2. Verify both UI and WebDAV respect the same rules +3. Check inheritance behavior for nested folders +4. Test edge cases: root folder, trash folder, special characters in paths + +### Adding New API Endpoints + +1. Create endpoint file in `public/api/` (e.g., `public/api/myFeature.php`) +2. Include config: `require_once __DIR__ . '/../../config/config.php';` +3. Check authentication: `if (empty($_SESSION['authenticated'])) { /* return 401 */ }` +4. Perform ACL checks using `ACL::can*()` methods before operations +5. Return JSON: `header('Content-Type: application/json'); echo json_encode($response);` + +### Working with Metadata + +Reading folder metadata: +```php +require_once PROJECT_ROOT . '/src/models/FolderModel.php'; +$meta = FolderModel::getFolderMeta($folderKey); // e.g., "root" or "invoices/2025" +``` + +Writing folder metadata: +```php +FolderModel::saveFolderMeta($folderKey, $metaArray); +``` + +### Rebuilding Metadata from Filesystem + +If files are added/removed outside FileRise: + +```bash +php scripts/scan_uploads.php +``` + +This rebuilds all `*_metadata.json` files by scanning the uploads directory. + +### Running in Docker + +The Dockerfile and start.sh handle: +- Setting PHP configuration (upload limits, timezone) +- Running scan_uploads.php if SCAN_ON_START=true +- Fixing permissions if CHOWN_ON_START=true +- Starting Apache + +Environment variables are processed in config/config.php (falls back to constants if not set). + +## Code Conventions + +### File Organization + +- Controllers handle HTTP requests and orchestrate business logic +- Models handle data persistence (JSON file I/O) +- ACL class is the **only** place for permission logic - never duplicate ACL checks +- FS class provides filesystem utilities and path safety checks + +### Security Requirements + +- **Always validate user input** - use regex patterns from config.php (REGEX_FILE_NAME, REGEX_FOLDER_NAME) +- **Always check ACLs** before file/folder operations +- **Always use FS::safeReal()** to prevent path traversal via symlinks +- **Never trust client-provided paths** - validate and sanitize all paths +- **Use CSRF tokens** for state-changing operations (token in $_SESSION['csrf_token']) +- **Sanitize output** when rendering user content (especially in previews) + +### Error Handling + +- Return appropriate HTTP status codes (401 Unauthorized, 403 Forbidden, 404 Not Found, 500 Internal Server Error) +- Log errors using `error_log()` for debugging +- Return user-friendly JSON error messages + +### Path Handling + +- Use DIRECTORY_SEPARATOR for cross-platform compatibility +- Always normalize folder keys with `ACL::normalizeFolder()` +- Convert between absolute paths and folder keys consistently: + - Absolute: `/var/www/uploads/invoices/2025/` + - Folder key: `invoices/2025` (relative to uploads, forward slashes) + - Root folder key: `root` + +## Testing + +FileRise does not currently have automated tests. When making changes: + +1. Test manually in browser UI +2. Test WebDAV operations (if applicable) +3. Test with different user permission levels +4. Test ACL inheritance behavior +5. Check error cases (invalid input, insufficient permissions, missing files) + +## CI/CD + +GitHub Actions workflows (in `.github/workflows/`): +- `ci.yml` - Basic CI checks +- `release-on-version.yml` - Automated releases when version changes +- `sync-changelog.yml` - Changelog synchronization + +## Important Notes + +- **No ORM/framework**: This is vanilla PHP - all database operations are manual JSON file I/O +- **Session-based auth**: Not JWT - sessions stored server-side, persistent tokens for "remember me" +- **Metadata consistency**: If you modify files directly, run scan_uploads.php to rebuild metadata +- **ACL is central**: Never bypass ACL checks - all file operations must go through ACL validation +- **Encryption key**: PERSISTENT_TOKENS_KEY must be set in production (default is insecure) +- **Pro features**: Some functionality is dynamically loaded from the Pro bundle - check FR_PRO_ACTIVE before calling Pro code + +## Performance Considerations + +- FileRise is designed to scale to **100k+ folders** in the sidebar tree +- Metadata files are loaded on-demand (not all at once) +- Large directory scans use scandir() with filtering - avoid recursive operations when possible +- WebDAV PROPFIND operations should be optimized (limit depth) + +## Debugging + +Enable PHP error reporting in development: +```php +ini_set('display_errors', '1'); +error_reporting(E_ALL); +``` + +Check logs: +- Apache error log: `/var/log/apache2/error.log` (or similar) +- PHP error_log() output: check Docker logs with `docker logs filerise` + +## Documentation + +- Main docs: GitHub Wiki at https://github.com/error311/FileRise/wiki +- API docs: Available at `/api.php` when logged in (Redoc interface) +- OpenAPI spec: `openapi.json.dist`