# CloudVault – cPanel Deployment Guide

This document explains how to deploy CloudVault to a shared cPanel host where
the application lives in a subfolder of `public_html` and is reached through a
URL like `https://yourdomain.com/<subfolder>/public/...`.

It also documents the recent changes that make the app work correctly when
mounted under a sub-path.

---

## 1. Server layout assumed by this guide

The application is uploaded to the server with this structure:

```
public_html/
└── <subfolder>/                e.g. cloudvault
    ├── app/                    (PHP application code)
    ├── database/               (SQL migrations)
    ├── routes/                 (web.php, api.php)
    ├── storage/                (files/, temp/, logs/, thumbnails/, versions/)
    ├── views/                  (PHP/HTML views)
    ├── install.php             (CLI installer)
    ├── .env                    (environment variables — keep outside web root)
    ├── .installed              (created by installer)
    └── public/                 ← THIS FOLDER IS THE WEB DOCUMENT ROOT
        ├── index.php
        ├── .htaccess
        └── assets/             (CSS / JS)
```

How the web points at it:

- **Option A (most common on cPanel with no subdomain):** Point a subdomain
  (e.g. `cloud.yourdomain.com`) at `<subfolder>/public/`. Visitors reach the
  app at `https://cloud.yourdomain.com/...`.
- **Option B (path-based):** Keep using `https://yourdomain.com/<subfolder>/public/...`
  directly. The application detects the URL prefix automatically.

Both options work without code changes — `public/index.php` calculates the
prefix from `$_SERVER['SCRIPT_NAME']` and exposes it as `BASE_URL`.

---

## 2. Files changed for sub-path support

The following files were updated so the application works correctly when
mounted at any URL prefix (e.g. `/cloudvault/public`):

| File | Change |
|---|---|
| `public/index.php` | Detects the URL prefix from `SCRIPT_NAME`, defines `BASE_URL`, and strips the prefix from the incoming URI before dispatch. |
| `routes/web.php` | The `/` route now redirects to `BASE_URL . '/login'` so the post-login redirect works on shared hosting. |
| `views/login.php` | Loads CSS via `BASE_URL`, exposes `window.CV.baseUrl` to JS, and posts to `BASE_URL + '/api/auth/login'`. After login it redirects to `BASE_URL + '/'`. |
| `views/app.php` | Loads CSS and JS through `BASE_URL` and injects `window.CV.baseUrl` for the front-end. |
| `public/assets/js/app.js` | All `fetch()` calls use a helper `window.apiUrl(path) = baseUrl + path`. The base is auto-detected from the current path as a fallback if the inline `<script>` is missing. |
| `app/Controllers/ShareController.php` | Generated share URLs use `BASE_URL` so the public link works on a sub-path. |

The constant `BASE_URL` is:

- `''` (empty) when the app is mounted at the web root.
- `'/cloudvault/public'` (or similar) when mounted in a subfolder.

Every redirect, link, CSS/JS reference, and API call flows through this
constant — no hard-coded paths remain.

---

## 3. One-time cPanel setup

### 3.1 Verify PHP version
cPanel → *MultiPHP Manager* → set the domain/subdomain to **PHP 8.2+**.
Required extensions (usually enabled by default): `pdo_mysql`, `fileinfo`,
`openssl`, `mbstring`, `gd`, `json`.

### 3.2 Create the database
cPanel → *MySQL® Databases*:
1. Create database `<cpaneluser>_cloudvault`.
2. Create user `<cpaneluser>_dbadmin` with a strong password.
3. Add the user to the database with **All Privileges**.

### 3.3 Upload files
- Compress everything in the project (excluding `.git`, `node_modules`, `vendor`)
  and upload the archive to `public_html/<subfolder>/` via File Manager or FTP.
- Extract in place. The directory layout should match §1.

### 3.4 Storage permissions
Set permissions on the storage subfolders so the web user can write:
```
storage/             755
storage/files/       755
storage/temp/        755
storage/logs/        755
storage/thumbnails/  755
storage/versions/    755
```
In File Manager: select each folder → *Permissions* → 755 → Recurse.

### 3.5 Configure `.env`
Edit `public_html/<subfolder>/.env`:
```
APP_NAME=CloudVault
APP_ENV=production
APP_DEBUG=false
APP_URL=https://yourdomain.com
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=<cpaneluser>_cloudvault
DB_USERNAME=<cpaneluser>_dbadmin
DB_PASSWORD=<your password>
STORAGE_DRIVER=local
JWT_SECRET=<paste a 64-char random string>
```

> **DB host:** On cPanel shared hosting, `localhost` often does **not** work.
> Use `127.0.0.1` first; if that fails, try the host's MySQL hostname shown in
> the cPanel *MySQL® Databases* page (e.g. `localhost:/tmp/mysql.sock` is
> usually resolved by PDO, but `127.0.0.1` is the most reliable choice).

### 3.6 Run the installer
In cPanel → *Terminal* (or SSH):
```bash
cd ~/public_html/<subfolder>
php install.php
```
Expected output:
```
[OK] Database connection established.
[OK] Database schema applied.
[OK] Default roles seeded.
[OK] Default permissions seeded.
[OK] Role-permission mappings seeded.
[OK] Default admin created: admin@cloudvault.local / Admin@123
[OK] Created directory: ...
[DONE] Installation complete!
```

If the script stops mid-way (often the admin line), the cause is usually that
the schema or default roles haven't been written yet. The script is
idempotent — run it again.

If the admin user is missing after install, insert manually via phpMyAdmin:
```sql
UPDATE users
SET password_hash = '<paste bcrypt hash here>',
    status = 'active'
WHERE email = 'admin@cloudvault.local';
```
Generate a hash with:
```bash
php -r "echo password_hash('Admin@123', PASSWORD_DEFAULT);"
```

### 3.7 Point the subdomain (optional)
cPanel → *Subdomains* → set the document root to
`public_html/<subfolder>/public`. With the sub-path option (Option B), skip
this step.

### 3.8 Force HTTPS (recommended)
At the project root (`public_html/<subfolder>/`), create a `.htaccess`:
```apache
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
```
The `public/.htaccess` already exists and forwards non-file requests to
`index.php`.

---

## 4. How `BASE_URL` is computed

In `public/index.php`:
```php
$scriptName = str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'] ?? ''));
define('BASE_URL', $scriptName === '/' || $scriptName === '' ? '' : rtrim($scriptName, '/'));
```

Examples:

| App URL                              | `SCRIPT_NAME`           | `BASE_URL`              |
|--------------------------------------|-------------------------|-------------------------|
| `https://example.com/`               | `/index.php`            | `''`                    |
| `https://example.com/cloudvault/public/` | `/cloudvault/public/index.php` | `/cloudvault/public` |
| `https://cloud.example.com/`         | `/index.php`            | `''`                    |

The dispatcher also strips the prefix from `REQUEST_URI` so the routes
defined as `/login`, `/api/auth/login`, etc. resolve to the same handler
regardless of the mount path.

---

## 5. Re-deploying after changes

For incremental updates, you only need to upload the files you actually
modified. The most common ones for this sub-path fix are:

```
public/index.php
public/.htaccess
public/assets/js/app.js
public/assets/css/style.css
routes/web.php
routes/api.php
views/login.php
views/app.php
views/install.php
views/share_password.php
views/share_view.php
app/Controllers/ShareController.php
app/Controllers/FileController.php
app/Controllers/NotificationController.php
```

No `vendor/` or `composer install` step is required — CloudVault uses only
the PHP standard library.

---

## 6. Troubleshooting

| Symptom | Likely cause | Fix |
|---|---|---|
| Blank page or 500 | PHP version < 8.2 or missing `pdo_mysql` | Switch to PHP 8.2 in MultiPHP Manager |
| `Database connection failed` | Wrong host/credentials | Set `DB_HOST=127.0.0.1`, recheck user/db names (cPanel prefixes them with your account name) |
| Login redirects to `/login` (wrong path) | Old `routes/web.php` (pre-fix) | Re-upload the updated `routes/web.php` and `public/index.php` |
| CSS/JS 404 | Browser cached old `app.php` | Hard refresh (Ctrl+Shift+R) |
| `CSRF token mismatch` | Old session token | Log out and back in to get a fresh token |
| Cannot upload large files | `upload_max_filesize` too small | Edit `public_html/<subfolder>/php.ini` (create if missing): `upload_max_filesize = 200M; post_max_size = 220M;` |
| Installer stops after `[OK] Role-permission mappings seeded.` | Schema FK constraint or partial state | Re-run `php install.php`; it is idempotent |

---

## 7. Default login

- **Email:** `admin@cloudvault.local`
- **Password:** `Admin@123`

Change the password immediately after first login. To change it directly in
the database:

```sql
UPDATE users
SET password_hash = '<new bcrypt hash>'
WHERE email = 'admin@cloudvault.local';
```

Generate a hash with:
```bash
php -r "echo password_hash('NewPasswordHere', PASSWORD_DEFAULT);"
```
