ApplicationLogger Class: - Structured JSON logging to logs/application.log - Tracks all actions: master_asset_submission, global_to_local_transform, box_upload, omg_api_lookup - Captures: timestamp, user email/name, status, detailed data, IP address, user agent - Methods: getRecentLogs(), getLogsByAction(), getLogsByUser(), getStatistics() Logging Integration: - submit.php: Logs all asset submissions (success/failure) - process-csv.php: Logs all CSV transformations - upload-to-box.php: Logs all Box uploads - Tracks campaign numbers, business units, file counts, dates Logs Viewer (logs-viewer.php): - New tab "Activity Logs" in navigation - Statistics dashboard (total actions, success rate, errors, unique users) - Filterable table (by action type, user, date range) - View detailed data for each log entry (expandable JSON) - Export to CSV functionality - Shows last 100 entries by default (configurable) Email Service Enhancement: - Added SMTP support (in addition to Mailgun API) - Configured for smtp.mailgun.org with provided credentials - Sends notifications to logged-in user email - Proper SMTP protocol implementation with AUTH LOGIN OMG API Configuration: - Added 'enabled' flag (currently false due to 403 error) - Added 'fallback_business_unit' for when OMG disabled - Uses X-API-Key header format - Comprehensive error logging - When API permissions are fixed, set enabled=true Security: - logs/ directory excluded from git - .gitkeep file to preserve directory structure - Protected by .htaccess (log files already blocked) Usage: - All activity automatically logged - View reports at /logs-viewer.php - Export logs as CSV for analysis - Filter by action type, user, or time period - Monitor system health and usage patterns 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
172 lines
5.4 KiB
PHP
172 lines
5.4 KiB
PHP
<?php
|
|
/**
|
|
* Form Submission Handler
|
|
* Processes the form and sends data to webhook
|
|
*/
|
|
|
|
// Enable error reporting for debugging
|
|
error_reporting(E_ALL);
|
|
ini_set('display_errors', 1);
|
|
ini_set('log_errors', 1);
|
|
|
|
// Set JSON header
|
|
header('Content-Type: application/json');
|
|
|
|
try {
|
|
// Load dependencies
|
|
require_once __DIR__ . '/vendor/autoload.php';
|
|
require_once __DIR__ . '/AuthMiddleware.php';
|
|
require_once __DIR__ . '/BoxService.php';
|
|
require_once __DIR__ . '/ApplicationLogger.php';
|
|
|
|
// Check authentication
|
|
$auth = new AuthMiddleware();
|
|
$user = $auth->requireAuth();
|
|
|
|
// Initialize logger
|
|
$logger = new ApplicationLogger();
|
|
|
|
// Check if this is a POST request
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|
http_response_code(405);
|
|
echo json_encode([
|
|
'success' => false,
|
|
'error' => 'Method not allowed'
|
|
]);
|
|
exit;
|
|
}
|
|
|
|
// Get request body
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
|
|
// Validate required fields
|
|
$requiredFields = ['boxId', 'supplyDate', 'liveDate', 'endDate', 'boxData'];
|
|
foreach ($requiredFields as $field) {
|
|
if (!isset($input[$field]) || empty($input[$field])) {
|
|
http_response_code(400);
|
|
echo json_encode([
|
|
'success' => false,
|
|
'error' => "Missing required field: $field"
|
|
]);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
// Load configuration
|
|
$config = require __DIR__ . '/config.php';
|
|
$webhookConfig = $config['webhook'];
|
|
|
|
// Prepare webhook payload
|
|
$payload = [
|
|
'userEmail' => $user['email'],
|
|
'userName' => $user['name'],
|
|
'boxId' => $input['boxId'],
|
|
'masterCampaignNumber' => $input['boxData']['masterCampaignNumber'] ?? 'N/A',
|
|
'masterCampaignId' => $input['boxData']['masterCampaignId'] ?? null,
|
|
'supplyDate' => $input['supplyDate'],
|
|
'liveDate' => $input['liveDate'],
|
|
'endDate' => $input['endDate'],
|
|
'boxContents' => [
|
|
'folderName' => $input['boxData']['folderName'] ?? '',
|
|
'totalItems' => $input['boxData']['contents']['total'] ?? 0,
|
|
'folders' => $input['boxData']['contents']['folders'] ?? [],
|
|
'files' => $input['boxData']['contents']['files'] ?? []
|
|
],
|
|
'submittedAt' => date('Y-m-d H:i:s')
|
|
];
|
|
|
|
// Send to webhook
|
|
// Make.com webhooks typically don't need API key headers
|
|
// The URL itself is the authentication
|
|
$ch = curl_init($webhookConfig['url']);
|
|
|
|
$jsonPayload = json_encode($payload);
|
|
error_log('Sending to webhook: ' . $webhookConfig['url']);
|
|
error_log('Payload: ' . $jsonPayload);
|
|
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_POST => true,
|
|
CURLOPT_POSTFIELDS => $jsonPayload,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => $webhookConfig['timeout'],
|
|
CURLOPT_HTTPHEADER => [
|
|
'Content-Type: application/json',
|
|
'x-make-apikey: ' . $webhookConfig['api_key']
|
|
]
|
|
]);
|
|
|
|
$webhookResponse = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
$curlError = curl_error($ch);
|
|
curl_close($ch);
|
|
|
|
if ($curlError) {
|
|
throw new Exception('Webhook request failed: ' . $curlError);
|
|
}
|
|
|
|
// Parse webhook response
|
|
$webhookData = json_decode($webhookResponse, true);
|
|
|
|
// Check if webhook returned success
|
|
if ($httpCode >= 200 && $httpCode < 300) {
|
|
// Log successful submission
|
|
$logger->logAssetSubmission(
|
|
$user,
|
|
$input['boxId'],
|
|
$input['boxData']['masterCampaignNumber'] ?? 'N/A',
|
|
[
|
|
'supply' => $input['supplyDate'],
|
|
'live' => $input['liveDate'],
|
|
'end' => $input['endDate']
|
|
],
|
|
'success'
|
|
);
|
|
|
|
// Webhook accepted the data
|
|
echo json_encode([
|
|
'success' => true,
|
|
'message' => 'Submission successful',
|
|
'webhookResponse' => $webhookData,
|
|
'webhookStatus' => $httpCode
|
|
]);
|
|
} else {
|
|
// Log failed submission
|
|
$logger->logAssetSubmission(
|
|
$user,
|
|
$input['boxId'],
|
|
$input['boxData']['masterCampaignNumber'] ?? 'N/A',
|
|
[
|
|
'supply' => $input['supplyDate'],
|
|
'live' => $input['liveDate'],
|
|
'end' => $input['endDate']
|
|
],
|
|
'error',
|
|
'Webhook returned status ' . $httpCode
|
|
);
|
|
// Webhook rejected or failed - return 200 to client but indicate webhook failure
|
|
error_log('Webhook failed with status: ' . $httpCode);
|
|
error_log('Webhook response: ' . $webhookResponse);
|
|
|
|
echo json_encode([
|
|
'success' => false,
|
|
'error' => 'Webhook processing failed',
|
|
'webhookResponse' => $webhookData ?? $webhookResponse,
|
|
'webhookStatus' => $httpCode,
|
|
'message' => 'The webhook returned status ' . $httpCode . '. Please check the webhook configuration.'
|
|
]);
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
// Log error
|
|
error_log('Submission error: ' . $e->getMessage());
|
|
error_log('Stack trace: ' . $e->getTraceAsString());
|
|
|
|
http_response_code(500);
|
|
echo json_encode([
|
|
'success' => false,
|
|
'error' => 'Server error occurred during submission',
|
|
'debug' => $e->getMessage(),
|
|
'file' => $e->getFile(),
|
|
'line' => $e->getLine()
|
|
]);
|
|
}
|