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>
11 KiB
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)
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
- Install dependencies:
composer install
- Create required directories:
mkdir -p uploads users metadata
chmod -R 775 uploads users metadata
- Set environment variables and start:
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)
- Root folder:
- 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 rulesmetadata/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()anddecryptData()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:
FileRiseFileandFileRiseDirectoryinsrc/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:
- Test with multiple user roles (admin, regular user, restricted user)
- Verify both UI and WebDAV respect the same rules
- Check inheritance behavior for nested folders
- Test edge cases: root folder, trash folder, special characters in paths
Adding New API Endpoints
- Create endpoint file in
public/api/(e.g.,public/api/myFeature.php) - Include config:
require_once __DIR__ . '/../../config/config.php'; - Check authentication:
if (empty($_SESSION['authenticated'])) { /* return 401 */ } - Perform ACL checks using
ACL::can*()methods before operations - Return JSON:
header('Content-Type: application/json'); echo json_encode($response);
Working with Metadata
Reading folder metadata:
require_once PROJECT_ROOT . '/src/models/FolderModel.php';
$meta = FolderModel::getFolderMeta($folderKey); // e.g., "root" or "invoices/2025"
Writing folder metadata:
FolderModel::saveFolderMeta($folderKey, $metaArray);
Rebuilding Metadata from Filesystem
If files are added/removed outside FileRise:
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
- Absolute:
Testing
FileRise does not currently have automated tests. When making changes:
- Test manually in browser UI
- Test WebDAV operations (if applicable)
- Test with different user permission levels
- Test ACL inheritance behavior
- Check error cases (invalid input, insufficient permissions, missing files)
CI/CD
GitHub Actions workflows (in .github/workflows/):
ci.yml- Basic CI checksrelease-on-version.yml- Automated releases when version changessync-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:
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.phpwhen logged in (Redoc interface) - OpenAPI spec:
openapi.json.dist