J3.x

Erweiterungen integrieren mit der Datenschutz Komponente

From Joomla! Documentation

This page is a translated version of the page J3.x:Integrate Extensions with the Privacy Component and the translation is 24% complete.

Other languages:
Deutsch • ‎English • ‎français • ‎italiano • ‎Nederlands

Die auf dieser Seite gezeigten Informationen sind an Entwickler von Erweiterungen gerichtet, um sie bei der Integration der Datenschutz Tools zu unterstützen.

Datenschutz zugehörige Erweiterungsmöglichkeiten

Die neue Datenschutzkomponente verfügt über einen Abschnitt Erweiterungsmöglichkeiten, der es Erweiterungen ermöglicht, datenschutzbezogene Funktionen zu melden. Das Ziel dieses Abschnitts ist es, die Benutzer zu unterstützen, um zu verstehen was eine Erweiterung in Bezug auf personenbezogene Daten von Nutzern bewirken kann. Den Website-Betreibern hilft es, entsprechend zu planen. Details zu diesem Abschnitt, einschließlich der Frage, wie ein Plugin damit integriert werden muss, ist auf der Seite Bericht von Erweiterungsmöglichkeiten an die Datenschutzkomponente zu finden.

Prüfung auf eine veröffentlichte Datenschutzerklärung

Der Check der Datenschutzkomponente informiert die Benutzer, wenn eine Datenschutzerklärung auf der Website veröffentlicht ist. Diese Prüfung wird durch das Ereignis onPrivacyCheckPrivacyPolicyPublished durchgeführt, das von Plugins in den Plugin-Gruppen privacy, system und user abgefragt werden kann. Das Ereignis erhält ein assoziatives Array als Referenz mit zwei Schlüsseln als Argument:

  • published - Ein boolescher Wert, der anzeigt, dass es eine veröffentlichte Richtlinie gibt.
  • editLink - Die URL zur Bearbeitung des Richtlinienelements, die angezeigt wird, wenn eine Datenschutzerklärung veröffentlicht wurde.
  • articlePublished - Der Beitrag gibt an, wann er in der Datenbank existiert.

Als Best Practice wird empfohlen das Plugins zunächst prüfen, ob das Flag published bereits auf true gesetzt ist. In diesem Fall keine weiteren Änderungen am Datenarray vornehmen. Beachte, dass das Kern-Plugin System - Datenschutz Zustimmung dieses Ereignis verarbeitet.

public function onPrivacyCheckPrivacyPolicyPublished(&$policy)
{
	// If another plugin has already indicated a policy is published, we won't change anything here
	if ($policy['published'])
	{
		return;
	}

	// Do stuff to find the privacy policy data

	// For core, we check if the article exists in the database and is published or not
	$query = $this->db->getQuery(true)
		->select($this->db->quoteName(array('id', 'state')))
		->from($this->db->quoteName('#__content'))
		->where($this->db->quoteName('id') . ' = ' . (int) $articleId);
	$this->db->setQuery($query);

	$article = $this->db->loadObject();

	// Check if the article exists
	if (!$article)
	{
		return;
	}

	// Check if the article is published
	if ($article->state == 1)
	{
		$policy['articlePublished'] = true;
	}

	$policy['published'] = true;
	$policy['editLink']  = ''; // The link to the item's edit page, processed through JRoute, i.e. JRoute::_('index.php?option=com_content&task=article.edit&id=1');
}


Daten zum Datenexport der Informationsanfrage hinzufügen

Es gibt mehrere Helfer Methoden in der Klasse PrivacyPlugin und es wird empfohlen, dass Datenschutz-Plugins diese Klasse erweitern, um diese Helfer zu erben (dies ist vergleichbar mit der Klasse FinderIndexerAdapter für Smart Search-Plugins als Beispiel).

JLoader::register('PrivacyPlugin', JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/plugin.php');

class PlgPrivacyContent extends PrivacyPlugin {}

To add data to an export request, a plugin in the privacy or system plugin groups must subscribe to the onPrivacyExportRequest event.

The event receives two arguments:

  • $request - A PrivacyTableRequest object containing the information request record from the database
  • $user - If there is an account for the email address of the information request, a Joomla\CMS\User\User object is given containing the user account data

The event must return an array of PrivacyExportDomain objects containing the data to be exported for a given domain. If the plugin has no data, it must return an empty array.

A PrivacyExportDomain data object typically represents the data found from a table in the database and is made up of three elements:

  • Domain name - A name to identify the domain
  • Domain description - A short description of the data contained in the domain
  • Domain items - An array of PrivacyExportItem data objects containing all items within the domain

A PrivacyExportItem data object represents a single item within the data domain and is made up of two elements:

  • Item ID - The primary identifier for this item within the domain, typically this will be the database record's primary key
  • Item fields - An array of PrivacyExportField data objects containing each field for the item

The PrivacyExportField data object represents a single field within an item and is made up of two elements:

  • Field name - The name of the field
  • Field value - The field's value

The general workflow for the export process is this:

  • Validate the plugin should actually process data
  • Query the data from the database
  • Create a domain for the results (the createDomain method inherited from the PrivacyPlugin class can help with this)
  • Add items for each row
    • The createItemFromArray method inherited from the PrivacyPlugin class can be used to create a PrivacyExportItem object from an array (this should be used in conjunction with the database's loadAssocList method)
    • The createItemForTable method inherited from the PrivacyPlugin class can be used to create a PrivacyExportItem object from a Joomla\CMS\Table\Table object
  • Return the domain

Below is an example for exporting articles created by a user, including custom field data.

use Joomla\CMS\User\User;

JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');
JLoader::register('PrivacyPlugin', JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/plugin.php');

class PlgPrivacyContent extends PrivacyPlugin
{
	/**
	 * @var  JDatabaseDriver
	 */
	protected $db;

	/**
	 * @var  array
	 */
	protected $contents = array();

	public function onPrivacyExportRequest(PrivacyTableRequest $request, User $user = null)
	{
		// This plugin only processes data for registered user accounts
		if (!$user)
		{
			return array();
		}

		$domains   = array();
		$domains[] = $this->createContentDomain($user);

		// Create domains for each article's custom fields
		foreach ($this->contents as $content)
		{
			$domains[] = $this->createContentCustomFieldsDomain($content);
		}

		return $domains;
	}

	private function createContentDomain(User $user)
	{
		$domain = $this->createDomain('user_content', 'joomla_user_content_data');

		$query = $this->db->getQuery(true)
			->select('*')
			->from($this->db->quoteName('#__content'))
			->where($this->db->quoteName('created_by') . ' = ' . (int) $user->id)
			->order($this->db->quoteName('ordering') . ' ASC');

		$items = $this->db->setQuery($query)->loadAssocList();

		// Add each article to the domain
		foreach ($items as $item)
		{
			$domain->addItem($this->createItemFromArray($item));

			// Store the article for use in the custom fields processing
			$this->contents[] = (object) $item;
		}

		return $domain;
	}

	private function createContentCustomFieldsDomain($content)
	{
		$domain = $this->createDomain('content_custom_fields', 'joomla_content_custom_fields_data');

		// Get item's fields, also preparing their value property for manual display
		$fields = FieldsHelper::getFields('com_content.article', $content);

		foreach ($fields as $field)
		{
			$fieldValue = is_array($field->value) ? implode(', ', $field->value) : $field->value;

			$data = array(
				'content_id'  => $content->id,
				'field_name'  => $field->name,
				'field_title' => $field->title,
				'field_value' => $fieldValue,
			);

			$domain->addItem($this->createItemFromArray($data));
		}

		return $domain;
	}
}


Process Removal Requests

Processing a removal request requires two steps: Validating that the subject's data can be removed, and the actual removal. Again it is suggested that plugins extend the PrivacyPlugin class, however this is not a strict requirement.

JLoader::register('PrivacyPlugin', JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/plugin.php');

class PlgPrivacyUser extends PrivacyPlugin {}

Validate Data Can Be Removed

If the plugin may need to block a subject's data from being removed, it must subscribe to the onPrivacyCanRemoveData event. Generally, a removal should be blocked if there are valid legal reasons to retain the data or if removal may cause permanent damage to the site (for example, the core Privacy - User Accounts prohibits removing a super user account).

The event receives two arguments:

  • $request - A PrivacyTableRequest object containing the information request record from the database
  • $user - If there is an account for the email address of the information request, a Joomla\CMS\User\User object is given containing the user account data

The event must return a PrivacyRemovalStatus data object which specifies if the data cannot be removed and a reason for the inability to remove the data.

use Joomla\CMS\Language\Text;
use Joomla\CMS\User\User;

JLoader::register('PrivacyPlugin', JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/plugin.php');
JLoader::register('PrivacyRemovalStatus', JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/removal/status.php');

class PlgPrivacyUser extends PrivacyPlugin
{
	public function onPrivacyCanRemoveData(PrivacyTableRequest $request, User $user = null)
	{
		$status = new PrivacyRemovalStatus;

		// We only need to check if there is an associated user account
		if (!$user)
		{
			return $status;
		}

		// We will not remove a super user account from the site
		if ($user->authorise('core.admin'))
		{
			$status->canRemove = false;
			$status->reason    = Text::_('PLG_PRIVACY_USER_ERROR_CANNOT_REMOVE_SUPER_USER');
		}

		return $status;
	}
}

Remove or Anonymize Data

If the plugin handles the removal or anonymization of data, it must subscribe to the onPrivacyRemoveData event.

The event receives two arguments:

  • $request - A PrivacyTableRequest object containing the information request record from the database
  • $user - If there is an account for the email address of the information request, a Joomla\CMS\User\User object is given containing the user account data

Unlike the other events in this component, plugins are not expected to return any data.

Depending on the underlying data's requirements, plugins should anonymize information that is retained and remove any data that is no longer necessary. If necessary, the plugin may perform other actions related to the request and/or user account.

The below example demonstrates how Joomla anonymizes and removes data related to the core user account.

use Joomla\CMS\Factory;
use Joomla\CMS\User\User;

JLoader::register('PrivacyPlugin', JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/plugin.php');

class PlgPrivacyUser extends PrivacyPlugin
{
	/**
	 * @var  JDatabaseDriver
	 */
	protected $db;

	public function onPrivacyRemoveData(PrivacyTableRequest $request, User $user = null)
	{
		// This plugin only processes data for registered user accounts
		if (!$user)
		{
			return;
		}

		$pseudoanonymisedData = array(
			'name'      => 'User ID ' . $user->id,
			'username'  => bin2hex(random_bytes(12)), // Generates a random username
			'email'     => 'UserID' . $user->id . 'removed@email.invalid',
			'block'     => true,
		);

		$user->bind($pseudoanonymisedData);

		$user->save();

		// Destroy all sessions for the user account
		$sessionIds = $this->db->setQuery(
			$this->db->getQuery(true)
				->select($this->db->quoteName('session_id'))
				->from($this->db->quoteName('#__session'))
				->where($this->db->quoteName('userid') . ' = ' . (int) $user->id)
		)->loadColumn();

		// If there aren't any active sessions then there's nothing to do here
		if (empty($sessionIds))
		{
			return;
		}

		$storeName = Factory::getConfig()->get('session_handler', 'none');
		$store     = JSessionStorage::getInstance($storeName);
		$quotedIds = array();

		// Destroy the sessions and quote the IDs to purge the session table
		foreach ($sessionIds as $sessionId)
		{
			$store->destroy($sessionId);
			$quotedIds[] = $this->db->quote($sessionId);
		}

		$this->db->setQuery(
			$this->db->getQuery(true)
				->delete($this->db->quoteName('#__session'))
				->where($this->db->quoteName('session_id') . ' IN (' . implode(', ', $quotedIds) . ')')
		)->execute();
	}
}