Joomla's actielogs gebruiken
Vroeg of laat stelt elke website-eigenaar een vraag die begint met "wie". Wie heeft gisteravond de homepage gedepubliceerd? Wie heeft die extensie geïnstalleerd die niemand herkent? Heeft de nieuwe redacteur echt twaalf artikelen verwijderd, of vergist de klant zich?
Zonder registratie hebben deze vragen geen antwoord en blijft je gissen.
Joomla beantwoordt ze met een kleine maar krachtige kerncomponent genaamd User Actions Log (com_actionlogs). Deze registreert stilletjes elke belangrijke wijziging op je site: opslaan, verwijderen, publiceren, inloggen, installeren en configuratiewijzigingen. Elke registratie bevat de gebruiker, de actie, het tijdstip en (optioneel) het IP-adres. Je hoeft niets te installeren. Het zit al in Joomla.
Wie wat deed, wanneer en vanaf waar, automatisch vastgelegd door Joomla zonder één enkele extensie van derden.
In dit artikel leggen we uit hoe de component Action Logs werkt, wat er wordt geregistreerd, hoe je het logboek kunt lezen en filteren, hoe meldingen en CSV-export werken en hoe je het logboek gezond houdt op een drukbezochte website. Het doel is om website-eigenaren, beheerders en ontwikkelaars voldoende inzicht te geven in deze stille getuige, zodat ze erop kunnen vertrouwen op de dag dat het nodig is.
1. De basis
1.1 Wat is het User Actions Log?
Het User Actions Log (com_actionlogs) is Joomla's ingebouwde auditlogcomponent. Joomla introduceerde deze in versie 3.9 (mei 2018) en sindsdien maakt deze standaard deel uit van de core.
Een aantal zaken maakt deze component bijzonder:
- Voor elke geregistreerde actie wordt één record opgeslagen in één tabel:
#__action_logs. - Het systeem werkt op basis van events, niet via polling. Elke actie genereert een Joomla-event, een plugin vangt dit op en schrijft een record weg.
- Elk record bevat de gebruiker, de tijdstempel, de extensiecontext, het item-ID, het IP-adres en een bericht gebaseerd op een taalstring.
- Het logboek is vanuit de interface alleen-lezen. Beheerders kunnen het bekijken, filteren, exporteren of opschonen, maar niet afzonderlijke records bewerken.
Dat laatste is belangrijk. Een auditlog die je kunt wijzigen is eigenlijk geen auditlog. Joomla biedt daarom bewust geen bewerkscherm voor logregels.
1.2 Een opmerking over de naamgeving: "Action Logs" versus "User Actions Log"
Voordat we verdergaan, is het goed om een veelvoorkomende bron van verwarring weg te nemen. Joomla gebruikt twee namen voor hetzelfde onderdeel, en die inconsistentie zorgt regelmatig voor verwarring:
| Waar je het ziet | Gebruikte naam |
|---|---|
| Menu-item in het beheer (J4 / 5 / 6) | Gebruikers → User Actions Log |
| Titel van het helpscherm | User Actions Log: Opties |
| Koptekst van de lijstweergave | User Actions Log |
| Officiële documentatiesite | User Actions Log |
| Componentmap / interne naam | com_actionlogs |
| Naam van de registratieplugin | Action Log - Joomla |
| Naam van de systeemplugin | System - User Actions Log |
"User Actions Log" is de formele, oorspronkelijke naam die Joomla in versie 3.9 aan deze functie gaf. Deze naam komt nog steeds voor in de helpdocumentatie en in de titelbalk. "Action Logs" is de kortere benaming die uiteindelijk in het beheermenu en in het dagelijks gebruik terechtkwam. Beide verwijzen naar dezelfde component, dezelfde databasetabellen en dezelfde plugins. Er bestaat geen aparte functie genaamd "User Action Logs".
Een historisch detail maakt de verwarring nog iets groter. In Joomla 3.9 en 3.10 stond het menu-item onder System → User Actions Log. Vanaf Joomla 4 verhuisde het naar Gebruikers → User Actions Log. Oudere handleidingen en schermafbeeldingen tonen daarom nog de oude naam en locatie. In dit artikel betekenen "Action Logs" en "User Actions Log" hetzelfde. Bij twijfel is de officiële identificatie com_actionlogs.
1.3 Waar vind ik het?
In de Joomla 6-beheeromgeving zijn de volgende locaties relevant:
Gebruikers → User Actions Log (de logviewer)
Gebruikers → User Actions Log → Opties (instellingen)
Gebruikers → Beheren → [een gebruiker] (e-mailmeldingen per gebruiker,
op het tabblad User Actions Log Options)
Systeem → Beheren → Plugins → Action Log - Joomla (de recorder)
Systeem → Beheren → Plugins → System - User Actions Log (de aanjager)
De component bevindt zich in administrator/components/com_actionlogs/. De twee plugins bevinden zich in plugins/actionlog/joomla/ (de recorder) en plugins/system/actionlogs/ (de systeemplugin die hem laadt).
Een detail waar veel mensen over struikelen: de component staat onder Gebruikers en niet onder Systeem. Oudere schermafbeeldingen suggereren soms anders.
1.4 De drie onderdelen
Action Logs bestaat uit drie onderdelen die samenwerken:
| Onderdeel | Functie |
|---|---|
com_actionlogs |
Backend-lijstweergave, filters, CSV-export en opschonen. |
plg_actionlog_joomla |
Luistert naar events en schrijft logregels weg. |
plg_system_actionlogs |
Laadt de recorder en voegt de e-mailvoorkeuren per gebruiker toe aan het gebruikersformulier. |
Schakel je de recorder uit, dan wordt er niets meer geregistreerd. Schakel je de systeemplugin uit, dan wordt er ook niets meer geregistreerd, om de reden die in 3.3 staat - het is geen optionele extra.
1.5 Eerste kennismaking met het logboek
Open Gebruikers → User Actions Log. De lijst wordt standaard gesorteerd op nieuwste eerst. Een typische regel ziet er als volgt uit:
| Kolom | Voorbeeld |
|---|---|
| Actie | Gebruiker article-editor heeft ingelogd in het beheer. |
| Datum | 2026-05-28 09:14:02 (relatief: "een paar seconden geleden") |
| Extensie | com_users |
| Gebruiker | admin |
| IP-adres | 10.10.10.1. Staat IP-registratie uit - de standaard - dan is de hele kolom verborgen. |
De actiecel wordt opgebouwd uit de opgeslagen taalsleutel en de bijbehorende JSON, met links naar het item en naar de handelende gebruiker. De regel klapt niet open: klikken volgt die links. De ruwe JSON zie je alleen in de database. Op die JSON komen we terug in sectie 6.
1.6 De lijst filteren
De filterbalk boven de lijstweergave biedt vier hulpmiddelen:
- Zoeken: vrije tekst op basis van het weergegeven bericht.
- Gebruiker: filter op activiteiten van één gebruiker.
- Extensie: alleen
com_content, alleencom_users, enzovoort. - Datum: een keuzelijst met vaste periodes - Vandaag, Afgelopen week, Afgelopen maand, Afgelopen 3 maanden, Afgelopen 6 maanden, Afgelopen jaar. Een begin- en einddatum kiezen kan niet.
De meest bruikbare combinatie is Gebruiker + Datum. Omdat het datumfilter alleen vaste periodes biedt, betekent een vraag als "alles wat Alice afgelopen woensdag deed" dat je Afgelopen week kiest en de lijst doorneemt, of de tabel rechtstreeks bevraagt (sectie 8.4).
Naar boven2. Wat wordt er gelogd?
2.1 De standaard gelogde extensies
Je bepaalt zelf welke componenten worden gevolgd via Opties → Events To Log. Dit is een meerkeuzelijst, en standaard staan er 21 core-extensies aan - niet allemaal. Smart Search, Associaties, Workflow, Privacy, Joomla Update en Action Logs zelf staan niet in die standaardlijst:
com_banners com_cache com_categories com_checkin
com_config com_contact com_content com_fields
com_guidedtours com_installer com_media com_menus
com_messages com_modules com_newsfeeds com_plugins
com_redirect com_scheduler com_tags com_templates
com_users
Verwijder je een extensie uit deze lijst, dan worden de gebeurtenissen ervan stilzwijgend genegeerd. Er worden geen logregels meer aangemaakt. Het beperken van deze lijst is de meest effectieve manier om logvervuiling op een drukke website te verminderen.
2.2 Gebeurtenissen in de contentlevenscyclus
Voor elke logbare component abonneert de recorder-plugin zich op drie content-events:
| Event | Wat wordt gelogd |
|---|---|
onContentAfterSave |
Aanmaken of bijwerken, inclusief ID, titel en een nieuwe/bijgewerkte status. |
onContentAfterDelete |
Verwijderen, inclusief ID en titel (vastgelegd vóór verwijdering). |
onContentChangeState |
Publiceren, depubliceren, archiveren of naar de prullenbak verplaatsen, inclusief de nieuwe status. |
Elke keer dat je een artikel opslaat, een categorie verwijdert of een menu-item publiceert, wordt er dus een logregel aangemaakt.
2.3 Gebeurtenissen in de gebruikerslevenscyclus
Gebruikersgebeurtenissen zijn het belangrijkst voor het opsporen van misbruik van accounts:
| Event | Wat wordt gelogd |
|---|---|
onUserAfterLogin |
Succesvolle login (frontend of backend, maar nooit API-logins). |
onUserLoginFailure |
Mislukte login, maar alleen als de gebruikersnaam bestaat. |
onUserLogout |
Expliciet uitloggen. |
onUserAfterSave |
Aanmaken of bewerken van een gebruiker (inclusief groepswijzigingen). |
onUserAfterDelete |
Verwijderen van een gebruiker. |
onUserAfterRemind |
Aanvraag voor "Gebruikersnaam vergeten". |
onUserAfterResetRequest |
Aanvraag voor een wachtwoordresetlink. |
onUserAfterResetComplete |
Voltooien van een wachtwoordreset. |
Een detail dat veel mensen verrast: mislukte logins met een onbekende gebruikersnaam worden niet gelogd. De plugin controleert eerst of de gebruiker bestaat, waardoor geautomatiseerde scans en bots niet in het auditlog terechtkomen.
2.4 Gebeurtenissen rond extensies
Alles wat wijzigingen aanbrengt in de extensietabel wordt geregistreerd:
| Event | Wat wordt gelogd |
|---|---|
onExtensionAfterInstall |
Installatie, inclusief type, naam en versie. |
onExtensionAfterUpdate |
Update van oude naar nieuwe versie. |
onExtensionAfterUninstall |
Deïnstallatie. |
onExtensionAfterSave |
Bewerking, bijvoorbeeld het in- of uitschakelen van een plugin. |
onJoomlaAfterUpdate |
Bijwerken van de Joomla-coreversie. |
Dit is bijzonder waardevol bij onderzoek na een incident. De vraag "wanneer hebben we die kwetsbare plugin geïnstalleerd?" is dan met één zoekopdracht te beantwoorden.
2.5 Configuratiewijzigingen
Joomla registreert ook het opslaan van configuraties:
onApplicationAfterSave: de Algemene Configuratie is opgeslagen.onExtensionAfterSavemet contextcom_config.component: het Opties-scherm van een component is opgeslagen.
In beide gevallen wordt alleen vastgelegd dat de instellingen zijn opgeslagen, plus wie dat deed - niet welke instellingengroep is gewijzigd en niet welke waarden precies zijn veranderd. Als je een exacte vergelijking tussen oude en nieuwe waarden nodig heeft, is daarvoor een kleine maatwerkplugin nodig (zie sectie 11).
2.6 Operationele gebeurtenissen
Ook enkele onderhoudsacties worden geregistreerd:
| Event | Wat wordt gelogd |
|---|---|
onAfterCheckin |
Een beheerder heeft een vergrendeld item geforceerd ingecheckt. |
onAfterPurge |
De cache is geleegd. |
onAfterLogPurge |
Het actielogboek is opgeschoond. |
onAfterLogExport |
Een CSV-export is gedownload. |
Ja, het opschonen van het logboek wordt zelf ook gelogd. Na een opschoning blijft er precies één regel over: "Gebruiker admin heeft de actielogs opgeschoond." Het auditspoor documenteert zichzelf.
2.7 API-verzoeken (optioneel)
Als je Opties → Log API Requests = Ja inschakelt, registreert Joomla iedere Web Services API-aanroep tijdens de verwerking. Met een tweede optie, Request Methods To Log, bepaal je welke verzoektypen worden vastgelegd. Standaard staat alleen GET aan, maar op productiesites kiest men meestal minimaal ook voor POST, PUT, PATCH en DELETE.
Een waarschuwing: API-logging vult de tabel erg snel. Schakel het in tijdens een onderzoek en schakel het daarna weer uit voor normaal gebruik. In sectie 8 bekijken we de impact op de omvang van het logboek.
Naar boven3. Meldingen
3.1 Het opt-inmodel
Elke gebruiker kan zich aanmelden voor e-mailmeldingen van één of meer extensies op het eigen account, via Gebruikers → Beheren → [de gebruiker] → User Actions Log Options. De twee velden heten Email Notifications en Events to Email. Deze voorkeuren worden opgeslagen in #__action_logs_users:
user_id notify (0/1) extensions (JSON-array, bijv. ["com_users","com_installer"])
- Een gebruiker die niet in deze tabel voorkomt, ontvangt geen meldingen.
- Een gebruiker met
notify = 1enextensions = com_users,com_installerontvangt een e-mail telkens wanneer iemand gebruikers of extensies wijzigt.
Meldingen zijn een persoonlijke keuze per gebruiker en geen sitebrede instelling. Power users en security officers melden zich aan, terwijl andere gebruikers geen berichten ontvangen.
3.2 Hoe ziet de e-mail eruit?
De notifier gebruikt hetzelfde leesbare bericht als in de lijstweergave, aangevuld met:
- Een directe link naar het betreffende item, indien beschikbaar.
- De naam van de gebruiker die de actie uitvoerde.
De e-mail wordt verzonden via de ingestelde mailserver. Controleer daarom de configuratie onder Systeem → Algemene Configuratie → Server → E-mail voordat je op meldingen vertrouwt. In een lokale Docker-omgeving kan een tool zoals MailHog alle uitgaande berichten opvangen zodat je veilig kunt testen.
3.3 De rol van de systeemplugin
Deze is het waard om goed te lezen, want de voor de hand liggende uitleg is precies verkeerd om. De systeemplugin is geen notificatielaag bovenop een logger. Hij is juist wat de logger überhaupt laat draaien.
Joomla laadt een plugingroep alleen als iets erom vraagt, en om de groep actionlog wordt op precies één plek gevraagd - in plg_system_actionlogs, bij elk verzoek:
public function onAfterInitialise(AfterInitialiseEvent $event): void
{
// Import actionlog plugin group so that these plugins will be triggered for events
PluginHelper::importPlugin('actionlog', null, true, $event->getApplication()->getDispatcher());
}
De taakverdeling is dus:
- Action Log - Joomla luistert naar de content-, gebruikers- en extensie-events en schrijft de regels weg - maar pas nadat de systeemplugin hem heeft geladen.
- System - User Actions Log laadt die groep, voegt het tabblad User Actions Log Options toe aan het gebruikersformulier (de velden Email Notifications en Events to Email) en houdt
#__action_logs_usersbij als gebruikers worden opgeslagen of verwijderd. - com_actionlogs, de component, doet de rest:
ActionlogModel::addLog()schrijft elke regel weg en roept daarnasendNotificationEmails()aan, enActionlogsHelper::getHumanReadableLogMessage()maakt van een opgeslagen taalsleutel plus de bijbehorende JSON de zin die je in de lijst leest.
Het gevolg is dus het omgekeerde van wat je zou verwachten: de systeemplugin uitschakelen stopt het loggen volledig. De recorder wordt nooit geladen, er worden geen regels weggeschreven, en zonder nieuwe regels zijn er ook geen e-mails. Je houdt dus geen groeiend logboek met een stille mailbox over.
Wil je tijdens een grote migratie de e-mailstroom stilleggen en het auditspoor behouden, blijf dan van de plugins af. Leeg Events to Email op de accounts die zich hebben aangemeld, of zet Email Notifications zolang op Nee.
Naar boven4. Exporteren en opschonen
4.1 CSV-export
De lijstweergave bevat twee exportknoppen in de werkbalk:
| Knop | Wat wordt geëxporteerd |
|---|---|
| Export Selected as CSV | Alleen de regels die je hebt geselecteerd. |
| Export All as CSV | Het volledige logboek, rekening houdend met de actieve filters. |
Het scheidingsteken is instelbaar via Opties → CSV-scheidingsteken. Kies een puntkomma (;) als je spreadsheetprogramma (zoals de Nederlandse versie van Excel) komma's als decimaalteken gebruikt.
De export wordt streamend uitgevoerd, één regel tegelijk. Daardoor raakt zelfs een logboek met een miljoen records niet door het beschikbare PHP-geheugen heen.
4.2 Bescherming tegen CSV-injectie
Joomla ontsnapt automatisch elke cel die begint met =, +, - of @ door er een spatie voor te plaatsen. Dit voorkomt de klassieke aanval via "Excel-formule-injectie", waarbij een gelogde gebruikersnaam zoals =cmd|'/c calc'!A1 anders als formule zou worden uitgevoerd zodra een beheerder het CSV-bestand opent.
Als je ooit een eigen exportfunctie ontwikkelt, behoud deze beveiliging. Die is er met een goede reden.
4.3 Het logboek opschonen
Met de knop Clear Log in de werkbalk verwijder je alle records uit #__action_logs. (De aparte knop Delete verwijdert alleen de regels die je hebt aangevinkt.) Daarna schrijft Joomla direct één nieuwe logregel weg, zodat er altijd één record overblijft waarin staat wie het logboek heeft opgeschoond en wanneer.
Veelvoorkomende redenen om het logboek op te schonen:
- Na een langdurige migratieperiode, wanneer je met een schone lei wilt beginnen.
- Voordat je uitsluitend recente activiteiten wilt exporteren.
Er is geen mogelijkheid om dit ongedaan te maken. Voor geautomatiseerde opruiming levert de core een taak Delete ActionLogs (zie sectie 11.3).
Naar boven5. IP-logging en privacy
5.1 Standaardinstelling: IP-logging uitgeschakeld
Standaard staat Opties → IP-logging = Nee. Wanneer IP-logging is uitgeschakeld, wordt in iedere logregel een tijdelijke aanduiding opgeslagen in plaats van een echt IP-adres en toont de lijstweergave "Uitgeschakeld".
Wanneer je IP-logging inschakelt, leest Joomla het IP-adres van de bezoeker uit en houdt het rekening met de headers X-Forwarded-For en Client-Ip. Dat is één aan/uit-schakelaar, Behind Load Balancer (standaard Nee) onder Algemene Configuratie → Server → Proxy; de core houdt geen lijst met vertrouwde proxyservers bij. Als de gevonden waarde geen geldig IP-adres is, wordt in het logboek "Invalid" opgeslagen.
5.2 AVG-overwegingen
Een IP-adres is volgens de AVG (GDPR) persoonsgegeven. Wanneer je IP-logging inschakelt, moet je daarom rekening houden met het volgende:
- Zorg voor een geldige grondslag. Gerechtvaardigd belang voor beveiliging is meestal voldoende.
- Vermeld IP-logging in je privacyverklaring.
- Definieer een bewaartermijn. Het onbeperkt bewaren van IP-adressen is lastig te rechtvaardigen.
Praktische standaardinstellingen voor een publieke Joomla-website:
- IP-logging ingeschakeld, je zult blij zijn dat je het hebt wanneer er ooit een beveiligingsincident plaatsvindt.
- Een bewaartermijn van ongeveer 90 dagen, verwijder oudere records automatisch via een Taakplanner-taak.
- Een vermelding in de privacyverklaring onder het kopje "Beveiligingslogboeken".
5.3 Verzoeken op grond van het recht om vergeten te worden
Wanneer een gebruiker vraagt om verwijdering van zijn gegevens, hoef je niet het volledige auditspoor te vernietigen. Anonimiseren is meestal voldoende:
- Verwijder de gebruiker via
com_users. Hierdoor wordt nog één laatste logregel aangemaakt waarin naar het verwijderde account-ID wordt verwezen. - Voer vervolgens een SQL-update uit om historische gegevens te anonimiseren:
UPDATE jos_action_logs
SET user_id = 0,
ip_address = '0.0.0.0',
message = REPLACE(message, 'OldUsername', 'deleted-user')
WHERE user_id = 123;
Het auditspoor blijft intact, alleen de persoonlijk identificeerbare gegevens worden verwijderd. Vervang jos_ door het daadwerkelijke databasevoorvoegsel van je website.
6. Onder de motorkap
6.1 De vier tabellen
Action Logs gebruikt vier databasetabellen:
#__action_logs één record per gelogde actie
#__action_logs_extensions de lijst met deelnemende extensies
#__action_log_config hoe elk contenttype wordt weergegeven
#__action_logs_users meldingsvoorkeuren per gebruiker
De belangrijkste tabel is #__action_logs. De drie andere zijn relatief kleine referentietabellen.
6.2 De hoofdlogtabel
De belangrijkste velden van #__action_logs zijn:
id auto-increment primaire sleutel
message_language_key sjabloonsleutel, bijvoorbeeld PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED
message JSON met de plaatsvervangende waarden
log_date tijdstip waarop de actie plaatsvond
extension context, bijvoorbeeld com_content.article
user_id uitvoerende gebruiker (0 = gast of systeem)
item_id ID van het betrokken item (0 indien niet van toepassing)
ip_address echt IP-adres, "Disabled" of "Invalid"
De tabel bevat verschillende indexen op user_id, (user_id, log_date), (user_id, extension) en (extension, item_id). Dankzij deze indexen blijft een filter zoals "toon alle acties van gebruiker X" snel werken, zelfs wanneer het logboek miljoenen records bevat.
6.3 De JSON-berichtenstructuur
Hier wordt het interessant. De kolom message bevat niet de uiteindelijke tekst die je in het logboek ziet. In plaats daarvan bevat deze een JSON-object met plaatsvervangende waarden:
{
"action": "update",
"type": "PLG_ACTIONLOG_JOOMLA_TYPE_ARTICLE",
"id": 42,
"title": "About Us",
"itemlink": "index.php?option=com_content&task=article.edit&id=42",
"userid": 100,
"username": "admin",
"accountlink": "index.php?option=com_users&task=user.edit&id=100"
}
De message_language_key verwijst naar een sjabloon, bijvoorbeeld:
"User {username} updated {type} {title}."
Tijdens het weergeven vervangt Joomla de JSON-waarden door de daadwerkelijke gegevens en maakt het van de gebruikersnaam en titel klikbare links. Dit is precies waarom het logboek vertaalbaar is: het bericht bestaat uit een sleutel en niet uit een vaste tekst. Installeer je het Nederlandse taalpakket, dan verandert "User admin updated..." automatisch in "Gebruiker admin heeft ... bijgewerkt."
6.4 De contenttype-mapping
De tabel #__action_log_config vertelt de renderer hoe elk contenttype moet worden verwerkt. Voor ieder type wordt vastgelegd welke kolom het ID bevat, welke kolom de titel bevat, welke tabel gebruikt wordt en welke tekstprefix nodig is om de juiste taalstring op te bouwen:
type_alias id_holder title_holder table_name
com_content.article id title #__content
com_categories.category id title #__categories
com_redirect.link id old_url #__redirect_links
com_modules.module id title #__modules
...ongeveer 23 regels in Joomla 6
Een maatwerkcomponent kan zijn eigen contenttype registreren door hier een extra record toe te voegen. Ontwikkelaars gebruiken dit mechanisme om hun eigen extensies compatibel te maken met Action Logs (zie sectie 11).
Naar boven7. Rechten en toegang
7.1 Er is geen ACL per component
Deze sectie beschreef eerder een tabblad Opties → Rechten en een alleen-lezen "audit officer"-groep. Geen van beide bestaat. Dat is het waard om expliciet te zeggen, want het patroon klinkt logisch en mensen gaan er daadwerkelijk naar zoeken.
com_actionlogs levert geen access.xml mee - 23 andere core-componenten doen dat wel - en de config.xml bevat één fieldset, actionlogs, met de zes logging-opties en verder niets. Het Opties-scherm van een component wordt alleen uit dat bestand opgebouwd, dus er is geen tabblad Rechten om te openen en er zijn geen rechten per component om toe te kennen of te ontnemen.
De toegang wordt in plaats daarvan op één plek bepaald, en dat gaat grofmazig:
// administrator/components/com_actionlogs/src/Dispatcher/Dispatcher.php
protected function checkAccess()
{
$user = $this->app->getIdentity();
// Access check
if (!$user->authorise('core.admin')) {
throw new NotAllowed(..., 403);
}
}
Dat is site-brede core.admin, het Super User-recht. Wie daar niet aan voldoet, krijgt een 403 op de hele component.
7.2 Wat dit in de praktijk betekent
De gevolgen zijn het waard om uit te schrijven, want ze druisen in tegen hoe de meeste mensen verwachten dat een auditlog werkt:
- Alleen Super Users kunnen het logboek lezen. Er is geen manier om een manager, een security officer of een auditor via de Joomla-interface leesrechten op Action Logs te geven.
- Er is geen alleen-lezen modus. Iedereen die het logboek kan lezen, kan het ook leegmaken. De werkbalk biedt Delete voor de geselecteerde regels en Clear Log voor alles, en niets behandelt die twee verschillend.
- Iedereen die het kan lezen, kan dus ook zijn eigen sporen wissen - niet met ruwe SQL, maar met twee klikken in de lijstweergave.
Action Logs is dus een auditspoor voor een site waar je elke Super User vertrouwt. Het is geen maatregel die hen beperkt. Heb je functiescheiding nodig - iemand die activiteit kan beoordelen maar het verslag niet kan wijzigen, of een Super User wiens handelingen worden vastgelegd op een plek waar hij niet bij kan - dan moet dat buiten Joomla: stuur de regels naar een externe logcollector, repliceer de tabel, of maak database-back-ups die een beheerder niet kan verwijderen.
Wat de component wél goed doet, is de vorm van het verslag zelf. Er is nergens in de interface een Aanmaken of Bewerken: je kunt geen regel met de hand toevoegen en geen regel wijzigen. Regels worden door de recorder geschreven of helemaal niet.
Naar boven8. Prestaties en schaalbaarheid
8.1 Hoe snel groeit het logboek?
Voor een gemiddeld contentteam blijft het logboek relatief klein. Een team van vijf redacteuren genereert bijvoorbeeld ongeveer:
~50 artikelwijzigingen per dag + ~20 menu-/modulewijzigingen per dag + ~10 logins per dag
= ongeveer 80 records per dag = ~2.400 records per maand = ~30.000 records per jaar
Elke logregel neemt ongeveer 500 bytes in beslag. Eén jaar aan gegevens komt daarmee neer op circa 15 MB. Dat vormt geen enkel probleem.
API-logging verandert dit beeld volledig. Een website die via de API gemiddeld 10 verzoeken per seconde verwerkt, genereert al snel 864.000 logregels per dag. Schakel deze functie daarom niet zonder goede reden in.
8.2 Strategieën voor opschonen
Voor een beleid puur op ouderdom gebruik je de core-taak Delete ActionLogs (sectie 11.3) - die doet precies dit en heeft geen SQL nodig. Wat die taak niet kan, is onderscheid maken per extensie; een selectief beleid betekent dus nog steeds SQL, handmatig tijdens onderhoud of vanuit een eigen taakplugin. Een eenvoudige opschoning verwijdert alles wat ouder is dan 90 dagen:
DELETE FROM jos_action_logs
WHERE log_date < NOW() - INTERVAL 90 DAY;
Een slimmere aanpak bewaart beveiligingsrelevante gebeurtenissen langer en verwijdert alleen routinematige contentwijzigingen:
DELETE FROM jos_action_logs
WHERE log_date < NOW() - INTERVAL 90 DAY
AND extension NOT IN ('com_users', 'com_installer', 'com_config');
Logins, extensie-installaties en configuratiewijzigingen zijn doorgaans waardevoller voor forensisch onderzoek dan gewone opslagacties. Hun belang neemt vaak juist toe naarmate ze ouder worden.
8.3 Snelle en trage query's
Dankzij de aanwezige indexen blijven query's die filteren op gebruiker, datum, extensie of item-ID snel:
-- Snel: alle acties van één gebruiker in de afgelopen 7 dagen
SELECT * FROM jos_action_logs
WHERE user_id = 100 AND log_date > NOW() - INTERVAL 7 DAY
ORDER BY log_date DESC;
Vrije-tekstzoekopdrachten in het JSON-bericht beschikken echter over geen bruikbare index en moeten de volledige tabel doorzoeken:
-- Traag: vrije-tekstzoekactie in het bericht
SELECT * FROM jos_action_logs
WHERE message LIKE '%phishing%';
De zoekfunctie in de lijstweergave gebruikt precies zo'n LIKE '%...%'-query. Voor incidenteel gebruik door een beheerder is dat prima, maar gebruik dit niet als basis voor geautomatiseerde monitoring of polling.
8.4 Praktische SQL-query's voor onderzoek
Mislukte logins van gisteren, een handige indicator voor brute-force-aanvallen:
SELECT user_id, COUNT(*) AS attempts
FROM jos_action_logs
WHERE message_language_key = 'PLG_ACTIONLOG_JOOMLA_USER_LOGIN_FAILED'
AND log_date > NOW() - INTERVAL 1 DAY
GROUP BY user_id
HAVING attempts > 5
ORDER BY attempts DESC;
Recente extensie-installaties, een nuttige controle op ongewenste software:
SELECT log_date, user_id, message
FROM jos_action_logs
WHERE extension = 'com_installer'
AND log_date > NOW() - INTERVAL 7 DAY
ORDER BY log_date DESC;
Vergeet niet jos_ te vervangen door het daadwerkelijke databasevoorvoegsel van je Joomla-installatie.
9. Veelvoorkomende fouten en valkuilen
9.1 "Er wordt niets gelogd"
Doorloop deze controlelijst in volgorde:
- Is de plugin Action Log - Joomla ingeschakeld?
- Staat de betreffende component in de lijst Events To Log?
- Is de actie daadwerkelijk geslaagd? De recorder werkt met "after"-events, dus een opslagactie die faalt door validatiefouten wordt niet geregistreerd.
- Controleer je het juiste datumbereik in de filters?
9.2 "Niet alle mislukte logins worden gelogd"
Dat is bewust zo ontworpen. De plugin negeert mislukte inlogpogingen voor niet-bestaande gebruikersnamen om te voorkomen dat geautomatiseerde scanners de tabel vullen met nutteloze gegevens. Alleen mislukte pogingen voor bestaande gebruikers worden geregistreerd.
9.3 "Artikelwijzigingen worden dubbel gelogd"
Dat gebeurt niet. De recorder luistert inderdaad naar onContentAfterSave voor zowel het backend-bewerkscherm als het frontend-inzendformulier, maar hij zet de ene context om in de andere voordat er wordt weggeschreven:
protected $contextAliases = ['com_content.form' => 'com_content.article'];
Een inzending via de voorkant levert dus één regel op, vastgelegd onder com_content.article. Zie je toch twee regels voor één opslag, zoek dan naar een tweede extensie die op hetzelfde event meeluistert in plaats van aan te nemen dat de core dat doet.
9.4 "De weergegeven gebruiker heeft de actie niet uitgevoerd"
De recorder registreert de gebruiker die op het moment van de gebeurtenis is geauthenticeerd. CLI-scripts en Taakplanner-taken draaien als gastgebruiker en verschijnen daarom met user_id = 0.
Een waarde van user_id = 0 betekent meestal één van de volgende situaties:
- Een niet-geauthenticeerde frontendactie, zoals een verzoek voor een wachtwoordreset.
- Een geplande taak of CLI-commando.
- Een maatwerkplugin die buiten een HTTP-verzoek wordt uitgevoerd.
De kolom extension en, indien ingeschakeld, het IP-adres helpen meestal om het verschil tussen deze situaties te herkennen.
9.5 "Het bericht toont 'User undefined updated ...'"
Dit wijst op een ontbrekende taalstring. Dat gebeurt wanneer een maatwerkextensie wel een event genereert maar geen bijbehorende PLG_ACTIONLOG_...-taalstrings bevat, of wanneer de actieve taalvertaling de betreffende sleutel mist.
De oplossing is het toevoegen van de ontbrekende taalstring aan het taalbestand of het registreren van de juiste prefix in #__action_log_config.
9.6 "Opschonen heeft mijn bewijsmateriaal verwijderd"
Er bestaat geen mogelijkheid om een opschoning ongedaan te maken. Voordat je ooit het logboek opschoont:
- Maak eerst een CSV-export via de knop Export All as CSV.
- Bewaar het CSV-bestand buiten de Joomla-installatie.
- Voer pas daarna de opschoning uit.
Voor websites die moeten voldoen aan compliance- of auditvereisten geldt een eenvoudige regel: verwijder nooit loggegevens zonder eerst een export te maken en vast te leggen wie de opschoning heeft uitgevoerd.
9.7 "Ik kan Action Logs niet vinden in het menu"
De component bevindt zich onder Gebruikers en niet onder Systeem. Daarnaast weigert de component iedereen zonder site-brede core.admin: wie geen Super User is ziet de link niet en krijgt een 403 bij rechtstreeks navigeren (sectie 7.1).
10. Beveiliging en compliance
10.1 Het auditspoor is zelf ook een doelwit
Een aanvaller die beheerderstoegang verkrijgt, wil vaak niet alleen iets kwaadaardigs uitvoeren, maar ook de sporen wissen. Het actielogboek maakt dat moeilijker, maar biedt geen volledige garantie. Een Super User kan het logboek leegmaken, geselecteerde regels verwijderen of de recorder uitschakelen - allemaal vanuit de interface, zonder databasetoegang. En omdat alleen Super Users de component überhaupt kunnen openen, zijn de mensen die het logboek het nuttigst zou beperken precies de mensen die het kunnen aanpassen.
Verstandige maatregelen zijn onder meer:
- Beperk het recht Verwijderen tot één speciaal beveiligingsaccount.
- Sla loggegevens ook extern op, zodat de lokale kopie niet de enige bron van waarheid is.
- Controleer actief op meta-gebeurtenissen, zoals het opschonen van het logboek of het uitschakelen van de recorder-plugin.
Ook je eigen beheerders verdienen controle. Het logboek is een afschrikmiddel en een forensisch hulpmiddel, geen absolute garantie.
10.2 Loggegevens omzetten in actie
Een logboek dat je pas achteraf bekijkt benut slechts de helft van zijn waarde. Action Logs kunnen ook gebruikt worden als basis voor automatische detectie en waarschuwingen:
- Waarschuwingen bij brute-force-aanvallen: een Taakplanner-taak voert periodiek de query voor mislukte logins uit en verstuurt een melding via Slack of e-mail zodra een drempelwaarde wordt overschreden.
- Meldingen bij verdachte installaties: een webhook die reageert op extensie-installaties en direct het beveiligingsteam informeert. Een plugin-installatie om 03:00 uur door een beheerder die normaal alleen overdag werkt, is bijvoorbeeld verdacht.
- Bewaking van privilege-escalatie: een melding wanneer iemand wordt toegevoegd aan de groep Super Users. Dit hoort slechts zelden voor te komen.
Het actielogboek vormt je detectielaag. Combineer het met een reactielaag, bijvoorbeeld via Joomla-plug-ins, Taakplanner-taken of een extern monitoringsysteem.
10.3 Een minimale maar effectieve beveiligingsconfiguratie
Voor een productiewebsite die echt belangrijk is, levert ongeveer twintig minuten configuratiewerk veel extra veiligheid op:
- Action Logs inschakelen voor
com_users,com_installer,com_config,com_plugins,com_modulesencom_templates. - IP-logging inschakelen en een bewaartermijn van 90 dagen instellen via een geplande taak.
- Meldingen inschakelen voor Super User-accounts, met toezicht op
com_usersencom_installer. - Het recht Verwijderen beperken tot één speciaal beveiligingsaccount.
- Dagelijks de query voor mislukte logins controleren, of een dashboard gebruiken dat dezelfde informatie toont.
De investering betaalt zich terug zodra iemand probeert slimmer te zijn dan het systeem.
Naar boven11. Aanpassingen voor ontwikkelaars
11.1 Een eigen component registreren voor logging
U kunt een eigen component compatibel maken met Action Logs in twee stappen, zonder een aparte plugin te schrijven. Voeg de component eerst toe aan de lijst met logbare extensies:
INSERT INTO jos_action_logs_extensions (extension)
VALUES ('com_mycomponent');
Voeg vervolgens één of meer contenttype-definities toe zodat Joomla weet hoe berichten moeten worden opgebouwd:
INSERT INTO jos_action_log_config
(type_title, type_alias, id_holder, title_holder, table_name, text_prefix)
VALUES
('myitem', 'com_mycomponent.item', 'id', 'name',
'#__mycomponent_items', 'PLG_ACTIONLOG_MYCOMPONENT');
Lever daarna taalstrings mee die beginnen met PLG_ACTIONLOG_MYCOMPONENT_... voor iedere actie die je wil registreren. Zolang je component standaardevents zoals onContentAfterSave en vergelijkbare gebeurtenissen uitzendt met de juiste context, verwerkt de bestaande recorder-plugin de rest automatisch.
11.2 Logregels vanuit eigen code toevoegen
Voor een eenmalige logregel vanuit een controller, model of importscript kun je rechtstreeks het Action Logs-model gebruiken:
$model = $this->app->bootComponent('com_actionlogs')
->getMVCFactory()
->createModel('Actionlog', 'Administrator');
$model->addLog(
[['action' => 'custom', 'detail' => 'Handmatige registratie vanuit importscript']],
'COM_MYCOMPONENT_LOG_IMPORT_RAN',
'com_mycomponent.import',
$userId // 0 = huidige gebruiker
);
Dit is bijzonder handig voor batchprocessen of importscripts die een spoor in het auditlog moeten achterlaten zonder gebruik te maken van het eventsysteem.
11.3 Geautomatiseerd opschonen
De core levert hier een kant-en-klare taak voor. Je hebt geen ruwe SQL-taak nodig, en het taaktype "SQL Operations" waar oudere adviezen naar verwijzen bestaat in Joomla 6 helemaal niet.
Schakel de plugin Task - Delete Action Logs in en ga daarna naar Systeem → Beheren → Scheduled Tasks → Nieuw en kies Delete ActionLogs:
| Veld | Waarde |
|---|---|
| Taaktype | Delete ActionLogs ("Delete Action logs after specified days.") |
| Titel | Wat je wilt, bijvoorbeeld Action logs opschonen |
| Days to delete action logs after | logDeletePeriod, standaard 7, minimaal 1. Zet dit op je eigen bewaartermijn - 90 voor een kwartaal, 365 voor een jaar. |
| Regel | Cron-stijl: 0 3 * * * (elke nacht om 03:00) |
De taak verwijdert regels uit #__action_logs waarvan log_date ouder is dan de termijn die je instelt. Verder blijft alles staan: de meldingsvoorkeuren in #__action_logs_users en de extensielijst in #__action_log_config worden niet aangeraakt.
Let op de standaardwaarde. Op 7 dagen gooit een taak die je zonder aanpassing opslaat vrijwel alles weg, precies het omgekeerde van waarvoor de meeste mensen een bewaartaak inrichten. Bepaal het getal voordat je opslaat.
Voor een betrouwbare timing start je de Taakplanner vanuit een echte systeem-cronjob in plaats van te vertrouwen op websiteverkeer.
Naar boven12. Action Logs versus andere logbestanden
12.1 Action Logs versus het systeemlogboek
Joomla beschikt ook over een technisch systeemlogboek dat wordt gevuld via Log::add(). Beide logsystemen hebben een ander doel:
| Aspect | Action Logs | Systeemlogboek |
|---|---|---|
| Gebruiksvriendelijke interface | Ja | Nee, tekstbestanden |
| Opslaglocatie | Database | Bestanden |
| Vertaalbare berichten | Ja | Nee |
| Meldingen per gebruiker | Ja | Nee |
| Beste toepassing | Audittrail voor contentbeheer (wie deed wat) | Technische gebeurtenissen (fouten, prestaties) |
Gebruik Action Logs om te achterhalen wie wat heeft gedaan binnen Joomla. Gebruik het systeemlogboek voor technische gebeurtenissen. Beide vullen elkaar aan.
12.2 Action Logs versus serverlogs
Action Logs werken op het niveau van de applicatie. Alles wat het Joomla-eventsysteem niet bereikt, blijft onzichtbaar voor het actielogboek. Voor een compleet beeld heb je daarom ook de infrastructuurlaag nodig:
| Laag | Wat wordt gezien | Wat ontbreekt |
|---|---|---|
| Action Logs | CRUD-acties, logins, installaties, configuratiewijzigingen, wie deed wat | Verzoeken die niet zijn verwerkt, PHP-fatals, serverblokkades |
| Apache/nginx access log | Elk HTTP-verzoek: URL, statuscode, IP-adres en user-agent | De Joomla-gebruiker, het betrokken item en de intentie |
| PHP-foutenlogboek | Fatals, waarschuwingen en stacktraces | Succesvolle acties en gebruikersidentiteit |
Een voorbeeld maakt het verschil duidelijk. Een artikel dat een HTTP 500-fout veroorzaakt verschijnt in het PHP-foutenlogboek en in het access log, maar niet in Action Logs, omdat het opslag-event nooit werd uitgevoerd. Het omgekeerde geldt ook: een redacteur die stilletjes een pagina naar de prullenbak verplaatst, verschijnt duidelijk in Action Logs, terwijl het access log slechts een gewone POST-aanvraag met statuscode 200 laat zien.
Voor serieus forensisch onderzoek combineer je tijdstempels uit al deze bronnen. Action Logs beantwoorden de vraag wie, serverlogs beantwoorden de vraag hoe het verzoek binnenkwam. Samen vertellen ze wat er werkelijk is gebeurd.
Naar boven13. Best practices
Als je slechts een paar dingen uit dit artikel onthoudt, laat het dan deze zijn:
- Laat beide Action Logs-plug-ins ingeschakeld op productiewebsites.
- Beperk de lijst met gelogde extensies om ruis op drukke websites te verminderen.
- Schakel IP-logging in, maar combineer dit met een bewaartermijn en een vermelding in de privacyverklaring.
- Voer nooit een opschoning uit zonder eerst een CSV-export veilig buiten Joomla op te slaan.
- Beperk het recht Verwijderen tot één speciaal beveiligingsaccount.
- Laat API-logging uitgeschakeld tenzij je actief onderzoek doet naar een probleem of incident.
14. In het kort
COMPONENT Gebruikers → User Actions Log
MELDINGEN Gebruikers → Beheren → [gebruiker] → User Actions Log Options
OPTIES Gebruikers → User Actions Log → Opties
RECORDER Systeem → Plugins → Action Log - Joomla
NOTIFIER Systeem → Plugins → System - User Actions Log
HOOFDTABEL #__action_logs
EVENTS TO LOG Opties → Events To Log (standaard 21)
IP-LOGGING Opties → IP-logging (standaard UIT)
API-LOGGING Opties → Log API Requests (standaard UIT)
EXPORT Werkbalk → Export All as CSV / Export Selected as CSV
OPSCHONEN Werkbalk → Opschonen (geen undo, wordt zelf gelogd)
RETENTIE Scheduled Tasks → Delete ActionLogs (Task - Delete Action Logs)
SINDS Joomla 3.9 (mei 2018)
Naar boven15. Samenvatting
Het User Actions Log is een van die Joomla-functies die weinig vraagt en veel oplevert. Het draait stil op de achtergrond, registreert iedere betekenisvolle wijziging en bewijst zijn waarde zodra een klant vraagt: "wie heeft de homepage gedepubliceerd?"
Met slechts enkele minuten configuratiewerk krijgt u:
- Direct inzetbare auditing voor 21 core-componenten, zonder extra extensies.
- Vertaalde en leesbare berichten die worden opgebouwd uit JSON-placeholders.
- Meldingen per gebruiker met gedetailleerde opt-inmogelijkheden.
- CSV-export met bescherming tegen formule-injecties voor veilig gebruik in spreadsheets.
- Optionele IP-logging die standaard privacyvriendelijk is ingesteld.
- Een geïndexeerde databasestructuur die moeiteloos miljoenen records aankan.
Het systeem is niet perfect. Het biedt op zichzelf geen bescherming tegen manipulatie en een vastberaden Super User kan nog steeds rechtstreeks wijzigingen in de database aanbrengen. Maar als detectielaag, gecombineerd met doordachte rechtenstructuren en een goed responsplan, verandert het de situatie van "we hebben geen idee wat er is gebeurd" naar "dit is precies wie wat heeft gedaan, en wanneer".
Beheer je een Joomla-website die belangrijk voor je is, schakel Action Logs dan in, stem de instellingen af op je situatie en leer het logboek lezen voordat je het echt nodig hebt.
Naar boven

Peter is Joomla specialist en Linux admin voor snelle, veilige en schaalbare websites.













