Files
musadaq-saas/app/modules_app/dashboard/recent_activity.php
2026-05-07 18:56:48 +03:00

184 lines
4.9 KiB
PHP

<?php
/**
* Dashboard Recent Activity Endpoint
*/
declare(strict_types=1);
use App\Core\Database;
use App\Core\Encryption;
use App\Middleware\AuthMiddleware;
$decoded = AuthMiddleware::check();
$db = Database::getInstance();
$tenantId = $decoded['tenant_id'] ?? null;
$role = $decoded['role'];
try {
if ($role === 'super_admin') {
$where = "WHERE 1=1";
$params = [];
} else {
$where = "WHERE a.tenant_id = ?";
$params = [$tenantId];
}
$stmt = $db->prepare("
SELECT
a.id,
a.action,
a.entity_type,
a.entity_id,
a.new_data,
a.created_at,
u.name AS user_name
FROM audit_logs a
LEFT JOIN users u ON a.user_id = u.id
$where
ORDER BY a.created_at DESC
LIMIT 20
");
$stmt->execute($params);
$activities = $stmt->fetchAll();
foreach ($activities as &$activity) {
$activity['user_name'] = decryptIfEncrypted($activity['user_name'] ?? null) ?: 'مستخدم مجهول';
$activity['details'] = decodeAuditData($activity['new_data'] ?? null);
$activity['summary'] = buildActivitySummary($activity);
unset($activity['new_data']);
}
unset($activity);
json_success($activities);
} catch (\Exception $e) {
error_log('Dashboard Recent Activity Error: ' . $e->getMessage());
json_error('Failed to fetch recent activity', 500);
}
function decodeAuditData(?string $json): array
{
if (!$json) {
return [];
}
$decoded = json_decode($json, true);
if (!is_array($decoded)) {
return [];
}
return decryptAuditPayload($decoded);
}
function decryptAuditPayload(array $payload): array
{
foreach ($payload as $key => $value) {
if (is_array($value)) {
$payload[$key] = decryptAuditPayload($value);
continue;
}
if (is_string($value)) {
$payload[$key] = decryptIfEncrypted($value);
}
}
return $payload;
}
function decryptIfEncrypted(mixed $value): string
{
if ($value === null) {
return '';
}
$text = trim((string)$value);
if ($text === '' || !looksEncrypted($text)) {
return $text;
}
try {
$decrypted = Encryption::decrypt($text);
return $decrypted !== false ? $decrypted : $text;
} catch (\Throwable $e) {
return $text;
}
}
function looksEncrypted(string $value): bool
{
$normalized = str_starts_with($value, '==') ? substr($value, 2) : $value;
if (strlen($normalized) < 40 || strlen($normalized) % 4 !== 0) {
return false;
}
return (bool)preg_match('/^[A-Za-z0-9+\/]+={0,2}$/', $normalized);
}
function buildActivitySummary(array $activity): string
{
$data = is_array($activity['details'] ?? null) ? $activity['details'] : [];
$action = (string)($activity['action'] ?? '');
return match ($action) {
'payment.created' => buildPaymentSummary('تم إنشاء طلب دفع', $data),
'payment.approved' => buildPaymentSummary('تم اعتماد طلب دفع', $data),
'payment.rejected' => buildPaymentSummary('تم رفض طلب دفع', $data),
'subscription.activated' => buildPaymentSummary('تم تفعيل الاشتراك', $data),
'invoice.approved' => buildEntitySummary('تم اعتماد الفاتورة', $data, ['invoice_number', 'number']),
'invoice.extracted' => buildEntitySummary('تم استخراج بيانات الفاتورة', $data, ['invoice_number', 'number']),
'company.created' => buildEntitySummary('تمت إضافة شركة', $data, ['name', 'company_name']),
'user.created' => buildEntitySummary('تمت إضافة مستخدم', $data, ['name', 'email']),
default => '',
};
}
function buildPaymentSummary(string $label, array $data): string
{
$parts = [$label];
$plan = firstTextValue($data, ['plan_name', 'plan_name_ar', 'plan_id']);
if ($plan !== '') {
$parts[] = "الباقة: {$plan}";
}
$amount = firstTextValue($data, ['amount', 'amount_jod', 'price_jod']);
if ($amount !== '') {
$parts[] = "القيمة: {$amount} د.أ";
}
$reference = firstTextValue($data, ['ref', 'reference', 'internal_reference']);
if ($reference !== '') {
$parts[] = "المرجع: {$reference}";
}
return implode(' - ', $parts);
}
function buildEntitySummary(string $label, array $data, array $keys): string
{
$value = firstTextValue($data, $keys);
return $value === '' ? $label : "{$label}: {$value}";
}
function firstTextValue(array $data, array $keys): string
{
foreach ($keys as $key) {
if (!array_key_exists($key, $data) || $data[$key] === null) {
continue;
}
$value = $data[$key];
if (is_scalar($value)) {
$text = trim((string)$value);
if ($text !== '') {
return $text;
}
}
}
return '';
}