Zwar kann man in Joomla in den globalen Benutzeroptionen das Ändern des Benutzernamens unterbinden, aber nicht das Ändern des Kennworts. Nachdem die Frage regelmäßig in Foren auftaucht, mir die Lösungen viel zu aufwendig oder "radikal" erscheinen, präsentiere ich hier ein abgespecktes Basisplugin, basierend auf einer Idee von Re:Later, der das mal als Demo für GHSVS programmierte.

Fehlermeldung bei nicht erlaubtem Speichern von durch Plugin blockierten Nutzern

Die Frage, wie sinnvoll es ist, einmal registrierten Benutzern zu verbieten, ihre Profil-Daten zu ändern, stellt sich in diesem Beitrag nicht. Eigentlich erhöht es die Sicherheit, wenn Nutzer regelmäßig ihr Kennwort ändern, noch dazu, wenn man in den globalen Benutzeroptionen (Menü Benutzer > Benutzer > Klick auf den Optionen-Button) die Einstellungen entsprechend hart macht.

Häufiges in Foren beschriebenes Szenario (auch hier möchte ich auf den (Un)Sinn nicht eingehen): Für mehrere Mitglieder wurde nur 1 Benutzer angelegt. Alle verwenden den selben Account und immer wieder passiert es, dass einer der Mitglieder das Kennwort ändert. Keiner kommt mehr rein. Joomla bietet bzgl. Profiländerungen diverse Wege und Schliche, was das Blockieren ohne Plugin entsprechend aufwendig macht. Man muss an mehreren Code-Stellen ansetzen, für mehrere Dateien Overrides erstellen oder in der Datenbank einen so genannten Trigger anlegen, der aber das Speichern von Nutzerdaten auch für SuperUser blockiert, also auch der Administrator muss den Trigger erst wieder entfernen, bevor er die "getriggerten" Benutzerdaten ändern kann, dann den Trigger wieder anlegen. Zwischenzeitlich ist die Blockierung nicht mehr aktiv und es kann doch wieder ein Spielkind was ändern. Nervt irgendwann.

Tipp vorneweg, wenn Sie nun doch diesen Weg "Einer für Alle" einschlagen wollen: Damit Benutzer sich nicht gegenseitig ausloggen oder wenigstens möglichst selten, sollte man im Joomla-eigenen Plugin "Benutzer - Joomla" die Einstellung "Alle Sitzungen beenden?" auf "Nein" setzen.

HINWEIS: Dieser Artikel war seinerzeit als Tutorial für Joomla-3-Plugins gedacht. Mittlerweile wurde die Entwicklung des Plugins "plg_system_blockusersaveghsvs" eingestellt. Es wurde durch das Plugin "PLG_SYSTEM_ONUSERGHSVS" ersetzt, das weitere Features hat und auch für Joomla 4 verfügbar ist. Den Download-Link finden Sie am Ende des Beitrags.

Also erstellen wir ein schmales Systemplugin, das Sie natürlich am Ende des Beitrags auch einfach runterladen können, wenn Sie das Programmierdings nicht die Bohne interessiert, mit folgenden Fetaures:

  • Auswahl aus einer Liste von Benutzeraccounts, die nicht geändert werden dürfen (Parameter / Option users_to_block).
  • Auswahl, ob Speicherung im Frontend und / oder Backend blockiert werden soll (Parameter / Optionen block_fe und block_be).
  • Auswahl, ob Super-Administratoren trotzdem immer speichern / ändern dürfen (Parameter / Option allow_admins).
System-Plugin blockusersaveghsvs. Backend-Einstellmöglichkeiten der kleinen Plugin-Version.

Weitere Optionen habe ich aus dem öffentlichen, kostenfreien Plugin entfernt (Filterung nach Benutzergruppen, Zugriffsebenen etc.), da ich vornehmlich Individuallösungen programmiere und Kunden nur einprogrammiert bekommen, was sie benötigen (und ehrlich gesagt gar keine Lust hatte das alles für diese Veröffentlichung noch mal durchzutesten).

Verzeichnisstruktur und Dateien

Zuerst erstellen wir eine Ordnerstruktur auf unserem lokalen Rechner, also noch nicht im Joomlaverzeichnis, natürlich ohne die eckigen Klammern. Achten Sie auf Kleinschreibung bei allen Dateien und Ordnern! [Korrekturlesung 2015-09: Das gilt nicht für die Sprachdateien (siehe GB)]

  • [plg_system_blockusersaveghsvs]
    • [fields]
    • [language]
      • [en-GB]

In [blockusersaveghsvs] legen wir 2 Dateien an

  • blockusersaveghsvs.xml
  • blockusersaveghsvs.php

Im Ordner [fields] 1 Datei

  • usersghsvs.php

Im Ordner [en-GB] 2 Dateien

  • en-GB.plg_system_blockusersaveghsvs.ini
  • en-GB.plg_system_blockusersaveghsvs.sys.ini

Auf die exakte Benennung der Sprachdateien und zugehöriger Ordner muss geachtet werden, sonst findet sie Joomla nicht.

System-Plugin blockusersaveghsvs. Die Ordner und Dateien

Der Inhalt von blockusersaveghsvs.xml

blockusersaveghsvs.xml ist die so genannte Manifest-Datei, die jede Joomla-Erweiterung benötigt, also auch unser Plugin. Hierin finden sich bei Plugins u.a. die oben beschriebenen Optionen in Form von fields, so, dass sie im Backend einstellbar sind Im Netz werden Sie fündig, was diese Datei noch für Aufgaben hat.

<?xml version="1.0" encoding="utf-8"?>
<extension version="3.4.3" type="plugin" group="system" method="upgrade">
 <name>PLG_SYSTEM_BLOCKUSERSAVEGHSVS</name>
 <author>Re:Later for G@HService Berlin Neukölln, Volkmar Volli Schlothauer</author>
 <creationDate>2014-03-29</creationDate>
 <copyright>Even if I would enter a copyright here 99% of the world would ignore it!</copyright>
 <license></license>
 <authorEmail>reLater @ ghsvs.de</authorEmail>
 <authorUrl>www.ghsvs.de</authorUrl>
 <version>2014.03.29</version>
 <versionHistory></versionHistory>
 <description>PLG_SYSTEM_BLOCKUSERSAVEGHSVS_DESC</description>

 <files>
  <filename plugin="blockusersaveghsvs">blockusersaveghsvs.php</filename>
  <filename>blockusersaveghsvs.xml</filename>
  <folder>language</folder>
  <folder>fields</folder>
 </files>

 <config>
  <fields name="params" addfieldpath="/plugins/system/blockusersaveghsvs/fields/">

   <fieldset name="basic">
    
    <field name="users_to_block" type="usersghsvs" multiple="true"
     description=""
     label="PLG_BLOCKUSERSAVEGHSVS_USERS_TO_BLOCK_LBL">
    </field>

    <field name="block_fe" type="list"
     description=""
     label="PLG_BLOCKUSERSAVEGHSVS_BLOCK_FE_LBL">
     <option value="0">JNO</option>
     <option value="1">JYES</option>
    </field>

    <field name="block_be" type="list"
     description=""
     label="PLG_BLOCKUSERSAVEGHSVS_BLOCK_BE_LBL">
     <option value="0">JNO</option>
     <option value="1">JYES</option>
    </field>

    <field name="allow_admins" type="list"
     description=""
     label="PLG_BLOCKUSERSAVEGHSVS_ALLOW_ADMINS">
     <option value="0">JNO</option>
     <option value="1">JYES</option>
    </field>    

   </fieldset>
  </fields>
 </config>
</extension>

INI-Sprachdateien

Da sich in der Manifest-Datei mehrere Joomla-Sprachplatzhalter befinden, befülle ich aus Gewohnheit erst mal die INI-Dateien. Man sieht, dass Re:Later ein Faulpelz ist. Einige Sprachplatzhalter sind in Deutsch, obwohl sie in der englischen Sprachdatei sind.

en-GB.plg_system_blockusersaveghsvs.sys.ini

PLG_SYSTEM_BLOCKUSERSAVEGHSVS="System - Block user saving (GHSVS)"

PLG_SYSTEM_BLOCKUSERSAVEGHSVS_DESC="Basisversion eines Demo-Plugins von Re:Later zum Blockieren des Speicherns ausgewählter Benutzer. Plugin nach Installation aktivieren und dann gewünschte Einstellungen im Plugin auswählen."

en-GB.plg_system_blockusersaveghsvs.ini

PLG_SYSTEM_BLOCKUSERSAVEGHSVS="System - Block user saving (GHSVS)"

PLG_SYSTEM_BLOCKUSERSAVEGHSVS_DESC="Basisversion Demo-Plugin zum Blockieren des Speicherns ausgewählter Benutzer."

PLG_SYSTEM_BLOCKUSERSAVEGHSVS_NOT_ALLOWED="Saving blocked by "_QQ_"Plugin System - Block user saving (GHSVS)"_QQ_""

PLG_BLOCKUSERSAVEGHSVS_USERS_TO_BLOCK_LBL="Blocked users"

PLG_BLOCKUSERSAVEGHSVS_BLOCK_FE_LBL="Block in frontend"

PLG_BLOCKUSERSAVEGHSVS_BLOCK_BE_LBL="Block in backend"

PLG_BLOCKUSERSAVEGHSVS_ALLOW_ADMINS="Allowed for super admins"

Eigenes Formularfeld (custom form field) usersghsvs.php

Die XML-Datei oben enthält addfieldpath="/plugins/system/blockusersaveghsvs/fields/", was den Pfad zum eigenen Formularfeld users_to_block vom Typ usersghsvs angibt. Dieses ermöglicht uns später die Auswahl der zu blockierenden User aus einer Liste aller Benutzeraccounts.

Anmerkung: Die Datenbankabfrage könnte für das Basisplugin noch kürzer gecodet sein. Die Gruppierung benötigen wir hier eigentlich nicht. Auch sollten DB-Abfragen zur Fehlerausgabe in ein try-catch-Konstrukt "verpackt" werden. Viel Spaß beim Optimieren!

<?php
defined('JPATH_PLATFORM') or die;
//use Joomla\Registry\Registry;
JFormHelper::loadFieldClass('list');
class JFormFieldUsersghsvs extends JFormFieldList
{

 public $type = 'usersghsvs';

 protected static $options = array();

 protected function getOptions()
 {
  $hash = md5($this->element);
  if (!isset(static::$options[$hash]))
  {
   static::$options[$hash] = parent::getOptions();

   $options = array();

   $db = JFactory::getDbo();

   $query = $db->getQuery(true)
    ->select('u.id AS value, u.name AS text')
    ->from('#__users AS u')
    ->group('u.id, u.name')
    ->order('u.name');

   $db->setQuery($query);

   if ($options = $db->loadObjectList())
   {
    static::$options[$hash] = array_merge(static::$options[$hash], $options);
   }
  }

  return static::$options[$hash];
 }
}

Plugin-Datei blockusersaveghsvs.php

Das Plugin "lauscht" auf den Moment, wenn ein User gespeichert werden soll (Zeile 10, Plugin-Event onUserBeforeSave). Wird ein neuer Benutzer angelegt, macht das Plugin nichts (Zeile 13). Andernfalls liest es die im Plugin gewählten Benutzer in ein Array aus (Zeile 15, users_to_block) und wird aktiv, wenn der zu speichernde Benutzer ($user), identifiziert durch die id, in dieser Liste enthalten ist (Zeile 17). Sollte die Prüfung weiterer Plugin-Einstellungen block_fe, block_be und allow_admins ergeben, dass nicht gespeichert werden darf, wird eine Fehlermeldung ausgegeben (Zeile 27) und der Benutzer NICHT gespeichert.

Das ist natürlich etwas plump, den Nutzer erst zu informieren, wenn er Speichern klickt und ggf. schon mühsam Eingaben gemacht hat, aber nur so ist der PHP-Code so kurz und übersichtlich wie er ist. Wer mehr draus machen will, könnte u.a. beim Plugin-Event onContentPrepareForm ansetzen, so, dass bereits vor dem Laden der verschiedenen, möglichen Formulare jeweils ein Hinweis erfolgt, dass die betr. Nutzerdaten nicht geändert werden dürfen.

<?php
defined('JPATH_BASE') or die;

class plgSystemBlockusersaveghsvs extends JPlugin{
 
 protected $app;
 // protected $db;
 protected $autoloadLanguage = true;

 public function onUserBeforeSave($user, $isnew, $new)
 {
  
  if ($isnew) return;
  
  $users = $this->params->get('users_to_block', array(), 'ARRAY');

  if (in_array($user['id'], $users))
  {
   $feBlock = $this->app->isSite() && $this->params->get('block_fe', 0);
   $beBlock = $this->app->isAdmin() && $this->params->get('block_be', 0);
   $isSuperAdmin = JFactory::getUser()->get('isRoot', false);

   if ($feBlock || $beBlock)
   {
    if (!$isSuperAdmin || ($isSuperAdmin && !$this->params->get('allow_admins', 0)))
    {
     $this->app->enqueueMessage(JText::_('PLG_SYSTEM_BLOCKUSERSAVEGHSVS_NOT_ALLOWED'), 'notice');
     return false;
    }
   }
  }
  
  return;
  
 }
}

ZIP-Datei für Installation erstellen

Abschließend gehe ich in den Ordner [plg_system_blockusersaveghsvs], markiere alles und verpacke bspw. mit 7-ZIP alles in eine Archivdatei, mit der ich das Plugin dann in Joomla installieren kann.

Plugin blockusersaveghsvs. Installierbare ZIP Datei mit 7-ZIP erstellen.

Benutzername vergessen

Auch hier blockiert das Plugin bereits beim ersten Schritt bevor der Benutzer seine Email mit dem Bestätigungscode bekommt. Hat man den Nutzer allerdings zwischenzeitlich während des Prozedere, versehentlich kurz freigegeben, darauf achten, dass der User von Joomla auf Nicht aktiviert gesetzt wird, bevor er ein neues Passwort eingeben darf, was ihn dann wieder mit neuem Kennwort aktiviert. Wenn er zwischenzeitlich wieder per Plugin blockiert wurde, muss ein Admin den User-Account im Backend wieder aktivieren. Das Kennwort bleibt dabei das alte.