Add CLAUDE.md with comprehensive codebase documentation
Some checks failed
CI / php-lint (8.1) (push) Has been cancelled
CI / php-lint (8.2) (push) Has been cancelled
CI / php-lint (8.3) (push) Has been cancelled
CI / shellcheck (push) Has been cancelled
CI / dockerfile-lint (push) Has been cancelled
CI / sanity (push) Has been cancelled
Some checks failed
CI / php-lint (8.1) (push) Has been cancelled
CI / php-lint (8.2) (push) Has been cancelled
CI / php-lint (8.3) (push) Has been cancelled
CI / shellcheck (push) Has been cancelled
CI / dockerfile-lint (push) Has been cancelled
CI / sanity (push) Has been cancelled
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 <noreply@anthropic.com>
This commit is contained in:
288
CLAUDE.md
Normal file
288
CLAUDE.md
Normal file
@@ -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`
|
||||||
Reference in New Issue
Block a user