Skip to content

Commit

Permalink
Entitlements finalization.
Browse files Browse the repository at this point in the history
  • Loading branch information
drudoi committed Jan 22, 2025
1 parent c394af5 commit 9f5d6a5
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 20 deletions.
5 changes: 4 additions & 1 deletion modules/quanthub_chat_overlay/quanthub_chat_overlay.module
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@
* Implements hook_page_attachments().
*/
function quanthub_chat_overlay_page_attachments(array &$attachments) {
$attachments['#attached']['library'][] = 'quanthub_chat_overlay/chat-overlay';
if (\Drupal::currentUser()->hasPermission('access ai')) {
$attachments['#attached']['library'][] = 'quanthub_chat_overlay/chat-overlay';
}
$attachments['#cache']['contexts'][] = 'user.permissions';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
access ai:
title: 'Access AI tools'
description: 'Access AI chat overlay and features.'
3 changes: 1 addition & 2 deletions modules/quanthub_core/quanthub_core.module
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ function quanthub_core_node_access(NodeInterface $node, $operation, AccountInter

$cacheable_metadata = (new CacheableMetadata())
->addCacheContexts(['user.roles:anonymous', 'user.permissions'])
->addCacheContexts($account->isAuthenticated() ? ['user'] : [])
->addCacheTags(['allowed_content_tag:' . $account->id()]);
->addCacheContexts($account->isAuthenticated() ? ['user.datasets'] : []);
$allowed_datasets = \Drupal::service('allowed_content_manager')
->getAllowedDatasetList();
$node_datasets = [];
Expand Down
12 changes: 12 additions & 0 deletions modules/quanthub_core/quanthub_core.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ services:
class: Drupal\quanthub_core\PowerBIEmbedConfigs
arguments: ['@config.factory', '@key.repository', '@logger.factory', '@http_client']

cache_context.user.datasets:
class: Drupal\quanthub_core\Cache\AllowedDatasetsCacheContext
arguments: ['@current_user', '@allowed_content_manager']
tags:
- { name: cache.context }

# Client for calls to SDMX API.
logger.channel.sdmx_api:
parent: logger.channel_base
Expand All @@ -61,3 +67,9 @@ services:
class: Drupal\quanthub_core\EventSubscriber\KernelEventsSubscriber
arguments: [ '@current_route_match', '@entity_type.manager' ]
tags: [ 'event_subscriber' ]

quanthub_core.oidc_subscriber:
class: Drupal\quanthub_core\EventSubscriber\OidcEventsSubscriber
arguments: [ '@oidc.openid_connect_session' ]
tags:
- { name: event_subscriber }
5 changes: 0 additions & 5 deletions modules/quanthub_core/src/AllowedContentManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use Drupal\Component\Datetime\Time;
use Drupal\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Language\LanguageManager;
use Drupal\Core\Session\AccountProxy;
Expand Down Expand Up @@ -121,10 +120,6 @@ public function getAllowedDatasetList() {
$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
61 changes: 61 additions & 0 deletions modules/quanthub_core/src/Cache/AllowedDatasetsCacheContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

namespace Drupal\quanthub_core\Cache;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\Context\CacheContextInterface;
use Drupal\Core\Cache\Context\UserCacheContextBase;
use Drupal\Core\Session\AccountInterface;
use Drupal\quanthub_core\AllowedContentManager;

/**
* Defines the User Allowed Datasets cache context service.
*
* Cache context ID: 'user.datasets'.
*/
class AllowedDatasetsCacheContext extends UserCacheContextBase implements CacheContextInterface {

/**
* The Allowed Content Manager service.
*
* @var \Drupal\quanthub_core\AllowedContentManager
*/
protected $allowedContentManager;

/**
* {@inheritdoc}
*/
public function __construct(AccountInterface $user, AllowedContentManager $allowed_content_manager) {
parent::__construct($user);

$this->allowedContentManager = $allowed_content_manager;
}

/**
* {@inheritdoc}
*/
public static function getLabel() {
return t('Allowed Datasets');
}

/**
* {@inheritdoc}
*/
public function getContext() {
$datasets = NULL;
if (getenv('WSO_IGNORE') !== 'TRUE') {
$datasets = $this->allowedContentManager->getAllowedDatasetList();
sort($datasets);
}
// We don't need to secure this information, crc32 is enough.
return hash('crc32', serialize($datasets));
}

/**
* {@inheritdoc}
*/
public function getCacheableMetadata() {
return (new CacheableMetadata())->setCacheTags(['user:' . $this->user->id()]);
}

}
93 changes: 93 additions & 0 deletions modules/quanthub_core/src/EventSubscriber/OidcEventsSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

namespace Drupal\quanthub_core\EventSubscriber;

use Drupal\externalauth\Event\ExternalAuthEvents;
use Drupal\externalauth\Event\ExternalAuthLoginEvent;
use Drupal\oidc\OpenidConnectSessionInterface;
use Drupal\oidc\Plugin\OpenidConnectRealm\GenericOpenidConnectRealm;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
* Event subscriber to assign user roles.
*/
class OidcEventsSubscriber implements EventSubscriberInterface {

/**
* Roles mapping.
*
* @todo make configurable.
*/
const ROLES = [
'Quanthub.ExternalUsers' => '',
'Quanthub.Users' => '',
'DataPlatformBasic' => '',
'DataPlatformEnhanced' => '',
'DataPlatformMedia' => 'media',
'PortalContentEditor' => 'content_editor',
'AiAssistant' => 'ai',
];

/**
* The OpenID Connect session service.
*
* @var \Drupal\oidc\OpenidConnectSessionInterface
*/
protected $session;

/**
* {@inheritdoc}
*/
public function __construct(OpenidConnectSessionInterface $session) {
$this->session = $session;
}

/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events[ExternalAuthEvents::LOGIN][] = 'onLogin';

return $events;
}

/**
* Updates the synced user roles on login.
*
* @param \Drupal\externalauth\Event\ExternalAuthLoginEvent $event
* The login event.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*/
public function onLogin(ExternalAuthLoginEvent $event) {
$plugin_id = $this->session->getRealmPluginId();
$provider = 'oidc:' . $this->session->getRealmPluginId();
$roles_claim = $this->session->getJsonWebTokens()->getClaim('roles');

// The provider must match the realm and provide the claim.
if (!$plugin_id || $provider !== $event->getProvider() || $roles_claim === NULL) {
return;
}

$roles = [];
if (is_array($roles_claim)) {
foreach ($roles_claim as $role) {
if (empty(self::ROLES[$role])) {
continue;
}
$roles[] = self::ROLES[$role];
}
}

// Only generic realms support this.
$plugin = $this->session->getRealmPlugin();
if ($plugin instanceof GenericOpenidConnectRealm && $plugin->getDefaultRoleId()) {
$roles[] = $plugin->getDefaultRoleId();
}

$event->getAccount()
->set('roles', array_unique($roles))
->save();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,6 @@ public function query() {
$this->query->addWhere($this->options['group'], $conditions);
}

/**
* {@inheritdoc}
*/
public function getCacheTags() {
$account = $this->view->getUser();
return Cache::mergeTags(
parent::getCacheTags(),
['allowed_content_tag:' . $account->id()]
);
}

/**
* {@inheritdoc}
*/
Expand All @@ -106,7 +95,7 @@ public function getCacheContexts() {
$contexts = ['user.permissions', 'user.roles:anonymous'];
// Cache per user if we filter by individual user's datasets.
if (!$account->hasPermission('bypass dataset access') && $account->isAuthenticated()) {
$contexts[] = 'user';
$contexts[] = 'user.datasets';
}
return Cache::mergeContexts(
parent::getCacheContexts(),
Expand Down

0 comments on commit 9f5d6a5

Please sign in to comment.