diff --git a/.gitignore b/.gitignore index 43b07d9..0ac9fc0 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ Thumbs.db # IDE .vscode/ .idea/ + diff --git a/admin/.gitignore b/admin/.gitignore deleted file mode 100644 index ce8c210..0000000 --- a/admin/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -# Test database -test.db - -# Error logs -error.log - -# Uploaded files (for testing) -data/theses/ -data/covers/ - -# Keep the data directories but ignore contents -!data/theses/.gitkeep -!data/covers/.gitkeep - -# PHP session files -sessions/ - -# Composer -vendor/ -composer.lock - -# OS files -.DS_Store -Thumbs.db - -# IDE -.vscode/ -.idea/ -*.swp -*.swo -*~ diff --git a/admin/data/cover/Théophile Gervreau-Mercier_2024_.png b/admin/data/cover/Théophile Gervreau-Mercier_2024_.png deleted file mode 100644 index 0a109c4..0000000 Binary files a/admin/data/cover/Théophile Gervreau-Mercier_2024_.png and /dev/null differ diff --git a/config/bootstrap.php b/config/bootstrap.php new file mode 100644 index 0000000..714f04b --- /dev/null +++ b/config/bootstrap.php @@ -0,0 +1,35 @@ + +``` + +--- + +## Migration Checklist + +- [ ] `just setup-server` - Create server directory +- [ ] `just deploy` - Deploy application +- [ ] `just deploy-nginx` - Update nginx config +- [ ] SSH to server and apply nginx config +- [ ] `sudo systemctl reload nginx` +- [ ] Verify site works: https://posterg.erg.be/ +- [ ] Verify security: https://posterg.erg.be/database/test.db → 404 +- [ ] Test admin: https://posterg.erg.be/admin/ +- [ ] Deploy database (if needed): `just deploy-database` + +--- + +## Commands Reference + +| Command | Purpose | +|---------|---------| +| `just setup-server` | Create `/var/www/posterg/` (first time only) | +| `just deploy` | Deploy application files | +| `just deploy-nginx` | Update nginx configuration | +| `just deploy-database` | Deploy database file | +| `just server-status` | Check server health | +| `just server-logs` | View server logs | + +--- + +## Directory Structure on Server + +``` +/var/www/posterg/ # Application root (private) +├── public/ # DocumentRoot (nginx points here) +│ ├── index.php +│ ├── search.php +│ ├── memoire.php +│ ├── admin/ +│ └── assets/ +├── includes/ # Templates (private) +├── config/ # Configuration (private) +├── database/ # Database (private) +├── lib/ # PHP classes (private) +└── vendor/ # Dependencies (private) +``` + +**Nginx DocumentRoot:** `/var/www/posterg/public/` + +Only the `public/` directory is accessible via web browser. Everything else is private. diff --git a/DIRECTORY_STRUCTURE.md b/docs/DIRECTORY_STRUCTURE.md similarity index 100% rename from DIRECTORY_STRUCTURE.md rename to docs/DIRECTORY_STRUCTURE.md diff --git a/MIGRATION_CHECKLIST.md b/docs/MIGRATION_CHECKLIST.md similarity index 100% rename from MIGRATION_CHECKLIST.md rename to docs/MIGRATION_CHECKLIST.md diff --git a/docs/MIGRATION_COMPLETE.md b/docs/MIGRATION_COMPLETE.md new file mode 100644 index 0000000..5c597b3 --- /dev/null +++ b/docs/MIGRATION_COMPLETE.md @@ -0,0 +1,214 @@ +# ✅ Migration to public/ Directory Structure - COMPLETE + +## 📊 Summary of Changes + +### Directory Structure Created +``` +posterg-website/ +├── config/ # ✅ NEW - Configuration files +│ └── bootstrap.php # Central path management +├── public/ # ✅ NEW - DocumentRoot (web-accessible) +│ ├── admin/ # Moved from /admin/ +│ ├── assets/ # Moved from /assets/ +│ ├── index.php # Moved from /index.php +│ ├── search.php # Moved from /search.php +│ └── memoire.php # Moved from /memoire.php +├── resources/ # ✅ NEW - Application resources +│ └── views/ # Moved from /inc/ +│ ├── header.php +│ └── footer.php +├── var/ # ✅ NEW - Runtime files +│ ├── cache/ +│ ├── logs/ +│ └── tmp/ +├── database/ # ✅ KEPT - Now private +├── lib/ # ✅ KEPT - Now private +├── vendor/ # ✅ KEPT - Now private +└── tests/ # ✅ KEPT - Now private +``` + +### Files Modified + +**1. config/bootstrap.php** (NEW) +- Central path configuration +- Defines APP_ROOT, PUBLIC_ROOT, DATABASE_PATH, etc. +- Helper functions: view(), getDatabase() +- Environment detection (dev vs production) +- Error handling configuration + +**2. public/*.php** (3 files updated) +- index.php: Uses bootstrap, updated require paths +- search.php: Uses bootstrap, updated require paths +- memoire.php: Uses bootstrap, updated require paths +- All now use view() helper for header/footer + +**3. public/admin/*.php** (7 files updated) +- add.php, edit.php, formulaire.php, import.php +- index.php, publish.php, thanks.php +- All updated to use ../../ paths for lib access +- Bootstrap added where needed + +**4. justfile** (Updated) +- Dev server: `php -S 127.0.0.1:8000 -t public/` +- Deploy: Now deploys to `/var/www/posterg/` +- Database deploy: Updated paths to `/var/www/posterg/` +- Nginx deploy: Checks for correct DocumentRoot + +**5. nginx/posterg.conf** (Updated) +- DocumentRoot: `/var/www/html` → `/var/www/posterg/public` +- Admin location: `/formulaire/` → `/admin/` + +**6. .gitignore** (Updated) +- Added var/ directory patterns +- Keeps .gitkeep files, ignores contents + +### Security Improvements + +**Before:** +- ❌ All files in DocumentRoot (/var/www/html/) +- ❌ Database accessible at /database/test.db +- ❌ Config files accessible +- ❌ Dev server exposed everything +- ❌ Relied on nginx deny rules + +**After:** +- ✅ Only public/ in DocumentRoot +- ✅ Database physically outside web root +- ✅ Config files physically private +- ✅ Dev server matches production security +- ✅ Physical separation = secure by default + +## 🧪 Testing + +### Local Development +```bash +# Start dev server +just serve + +# Test in browser: +# - http://localhost:8000/ → Should work +# - http://localhost:8000/admin/ → Should work +# - http://localhost:8000/database/test.db → Should 404 ✅ +# - http://localhost:8000/config/ → Should 404 ✅ +# - http://localhost:8000/../database/test.db → Should 404 ✅ +``` + +### Security Verification +```bash +# These should all return 404: +curl http://localhost:8000/database/test.db +curl http://localhost:8000/config/bootstrap.php +curl http://localhost:8000/vendor/autoload.php +curl http://localhost:8000/../database/test.db +curl http://localhost:8000/lib/Database.php +``` + +### Production Deployment + +**BEFORE deploying to production:** + +1. **Update nginx config on server:** + ```bash + # Edit /etc/nginx/sites-available/posterg + # Change: root /var/www/html; + # To: root /var/www/posterg/public; + ``` + +2. **Create new directory on server:** + ```bash + ssh posterg "sudo mkdir -p /var/www/posterg" + ``` + +3. **Deploy application:** + ```bash + just deploy + ``` + +4. **Deploy nginx config:** + ```bash + just deploy-nginx + # Then on server: + ssh posterg + sudo bash /tmp/deploy-production.sh + sudo systemctl reload nginx + ``` + +5. **Verify:** + ```bash + just server-status + curl -I https://posterg.erg.be/ + curl -I https://posterg.erg.be/admin/ + curl -I https://posterg.erg.be/database/test.db # Must 404! + ``` + +## 📝 Path Reference + +### From public/*.php files: +```php + 'Title']); // Template +``` + +### From public/admin/*.php files: +```php + + +# Or abandon current changes +jj abandon @ +``` + +## 📚 Documentation + +See also: +- `DIRECTORY_STRUCTURE.md` - Full structure reference +- `DEPLOYMENT_MIGRATION.md` - Detailed migration guide +- `MIGRATION_CHECKLIST.md` - Quick checklist + +## ✨ Benefits Achieved + +1. **Security**: Private files physically separated from public +2. **Standards**: Follows PHP-FIG and Standard PHP Package Skeleton +3. **Development**: Dev server matches production security +4. **Maintainability**: Clear separation of concerns +5. **Portability**: Path constants make relocation easy +6. **Best Practices**: Industry-standard directory structure diff --git a/docs/SERVER_SETUP.md b/docs/SERVER_SETUP.md new file mode 100644 index 0000000..793f9d5 --- /dev/null +++ b/docs/SERVER_SETUP.md @@ -0,0 +1,118 @@ +# Server Setup (Manual) + +Since sudo prompts don't work over SSH in justfile, do the initial setup manually. + +## One-Time Setup on Server + +```bash +# 1. SSH to server +ssh posterg + +# 2. Backup current site (recommended) +sudo cp -r /var/www/html /var/www/html.backup + +# 3. Create new directory structure +sudo mkdir -p /var/www/posterg + +# 4. Set ownership (www-data is the web server user) +sudo chown www-data:posterg /var/www/posterg + +# 5. Set permissions (775 = rwxrwxr-x) +sudo chmod 775 /var/www/posterg + +# 6. Verify +ls -ld /var/www/posterg +# Should show: drwxrwxr-x 2 www-data posterg 4096 ... /var/www/posterg + +# 7. Exit server +exit +``` + +## Deploy from Local Machine + +```bash +just deploy +``` + +## Complete Deployment Process + +```bash +# On server (one time) +ssh posterg +sudo mkdir -p /var/www/posterg +sudo chown www-data:posterg /var/www/posterg +sudo chmod 775 /var/www/posterg +exit + +# From local machine +just deploy # Deploy files +just deploy-nginx # Update nginx config + +# On server - apply nginx config +ssh posterg +sudo bash /tmp/deploy-production.sh +sudo systemctl reload nginx +exit + +# Verify from local +just server-status +``` + +## Important Notes + +- **Don't delete `/var/www/html/` yet!** Keep it as backup until you confirm the new structure works +- The new structure uses `/var/www/posterg/public/` as DocumentRoot +- Nginx must be updated to point to the new location + +## After Confirming Everything Works + +Once you've verified the new deployment works: + +```bash +ssh posterg +sudo rm -rf /var/www/html.backup # Remove backup if no longer needed +sudo rm -rf /var/www/html # Remove old directory +``` + +## Directory Structure on Server + +``` +/var/www/ +├── html/ ← OLD (keep as backup for now) +├── html.backup/ ← BACKUP (can delete later) +└── posterg/ ← NEW + ├── public/ ← DocumentRoot (nginx serves from here) + ├── includes/ + ├── config/ + ├── database/ + ├── lib/ + └── vendor/ +``` + +## Troubleshooting + +### Permission denied during deploy +**Cause:** Directory doesn't exist or has wrong ownership +**Fix:** Run the setup commands above + +### Nginx 403 Forbidden +**Cause:** Wrong permissions on files +**Fix:** +```bash +ssh posterg +cd /var/www/posterg +sudo chown -R www-data:posterg . +sudo find . -type d -exec chmod 755 {} \; +sudo find . -type f -exec chmod 644 {} \; +sudo chmod 775 database/ +sudo chmod 660 database/*.db +``` + +### Database connection errors +**Cause:** Database file permissions +**Fix:** +```bash +ssh posterg +sudo chown www-data:posterg /var/www/posterg/database/test.db +sudo chmod 660 /var/www/posterg/database/test.db +``` diff --git a/docs/SIMPLIFICATION.md b/docs/SIMPLIFICATION.md new file mode 100644 index 0000000..f2fbb18 --- /dev/null +++ b/docs/SIMPLIFICATION.md @@ -0,0 +1,182 @@ +# Website Structure Simplification + +## Problem Identified + +The initial migration used the **Standard PHP Package Skeleton**, which is designed for **reusable PHP packages/libraries** (like Composer packages), not for websites. + +This resulted in: +- ❌ Overcomplicated structure (`var/`, `resources/`, complex bootstrap) +- ❌ Unused directories (`var/cache/`, `var/logs/`, `var/tmp/`) +- ❌ Package-oriented naming (`resources/views/`) +- ❌ Unnecessary constants and helper functions + +## Solution: Simplified for Website + +### Removed + +1. **`var/` directory** - Completely unused, only needed for complex applications with: + - Custom caching systems + - Application-level logging + - Temporary file processing + +2. **`resources/` directory** - Package-oriented name, renamed to simple `includes/` + +3. **Complex bootstrap** - Removed unused constants: + - `VAR_ROOT`, `CACHE_ROOT`, `LOGS_ROOT` + - `PUBLIC_ROOT`, `CONFIG_ROOT`, `RESOURCES_ROOT` + - `view()` helper function + +### Simplified Structure + +``` +posterg-website/ +├── public/ # DocumentRoot (web-accessible) ✅ +│ ├── index.php +│ ├── search.php +│ ├── memoire.php +│ ├── admin/ +│ └── assets/ +│ +├── includes/ # Simple template includes ✅ +│ ├── header.php +│ └── footer.php +│ +├── config/ # Minimal configuration ✅ +│ └── bootstrap.php (simplified) +│ +├── database/ # Database files (private) +│ └── test.db +│ +├── lib/ # PHP classes (private) +│ ├── Database.php +│ ├── RateLimit.php +│ └── cache/rate_limit/ (used by RateLimit) +│ +├── vendor/ # Composer dependencies (private) +└── tests/ # Tests (private) +``` + +### Simplified config/bootstrap.php + +**Before:** 66 lines with many unused constants +**After:** 33 lines with only essentials + +```php + $title]); +``` + +**After:** +```php +require_once __DIR__ . '/../config/bootstrap.php'; +require_once APP_ROOT . '/lib/Database.php'; +include APP_ROOT . '/includes/header.php'; +``` + +## Comparison: Package vs Website + +| Feature | PHP Package | PHP Website (this project) | +|---------|-------------|----------------------------| +| Purpose | Reusable library | Single website | +| Structure | Complex (PSR-4, namespaces) | Simple (includes, classes) | +| Directories | `src/`, `resources/`, `var/`, `bin/` | `public/`, `includes/`, `lib/` | +| Autoloading | PSR-4 namespaces | Simple require statements | +| Config | Complex bootstrap with many constants | Minimal bootstrap | +| Caching | `var/cache/` with framework | Simple file-based if needed | +| Logging | `var/logs/` with logger | PHP error_log | + +## Benefits of Simplification + +### Before (Package-oriented) +- ❌ 66-line bootstrap file +- ❌ 10+ unused constants +- ❌ `resources/views/` (confusing name) +- ❌ `var/` directory (completely unused) +- ❌ Helper functions for simple includes +- ❌ Over-engineered for a simple website + +### After (Website-focused) +- ✅ 33-line bootstrap file (50% smaller) +- ✅ 2 essential constants (APP_ROOT, DATABASE_PATH) +- ✅ `includes/` (clear, simple name) +- ✅ No unused directories +- ✅ Standard PHP `include` statements +- ✅ Appropriate for a PHP website + +### Security (Unchanged) +- ✅ Still uses `public/` as DocumentRoot +- ✅ Database still outside web root +- ✅ Config still private +- ✅ All security improvements retained + +## Testing + +All PHP files pass syntax check: +```bash +$ php -l config/bootstrap.php # OK +$ php -l public/index.php # OK +$ php -l public/search.php # OK +$ php -l public/memoire.php # OK +$ php -l public/admin/index.php # OK +``` + +Start dev server: +```bash +$ just serve +``` + +## When You WOULD Need var/ + +You would need a `var/` directory if you were building: +- A framework (Laravel, Symfony) +- A CMS (WordPress, Drupal) +- An application with: + - Template compilation/caching + - Session storage + - File upload processing + - Application-level logging + - Queue systems + +For your thesis website: **Not needed** ✅ + +## Conclusion + +- ✅ Structure is now appropriate for a **PHP website** +- ✅ Removed package-oriented complexity +- ✅ Kept all security improvements (public/ directory) +- ✅ Simpler, cleaner, easier to maintain +- ✅ Still follows best practices (just the right ones) + +The core improvement (public/ directory for security) remains intact, but now with a structure that fits a website, not a reusable package. diff --git a/inc/footer.php b/includes/footer.php similarity index 100% rename from inc/footer.php rename to includes/footer.php diff --git a/inc/header.php b/includes/header.php similarity index 100% rename from inc/header.php rename to includes/header.php diff --git a/index.php b/index.php deleted file mode 100644 index 7077393..0000000 --- a/index.php +++ /dev/null @@ -1,86 +0,0 @@ -getPublishedTheses($itemsPerPage, $offset); - $totalItems = $db->countPublishedTheses(); - $totalPages = ceil($totalItems / $itemsPerPage); -} catch (Exception $e) { - error_log("Error loading theses: " . $e->getMessage()); - $itemsToLoad = []; - $totalPages = 0; -} - -include "inc/header.php"; ?> - -
- - " class="card-link"> -
- getThesisFiles($item["id"]); - foreach ($files as $file) { - $ext = strtolower( - pathinfo($file["file_path"], PATHINFO_EXTENSION), - ); - if ( - in_array($ext, ["jpg", "jpeg", "png", "gif"]) && - $file["file_type"] === "main" - ) { - $coverImage = $file["file_path"]; - break; - } - } - } - ?> - -
-
- Image preview -
-
- -
-

- -

-

- -

- -

- $excerpt_length - ? substr($synopsis, 0, $excerpt_length) . "..." - : $synopsis; - ?> - -

-
- -
-
- -
- \ No newline at end of file diff --git a/justfile b/justfile index 12a8109..9d2bcdc 100644 --- a/justfile +++ b/justfile @@ -25,6 +25,7 @@ serve: @echo "" @echo "📍 Public site: http://localhost:8000" @echo "📍 Admin panel: http://localhost:8000/admin/" + @echo "🔒 Serving from public/ directory (matches production)" @echo "" @if [ -d "vendor/php-live-reload" ]; then \ echo "✨ Live reload enabled - browser auto-refreshes on file save!"; \ @@ -34,7 +35,7 @@ serve: @echo "" @echo "Press Ctrl+C to stop" @echo "" - @php -S 127.0.0.1:8000 + @php -S 127.0.0.1:8000 -t public/ [group('dev')] stop: @@ -63,47 +64,69 @@ deploy: @echo "📤 Deploying Post-ERG complete site" @echo "====================================" @echo "" - @echo "Deploying public site..." + @echo "⚠️ First time? Ensure /var/www/posterg/ exists on server with:" + @echo " ssh posterg" + @echo " sudo mkdir -p /var/www/posterg" + @echo " sudo chown www-data:posterg /var/www/posterg" + @echo " sudo chmod 775 /var/www/posterg" + @echo "" + @echo "Step 1: Deploying application to /var/www/posterg/..." rsync -vur --progress \ - --chown="root:posterg" \ + --chown="www-data:posterg" \ --exclude 'vendor' \ --exclude 'tests' \ --exclude 'test.db' \ - --exclude '*.db' \ - --exclude 'cache' \ --exclude '*.md' \ --exclude '.git*' \ --exclude '.jj' \ --exclude '.DS_Store' \ - --exclude 'database' \ + --exclude 'database/backup_*' \ + --exclude 'database/fixtures' \ + --exclude 'database/docs' \ --exclude 'nginx' \ --exclude 'docs' \ --exclude 'justfile*' \ --exclude 'migrate-structure.sh' \ --exclude 'setup-dev.sh' \ - ./ posterg:/var/www/html/ + --exclude 'var/cache/*' \ + --exclude 'var/logs/*' \ + ./ posterg:/var/www/posterg/ @echo "" - @echo "Fixing permissions..." - ssh posterg "chgrp -R posterg /var/www/html/inc /var/www/html/lib && \ - chmod 755 /var/www/html/inc && chmod 644 /var/www/html/inc/* && \ - find /var/www/html/lib -type d -exec chmod 755 {} \; && \ - find /var/www/html/lib -type f -exec chmod 644 {} \;" + @echo "Step 2: Setting up directories and permissions..." + ssh posterg "cd /var/www/posterg && \ + mkdir -p var/{cache,logs,tmp} && \ + chown -R www-data:posterg . && \ + chmod -R 755 . && \ + chmod -R 775 var/ database/ && \ + chmod 660 database/*.db 2>/dev/null || true" @echo "" @echo "✅ Deployment complete!" @echo "" + @echo "📁 Server structure:" + @echo " • App root: /var/www/posterg/" + @echo " • DocumentRoot: /var/www/posterg/public/" + @echo "" @echo "🔍 Verify deployment:" @echo " • Public: https://posterg.erg.be/" @echo " • Admin: https://posterg.erg.be/admin/" + @echo "" + @echo "⚠️ IMPORTANT: Update nginx config to point to /var/www/posterg/public/" + @echo " Run: just deploy-nginx" [group('deploy')] -test-deploy: +deploy-database: @echo "⚠️ Deploying test database (will overwrite remote test.db)" @echo "Creating database directory if needed..." - ssh posterg "mkdir -p /var/www/html/database" - rsync -vur --progress ./database/test.db posterg:/var/www/html/database/test.db + ssh posterg "mkdir -p /var/www/posterg/database" + rsync -vur --progress ./database/test.db posterg:/var/www/posterg/database/test.db @echo "Setting correct permissions..." - ssh posterg "chgrp posterg /var/www/html/database /var/www/html/database/test.db && chmod 775 /var/www/html/database && chmod 660 /var/www/html/database/test.db" + ssh posterg "chown www-data:posterg /var/www/posterg/database /var/www/posterg/database/test.db && chmod 775 /var/www/posterg/database && chmod 660 /var/www/posterg/database/test.db" @echo "✅ Test database deployed and configured" + +# Legacy alias +[group('deploy')] +test-deploy: + @just deploy-database # ============================================================================ # Testing # ============================================================================ @@ -230,13 +253,28 @@ deploy-test-db: [group('server')] deploy-nginx: @echo "🔧 Deploying nginx configuration..." + @echo "" + @echo "⚠️ IMPORTANT: Checking nginx config has correct DocumentRoot..." + @if ! grep -q "/var/www/posterg/public" nginx/posterg.conf 2>/dev/null; then \ + echo "❌ ERROR: nginx/posterg.conf must contain '/var/www/posterg/public'"; \ + echo " Current DocumentRoot needs updating!"; \ + echo ""; \ + echo " Edit nginx/posterg.conf and change:"; \ + echo " root /var/www/html;"; \ + echo " To:"; \ + echo " root /var/www/posterg/public;"; \ + exit 1; \ + fi + @echo "✅ nginx config looks correct" + @echo "" rsync -vur --progress ./nginx/posterg.conf posterg:/tmp/posterg.conf - rsync -vur --progress ./nginx/deploy-production.sh posterg:/tmp/deploy-production.sh + rsync -vur --progress ./nginx/deploy-production-new.sh posterg:/tmp/deploy-production.sh @echo "✅ Files uploaded to /tmp/ on server" @echo "" @echo "Next steps on the server:" @echo " ssh posterg" @echo " sudo bash /tmp/deploy-production.sh" + @echo " (This will apply config and show reload command)" [group('server')] deploy-admin-tools: diff --git a/justfile.old b/justfile.old deleted file mode 100644 index 1be0d9d..0000000 --- a/justfile.old +++ /dev/null @@ -1,205 +0,0 @@ -# Default recipe - show available commands -default: - @just --list - -# ============================================================================ -# Deploy Group -# ============================================================================ -# Note: Regular deploy recipes exclude test.db and all *.db files by default -# Use test-deploy explicitly to deploy the test database - -[group('deploy')] -deploy-public: - rsync -vur --progress --exclude 'test.db' --exclude '*.db' --exclude 'tests/' --exclude 'cache/' --exclude '*.md' --exclude 'run-tests.php' ./apps/public/ posterg:/var/www/html/ - rsync -vur --progress --exclude 'test.db' ./shared/ posterg:/var/www/html/shared/ - @echo "Fixing shared library paths for production..." - ssh posterg "cd /var/www/html && find . -maxdepth 1 -name '*.php' -type f -exec sed -i \"s|__DIR__ \. '/\.\./\.\./shared/|__DIR__ . '/shared/|g\" {} \;" - @echo "Fixing permissions..." - ssh posterg "chgrp -R posterg /var/www/html/inc && chmod 755 /var/www/html/inc && chmod 644 /var/www/html/inc/*" - @echo "✓ Deployment complete" - -[group('deploy')] -deploy-admin: - rsync -vur --progress --exclude 'test.db' --exclude '*.db' --exclude 'cache/' --exclude '*.md' ./apps/admin/ posterg:/var/www/html/admin/ - rsync -vur --progress --exclude 'test.db' ./shared/ posterg:/var/www/html/shared/ - @echo "Fixing shared library paths for production (admin)..." - ssh posterg "cd /var/www/html/formulaire && find . -maxdepth 1 -name '*.php' -type f -exec sed -i \"s|__DIR__ \. '/\.\./\.\./shared/|__DIR__ . '/../shared/|g\" {} \;" - @echo "✓ Admin paths fixed" - -[group('deploy')] -deploy: deploy-public deploy-admin - @echo "" - @echo "✅ Deployment complete (test.db excluded)" - @echo "To deploy test database, run: just test-deploy" - -[group('deploy')] -deploy-database: - @echo "Deploying database directory (excludes test.db by default)..." - rsync -vur --progress --exclude 'test.db' --exclude '*.db-journal' ./database/ posterg:/var/www/html/database/ - @echo "✅ Database directory deployed (schema, fixtures, docs only)" - -[group('deploy')] -test-deploy: - @echo "⚠️ Deploying test database (will overwrite remote test.db)" - @echo "Creating database directory if needed..." - ssh posterg "mkdir -p /var/www/html/database" - rsync -vur --progress ./database/test.db posterg:/var/www/html/database/test.db - @echo "Setting correct permissions..." - ssh posterg "chgrp posterg /var/www/html/database /var/www/html/database/test.db && chmod 775 /var/www/html/database && chmod 660 /var/www/html/database/test.db" - @echo "✅ Test database deployed and configured" - -[group('deploy')] -deploy-nginx: - @echo "🚀 Deploying production nginx configuration..." - rsync -vur --progress ./nginx/posterg.conf posterg:/tmp/posterg.conf - rsync -vur --progress ./nginx/deploy-production.sh posterg:/tmp/deploy-production.sh - @echo "✅ Files uploaded to server" - @echo "" - @echo "Next steps on the server:" - @echo " ssh posterg" - @echo " sudo bash /tmp/deploy-production.sh" - @echo "" - @echo "This will:" - @echo " • Fix file permissions (posterg group)" - @echo " • Install nginx configuration" - @echo " • Set up admin password (if needed)" - @echo " • Test and reload nginx" - -[group('deploy')] -deploy-admin-tools: - @echo "📤 Uploading admin user management tools..." - rsync -vur --progress ./nginx/manage-admin-users.sh posterg:/tmp/manage-admin-users.sh - @echo "✅ Script uploaded" - @echo "" - @echo "To manage admin users on the server:" - @echo " ssh posterg" - @echo " sudo bash /tmp/manage-admin-users.sh" - -# ============================================================================ -# Public Site Development -# ============================================================================ - -[group('public-dev')] -serve-public: - @echo "Starting public site on http://localhost:8002" - @echo "Press Ctrl+C to stop" - @cd apps/public && php -S 127.0.0.1:8002 - -[group('public-dev')] -test-public: - @echo "Testing public site..." - @cd apps/public && php test_db.php - -[group('public-dev')] -test-public-all: - @echo "Running all public site tests..." - @cd apps/public && php run-tests.php - -[group('public-dev')] -stats-public: - @echo "=== Public Database Statistics ===" - @sqlite3 database/test.db "SELECT COUNT(*) || ' total theses' FROM theses;" - @sqlite3 database/test.db "SELECT COUNT(*) || ' published theses' FROM theses WHERE is_published = 1;" - @sqlite3 database/test.db "SELECT COUNT(*) || ' authors' FROM authors;" - @sqlite3 database/test.db "SELECT COUNT(*) || ' keywords' FROM keywords;" - -[group('public-dev')] -recent-public: - @echo "=== Recent Published Theses ===" - @sqlite3 -column -header database/test.db "SELECT id, title, year, authors FROM v_theses_public ORDER BY year DESC, title LIMIT 10;" - -[group('public-dev')] -check-public: - @echo "Checking public site PHP syntax..." - @cd apps/public && find . -name "*.php" -not -path "./vendor/*" -not -path "./tests/*" -exec php -l {} \; | grep -v "No syntax errors" - @echo "✓ All files have valid syntax" - -[group('public-dev')] -logs-public: - @if [ -f apps/public/error.log ]; then tail -n 50 apps/public/error.log; else echo "No error log found"; fi - -# ============================================================================ -# Admin Panel Development -# ============================================================================ - -[group('admin-dev')] -init-test-db: - @echo "Creating test database from schema..." - @sqlite3 database/test.db < database/schema.sql - @echo "✓ Test database created" - @sqlite3 database/test.db "SELECT COUNT(*) || ' tables created' FROM sqlite_master WHERE type='table';" - @sqlite3 database/test.db "SELECT COUNT(*) || ' orientations loaded' FROM orientations;" - @sqlite3 database/test.db "SELECT COUNT(*) || ' AP programs loaded' FROM ap_programs;" - -[group('admin-dev')] -serve-admin: init-test-db - @echo "Starting admin panel on http://localhost:3000" - @echo "Press Ctrl+C to stop" - @cd apps/admin && php -S 127.0.0.1:3000 - -[group('admin-dev')] -serve-admin-only: - @echo "Starting admin panel on http://localhost:3000" - @echo "Press Ctrl+C to stop" - @cd apps/admin && php -S 127.0.0.1:3000 - -[group('admin-dev')] -cleanup-admin: - @echo "Cleaning up admin test files..." - @rm -f database/test.db - @rm -f apps/admin/error.log - @rm -rf apps/admin/data/theses/* - @rm -rf apps/admin/data/covers/* - @echo "✓ Cleanup complete" - -[group('admin-dev')] -reset-admin: cleanup-admin init-test-db - @echo "✓ Admin test environment reset" - -[group('admin-dev')] -stats-admin: - @echo "=== Admin Database Statistics ===" - @sqlite3 database/test.db "SELECT COUNT(*) || ' theses' FROM theses;" - @sqlite3 database/test.db "SELECT COUNT(*) || ' authors' FROM authors;" - @sqlite3 database/test.db "SELECT COUNT(*) || ' supervisors' FROM supervisors;" - @sqlite3 database/test.db "SELECT COUNT(*) || ' keywords' FROM keywords;" - @sqlite3 database/test.db "SELECT COUNT(*) || ' files uploaded' FROM thesis_files;" - -[group('admin-dev')] -recent-admin: - @echo "=== Recent Submissions ===" - @sqlite3 -column -header database/test.db "SELECT identifier, title, year, submitted_at FROM theses ORDER BY submitted_at DESC LIMIT 5;" - -[group('admin-dev')] -setup-dirs: - @mkdir -p apps/admin/data/theses - @mkdir -p apps/admin/data/covers - @mkdir -p apps/admin/data/yaml - @touch apps/admin/data/theses/.gitkeep - @touch apps/admin/data/covers/.gitkeep - @echo "✓ Data directories created" - -[group('admin-dev')] -dev-admin: setup-dirs init-test-db serve-admin - -# ============================================================================ -# Database Operations -# ============================================================================ - -[group('database')] -query-db: - @sqlite3 database/test.db - -[group('database')] -show-thesis id: - @sqlite3 -column -header database/test.db "SELECT * FROM v_theses_full WHERE id = {{id}};" - -[group('database')] -dump-db: - @sqlite3 database/test.db .dump > database/backup_$(date +%Y%m%d_%H%M%S).sql - @echo "✓ Database dumped to database/backup_$(date +%Y%m%d_%H%M%S).sql" - -[group('database')] -create-fixtures: - @echo "Creating test database with fixtures..." - @php database/fixtures/CreateTestDatabase.php diff --git a/lib/cache/rate_limit/f528764d624db129b32c21fbca0cb8d6.json b/lib/cache/rate_limit/f528764d624db129b32c21fbca0cb8d6.json index 94ffacc..fe0acea 100644 --- a/lib/cache/rate_limit/f528764d624db129b32c21fbca0cb8d6.json +++ b/lib/cache/rate_limit/f528764d624db129b32c21fbca0cb8d6.json @@ -1 +1 @@ -[1770322829] \ No newline at end of file +[1770377487] \ No newline at end of file diff --git a/nginx/deploy-production-new.sh b/nginx/deploy-production-new.sh new file mode 100755 index 0000000..75e7d8d --- /dev/null +++ b/nginx/deploy-production-new.sh @@ -0,0 +1,105 @@ +#!/bin/bash +# Deploy production nginx configuration for Post-ERG (NEW STRUCTURE) +# This script applies the nginx config for /var/www/posterg/public/ structure + +set -e + +echo "🚀 Post-ERG Production Deployment (NEW STRUCTURE)" +echo "==================================================" +echo "" + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +# Check if running as root +if [ "$EUID" -ne 0 ]; then + echo -e "${RED}Error: This script must be run as root (use sudo)${NC}" + exit 1 +fi + +echo "📋 Step 1: Fixing file permissions..." +echo "--------------------------------------" + +# Change ownership to www-data:posterg +chown -R www-data:posterg /var/www/posterg/ +echo "✓ Changed ownership to www-data:posterg" + +# Set directory permissions (755) +find /var/www/posterg -type d -exec chmod 755 {} \; +echo "✓ Set directory permissions to 755" + +# Set file permissions (644) +find /var/www/posterg -type f -exec chmod 644 {} \; +echo "✓ Set file permissions to 644" + +# Make database directory writable by group +if [ -d "/var/www/posterg/database" ]; then + chmod 775 /var/www/posterg/database + echo "✓ Made database directory group-writable (775)" +fi + +# Fix database file permissions +if [ -f "/var/www/posterg/database/test.db" ]; then + chmod 660 /var/www/posterg/database/test.db + chown www-data:posterg /var/www/posterg/database/test.db + echo "✓ Fixed database file permissions (660)" +fi + +# Make admin upload directories writable by group +if [ -d "/var/www/posterg/public/admin/data" ]; then + find /var/www/posterg/public/admin/data -type d -exec chmod 775 {} \; + echo "✓ Made admin upload directories group-writable" +fi + +echo "" +echo "📋 Step 2: Deploying nginx configuration..." +echo "--------------------------------------" + +# Backup existing config +if [ -f "/etc/nginx/sites-available/posterg" ]; then + cp /etc/nginx/sites-available/posterg /etc/nginx/sites-available/posterg.backup.$(date +%Y%m%d_%H%M%S) + echo "✓ Backed up existing config" +fi + +# Copy new config +if [ -f "/tmp/posterg.conf" ]; then + cp /tmp/posterg.conf /etc/nginx/sites-available/posterg + echo "✓ Installed new nginx config" +else + echo -e "${RED}Error: /tmp/posterg.conf not found${NC}" + echo "Run 'just deploy-nginx' first" + exit 1 +fi + +# Test nginx configuration +echo "" +echo "📋 Step 3: Testing nginx configuration..." +echo "--------------------------------------" + +if nginx -t; then + echo -e "${GREEN}✓ Nginx configuration is valid${NC}" +else + echo -e "${RED}✗ Nginx configuration has errors!${NC}" + echo "Restoring backup..." + cp /etc/nginx/sites-available/posterg.backup.$(date +%Y%m%d_%H%M%S | tail -1) /etc/nginx/sites-available/posterg + exit 1 +fi + +echo "" +echo "📋 Step 4: Summary..." +echo "--------------------------------------" +echo -e "${GREEN}✓ Permissions fixed${NC}" +echo -e "${GREEN}✓ Nginx config installed${NC}" +echo -e "${GREEN}✓ Configuration validated${NC}" +echo "" +echo -e "${YELLOW}Ready to reload nginx!${NC}" +echo "" +echo "Run: ${GREEN}sudo systemctl reload nginx${NC}" +echo "" +echo "After reload, verify:" +echo " • https://posterg.erg.be/" +echo " • https://posterg.erg.be/admin/" +echo " • https://posterg.erg.be/database/test.db (should 404)" diff --git a/nginx/posterg.conf b/nginx/posterg.conf index 1a9c779..20eba8d 100644 --- a/nginx/posterg.conf +++ b/nginx/posterg.conf @@ -14,7 +14,7 @@ server { server_name posterg.erg.be www.posterg.erg.be; - root /var/www/html; + root /var/www/posterg/public; # Add index.php to the list index index.php index.html index.htm; @@ -65,7 +65,7 @@ server { } # Admin panel - password protected - location ^~ /formulaire/ { + location ^~ /admin/ { # HTTP Basic Authentication auth_basic "Admin Access - Post-ERG"; auth_basic_user_file /etc/nginx/.htpasswd-posterg; @@ -74,7 +74,7 @@ server { limit_req zone=admin burst=5 nodelay; # Allow access to public assets without authentication - location ~ ^/formulaire/(css|js|images)/ { + location ~ ^/admin/(css|js|images)/ { auth_basic off; } diff --git a/admin/.htaccess b/public/admin/.htaccess similarity index 100% rename from admin/.htaccess rename to public/admin/.htaccess diff --git a/admin/README.md b/public/admin/README.md similarity index 100% rename from admin/README.md rename to public/admin/README.md diff --git a/admin/add.php b/public/admin/add.php similarity index 98% rename from admin/add.php rename to public/admin/add.php index a639354..5202f72 100644 --- a/admin/add.php +++ b/public/admin/add.php @@ -1,4 +1,7 @@ - +
@@ -243,4 +246,4 @@ function wasSelected($key, $value)
- \ No newline at end of file + \ No newline at end of file diff --git a/admin/edit.php b/public/admin/edit.php similarity index 99% rename from admin/edit.php rename to public/admin/edit.php index cade481..5c928ee 100644 --- a/admin/edit.php +++ b/public/admin/edit.php @@ -1,4 +1,7 @@ Voir: ../db/Database_TFE_test.csv

- \ No newline at end of file + \ No newline at end of file diff --git a/admin/inc/footer.php b/public/admin/inc/footer.php similarity index 100% rename from admin/inc/footer.php rename to public/admin/inc/footer.php diff --git a/admin/inc/head.php b/public/admin/inc/head.php similarity index 60% rename from admin/inc/head.php rename to public/admin/inc/head.php index 277ef7d..af5be21 100644 --- a/admin/inc/head.php +++ b/public/admin/inc/head.php @@ -5,18 +5,18 @@ - <? echo $pageTitle ?> - + <?php echo $pageTitle ?> + - +
-

+

\ No newline at end of file diff --git a/admin/index.php b/public/admin/index.php similarity index 98% rename from admin/index.php rename to public/admin/index.php index df7f471..70debdd 100644 --- a/admin/index.php +++ b/public/admin/index.php @@ -1,4 +1,7 @@ - +