2025-05-16 20:02:49 -04:00
|
|
|
<?php
|
|
|
|
|
// Main entry point for the application
|
|
|
|
|
require_once 'config/config.php';
|
Implement comprehensive improvement plan (Phases 1-6)
Security (Phase 1-2):
- Add SecurityHeadersMiddleware with CSP, X-Frame-Options, etc.
- Add RateLimitMiddleware for API rate limiting
- Add security event logging to AuditLogModel
- Add ResponseHelper for standardized API responses
- Update config.php with security constants
Database (Phase 3):
- Add migration 014 for additional indexes
- Add migration 015 for ticket dependencies
- Add migration 016 for ticket attachments
- Add migration 017 for recurring tickets
- Add migration 018 for custom fields
Features (Phase 4-5):
- Add ticket dependencies with DependencyModel and API
- Add duplicate detection with check_duplicates API
- Add file attachments with AttachmentModel and upload/download APIs
- Add @mentions with autocomplete and highlighting
- Add quick actions on dashboard rows
Collaboration (Phase 5):
- Add mention extraction in CommentModel
- Add mention autocomplete dropdown in ticket.js
- Add mention highlighting CSS styles
Admin & Export (Phase 6):
- Add StatsModel for dashboard widgets
- Add dashboard stats cards (open, critical, unassigned, etc.)
- Add CSV/JSON export via export_tickets API
- Add rich text editor toolbar in markdown.js
- Add RecurringTicketModel with cron job
- Add CustomFieldModel for per-category fields
- Add admin views: RecurringTickets, CustomFields, Workflow,
Templates, AuditLog, UserActivity
- Add admin APIs: manage_workflows, manage_templates,
manage_recurring, custom_fields, get_users
- Add admin routes in index.php
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 09:55:01 -05:00
|
|
|
require_once 'middleware/SecurityHeadersMiddleware.php';
|
2026-01-01 15:40:32 -05:00
|
|
|
require_once 'middleware/AuthMiddleware.php';
|
|
|
|
|
require_once 'models/AuditLogModel.php';
|
2025-05-16 20:02:49 -04:00
|
|
|
|
Implement comprehensive improvement plan (Phases 1-6)
Security (Phase 1-2):
- Add SecurityHeadersMiddleware with CSP, X-Frame-Options, etc.
- Add RateLimitMiddleware for API rate limiting
- Add security event logging to AuditLogModel
- Add ResponseHelper for standardized API responses
- Update config.php with security constants
Database (Phase 3):
- Add migration 014 for additional indexes
- Add migration 015 for ticket dependencies
- Add migration 016 for ticket attachments
- Add migration 017 for recurring tickets
- Add migration 018 for custom fields
Features (Phase 4-5):
- Add ticket dependencies with DependencyModel and API
- Add duplicate detection with check_duplicates API
- Add file attachments with AttachmentModel and upload/download APIs
- Add @mentions with autocomplete and highlighting
- Add quick actions on dashboard rows
Collaboration (Phase 5):
- Add mention extraction in CommentModel
- Add mention autocomplete dropdown in ticket.js
- Add mention highlighting CSS styles
Admin & Export (Phase 6):
- Add StatsModel for dashboard widgets
- Add dashboard stats cards (open, critical, unassigned, etc.)
- Add CSV/JSON export via export_tickets API
- Add rich text editor toolbar in markdown.js
- Add RecurringTicketModel with cron job
- Add CustomFieldModel for per-category fields
- Add admin views: RecurringTickets, CustomFields, Workflow,
Templates, AuditLog, UserActivity
- Add admin APIs: manage_workflows, manage_templates,
manage_recurring, custom_fields, get_users
- Add admin routes in index.php
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 09:55:01 -05:00
|
|
|
// Apply security headers early
|
|
|
|
|
SecurityHeadersMiddleware::apply();
|
|
|
|
|
|
2025-09-05 11:08:56 -04:00
|
|
|
// Parse the URL - no need to remove base path since we're at document root
|
2025-05-16 20:02:49 -04:00
|
|
|
$request = $_SERVER['REQUEST_URI'];
|
|
|
|
|
|
2025-09-05 11:08:56 -04:00
|
|
|
// Remove query string for routing (but keep it available)
|
|
|
|
|
$requestPath = strtok($request, '?');
|
|
|
|
|
|
|
|
|
|
// Create database connection for non-API routes
|
|
|
|
|
if (!str_starts_with($requestPath, '/api/')) {
|
|
|
|
|
$conn = new mysqli(
|
|
|
|
|
$GLOBALS['config']['DB_HOST'],
|
|
|
|
|
$GLOBALS['config']['DB_USER'],
|
|
|
|
|
$GLOBALS['config']['DB_PASS'],
|
|
|
|
|
$GLOBALS['config']['DB_NAME']
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if ($conn->connect_error) {
|
|
|
|
|
die("Connection failed: " . $conn->connect_error);
|
|
|
|
|
}
|
2026-01-01 15:40:32 -05:00
|
|
|
|
|
|
|
|
// Authenticate user via Authelia forward auth
|
|
|
|
|
$authMiddleware = new AuthMiddleware($conn);
|
|
|
|
|
$currentUser = $authMiddleware->authenticate();
|
|
|
|
|
|
|
|
|
|
// Store current user in globals for controllers
|
|
|
|
|
$GLOBALS['currentUser'] = $currentUser;
|
|
|
|
|
|
|
|
|
|
// Initialize audit log model
|
|
|
|
|
$GLOBALS['auditLog'] = new AuditLogModel($conn);
|
2026-01-20 21:54:04 -05:00
|
|
|
|
|
|
|
|
// Check if user has a timezone preference and apply it
|
|
|
|
|
if ($currentUser && isset($currentUser['user_id'])) {
|
|
|
|
|
require_once 'models/UserPreferencesModel.php';
|
|
|
|
|
$prefsModel = new UserPreferencesModel($conn);
|
|
|
|
|
$userTimezone = $prefsModel->getPreference($currentUser['user_id'], 'timezone', null);
|
|
|
|
|
if ($userTimezone) {
|
|
|
|
|
// Override system timezone with user preference
|
|
|
|
|
date_default_timezone_set($userTimezone);
|
|
|
|
|
$GLOBALS['config']['TIMEZONE'] = $userTimezone;
|
|
|
|
|
$now = new DateTime('now', new DateTimeZone($userTimezone));
|
|
|
|
|
$GLOBALS['config']['TIMEZONE_OFFSET'] = $now->getOffset() / 60;
|
|
|
|
|
$GLOBALS['config']['TIMEZONE_ABBREV'] = $now->format('T');
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-05 11:08:56 -04:00
|
|
|
}
|
2025-05-16 20:02:49 -04:00
|
|
|
|
|
|
|
|
// Simple router
|
|
|
|
|
switch (true) {
|
2025-09-05 11:08:56 -04:00
|
|
|
case $requestPath == '/' || $requestPath == '':
|
2025-05-16 20:02:49 -04:00
|
|
|
require_once 'controllers/DashboardController.php';
|
|
|
|
|
$controller = new DashboardController($conn);
|
|
|
|
|
$controller->index();
|
|
|
|
|
break;
|
|
|
|
|
|
2025-09-05 11:08:56 -04:00
|
|
|
case preg_match('/^\/ticket\/(\d+)$/', $requestPath, $matches):
|
2025-05-16 20:02:49 -04:00
|
|
|
require_once 'controllers/TicketController.php';
|
|
|
|
|
$controller = new TicketController($conn);
|
|
|
|
|
$controller->view($matches[1]);
|
|
|
|
|
break;
|
|
|
|
|
|
2025-09-05 11:08:56 -04:00
|
|
|
case $requestPath == '/ticket/create':
|
2025-05-16 20:02:49 -04:00
|
|
|
require_once 'controllers/TicketController.php';
|
|
|
|
|
$controller = new TicketController($conn);
|
|
|
|
|
$controller->create();
|
|
|
|
|
break;
|
|
|
|
|
|
2025-09-05 11:08:56 -04:00
|
|
|
// API Routes - these handle their own database connections
|
|
|
|
|
case $requestPath == '/api/update_ticket.php':
|
|
|
|
|
require_once 'api/update_ticket.php';
|
2025-05-16 20:02:49 -04:00
|
|
|
break;
|
|
|
|
|
|
2025-09-05 11:08:56 -04:00
|
|
|
case $requestPath == '/api/add_comment.php':
|
|
|
|
|
require_once 'api/add_comment.php';
|
2025-05-16 20:02:49 -04:00
|
|
|
break;
|
Implement comprehensive improvement plan (Phases 1-6)
Security (Phase 1-2):
- Add SecurityHeadersMiddleware with CSP, X-Frame-Options, etc.
- Add RateLimitMiddleware for API rate limiting
- Add security event logging to AuditLogModel
- Add ResponseHelper for standardized API responses
- Update config.php with security constants
Database (Phase 3):
- Add migration 014 for additional indexes
- Add migration 015 for ticket dependencies
- Add migration 016 for ticket attachments
- Add migration 017 for recurring tickets
- Add migration 018 for custom fields
Features (Phase 4-5):
- Add ticket dependencies with DependencyModel and API
- Add duplicate detection with check_duplicates API
- Add file attachments with AttachmentModel and upload/download APIs
- Add @mentions with autocomplete and highlighting
- Add quick actions on dashboard rows
Collaboration (Phase 5):
- Add mention extraction in CommentModel
- Add mention autocomplete dropdown in ticket.js
- Add mention highlighting CSS styles
Admin & Export (Phase 6):
- Add StatsModel for dashboard widgets
- Add dashboard stats cards (open, critical, unassigned, etc.)
- Add CSV/JSON export via export_tickets API
- Add rich text editor toolbar in markdown.js
- Add RecurringTicketModel with cron job
- Add CustomFieldModel for per-category fields
- Add admin views: RecurringTickets, CustomFields, Workflow,
Templates, AuditLog, UserActivity
- Add admin APIs: manage_workflows, manage_templates,
manage_recurring, custom_fields, get_users
- Add admin routes in index.php
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 09:55:01 -05:00
|
|
|
|
2026-01-24 16:59:29 -05:00
|
|
|
case $requestPath == '/api/update_comment.php':
|
|
|
|
|
require_once 'api/update_comment.php';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case $requestPath == '/api/delete_comment.php':
|
|
|
|
|
require_once 'api/delete_comment.php';
|
|
|
|
|
break;
|
|
|
|
|
|
2026-01-23 21:19:24 -05:00
|
|
|
case $requestPath == '/api/ticket_dependencies.php':
|
|
|
|
|
require_once 'api/ticket_dependencies.php';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case $requestPath == '/api/upload_attachment.php':
|
|
|
|
|
require_once 'api/upload_attachment.php';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case $requestPath == '/api/delete_attachment.php':
|
|
|
|
|
require_once 'api/delete_attachment.php';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case $requestPath == '/api/get_users.php':
|
|
|
|
|
require_once 'api/get_users.php';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case $requestPath == '/api/assign_ticket.php':
|
|
|
|
|
require_once 'api/assign_ticket.php';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case $requestPath == '/api/get_template.php':
|
|
|
|
|
require_once 'api/get_template.php';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case $requestPath == '/api/bulk_operation.php':
|
|
|
|
|
require_once 'api/bulk_operation.php';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case $requestPath == '/api/export_tickets.php':
|
|
|
|
|
require_once 'api/export_tickets.php';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case $requestPath == '/api/generate_api_key.php':
|
|
|
|
|
require_once 'api/generate_api_key.php';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case $requestPath == '/api/revoke_api_key.php':
|
|
|
|
|
require_once 'api/revoke_api_key.php';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case $requestPath == '/api/manage_templates.php':
|
|
|
|
|
require_once 'api/manage_templates.php';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case $requestPath == '/api/manage_workflows.php':
|
|
|
|
|
require_once 'api/manage_workflows.php';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case $requestPath == '/api/manage_recurring.php':
|
|
|
|
|
require_once 'api/manage_recurring.php';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case $requestPath == '/api/check_duplicates.php':
|
|
|
|
|
require_once 'api/check_duplicates.php';
|
|
|
|
|
break;
|
|
|
|
|
|
Implement comprehensive improvement plan (Phases 1-6)
Security (Phase 1-2):
- Add SecurityHeadersMiddleware with CSP, X-Frame-Options, etc.
- Add RateLimitMiddleware for API rate limiting
- Add security event logging to AuditLogModel
- Add ResponseHelper for standardized API responses
- Update config.php with security constants
Database (Phase 3):
- Add migration 014 for additional indexes
- Add migration 015 for ticket dependencies
- Add migration 016 for ticket attachments
- Add migration 017 for recurring tickets
- Add migration 018 for custom fields
Features (Phase 4-5):
- Add ticket dependencies with DependencyModel and API
- Add duplicate detection with check_duplicates API
- Add file attachments with AttachmentModel and upload/download APIs
- Add @mentions with autocomplete and highlighting
- Add quick actions on dashboard rows
Collaboration (Phase 5):
- Add mention extraction in CommentModel
- Add mention autocomplete dropdown in ticket.js
- Add mention highlighting CSS styles
Admin & Export (Phase 6):
- Add StatsModel for dashboard widgets
- Add dashboard stats cards (open, critical, unassigned, etc.)
- Add CSV/JSON export via export_tickets API
- Add rich text editor toolbar in markdown.js
- Add RecurringTicketModel with cron job
- Add CustomFieldModel for per-category fields
- Add admin views: RecurringTickets, CustomFields, Workflow,
Templates, AuditLog, UserActivity
- Add admin APIs: manage_workflows, manage_templates,
manage_recurring, custom_fields, get_users
- Add admin routes in index.php
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 09:55:01 -05:00
|
|
|
// Admin Routes - require admin privileges
|
|
|
|
|
case $requestPath == '/admin/recurring-tickets':
|
|
|
|
|
if (!$currentUser || !$currentUser['is_admin']) {
|
|
|
|
|
header("HTTP/1.0 403 Forbidden");
|
|
|
|
|
echo 'Admin access required';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
require_once 'models/RecurringTicketModel.php';
|
|
|
|
|
$recurringModel = new RecurringTicketModel($conn);
|
|
|
|
|
$recurringTickets = $recurringModel->getAll(true);
|
|
|
|
|
include 'views/admin/RecurringTicketsView.php';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case $requestPath == '/admin/custom-fields':
|
|
|
|
|
if (!$currentUser || !$currentUser['is_admin']) {
|
|
|
|
|
header("HTTP/1.0 403 Forbidden");
|
|
|
|
|
echo 'Admin access required';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
require_once 'models/CustomFieldModel.php';
|
|
|
|
|
$fieldModel = new CustomFieldModel($conn);
|
|
|
|
|
$customFields = $fieldModel->getAllDefinitions(null, false);
|
|
|
|
|
include 'views/admin/CustomFieldsView.php';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case $requestPath == '/admin/workflow':
|
|
|
|
|
if (!$currentUser || !$currentUser['is_admin']) {
|
|
|
|
|
header("HTTP/1.0 403 Forbidden");
|
|
|
|
|
echo 'Admin access required';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
$result = $conn->query("SELECT * FROM status_transitions ORDER BY from_status, to_status");
|
|
|
|
|
$workflows = [];
|
|
|
|
|
while ($row = $result->fetch_assoc()) {
|
|
|
|
|
$workflows[] = $row;
|
|
|
|
|
}
|
|
|
|
|
include 'views/admin/WorkflowDesignerView.php';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case $requestPath == '/admin/templates':
|
|
|
|
|
if (!$currentUser || !$currentUser['is_admin']) {
|
|
|
|
|
header("HTTP/1.0 403 Forbidden");
|
|
|
|
|
echo 'Admin access required';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
$result = $conn->query("SELECT * FROM ticket_templates ORDER BY template_name");
|
|
|
|
|
$templates = [];
|
|
|
|
|
while ($row = $result->fetch_assoc()) {
|
|
|
|
|
$templates[] = $row;
|
|
|
|
|
}
|
|
|
|
|
include 'views/admin/TemplatesView.php';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case $requestPath == '/admin/audit-log':
|
|
|
|
|
if (!$currentUser || !$currentUser['is_admin']) {
|
|
|
|
|
header("HTTP/1.0 403 Forbidden");
|
|
|
|
|
echo 'Admin access required';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
$page = isset($_GET['page']) ? max(1, (int)$_GET['page']) : 1;
|
|
|
|
|
$perPage = 50;
|
|
|
|
|
$offset = ($page - 1) * $perPage;
|
|
|
|
|
|
|
|
|
|
$filters = [];
|
|
|
|
|
$whereConditions = [];
|
|
|
|
|
$params = [];
|
|
|
|
|
$types = '';
|
|
|
|
|
|
|
|
|
|
if (!empty($_GET['action_type'])) {
|
|
|
|
|
$whereConditions[] = "al.action_type = ?";
|
|
|
|
|
$params[] = $_GET['action_type'];
|
|
|
|
|
$types .= 's';
|
|
|
|
|
$filters['action_type'] = $_GET['action_type'];
|
|
|
|
|
}
|
|
|
|
|
if (!empty($_GET['user_id'])) {
|
|
|
|
|
$whereConditions[] = "al.user_id = ?";
|
|
|
|
|
$params[] = (int)$_GET['user_id'];
|
|
|
|
|
$types .= 'i';
|
|
|
|
|
$filters['user_id'] = $_GET['user_id'];
|
|
|
|
|
}
|
|
|
|
|
if (!empty($_GET['date_from'])) {
|
|
|
|
|
$whereConditions[] = "DATE(al.created_at) >= ?";
|
|
|
|
|
$params[] = $_GET['date_from'];
|
|
|
|
|
$types .= 's';
|
|
|
|
|
$filters['date_from'] = $_GET['date_from'];
|
|
|
|
|
}
|
|
|
|
|
if (!empty($_GET['date_to'])) {
|
|
|
|
|
$whereConditions[] = "DATE(al.created_at) <= ?";
|
|
|
|
|
$params[] = $_GET['date_to'];
|
|
|
|
|
$types .= 's';
|
|
|
|
|
$filters['date_to'] = $_GET['date_to'];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$where = !empty($whereConditions) ? 'WHERE ' . implode(' AND ', $whereConditions) : '';
|
|
|
|
|
|
|
|
|
|
$countSql = "SELECT COUNT(*) as total FROM audit_log al $where";
|
|
|
|
|
if (!empty($params)) {
|
|
|
|
|
$stmt = $conn->prepare($countSql);
|
|
|
|
|
$stmt->bind_param($types, ...$params);
|
|
|
|
|
$stmt->execute();
|
|
|
|
|
$countResult = $stmt->get_result();
|
|
|
|
|
} else {
|
|
|
|
|
$countResult = $conn->query($countSql);
|
|
|
|
|
}
|
|
|
|
|
$totalLogs = $countResult->fetch_assoc()['total'];
|
|
|
|
|
$totalPages = ceil($totalLogs / $perPage);
|
|
|
|
|
|
|
|
|
|
$sql = "SELECT al.*, u.display_name, u.username
|
|
|
|
|
FROM audit_log al
|
|
|
|
|
LEFT JOIN users u ON al.user_id = u.user_id
|
|
|
|
|
$where
|
|
|
|
|
ORDER BY al.created_at DESC
|
|
|
|
|
LIMIT $perPage OFFSET $offset";
|
|
|
|
|
|
|
|
|
|
if (!empty($params)) {
|
|
|
|
|
$stmt = $conn->prepare($sql);
|
|
|
|
|
$stmt->bind_param($types, ...$params);
|
|
|
|
|
$stmt->execute();
|
|
|
|
|
$result = $stmt->get_result();
|
|
|
|
|
} else {
|
|
|
|
|
$result = $conn->query($sql);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$auditLogs = [];
|
|
|
|
|
while ($row = $result->fetch_assoc()) {
|
|
|
|
|
$auditLogs[] = $row;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$usersResult = $conn->query("SELECT user_id, username, display_name FROM users ORDER BY display_name");
|
|
|
|
|
$users = [];
|
|
|
|
|
while ($row = $usersResult->fetch_assoc()) {
|
|
|
|
|
$users[] = $row;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
include 'views/admin/AuditLogView.php';
|
|
|
|
|
break;
|
|
|
|
|
|
2026-01-23 10:01:50 -05:00
|
|
|
case $requestPath == '/admin/api-keys':
|
|
|
|
|
if (!$currentUser || !$currentUser['is_admin']) {
|
|
|
|
|
header("HTTP/1.0 403 Forbidden");
|
|
|
|
|
echo 'Admin access required';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
require_once 'models/ApiKeyModel.php';
|
|
|
|
|
$apiKeyModel = new ApiKeyModel($conn);
|
|
|
|
|
$apiKeys = $apiKeyModel->getAllKeys();
|
|
|
|
|
include 'views/admin/ApiKeysView.php';
|
|
|
|
|
break;
|
|
|
|
|
|
Implement comprehensive improvement plan (Phases 1-6)
Security (Phase 1-2):
- Add SecurityHeadersMiddleware with CSP, X-Frame-Options, etc.
- Add RateLimitMiddleware for API rate limiting
- Add security event logging to AuditLogModel
- Add ResponseHelper for standardized API responses
- Update config.php with security constants
Database (Phase 3):
- Add migration 014 for additional indexes
- Add migration 015 for ticket dependencies
- Add migration 016 for ticket attachments
- Add migration 017 for recurring tickets
- Add migration 018 for custom fields
Features (Phase 4-5):
- Add ticket dependencies with DependencyModel and API
- Add duplicate detection with check_duplicates API
- Add file attachments with AttachmentModel and upload/download APIs
- Add @mentions with autocomplete and highlighting
- Add quick actions on dashboard rows
Collaboration (Phase 5):
- Add mention extraction in CommentModel
- Add mention autocomplete dropdown in ticket.js
- Add mention highlighting CSS styles
Admin & Export (Phase 6):
- Add StatsModel for dashboard widgets
- Add dashboard stats cards (open, critical, unassigned, etc.)
- Add CSV/JSON export via export_tickets API
- Add rich text editor toolbar in markdown.js
- Add RecurringTicketModel with cron job
- Add CustomFieldModel for per-category fields
- Add admin views: RecurringTickets, CustomFields, Workflow,
Templates, AuditLog, UserActivity
- Add admin APIs: manage_workflows, manage_templates,
manage_recurring, custom_fields, get_users
- Add admin routes in index.php
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 09:55:01 -05:00
|
|
|
case $requestPath == '/admin/user-activity':
|
|
|
|
|
if (!$currentUser || !$currentUser['is_admin']) {
|
|
|
|
|
header("HTTP/1.0 403 Forbidden");
|
|
|
|
|
echo 'Admin access required';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$dateRange = [
|
|
|
|
|
'from' => $_GET['date_from'] ?? date('Y-m-d', strtotime('-30 days')),
|
|
|
|
|
'to' => $_GET['date_to'] ?? date('Y-m-d')
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$sql = "SELECT
|
|
|
|
|
u.user_id, u.username, u.display_name, u.is_admin,
|
|
|
|
|
(SELECT COUNT(*) FROM tickets t WHERE t.created_by = u.user_id AND DATE(t.created_at) BETWEEN ? AND ?) as tickets_created,
|
|
|
|
|
(SELECT COUNT(*) FROM tickets t WHERE t.assigned_to = u.user_id AND t.status = 'Closed' AND DATE(t.updated_at) BETWEEN ? AND ?) as tickets_resolved,
|
|
|
|
|
(SELECT COUNT(*) FROM ticket_comments tc WHERE tc.user_id = u.user_id AND DATE(tc.created_at) BETWEEN ? AND ?) as comments_added,
|
|
|
|
|
(SELECT COUNT(*) FROM tickets t WHERE t.assigned_to = u.user_id AND DATE(t.created_at) BETWEEN ? AND ?) as tickets_assigned,
|
|
|
|
|
(SELECT MAX(al.created_at) FROM audit_log al WHERE al.user_id = u.user_id) as last_activity
|
|
|
|
|
FROM users u
|
|
|
|
|
ORDER BY tickets_created DESC, tickets_resolved DESC";
|
|
|
|
|
|
|
|
|
|
$stmt = $conn->prepare($sql);
|
|
|
|
|
$stmt->bind_param('ssssssss',
|
|
|
|
|
$dateRange['from'], $dateRange['to'],
|
|
|
|
|
$dateRange['from'], $dateRange['to'],
|
|
|
|
|
$dateRange['from'], $dateRange['to'],
|
|
|
|
|
$dateRange['from'], $dateRange['to']
|
|
|
|
|
);
|
|
|
|
|
$stmt->execute();
|
|
|
|
|
$result = $stmt->get_result();
|
|
|
|
|
|
|
|
|
|
$userStats = [];
|
|
|
|
|
while ($row = $result->fetch_assoc()) {
|
|
|
|
|
$userStats[] = $row;
|
|
|
|
|
}
|
|
|
|
|
$stmt->close();
|
|
|
|
|
|
|
|
|
|
include 'views/admin/UserActivityView.php';
|
|
|
|
|
break;
|
|
|
|
|
|
2025-09-05 11:08:56 -04:00
|
|
|
// Legacy support for old URLs
|
|
|
|
|
case $requestPath == '/dashboard.php':
|
|
|
|
|
header("Location: /");
|
|
|
|
|
exit;
|
|
|
|
|
|
|
|
|
|
case preg_match('/^\/ticket\.php/', $requestPath) && isset($_GET['id']):
|
|
|
|
|
header("Location: /ticket/" . $_GET['id']);
|
|
|
|
|
exit;
|
|
|
|
|
|
2025-05-16 20:02:49 -04:00
|
|
|
default:
|
|
|
|
|
// 404 Not Found
|
|
|
|
|
header("HTTP/1.0 404 Not Found");
|
|
|
|
|
echo '404 Page Not Found';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-05 11:08:56 -04:00
|
|
|
// Close database connection if it was opened
|
|
|
|
|
if (isset($conn)) {
|
|
|
|
|
$conn->close();
|
|
|
|
|
}
|
|
|
|
|
?>
|