#include "audit_log.h" #include namespace mosis { //============================================================================= // CONSTRUCTOR //============================================================================= AuditLog::AuditLog(size_t max_entries) : m_max_entries(max_entries) { m_entries.resize(max_entries); } //============================================================================= // LOGGING //============================================================================= void AuditLog::Log(AuditEvent event, const std::string& app_id, const std::string& details, bool success) { std::lock_guard lock(m_mutex); AuditEntry entry{ .timestamp = std::chrono::system_clock::now(), .event = event, .app_id = app_id, .details = details, .success = success }; m_entries[m_write_index] = std::move(entry); m_write_index = (m_write_index + 1) % m_max_entries; m_total_logged++; if (m_total_logged > m_max_entries) { m_wrapped = true; } } //============================================================================= // QUERIES //============================================================================= std::vector AuditLog::GetEntries(size_t count) const { std::lock_guard lock(m_mutex); std::vector result; size_t stored = GetStoredEntries(); count = std::min(count, stored); result.reserve(count); // Read from most recent backwards for (size_t i = 0; i < count; i++) { size_t idx = (m_write_index + m_max_entries - 1 - i) % m_max_entries; result.push_back(m_entries[idx]); } return result; } std::vector AuditLog::GetEntriesForApp(const std::string& app_id, size_t count) const { std::lock_guard lock(m_mutex); std::vector result; result.reserve(count); size_t stored = GetStoredEntries(); for (size_t i = 0; i < stored && result.size() < count; i++) { size_t idx = (m_write_index + m_max_entries - 1 - i) % m_max_entries; if (m_entries[idx].app_id == app_id) { result.push_back(m_entries[idx]); } } return result; } std::vector AuditLog::GetEntriesByEvent(AuditEvent event, size_t count) const { std::lock_guard lock(m_mutex); std::vector result; result.reserve(count); size_t stored = GetStoredEntries(); for (size_t i = 0; i < stored && result.size() < count; i++) { size_t idx = (m_write_index + m_max_entries - 1 - i) % m_max_entries; if (m_entries[idx].event == event) { result.push_back(m_entries[idx]); } } return result; } //============================================================================= // STATISTICS //============================================================================= size_t AuditLog::GetTotalEntries() const { std::lock_guard lock(m_mutex); return m_total_logged; } size_t AuditLog::GetStoredEntries() const { // Note: caller should hold lock if (m_wrapped) { return m_max_entries; } return m_write_index; } size_t AuditLog::CountEvents(AuditEvent event, const std::string& app_id) const { std::lock_guard lock(m_mutex); size_t count = 0; size_t stored = GetStoredEntries(); for (size_t i = 0; i < stored; i++) { const auto& entry = m_entries[i]; if (entry.event == event) { if (app_id.empty() || entry.app_id == app_id) { count++; } } } return count; } //============================================================================= // CLEAR //============================================================================= void AuditLog::Clear() { std::lock_guard lock(m_mutex); m_write_index = 0; m_total_logged = 0; m_wrapped = false; // Clear all entries for (auto& entry : m_entries) { entry = AuditEntry{}; } } //============================================================================= // UTILITIES //============================================================================= const char* AuditLog::EventToString(AuditEvent event) { switch (event) { case AuditEvent::AppStart: return "AppStart"; case AuditEvent::AppStop: return "AppStop"; case AuditEvent::PermissionCheck: return "PermissionCheck"; case AuditEvent::PermissionGranted: return "PermissionGranted"; case AuditEvent::PermissionDenied: return "PermissionDenied"; case AuditEvent::NetworkRequest: return "NetworkRequest"; case AuditEvent::NetworkBlocked: return "NetworkBlocked"; case AuditEvent::FileAccess: return "FileAccess"; case AuditEvent::FileBlocked: return "FileBlocked"; case AuditEvent::DatabaseAccess: return "DatabaseAccess"; case AuditEvent::CameraAccess: return "CameraAccess"; case AuditEvent::MicrophoneAccess: return "MicrophoneAccess"; case AuditEvent::LocationAccess: return "LocationAccess"; case AuditEvent::SandboxViolation: return "SandboxViolation"; case AuditEvent::ResourceLimitHit: return "ResourceLimitHit"; case AuditEvent::RateLimitHit: return "RateLimitHit"; case AuditEvent::Custom: return "Custom"; default: return "Unknown"; } } //============================================================================= // GLOBAL INSTANCE //============================================================================= AuditLog& GetAuditLog() { static AuditLog instance(10000); return instance; } } // namespace mosis