Terug naar hoofdinhoud
Joomla's actielogs gebruiken
Op deze pagina
# Topics

Joomla's actielogs gebruiken

20 juni 2026

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 zietGebruikte 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:

OnderdeelFunctie
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:

KolomVoorbeeld
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, alleen com_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 boven

2. 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:

EventWat 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:

EventWat 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:

EventWat 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.
  • onExtensionAfterSave met context com_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:

EventWat 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 boven

3. 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 = 1 en extensions = com_users,com_installer ontvangt 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_users bij als gebruikers worden opgeslagen of verwijderd.
  • com_actionlogs, de component, doet de rest: ActionlogModel::addLog() schrijft elke regel weg en roept daarna sendNotificationEmails() aan, en ActionlogsHelper::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 boven

4. Exporteren en opschonen

4.1 CSV-export

De lijstweergave bevat twee exportknoppen in de werkbalk:

KnopWat 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 boven

5. 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:

  1. Zorg voor een geldige grondslag. Gerechtvaardigd belang voor beveiliging is meestal voldoende.
  2. Vermeld IP-logging in je privacyverklaring.
  3. 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:

  1. Verwijder de gebruiker via com_users. Hierdoor wordt nog één laatste logregel aangemaakt waarin naar het verwijderde account-ID wordt verwezen.
  2. 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.

Naar boven

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 boven

7. 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 boven

8. 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.

Naar boven

9. Veelvoorkomende fouten en valkuilen

9.1 "Er wordt niets gelogd"

Doorloop deze controlelijst in volgorde:

  1. Is de plugin Action Log - Joomla ingeschakeld?
  2. Staat de betreffende component in de lijst Events To Log?
  3. Is de actie daadwerkelijk geslaagd? De recorder werkt met "after"-events, dus een opslagactie die faalt door validatiefouten wordt niet geregistreerd.
  4. 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:

  1. Maak eerst een CSV-export via de knop Export All as CSV.
  2. Bewaar het CSV-bestand buiten de Joomla-installatie.
  3. 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).

Naar boven

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:

  1. Action Logs inschakelen voor com_users, com_installer, com_config, com_plugins, com_modules en com_templates.
  2. IP-logging inschakelen en een bewaartermijn van 90 dagen instellen via een geplande taak.
  3. Meldingen inschakelen voor Super User-accounts, met toezicht op com_users en com_installer.
  4. Het recht Verwijderen beperken tot één speciaal beveiligingsaccount.
  5. 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 boven

11. 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:

VeldWaarde
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 boven

12. 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:

AspectAction LogsSysteemlogboek
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:

LaagWat wordt gezienWat 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 boven

13. 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.
Naar boven

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 boven

15. 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
Joomla's actielogs gebruiken
Peter Martin
Peter Martin
Joomla Specialist

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

Gerelateerde artikelen