diff --git a/DEPLOYMENT_GUIDE.md b/DEPLOYMENT_GUIDE.md deleted file mode 100644 index e1565a3..0000000 --- a/DEPLOYMENT_GUIDE.md +++ /dev/null @@ -1,445 +0,0 @@ -# Tinker Tickets SSO Integration - Deployment Guide - -## โœ… Implementation Complete - -All code for Authelia SSO with LLDAP integration has been implemented. This guide will walk you through deployment and testing. - -## ๐Ÿ“‹ What Was Implemented - -### 1. Database Schema (New Tables) -- **users** - Stores user accounts synced from LLDAP -- **api_keys** - Manages API keys for external services (hwmonDaemon) -- **audit_log** - Tracks all user actions for audit trail - -### 2. Authentication System -- **AuthMiddleware.php** - Reads Authelia forward auth headers and syncs users -- **ApiKeyAuth.php** - Validates API keys for external services -- Session management with 5-hour timeout -- Group-based access control (admin/employee groups) - -### 3. Models -- **UserModel.php** - User CRUD operations and authentication -- **ApiKeyModel.php** - API key generation and validation -- **AuditLogModel.php** - Audit trail logging -- Updated **TicketModel.php** and **CommentModel.php** with user tracking - -### 4. Protected Endpoints -- All web pages now require Authelia authentication -- API endpoints require session authentication -- `/create_ticket_api.php` requires API key authentication - -### 5. User Interface Updates -- User info header showing logged-in user -- Admin badge for admin users -- Comment display shows user's display name from LLDAP - -## ๐Ÿš€ Deployment Steps - -### Step 1: Push Code to Git - -```bash -cd /root/code/tinker_tickets -git add . -git commit -m "Add Authelia SSO integration with LLDAP - -- Implement user authentication via forward auth headers -- Add API key authentication for hwmonDaemon -- Create audit log for all user actions -- Add user tracking to tickets and comments -- Update views to display user information" -git push origin main -``` - -The Gitea webhook will automatically deploy to production at 10.10.10.45. - -### Step 2: Run Database Migrations - -SSH into the production server: - -```bash -ssh jared@10.10.10.45 -``` - -Navigate to the application directory: - -```bash -cd /var/www/html/tinkertickets -``` - -Run the migrations: - -```bash -php migrations/run_migrations.php -``` - -Expected output: -``` -Connected to database: ticketing_system - -Found 6 migration(s): - - 001_create_users_table.sql - - 002_create_api_keys_table.sql - - 003_create_audit_log_table.sql - - 004_alter_tickets_table.sql - - 005_alter_comments_table.sql - - 006_add_indexes.sql - -Executing: 001_create_users_table.sql... OK -Executing: 002_create_api_keys_table.sql... OK -Executing: 003_create_audit_log_table.sql... OK -Executing: 004_alter_tickets_table.sql... OK -Executing: 005_alter_comments_table.sql... OK -Executing: 006_add_indexes.sql... OK - -Migration Summary: - Success: 6 - Errors: 0 - -All migrations completed successfully! -``` - -### Step 3: Generate API Key for hwmonDaemon - -Since we need an admin user to generate API keys, we'll create a temporary PHP script: - -Create `/var/www/html/tinkertickets/generate_api_key.php`: - -```php -connect_error) { - die("Connection failed: " . $conn->connect_error); -} - -$userModel = new UserModel($conn); -$apiKeyModel = new ApiKeyModel($conn); - -// Get system user (should exist from migration) -$systemUser = $userModel->getSystemUser(); - -if (!$systemUser) { - die("Error: System user not found. Check migrations.\n"); -} - -echo "System user found: ID " . $systemUser['user_id'] . "\n"; - -// Generate API key -$result = $apiKeyModel->createKey( - 'hwmonDaemon', - $systemUser['user_id'], - null // No expiration -); - -if ($result['success']) { - echo "\nโœ… API Key generated successfully!\n\n"; - echo "API Key: " . $result['api_key'] . "\n"; - echo "Key Prefix: " . $result['key_prefix'] . "\n"; - echo "\nโš ๏ธ IMPORTANT: Save this API key now! It cannot be retrieved later.\n"; - echo "\nAdd this to hwmonDaemon .env file:\n"; - echo "TICKET_API_KEY=" . $result['api_key'] . "\n"; -} else { - echo "Error generating API key: " . $result['error'] . "\n"; -} - -$conn->close(); -?> -``` - -Run it: - -```bash -php generate_api_key.php -``` - -Save the API key output - you'll need it for hwmonDaemon. - -Delete the script after use: - -```bash -rm generate_api_key.php -``` - -### Step 4: Update hwmonDaemon Configuration - -On each Proxmox server running hwmonDaemon, update the `.env` file: - -```bash -# On each Proxmox server -cd /path/to/hwmonDaemon -nano .env -``` - -Add the API key: - -```env -TICKET_API_KEY= -``` - -Update `hwmonDaemon.py` to send the Authorization header (around line 1198): - -```python -def create_ticket(self, title, description, priority=4, category="Hardware", ticket_type="Issue"): - """Create a ticket via the API""" - url = self.CONFIG["TICKET_API_URL"] - - payload = { - "title": title, - "description": description, - "priority": priority, - "category": category, - "type": ticket_type - } - - headers = { - 'Content-Type': 'application/json', - 'Authorization': f'Bearer {self.CONFIG["TICKET_API_KEY"]}' - } - - try: - response = requests.post(url, json=payload, headers=headers, timeout=10) - response.raise_for_status() - return response.json() - except Exception as e: - logger.error(f"Failed to create ticket: {e}") - return None -``` - -Restart hwmonDaemon: - -```bash -sudo systemctl restart hwmonDaemon -``` - -### Step 5: Migrate Legacy Data (Optional) - -If you want to assign existing comments to a specific user: - -1. First, log into the web UI to create your user account in the database -2. Then run this SQL to update existing comments: - -```sql --- Get jared's user_id (replace with actual value after login) -SELECT user_id FROM users WHERE username = 'jared'; - --- Update existing comments (replace 1 with actual user_id) -UPDATE ticket_comments SET user_id = 1 WHERE user_id IS NULL; -``` - -## ๐Ÿงช Testing - -### Test 1: Web UI Authentication - -1. Open https://t.lotusguild.org in your browser -2. You should be redirected to Authelia login (if not already logged in) -3. Log in with your LLDAP credentials -4. Verify you see your name in the top-right corner -5. If you're in the admin group, verify you see the "Admin" badge - -### Test 2: Create Ticket via Web UI - -1. Click "New Ticket" -2. Fill out the form -3. Submit the ticket -4. Verify the ticket appears in the dashboard -5. Check the database to confirm `created_by` is set: - -```sql -SELECT ticket_id, title, created_by FROM tickets ORDER BY created_at DESC LIMIT 5; -``` - -### Test 3: Add Comment - -1. Open a ticket -2. Add a comment -3. Verify your display name appears on the comment -4. Check the database to confirm `user_id` is set: - -```sql -SELECT comment_id, ticket_id, user_id, comment_text FROM ticket_comments ORDER BY created_at DESC LIMIT 5; -``` - -### Test 4: hwmonDaemon API - -1. Trigger a hardware issue or manually test the API: - -```bash -curl -X POST https://t.lotusguild.org/create_ticket_api.php \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer " \ - -d '{ - "title": "[test-server][auto][hardware]Test Ticket[single-device][production][warning]", - "description": "This is a test ticket from hwmonDaemon", - "priority": "2", - "category": "Hardware", - "type": "Issue" - }' -``` - -Expected response: - -```json -{ - "success": true, - "ticket_id": "123456789", - "message": "Ticket created successfully" -} -``` - -2. Verify the ticket appears in the dashboard -3. Check the database to confirm `created_by` is the system user: - -```sql -SELECT t.ticket_id, t.title, u.username -FROM tickets t -LEFT JOIN users u ON t.created_by = u.user_id -ORDER BY t.created_at DESC LIMIT 5; -``` - -### Test 5: Audit Log - -Check that actions are being logged: - -```sql --- View recent audit log entries -SELECT al.*, u.username, u.display_name -FROM audit_log al -LEFT JOIN users u ON al.user_id = u.user_id -ORDER BY al.created_at DESC -LIMIT 20; -``` - -You should see entries for: -- Ticket views -- Ticket creations -- Ticket updates -- Comment creations - -## ๐Ÿ”’ Security Notes - -1. **API Keys**: The API key generated for hwmonDaemon is shown only once. Store it securely. -2. **Session Timeout**: Web sessions expire after 5 hours of inactivity. -3. **Group Access**: Only users in `admin` or `employee` groups can access the system. -4. **Audit Trail**: All actions are logged with user ID, IP address, and timestamp. - -## ๐Ÿ”„ Rollback Procedure - -If you need to rollback the changes: - -```bash -cd /var/www/html/tinkertickets -mysql -u -p ticketing_system < migrations/rollback_all.sql -``` - -Then revert the git commit: - -```bash -git revert HEAD -git push origin main -``` - -## ๐Ÿ“Š Database Indexes Added - -For improved performance: -- `tickets.status` - Speeds up status filtering -- `tickets.priority` - Speeds up priority filtering -- `tickets.created_at` - Speeds up date sorting -- `users.username` - Speeds up user lookups -- `audit_log.user_id` - Speeds up user audit queries -- `audit_log.created_at` - Speeds up date-based audit queries - -## ๐ŸŽฏ Next Steps (Future Enhancements) - -1. **Admin Panel** - Create UI for managing API keys -2. **Bulk Actions** - Admin-only bulk ticket operations -3. **User Audit View** - UI to view audit logs per ticket -4. **Advanced Permissions** - Fine-grained permission system -5. **Email Notifications** - Email users on ticket updates - -## ๐Ÿ“ Files Created/Modified - -### New Files Created: -- `migrations/001_create_users_table.sql` -- `migrations/002_create_api_keys_table.sql` -- `migrations/003_create_audit_log_table.sql` -- `migrations/004_alter_tickets_table.sql` -- `migrations/005_alter_comments_table.sql` -- `migrations/006_add_indexes.sql` -- `migrations/rollback_all.sql` -- `migrations/run_migrations.php` -- `middleware/AuthMiddleware.php` -- `middleware/ApiKeyAuth.php` -- `models/UserModel.php` -- `models/ApiKeyModel.php` -- `models/AuditLogModel.php` -- `DEPLOYMENT_GUIDE.md` (this file) - -### Modified Files: -- `index.php` - Added authentication -- `create_ticket_api.php` - Added API key auth -- `api/add_comment.php` - Added session auth -- `api/update_ticket.php` - Added session auth -- `models/TicketModel.php` - Added user_id parameters -- `models/CommentModel.php` - Added user_id parameters -- `controllers/TicketController.php` - Pass current user, log actions -- `views/TicketView.php` - Display user info -- `views/DashboardView.php` - Display user info - -## โ“ Troubleshooting - -### Issue: "Authentication Required" error on web UI - -**Solution**: Check that Nginx Proxy Manager is sending the forward auth headers: -- Remote-User -- Remote-Groups -- Remote-Name -- Remote-Email - -Verify headers are being sent: - -```php - -``` - -Access https://t.lotusguild.org/test.php and look for `HTTP_REMOTE_USER` in the output. - -### Issue: hwmonDaemon tickets failing with 401 Unauthorized - -**Solution**: -1. Verify API key is correct in hwmonDaemon `.env` -2. Check that Authorization header is being sent -3. Verify API key exists in database: `SELECT * FROM api_keys WHERE is_active = 1;` - -### Issue: Existing comments show "Unknown User" - -**Solution**: This is expected for legacy data. To fix: -1. Log into the web UI to create your user account -2. Run the SQL migration to assign your user_id to legacy comments - -### Issue: Database migration fails - -**Solution**: -1. Check database connection in `.env` -2. Ensure database user has CREATE, ALTER, and INSERT privileges -3. Review migration output for specific error messages -4. Check `/tmp/api_debug.log` for detailed errors - -## ๐Ÿ“ง Support - -For issues or questions: -1. Check the audit log: `SELECT * FROM audit_log ORDER BY created_at DESC LIMIT 50;` -2. Check PHP error logs: `tail -f /var/log/php-fpm/error.log` -3. Check debug logs: `tail -f /tmp/api_debug.log` -4. Review Authelia logs: `docker logs authelia` diff --git a/assets/css/dashboard.css b/assets/css/dashboard.css index 8f1de8d..2beddf7 100644 --- a/assets/css/dashboard.css +++ b/assets/css/dashboard.css @@ -1288,25 +1288,6 @@ input[type="checkbox"]:checked { } /* ===== UTILITY STYLES ===== */ -.theme-toggle { - position: absolute; - top: 20px; - right: 20px; - z-index: 100; - padding: 12px; - border-radius: 50%; - background: var(--bg-secondary); - border: 1px solid var(--border-color); - cursor: pointer; - box-shadow: var(--shadow); - font-size: 1.2em; - transition: transform 0.3s ease; -} - -.theme-toggle:hover { - transform: scale(1.1); -} - .ticket-link { font-family: 'Courier New', monospace; font-weight: bold; diff --git a/assets/js/dashboard.js b/assets/js/dashboard.js index 017002c..527fa75 100644 --- a/assets/js/dashboard.js +++ b/assets/js/dashboard.js @@ -37,12 +37,11 @@ document.addEventListener('DOMContentLoaded', function() { } // Initialize for all pages - initThemeToggle(); initSettingsModal(); - - // Load saved theme preference - const savedTheme = localStorage.getItem('theme') || 'light'; - document.documentElement.setAttribute('data-theme', savedTheme); + + // Force dark mode only (terminal aesthetic - no theme switching) + document.documentElement.setAttribute('data-theme', 'dark'); + document.body.classList.add('dark-mode'); }); function initTableSorting() { @@ -178,19 +177,6 @@ function saveSettings() { window.location.reload(); } -function initThemeToggle() { - const toggle = document.createElement('button'); - toggle.className = 'theme-toggle'; - toggle.innerHTML = '๐ŸŒ“'; - toggle.onclick = () => { - const currentTheme = document.documentElement.getAttribute('data-theme'); - const newTheme = currentTheme === 'dark' ? 'light' : 'dark'; - document.documentElement.setAttribute('data-theme', newTheme); - localStorage.setItem('theme', newTheme); - }; - document.body.appendChild(toggle); -} - function initStatusFilter() { const filterContainer = document.createElement('div'); filterContainer.className = 'status-filter-container'; diff --git a/test_api.php b/test_api.php deleted file mode 100644 index baa6cbc..0000000 --- a/test_api.php +++ /dev/null @@ -1,79 +0,0 @@ -\n"; - echo "Example: php test_api.php d8f356a06bd5612eca9c5ff948b592a56020cc61937764461458372c9ef30932\n"; - exit(1); -} - -$apiKey = $argv[1]; -echo "API Key: " . substr($apiKey, 0, 10) . "...\n\n"; - -// Test data -$testTicket = [ - 'title' => 'Test Ticket from PHP Script', - 'description' => 'This is a test ticket to debug the API', - 'priority' => '3', - 'category' => 'Test', - 'type' => 'Issue', - 'status' => 'Open' -]; - -echo "Sending test ticket...\n"; -echo "URL: http://10.10.10.45/create_ticket_api.php\n\n"; - -// Make the API call -$ch = curl_init('http://10.10.10.45/create_ticket_api.php'); -curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'Authorization: Bearer ' . $apiKey -]); -curl_setopt($ch, CURLOPT_POST, 1); -curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($testTicket)); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_VERBOSE, true); -curl_setopt($ch, CURLOPT_TIMEOUT, 10); - -// Capture verbose output -$verbose = fopen('php://temp', 'w+'); -curl_setopt($ch, CURLOPT_STDERR, $verbose); - -$response = curl_exec($ch); -$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); -$curlError = curl_error($ch); - -// Get verbose output -rewind($verbose); -$verboseLog = stream_get_contents($verbose); -fclose($verbose); - -curl_close($ch); - -echo "HTTP Code: $httpCode\n"; -echo "cURL Error: " . ($curlError ?: 'None') . "\n\n"; - -echo "=== Raw Response ===\n"; -echo "Length: " . strlen($response) . " bytes\n"; -echo "Content:\n"; -var_dump($response); -echo "\n"; - -if ($response) { - echo "=== Decoded JSON ===\n"; - $decoded = json_decode($response, true); - if ($decoded === null) { - echo "ERROR: Failed to decode JSON\n"; - echo "JSON Error: " . json_last_error_msg() . "\n"; - } else { - print_r($decoded); - } -} else { - echo "ERROR: Empty response received\n"; -} - -echo "\n=== cURL Verbose Log ===\n"; -echo $verboseLog; -echo "\n"; diff --git a/views/CreateTicketView.php b/views/CreateTicketView.php index 0c10330..b17dbff 100644 --- a/views/CreateTicketView.php +++ b/views/CreateTicketView.php @@ -13,86 +13,229 @@ -
-
-

Create New Ticket

+
+ - - -
- - -
-
-
- - -
+
+ + ๐Ÿ‘ค + + Admin + + +
+
+ -
- - -
- -
-
- - -
-
- - -
-
- - -
-
- - -
-
- -
- - + +
+ โ•š + โ• + + +
Create New Ticket
+
+
+
+

New Ticket Form

+

+ Complete the form below to create a new ticket +

- - + + + +
+ + +
+
+
+ โš  Error: +
+
+ + + +
+ + + + +
Template Selection
+
+
+
+ + +

+ Select a template to auto-fill form fields +

+
+
+
+ + +
+ + +
Basic Information
+
+
+
+ + +
+
+
+ + +
+ + +
Ticket Metadata
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+ + +
Detailed Description
+
+
+
+ + +
+
+
+ + +
+ + +
Form Actions
+
+
+ +
+
+
+ - \ No newline at end of file + diff --git a/views/DashboardView.php b/views/DashboardView.php index 6fb5482..a1b1259 100644 --- a/views/DashboardView.php +++ b/views/DashboardView.php @@ -29,27 +29,16 @@