Files
FileRise/CLAUDE.md
Joachim Hummel e0de36e734
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
Add CLAUDE.md with comprehensive codebase documentation
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>
2025-12-07 01:17:05 +00:00

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

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:
composer install
  1. Create required directories:
mkdir -p uploads users metadata
chmod -R 775 uploads users metadata
  1. 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)
  • 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:

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

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:

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