Skip to content
Snippets Groups Projects
Commit c656ad1f authored by Jürgen Haas's avatar Jürgen Haas
Browse files

Issue #3308570: Create events for user role and permission changes

parent 36a25b2a
No related branches found
No related tags found
No related merge requests found
......@@ -84,3 +84,22 @@ function danse_install() {
}
}
}
/**
* Add new base field uid to event entities.
*/
function danse_update_8001() {
if ($entity_type = Drupal::entityTypeManager()->getDefinition('danse_event')) {
$field_definition = Event::baseFieldDefinitions($entity_type);
Drupal::entityDefinitionUpdateManager()->installFieldStorageDefinition(
'uid',
$entity_type->id(),
$entity_type->getProvider(),
$field_definition['uid']
);
// Explicitly set the default value.
Drupal::database()->update('danse_event')
->fields(['uid' => 0])
->execute();
}
}
......@@ -3,6 +3,7 @@
namespace Drupal\danse_config;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\danse\Entity\Event;
use Drupal\node\Entity\Node;
use Drupal\danse\Entity\EventInterface;
use Drupal\danse\PayloadBase;
......@@ -29,7 +30,7 @@ final class Payload extends PayloadBase {
/**
* {@inheritdoc}
*/
public function label(): string {
public function label(Event $event): string {
return 'config';
}
......
......@@ -37,7 +37,7 @@ final class Payload extends PayloadBase {
/**
* {@inheritdoc}
*/
public function label(): string {
public function label(Event $event): string {
return $this->entity->label();
}
......
......@@ -41,7 +41,7 @@ final class Payload extends PayloadBase {
/**
* {@inheritdoc}
*/
public function label(): string {
public function label(Event $event): string {
return $this->form['#form_id'];
}
......
......@@ -50,7 +50,7 @@ final class Payload extends PayloadBase {
/**
* {@inheritdoc}
*/
public function label(): string {
public function label(Event $event): string {
$args = $this->context;
unset($args['backtrace']);
return trim(PlainTextOutput::renderFromHtml((string) $this->t($this->message, $args)));
......
......@@ -2,7 +2,10 @@
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\danse_user\Plugin\Danse\Role;
use Drupal\danse_user\Plugin\Danse\User;
use Drupal\danse_user\UserPayload;
use Drupal\user\RoleInterface;
use Drupal\user\UserInterface;
/**
......@@ -12,6 +15,13 @@ function _danse_user_plugin(): User {
return Drupal::service('plugin.manager.danse.plugin')->createInstance('user');
}
/**
* @return \Drupal\danse_user\Plugin\Danse\Role;
*/
function _danse_user_role_plugin(): Role {
return Drupal::service('plugin.manager.danse.plugin')->createInstance('role');
}
/**
* Implements hook_user_cancel().
*
......@@ -20,7 +30,7 @@ function _danse_user_plugin(): User {
* @param string $method
*/
function danse_user_user_cancel(array $edit, UserInterface $account, string $method): void {
_danse_user_plugin()->createUserEvent(User::TOPIC_CANCEL, $account);
_danse_user_plugin()->createUserEvent(UserPayload::TOPIC_CANCEL, $account);
}
/**
......@@ -29,7 +39,7 @@ function danse_user_user_cancel(array $edit, UserInterface $account, string $met
* @param \Drupal\user\UserInterface $account
*/
function danse_user_user_login(UserInterface $account): void {
_danse_user_plugin()->createUserEvent(User::TOPIC_LOGIN, $account);
_danse_user_plugin()->createUserEvent(UserPayload::TOPIC_LOGIN, $account);
}
/**
......@@ -38,17 +48,22 @@ function danse_user_user_login(UserInterface $account): void {
* @param \Drupal\Core\Session\AccountInterface $account
*/
function danse_user_user_logout(AccountInterface $account): void {
_danse_user_plugin()->createUserEvent(User::TOPIC_LOGOUT, $account);
_danse_user_plugin()->createUserEvent(UserPayload::TOPIC_LOGOUT, $account);
}
/**
* Implements hook_entity_create().
* Implements hook_entity_insert().
*
* @param \Drupal\Core\Entity\EntityInterface $entity
*/
function danse_user_entity_create(EntityInterface $entity): void {
function danse_user_entity_insert(EntityInterface $entity): void {
if ($entity instanceof UserInterface) {
_danse_user_plugin()->createUserEvent(User::TOPIC_CREATE, $entity);
$plugin = _danse_user_plugin();
$plugin->createUserEvent(UserPayload::TOPIC_INSERT, $entity);
_danse_user_plugin()->createChangedRolesEvents([], $entity);
}
elseif ($entity instanceof RoleInterface) {
_danse_user_role_plugin()->createChangedPermissionsEvents([], $entity);
}
}
......@@ -59,6 +74,11 @@ function danse_user_entity_create(EntityInterface $entity): void {
*/
function danse_user_entity_update(EntityInterface $entity): void {
if ($entity instanceof UserInterface) {
_danse_user_plugin()->createUserEvent(User::TOPIC_UPDATE, $entity);
$plugin = _danse_user_plugin();
$plugin->createUserEvent(UserPayload::TOPIC_UPDATE, $entity);
$plugin->createChangedRolesEvents($entity->original->getRoles(TRUE), $entity);
}
elseif ($entity instanceof RoleInterface) {
_danse_user_role_plugin()->createChangedPermissionsEvents($entity->original->getPermissions(), $entity);
}
}
<?php
namespace Drupal\danse_user\Plugin\Danse;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\danse\Entity\EventInterface;
use Drupal\danse\PayloadInterface;
use Drupal\danse\PluginBase;
use Drupal\danse_user\RolePayload;
use Drupal\user\RoleInterface;
/**
* Plugin implementation of DANSE.
*
* @Danse(
* id = "role",
* label = @Translation("Role"),
* description = @Translation("Manages all role events.")
* )
*/
class Role extends PluginBase {
/**
* {@inheritdoc}
*/
public function assertPayload(PayloadInterface $payload): bool {
return $payload instanceof RolePayload;
}
/**
* {@inheritdoc}
*/
public function getSupportedSubscriptions($roles): array {
return [];
}
/**
* {@inheritdoc}
*/
public function buildForm(&$form, FormStateInterface $form_state) {
return FALSE;
}
/**
* {@inheritdoc}
*/
public function getRedirectUrl(EventInterface $event): Url {
return Url::fromRoute('<front>');
}
/**
* @param array $oldPermissions
* @param \Drupal\user\RoleInterface $role
*/
public function createChangedPermissionsEvents(array $oldPermissions, RoleInterface $role): void {
$payload = new RolePayload($role);
$newPermissions = $role->getPermissions();
foreach (array_diff($oldPermissions, $newPermissions) as $permission) {
$this->createEvent(RolePayload::TOPIC_PERMISSION_REMOVED, $permission, $payload);
}
foreach (array_diff($newPermissions, $oldPermissions) as $permission) {
$this->createEvent(RolePayload::TOPIC_PERMISSION_ADDED, $permission, $payload);
}
}
}
......@@ -8,7 +8,7 @@ use Drupal\Core\Url;
use Drupal\danse\Entity\EventInterface;
use Drupal\danse\PayloadInterface;
use Drupal\danse\PluginBase;
use Drupal\danse_user\Payload;
use Drupal\danse_user\UserPayload;
/**
* Plugin implementation of DANSE.
......@@ -21,21 +21,11 @@ use Drupal\danse_user\Payload;
*/
class User extends PluginBase {
public const TOPIC_CREATE = 'create';
public const TOPIC_UPDATE = 'update';
public const TOPIC_CANCEL = 'cancel';
public const TOPIC_LOGIN = 'login';
public const TOPIC_LOGOUT = 'logout';
/**
* {@inheritdoc}
*/
public function assertPayload(PayloadInterface $payload): bool {
return $payload instanceof Payload;
return $payload instanceof UserPayload;
}
/**
......@@ -67,8 +57,23 @@ class User extends PluginBase {
*/
public function createUserEvent(string $topic, AccountInterface $account): ?EventInterface {
$message = $account->getDisplayName();
$payload = new Payload($account);
$payload = new UserPayload($account);
return $this->createEvent($topic, $message, $payload);
}
/**
* @param array $oldRoles
* @param \Drupal\Core\Session\AccountInterface $account
*/
public function createChangedRolesEvents(array $oldRoles, AccountInterface $account): void {
$payload = new UserPayload($account);
$newRoles = $account->getRoles(TRUE);
foreach (array_diff($oldRoles, $newRoles) as $role) {
$this->createEvent(UserPayload::TOPIC_ROLE_REMOVED, $role, $payload);
}
foreach (array_diff($newRoles, $oldRoles) as $role) {
$this->createEvent(UserPayload::TOPIC_ROLE_ADDED, $role, $payload);
}
}
}
<?php
namespace Drupal\danse_user;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\danse\Entity\Event;
use Drupal\danse\Entity\EventInterface;
use Drupal\danse\PayloadBase;
use Drupal\danse\PayloadInterface;
use Drupal\user\Entity\Role;
use Drupal\user\RoleInterface;
/**
* Class Payload.
*
* @package Drupal\danse_user
*/
final class RolePayload extends PayloadBase {
public const TOPIC_PERMISSION_ADDED = 'permission_added';
public const TOPIC_PERMISSION_REMOVED = 'permission_removed';
/**
* @var \Drupal\user\RoleInterface
*/
protected RoleInterface $role;
/**
* Content constructor.
*
* @param \Drupal\user\RoleInterface $role
*/
public function __construct(RoleInterface $role) {
$this->role = $role;
}
/**
* {@inheritdoc}
*/
public function label(Event $event): string {
return implode('/', [$this->role->label(), $event->label()]);
}
/**
* {@inheritdoc}
*/
public function getEventReference(): string {
return implode('-', ['role', $this->role->id()]);
}
/**
* {@inheritdoc}
*/
public function getSubscriptionReferences(EventInterface $event): array {
return [implode('-', ['role', $event->getTopic()])];
}
/**
* {@inheritdoc}
*/
public function prepareArray(): array {
return [
'role' => $this->role->id(),
];
}
/**
* {@inheritdoc}
*/
public static function createFromArray(array $payload): ?PayloadInterface {
/** @var \Drupal\user\RoleInterface $role */
if ($role = Role::load($payload['role'])) {
return new RolePayload($role);
}
return NULL;
}
/**
* {@inheritdoc}
*/
public function getEntity(): ContentEntityInterface {
/** @var \Drupal\danse\Entity\Event $entity */
$entity = Event::create([
'plugin' => 'role',
'topic' => '',
'label' => '',
'payload' => $this,
'push' => TRUE,
'force' => FALSE,
'silent' => FALSE,
]);
return $entity;
}
/**
* {@inheritdoc}
*/
public function hasAccess($uid): bool {
return FALSE;
}
}
......@@ -2,7 +2,6 @@
namespace Drupal\danse_user;
use Drupal;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\danse\Entity\Event;
......@@ -16,12 +15,26 @@ use Drupal\user\Entity\User;
*
* @package Drupal\danse_user
*/
final class Payload extends PayloadBase {
final class UserPayload extends PayloadBase {
public const TOPIC_INSERT = 'insert';
public const TOPIC_UPDATE = 'update';
public const TOPIC_CANCEL = 'cancel';
public const TOPIC_LOGIN = 'login';
public const TOPIC_LOGOUT = 'logout';
public const TOPIC_ROLE_ADDED = 'role_added';
public const TOPIC_ROLE_REMOVED = 'role_removed';
/**
* @var \Drupal\Core\Session\AccountInterface
*/
protected $account;
protected AccountInterface $account;
/**
* Content constructor.
......@@ -35,8 +48,15 @@ final class Payload extends PayloadBase {
/**
* {@inheritdoc}
*/
public function label(): string {
return $this->account->getDisplayName();
public function label(Event $event): string {
$name = $this->account->getDisplayName();
if (in_array($event->getTopic(), [
self::TOPIC_ROLE_ADDED,
self::TOPIC_ROLE_REMOVED,
], TRUE)) {
return implode('/', [$name, $event->label()]);
}
return $name;
}
/**
......@@ -68,7 +88,7 @@ final class Payload extends PayloadBase {
public static function createFromArray(array $payload): ?PayloadInterface {
/** @var \Drupal\user\UserInterface $user */
if ($user = User::load($payload['account'])) {
return new Payload($user);
return new UserPayload($user);
}
return NULL;
}
......@@ -77,7 +97,7 @@ final class Payload extends PayloadBase {
* {@inheritdoc}
*/
public function getEntity(): ContentEntityInterface {
/** @var Event $entity */
/** @var \Drupal\danse\Entity\Event $entity */
$entity = Event::create([
'plugin' => 'user',
'topic' => '',
......
......@@ -6,6 +6,7 @@ use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\danse\Entity\Event;
use Drupal\node\Entity\Node;
use Drupal\danse\Entity\EventInterface;
use Drupal\danse\PayloadBase;
......@@ -50,7 +51,7 @@ final class Payload extends PayloadBase {
/**
* {@inheritdoc}
*/
public function label(): string {
public function label(Event $event): string {
return $this->label;
}
......
......@@ -35,6 +35,7 @@ use Drupal\danse\PluginInterface;
* "id" = "id",
* "type" = "topic",
* "uuid" = "uuid",
* "label" = "label",
* "status" = "processed"
* },
* links = {
......@@ -57,6 +58,7 @@ class Event extends ContentEntityBase implements EventInterface {
if (!empty($values['silent'])) {
$values['processed'] = TRUE;
}
$values['uid'] = \Drupal::currentUser()->id();
parent::preCreate($storage, $values);
}
......@@ -170,6 +172,10 @@ class Event extends ContentEntityBase implements EventInterface {
$fields['changed'] = BaseFieldDefinition::create('changed')
->setLabel('Change')
->setRequired(TRUE);
$fields['uid'] = BaseFieldDefinition::create('entity_reference')
->setLabel('User ID')
->setSetting('target_type', 'user')
->setRequired(TRUE);
return $fields;
}
......
......@@ -3,6 +3,7 @@
namespace Drupal\danse;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\danse\Entity\Event;
use Drupal\danse\Entity\EventInterface;
/**
......@@ -11,9 +12,11 @@ use Drupal\danse\Entity\EventInterface;
interface PayloadInterface {
/**
* @param \Drupal\danse\Entity\Event $event
*
* @return string
*/
public function label(): string;
public function label(Event $event): string;
/**
* @return string
......
......@@ -17,7 +17,13 @@ class EventLabel extends EntityField {
$raw = $item['raw'];
/** @var \Drupal\danse\Entity\Event $event */
$event = $raw->getEntity();
$item['rendered']['#context']['value'] = $event->getPayload()->label();
if ($payload = $event->getPayload()) {
$label = $payload->label($event);
}
else {
$label = 'unknown';
}
$item['rendered']['#context']['value'] = $label;
return parent::render_item($count, $item);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment