Add dashboard audit log and configuration management

- Implemented dashboard audit logging with InsertAuditLog, GetRecentAuditLogs, GetAuditLogsByIP, and CleanupOldAuditLogs methods.
- Created dashboard configuration management with GetDashboardConfig and SetDashboardConfig methods.
- Added new tables for dashboard_audit_log and dashboard_config in both MySQL and SQLite migrations.
- Updated CMakeLists to include Crow and ASIO for dashboard server functionality.
- Enhanced existing database classes to support new dashboard features, including character, play key, and property management.
- Added new methods for retrieving and managing play keys, properties, and pet names.
- Updated TestSQLDatabase to include stubs for new dashboard-related methods.
- Modified shared and dashboard configuration files for new settings.
This commit is contained in:
Aaron Kimbrell
2026-04-22 11:01:41 -05:00
parent d532a9b063
commit e3467465b4
92 changed files with 9133 additions and 77 deletions

View File

@@ -5,6 +5,7 @@
#include <optional>
#include <string>
#include <string_view>
#include <vector>
enum class eGameMasterLevel : uint8_t;
@@ -38,7 +39,62 @@ public:
// Update the GameMaster level of an account.
virtual void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) = 0;
// Set the play_key_id for an account (used during registration)
virtual void UpdateAccountPlayKey(const uint32_t accountId, const uint32_t playKeyId) = 0;
// Get counts for dashboard/stats
virtual uint32_t GetBannedAccountCount() = 0;
virtual uint32_t GetLockedAccountCount() = 0;
virtual uint32_t GetAccountCount() = 0;
struct ListInfo {
uint32_t id{};
std::string name;
eGameMasterLevel gm_level{};
bool banned{};
bool locked{};
uint64_t mute_expire{};
uint32_t play_key_id{};
};
struct DetailedInfo {
uint32_t id{};
std::string name;
std::string email;
eGameMasterLevel gm_level{};
bool banned{};
bool locked{};
uint64_t mute_expire{};
uint32_t play_key_id{};
uint64_t created_at{};
};
struct SessionInfo {
uint64_t sessionId{};
std::string ipAddress;
uint64_t loginTime{};
uint64_t logoutTime{};
bool active{};
};
// Return all accounts for dashboard listing
virtual std::vector<ListInfo> GetAllAccounts() = 0;
// Update an account's locked status
virtual void UpdateAccountLock(const uint32_t accountId, const bool locked) = 0;
// Get detailed account info by ID (for dashboard viewing)
virtual std::optional<DetailedInfo> GetAccountById(const uint32_t accountId) = 0;
// Update account email (for dashboard)
virtual void UpdateAccountEmail(const uint32_t accountId, const std::string_view email) = 0;
// Delete account and all associated data
virtual void DeleteAccount(const uint32_t accountId) = 0;
// Get account session history
virtual std::vector<SessionInfo> GetAccountSessions(const uint32_t accountId, uint32_t limit = 50) = 0;
};
#endif //!__IACCOUNTS__H__

View File

@@ -15,6 +15,27 @@ class IActivityLog {
public:
// Update the activity log for the given account.
virtual void UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) = 0;
struct Entry {
LWOOBJID characterId{};
eActivityType activity{};
uint32_t timestamp{};
LWOMAPID mapId{};
};
// Retrieve recent activity entries ordered by time desc.
virtual std::vector<Entry> GetRecentActivity(const uint32_t limit) = 0;
// Get total count of activity log entries
virtual uint32_t GetActivityLogCount() = 0;
// Get paginated activity log entries with ordering
virtual std::vector<Entry> GetActivityLogPaginated(
uint32_t offset,
uint32_t limit,
const std::string& orderColumn = "time",
const std::string& orderDir = "DESC"
) = 0;
};
#endif //!__IACTIVITYLOG__H__

View File

@@ -2,7 +2,10 @@
#define __IBUGREPORTS__H__
#include <cstdint>
#include <string>
#include <string_view>
#include <vector>
#include <optional>
class IBugReports {
public:
@@ -14,7 +17,29 @@ public:
LWOOBJID characterId{};
};
struct DetailedInfo {
uint64_t id{};
std::string body;
std::string clientVersion;
std::string otherPlayer;
std::string selection;
LWOOBJID characterId{};
uint64_t submitted{};
uint64_t resolved_time{};
uint32_t resolved_by_id{};
std::string resolution;
};
// Add a new bug report to the database.
virtual void InsertNewBugReport(const Info& info) = 0;
// Dashboard methods
virtual std::vector<DetailedInfo> GetAllBugReports() = 0;
virtual std::vector<DetailedInfo> GetUnresolvedBugReports() = 0;
virtual std::vector<DetailedInfo> GetResolvedBugReports() = 0;
virtual std::optional<DetailedInfo> GetBugReportById(const uint64_t reportId) = 0;
virtual void ResolveBugReport(const uint64_t reportId, const uint32_t resolvedById, const std::string_view resolution) = 0;
virtual uint32_t GetBugReportCount() = 0;
virtual uint32_t GetUnresolvedBugReportCount() = 0;
};
#endif //!__IBUGREPORTS__H__

View File

@@ -9,6 +9,9 @@
#include "ePermissionMap.h"
// Forward declare eActivityType for Activity struct
enum class eActivityType : uint32_t;
class ICharInfo {
public:
struct Info {
@@ -19,6 +22,35 @@ public:
bool needsRename{};
LWOCLONEID cloneId{};
ePermissionMap permissionMap{};
// Extended fields for dashboard
uint32_t level{};
uint64_t uscore{};
uint32_t zoneId{};
uint64_t lastLogin{};
uint64_t createdOn{};
};
struct Stats {
uint64_t totalCurrencyCollected{};
uint64_t totalBricksCollected{};
uint64_t totalSmashables{};
uint64_t totalQuickbuildsCompleted{};
uint64_t totalEnemiesSmashed{};
uint64_t totalRocketsUsed{};
uint64_t totalMissionsCompleted{};
uint64_t totalPetsTamed{};
};
struct InventoryItem {
LWOOBJID itemId{};
uint32_t count{};
int32_t slot{};
};
struct Activity {
uint64_t timestamp{};
eActivityType activity{};
uint32_t mapId{};
};
// Get the approved names of all characters.
@@ -46,6 +78,41 @@ public:
virtual void UpdateLastLoggedInCharacter(const LWOOBJID characterId) = 0;
virtual bool IsNameInUse(const std::string_view name) = 0;
// Get total count of characters
virtual uint32_t GetCharacterCount() = 0;
// Get paginated list of all characters
virtual std::vector<Info> GetAllCharactersPaginated(
uint32_t offset,
uint32_t limit,
const std::string& orderColumn = "id",
const std::string& orderDir = "DESC"
) = 0;
// Get characters with pending names (for moderation)
virtual std::vector<Info> GetCharactersWithPendingNames() = 0;
// Update character permission map (for restrictions)
virtual void UpdateCharacterPermissions(const LWOOBJID characterId, ePermissionMap permissions) = 0;
// Set needs rename flag
virtual void SetCharacterNeedsRename(const LWOOBJID characterId, bool needsRename) = 0;
// Get character statistics
virtual std::optional<Stats> GetCharacterStats(const LWOOBJID characterId) = 0;
// Get character inventory
virtual std::vector<InventoryItem> GetCharacterInventory(const LWOOBJID characterId) = 0;
// Get character activity history
virtual std::vector<Activity> GetCharacterActivity(const LWOOBJID characterId, uint32_t limit = 50) = 0;
// Rescue character to a safe zone
virtual void RescueCharacter(const LWOOBJID characterId, uint32_t zoneId) = 0;
// Delete character and all associated data
virtual void DeleteCharacter(const LWOOBJID characterId) = 0;
};
#endif //!__ICHARINFO__H__

View File

@@ -2,13 +2,24 @@
#define __ICOMMANDLOG__H__
#include <cstdint>
#include <string>
#include <string_view>
#include <vector>
class ICommandLog {
public:
public:
struct Entry {
uint64_t timestamp{};
LWOOBJID characterId{};
std::string command;
std::string arguments;
};
// Insert a new slash command log entry.
virtual void InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) = 0;
// Get recent command log entries
virtual std::vector<Entry> GetCommandLogs(uint32_t limit = 100) = 0;
};
#endif //!__ICOMMANDLOG__H__

View File

@@ -0,0 +1,58 @@
#ifndef __IDASHBOARDAUDITLOG__H__
#define __IDASHBOARDAUDITLOG__H__
#include <cstdint>
#include <string>
#include <string_view>
#include <vector>
/**
* Interface for Dashboard audit log table.
* Records all API requests, security events, and administrative actions.
*/
class IDashboardAuditLog {
public:
struct AuditLogEntry {
uint64_t id;
uint64_t timestamp;
std::string ip_address;
std::string endpoint;
std::string method;
std::string user_agent;
int32_t response_code;
};
struct AdminActionLog {
uint64_t timestamp;
uint32_t adminAccountId;
std::string action;
std::string targetType;
uint64_t targetId;
std::string details;
};
// Insert a new audit log entry for API requests
virtual void InsertAuditLog(const std::string_view ip, const std::string_view endpoint,
const std::string_view method, const std::string_view user_agent,
int32_t response_code) = 0;
// Insert a new admin action log entry
virtual void InsertAdminActionLog(uint32_t adminAccountId, const std::string_view action,
const std::string_view targetType, uint64_t targetId,
const std::string_view details) = 0;
// Get recent audit log entries (limit = number of entries)
virtual std::vector<AuditLogEntry> GetRecentAuditLogs(uint32_t limit = 100) = 0;
// Get recent admin action logs
virtual std::vector<AdminActionLog> GetAuditLogs(uint32_t limit = 100) = 0;
// Get audit logs for a specific IP address
virtual std::vector<AuditLogEntry> GetAuditLogsByIP(const std::string_view ip, uint32_t limit = 100) = 0;
// Clear old audit logs (older than days_to_keep)
virtual void CleanupOldAuditLogs(uint32_t days_to_keep = 30) = 0;
};
#endif //!__IDASHBOARDAUDITLOG__H__

View File

@@ -0,0 +1,27 @@
#ifndef __IDASHBOARDCONFIG__H__
#define __IDASHBOARDCONFIG__H__
#include <optional>
#include <string>
#include <string_view>
/**
* Interface for Dashboard configuration table.
* Stores key-value configuration settings for the Dashboard server.
*/
class IDashboardConfig {
public:
struct DashboardConfig {
std::string key;
std::string value;
};
// Get a configuration value
virtual std::optional<std::string> GetDashboardConfig(const std::string_view key) = 0;
// Set a configuration value
virtual void SetDashboardConfig(const std::string_view key, const std::string_view value) = 0;
};
#endif //!__IDASHBOARDCONFIG__H__

View File

@@ -3,6 +3,8 @@
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
class IPetNames {
public:
@@ -11,11 +13,24 @@ public:
int32_t approvalStatus{};
};
struct DetailedInfo {
LWOOBJID id{};
std::string petName;
int32_t approvalStatus{};
LWOOBJID ownerId{};
};
// Set the pet name moderation status for the given pet id.
virtual void SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) = 0;
// Get pet info for the given pet id.
virtual std::optional<IPetNames::Info> GetPetNameInfo(const LWOOBJID& petId) = 0;
// Dashboard methods
virtual std::vector<DetailedInfo> GetAllPetNames() = 0;
virtual std::vector<DetailedInfo> GetPetNamesByStatus(int32_t status) = 0;
virtual void SetPetApprovalStatus(const LWOOBJID& petId, int32_t status) = 0;
virtual uint32_t GetPendingPetNamesCount() = 0;
};
#endif //!__IPETNAMES__H__

View File

@@ -3,13 +3,38 @@
#include <cstdint>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
class IPlayKeys {
public:
struct Info {
uint32_t id{};
std::string key_string;
uint32_t key_uses{};
uint32_t times_used{};
bool active{};
std::string notes;
uint64_t created_at{};
};
// Get the playkey id for the given playkey.
// Optional of bool may seem pointless, however the optional indicates if the playkey exists
// and the bool indicates if the playkey is active.
virtual std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) = 0;
// Dashboard methods
virtual std::vector<Info> GetAllPlayKeys() = 0;
virtual std::optional<Info> GetPlayKeyById(const uint32_t playkeyId) = 0;
// Find a playkey by its string value (e.g. "ABCD-EFGH-...."). Returns Info if found.
virtual std::optional<Info> GetPlayKeyByString(const std::string_view key_string) = 0;
// Consume one usage of the given playkey id. Returns true if consumed, false if no uses left or not active.
virtual bool ConsumePlayKeyUsage(const uint32_t playkeyId) = 0;
virtual void CreatePlayKey(const std::string_view key_string, uint32_t uses, const std::string_view notes) = 0;
virtual void UpdatePlayKey(const uint32_t playkeyId, uint32_t uses, bool active, const std::string_view notes) = 0;
virtual void DeletePlayKey(const uint32_t playkeyId) = 0;
virtual uint32_t GetPlayKeyCount() = 0;
};
#endif //!__IPLAYKEYS__H__

View File

@@ -61,8 +61,14 @@ public:
// Update the property performance cost for the given property id.
virtual void UpdatePerformanceCost(const LWOZONEID& zoneId, const float performanceCost) = 0;
// Insert a new property into the database.
virtual void InsertNewProperty(const IProperty::Info& info, const uint32_t templateId, const LWOZONEID& zoneId) = 0;
// Dashboard methods
virtual std::vector<Info> GetAllProperties() = 0;
virtual std::vector<Info> GetPropertiesByApprovalStatus(uint32_t approved) = 0;
virtual uint32_t GetPropertyCount() = 0;
virtual uint32_t GetUnapprovedPropertyCount() = 0;
};
#endif //!__IPROPERTY__H__