Skip to content

Commit

Permalink
Entitlements improve and refactoring. (#245)
Browse files Browse the repository at this point in the history
* Entitlements improve and refactoring.

* switch to PHP 8.2

---------

Co-authored-by: Illya Havsiyevych <[email protected]>
  • Loading branch information
drudoi and illya-havsiyevych authored Jan 16, 2025
1 parent 4a4bb4d commit c394af5
Show file tree
Hide file tree
Showing 12 changed files with 255 additions and 424 deletions.
17 changes: 8 additions & 9 deletions .github/workflows/code-standards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ on:
pull_request:
branches:
- 1.1.x
env:
PHP_VERSION: 8.1

jobs:
PHP-Code-Standards:
Expand All @@ -14,13 +12,14 @@ jobs:
- name: Check out repository code
uses: actions/checkout@v3

- name: Set PHP Version
run: |
sudo update-alternatives --set php /usr/bin/php$PHP_VERSION
sudo update-alternatives --set phar /usr/bin/phar$PHP_VERSION
sudo update-alternatives --set phpdbg /usr/bin/phpdbg$PHP_VERSION
sudo update-alternatives --set php-cgi /usr/bin/php-cgi$PHP_VERSION
sudo update-alternatives --set phar.phar /usr/bin/phar.phar$PHP_VERSION
- name: Setup PHP
id: setup-php
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'

- name: Print PHP version
run: echo ${{ steps.setup-php.outputs.php-version }}

- name: Сomposer Install
run: |
Expand Down
117 changes: 56 additions & 61 deletions modules/quanthub_core/quanthub_core.module
Original file line number Diff line number Diff line change
Expand Up @@ -7,90 +7,85 @@

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Cache\CacheableDependencyInterface;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\node\NodeInterface;
use Drupal\quanthub_core\Form\PowerBIMediaForm;

/**
* Implements hook_ENTITY_TYPE_access().
*/
function quanthub_core_node_access(EntityInterface $entity, $operation, AccountInterface $account) {
if ($operation == 'view') {
if ($entity->bundle() == 'dataset') {
// @todo remove when entitlement will be released.
if (
in_array('editor', $account->getRoles()) ||
in_array('publisher', $account->getRoles())
) {
return AccessResult::allowed();
}
if (getenv('WSO_IGNORE') !== 'TRUE') {
$allowed_datasets = \Drupal::service('allowed_content_manager')
->getAllowedDatasetList();
}
if (!empty($allowed_datasets)) {
$node_dataset = $entity->field_quanthub_urn->getString();
// @todo need to change and handle version of dataset urn.
foreach ($allowed_datasets as $allowed_dataset) {
if (str_contains($node_dataset, $allowed_dataset)) {
return AccessResult::allowed();
}
}
return AccessResult::forbidden();
}
}
if ($entity->bundle() == 'publication') {
// @todo remove when entitlement will be released.
if (
in_array('editor', $account->getRoles()) ||
in_array('publisher', $account->getRoles())
) {
return AccessResult::allowed();
}
// @todo rewrite in db_select.
$node_dataset = $entity->get('field_dataset')?->first()?->get('entity')?->getTarget()?->getValue()?->get('field_quanthub_urn')?->getString();
if (getenv('WSO_IGNORE') !== 'TRUE') {
$allowed_datasets = \Drupal::service('allowed_content_manager')
->getAllowedDatasetList();
}
if (!empty($allowed_datasets)) {
// @todo need to change and handle version of dataset urn.
foreach ($allowed_datasets as $allowed_dataset) {
if (str_contains($node_dataset, $allowed_dataset)) {
return AccessResult::allowed();
}
}
return AccessResult::forbidden();
}
function quanthub_core_node_access(NodeInterface $node, $operation, AccountInterface $account) {
if (
$operation !== 'view' ||
\Drupal::currentUser()->id() !== $account->id() ||
!$node->hasField('field_quanthub_urn') ||
getenv('WSO_IGNORE') === 'TRUE'
) {
return AccessResult::neutral();
}
if ($account->hasPermission('bypass dataset access')) {
return AccessResult::neutral()->cachePerPermissions();
}

$cacheable_metadata = (new CacheableMetadata())
->addCacheContexts(['user.roles:anonymous', 'user.permissions'])
->addCacheContexts($account->isAuthenticated() ? ['user'] : [])
->addCacheTags(['allowed_content_tag:' . $account->id()]);
$allowed_datasets = \Drupal::service('allowed_content_manager')
->getAllowedDatasetList();
$node_datasets = [];
$field = $node->get('field_quanthub_urn');
if ($field instanceof CacheableDependencyInterface) {
$cacheable_metadata->addCacheableDependency($field);
}
foreach ($field as $item) {
if ($item instanceof CacheableDependencyInterface) {
$cacheable_metadata->addCacheableDependency($item);
}
$node_datasets[] = $item->value;
}
if (!array_intersect($allowed_datasets, $node_datasets)) {
return AccessResult::forbidden('The dataset access is not allowed for the user.')
->addCacheableDependency($cacheable_metadata);
}

return AccessResult::neutral()->addCacheableDependency($cacheable_metadata);
}

/**
* Implements hook_views_data_alter().
*/
function quanthub_core_views_data_alter(array &$data) {
$data['node__field_quanthub_urn']['allowed_content_filter'] = [
$base = [
'title' => t('Allowed Content Filter'),
'help' => t('Content Filter By Dataset Urn'),
'group' => t('Quanthub'),
'filter' => [
'title' => t('Allowed Content Filter'),
'help' => t('Content Filter By Dataset Urn'),
'group' => t('Quanthub'),
'field' => 'field_quanthub_urn',
'id' => 'allowed_content_filter',
'allow empty' => FALSE,
],
];

$data['views']['quanthub_views_bulk_operations_bulk_form'] = [
'title' => t('Quanthub Views bulk operations'),
'help' => t("Process entities returned by the view with Views Bulk Operations' actions."),
'field' => [
'id' => 'quanthub_views_bulk_operations_bulk_form',
],
];
if (!empty($data['node__field_quanthub_urn']['field_quanthub_urn_value'])) {
$table = 'node__field_quanthub_urn';
$data[$table]['allowed_content_filter'] = $base;
$data[$table]['allowed_content_filter']['filter']['id'] = 'allowed_content_filter';
$data[$table]['allowed_content_filter']['filter'] += $data[$table]['field_quanthub_urn_value']['filter'];
}

foreach (array_keys($data) as $table) {
if (!str_starts_with($table, 'search_api_index') || empty($data[$table]['field_quanthub_urn'])) {
continue;
}
$data[$table]['allowed_content_filter'] = $base;
$data[$table]['allowed_content_filter']['real field'] = 'field_quanthub_urn';
$data[$table]['allowed_content_filter']['filter']['id'] = 'allowed_content_filter_search_api';
$data[$table]['allowed_content_filter']['filter'] += $data[$table]['field_quanthub_urn']['filter'];
}
}

/**
Expand Down
4 changes: 4 additions & 0 deletions modules/quanthub_core/quanthub_core.permissions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
bypass dataset access:
title: 'Bypass dataset access'
description: 'View all datasets and related content regardless of permission restrictions.'
restrict access: true
7 changes: 0 additions & 7 deletions modules/quanthub_core/quanthub_core.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,6 @@ services:
class: Drupal\quanthub_core\PowerBIEmbedConfigs
arguments: ['@config.factory', '@key.repository', '@logger.factory', '@http_client']

# User Info Cache Context based on User Info Role for anonymous and User Id for others.
cache_context.user_info_attributes:
class: Drupal\quanthub_core\Cache\Context\UserInfoAttributesCacheContext
arguments: ['@current_user', '@user.data']
tags:
- { name: cache.context}

# Client for calls to SDMX API.
logger.channel.sdmx_api:
parent: logger.channel_base
Expand Down
37 changes: 17 additions & 20 deletions modules/quanthub_core/src/AllowedContentManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,6 @@ public function __construct(
* Get Datasets IDs from cache if not existed updated this by request to wso2.
*/
public function getAllowedDatasetList() {
// For admin, editor and publisher, show all content related to datasets.
// @todo remove publisher and content_editor when entitlements released.
if (
$this->currentUser->id() == 1 ||
in_array('content_editor', $this->currentUser->getRoles()) ||
in_array('publisher', $this->currentUser->getRoles())
) {
return [];
}
// Check that user authenticated and is not admin.
// Check that dataset list is not already saved to cache.
if ($cache = $this->cache->get($this->getCacheCid())) {
Expand All @@ -116,18 +107,24 @@ public function getAllowedDatasetList() {
else {
$this->datasets = $this->getUserDatasetList();

// Update datasets in cache.
if ($this->datasets) {
$this->cache->set(
$this->getCacheCid(),
$this->datasets,
$this->time->getCurrentTime() + $this::CACHE_TIME
);

// Invalidating cache tags for updating views
// with datasets and publications.
Cache::invalidateTags(['allowed_content_tag:' . $this->currentUser->id()]);
// Support latest version.
foreach ($this->datasets as $dataset) {
$latest_dataset = preg_replace('/\(.+\)$/', '(~)', $dataset);
if ($latest_dataset !== $dataset) {
$this->datasets[] = $latest_dataset;
}
}

// Update datasets in cache.
$this->cache->set(
$this->getCacheCid(),
$this->datasets,
$this->time->getCurrentTime() + $this::CACHE_TIME
);

// Invalidating cache tags for updating views
// with datasets and publications.
Cache::invalidateTags(['allowed_content_tag:' . $this->currentUser->id()]);
}

return $this->datasets;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

namespace Drupal\quanthub_core\Plugin\Field\FieldType;

use Drupal\Core\Cache\CacheableDependencyInterface;
use Drupal\Core\Cache\RefinableCacheableDependencyTrait;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
use Drupal\Core\Field\FieldItemList;
use Drupal\Core\TypedData\ComputedItemListTrait;

/**
* Computed field to proxy QuantHub URN from references.
*/
class QuantHubUrnComputedList extends FieldItemList implements CacheableDependencyInterface {

use ComputedItemListTrait;
use RefinableCacheableDependencyTrait;

/**
* {@inheritdoc}
*/
protected function computeValue() {
$this->list = [];

$entity = $this->getEntity();
$field_name = $this->getFieldDefinition()->getSetting('field_reference_name');
if (!$field_name || !$entity->hasField($field_name)) {
return;
}
$references = $entity->get($field_name);
if (!$references instanceof EntityReferenceFieldItemListInterface) {
return;
}

$urns = [];
foreach ($references->referencedEntities() as $referencedEntity) {
if (
!$referencedEntity instanceof FieldableEntityInterface ||
!$referencedEntity->hasField('field_quanthub_urn')
) {
continue;
}

$this->addCacheableDependency($referencedEntity);

$field = $referencedEntity->get('field_quanthub_urn');
if ($field instanceof CacheableDependencyInterface) {
$this->addCacheableDependency($field);
}

foreach ($field as $item) {
if ($item instanceof CacheableDependencyInterface) {
$this->addCacheableDependency($item);
}
if ($item->value) {
$urns[] = $item->value;
}
}
}

foreach (array_values(array_unique($urns)) as $delta => $urn) {
$this->list[$delta] = $this->createItem($delta, $urn);
}
}

}
Loading

0 comments on commit c394af5

Please sign in to comment.