| Admin View | Player View |
![]() |
![]() |
- Player Reports - Create tickets with live chat support
- Voice Messages - Record and send audio messages in chat (optional)
- Admin Panel - Claim, resolve, and manage reports
- Permission Groups (RBAC) - Granular permissions with inheritance (optional)
- Moderation Tools - Teleport, heal, freeze, spectate, kick, screenshot
- Discord Integration - Webhook logging for all events
- Statistics Dashboard - Track team performance
- Inventory Management - View/modify player items (ox_inventory, ESX)
- Multi-Language - English & German included
- Dark/Light Theme - User preference saved
- FiveM Server
- oxmysql
- Node.js 20+
- screenshot-basic or screencapture (optional, for screenshot features)
# 1. Clone to resources
git clone https://github.com/SwisserDev/sws-report.git resources/sws-report
# 2. Import database
mysql -u root -p your_database < resources/sws-report/sql/install.sql
# 3. Build UI
cd resources/sws-report/web && npm install && npm run build
# 4. Add to server.cfg
ensure oxmysql
ensure sws-report
# 5. (Optional) Enable voice messages
mysql -u root -p your_database < resources/sws-report/sql/migrate_voice_messages.sql
# 6. (Optional) Enable inventory management
mysql -u root -p your_database < resources/sws-report/sql/migration_1.0.6_inventory_changes.sql
# 7. (Optional) Enable sound notifications
# Place notification.ogg and message.ogg in web/public/sounds/
# Then rebuild: cd web && npm run buildUpgrading from an older version? See UPGRADING.md
Edit config/main.lua:
Config.Locale = "en" -- Language (en/de)
Config.Command = "report" -- Command to open UI
Config.Cooldown = 60 -- Seconds between reports
Config.MaxActiveReports = 3 -- Max open reports per player
-- Admin access (choose one or both)
Config.AdminAcePermission = "report.admin"
Config.AdminIdentifiers = {
"license:abc123...",
"steam:123456..."
}
-- Discord webhook
Config.Discord = {
enabled = true,
webhook = "https://discord.com/api/webhooks/..."
}
-- Voice Messages (optional, requires migration)
Config.VoiceMessages = {
enabled = true,
maxDurationSeconds = 60,
maxFileSizeKB = 7500
}
-- Inventory Management (optional, requires migration)
Config.Inventory = {
enabled = true,
allowedActions = { add = true, remove = true, set = true, metadata_edit = true },
maxItemCount = 1000
}
-- Sound Notifications (optional)
Config.Sounds = {
enabled = true,
newReport = "notification.ogg",
newMessage = "message.ogg",
volume = 0.5
}
-- Screenshot Settings (optional, requires screenshot-basic or screencapture)
Config.Screenshot = {
provider = "screenshot-basic", -- "screenshot-basic" or "screencapture"
encoding = "jpg", -- "jpg" | "png" | "webp" (webp only with screencapture)
quality = 0.85, -- 0.0-1.0 (screenshot-basic only)
autoOnCreate = false -- Auto-screenshot when player creates report
}
-- Permission Groups (optional, omit for legacy full-access behavior)
Config.Permissions = {
groups = {
moderator = {
label = "Moderator",
permissions = {
"view_reports", "claim_report", "resolve_report", "set_priority",
"send_admin_message", "view_notes", "manage_notes",
"teleport_to", "bring_player", "heal_player", "revive_player",
"spectate_player", "screenshot_player", "view_player_history",
}
},
admin = {
label = "Admin",
inherits = "moderator", -- inherits all moderator permissions
permissions = {
"delete_report", "freeze_player", "ragdoll_player", "kick_player",
"manage_inventory", "view_statistics",
}
},
superadmin = {
label = "Super Admin",
inherits = "admin",
permissions = {}
}
},
aceGroups = {
["report.moderator"] = "moderator",
["report.admin"] = "admin",
["report.superadmin"] = "superadmin",
},
identifierGroups = {
-- ["license:xxx"] = "admin",
}
}Admin access is granted through FiveM's built-in ACE system. You define the
permissions in your server.cfg, then assign them to players (via their
identifier) or to a group (via a principal). The resource itself only checks
whether a player is allowed the configured ACE — it does not create any
ACEs for you.
There are two ways to use it, depending on whether you enabled Config.Permissions.
If Config.Permissions is left commented out, every admin gets full access.
The only ACE that matters is Config.AdminAcePermission (default report.admin).
Add the following to your server.cfg above ensure sws-report:
# Allow the "report.admin" ace object (deny by default elsewhere)
add_ace group.admin report.admin allow
# Option A: grant it to an existing principal/group
# (anyone in group.admin now has full report access)
# Option B: grant it directly to a specific player by identifier
add_principal identifier.license:abc123... group.admin
# or grant the ace straight to the identifier:
add_ace identifier.license:abc123... report.admin allowReplace
license:abc123...with the player's real identifier (license:,steam:,fivem:,discord:… all work).
Alternatively, you can skip ACE entirely and just list identifiers in
config/main.lua:
Config.AdminIdentifiers = {
"license:abc123...",
"steam:110000123456789"
}If you enabled Config.Permissions, the resource maps three ACE objects to
groups (see aceGroups in the config):
| ACE object | Group | Access level |
|---|---|---|
report.moderator |
moderator |
View, claim, resolve, basic mod tools |
report.admin |
admin |
Moderator + delete, kick, inventory… |
report.superadmin |
superadmin |
Everything (inherits admin) |
Define the ACEs and assign them in your server.cfg above ensure sws-report:
# 1. Allow each report ace for its matching group
add_ace group.moderator report.moderator allow
add_ace group.admin report.admin allow
add_ace group.superadmin report.superadmin allow
# 2. Add your staff members to the matching group
add_principal identifier.license:abc123... group.moderator
add_principal identifier.license:def456... group.admin
add_principal identifier.steam:1100001234... group.superadminWhen a player holds more than one matching ACE, the resource automatically picks the group with the highest access level.
Tip: Identifier-based groups in
Config.Permissions.identifierGroupstake priority over ACE groups, so you can pin a single person to a group without touchingserver.cfg.
| Command | Description |
|---|---|
/report |
Open report interface |
exports["sws-report"]:IsAdmin(source)
exports["sws-report"]:HasPermission(source, permission)
exports["sws-report"]:GetPlayerGroup(source)
exports["sws-report"]:GetReports(filter)
exports["sws-report"]:CloseReport(reportId)
exports["sws-report"]:IsInventoryAvailable()
exports["sws-report"]:GetInventorySystemName()exports["sws-report"]:OpenUI()
exports["sws-report"]:CloseUI()
exports["sws-report"]:IsUIOpen()AddEventHandler("sws-report:onCreated", function(report) end)
AddEventHandler("sws-report:onClaimed", function(report, adminId) end)
AddEventHandler("sws-report:onResolved", function(report, adminId) end)| Document | Description |
|---|---|
| INVENTORY.md | Inventory management setup, usage & custom adapters |
| UPGRADING.md | Migration guide for version upgrades |
- Fork the repository
- Create a feature branch (
git checkout -b feature/thing) - Commit changes (
git commit -m "Add thing") - Push to branch (
git push origin feature/thing) - Open a Pull Request




