Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions config/install/field.field.user.user.field_accepted_date.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
langcode: en
status: true
dependencies:
config:
- field.storage.user.field_accepted_date
module:
- user
- datetime
id: user.user.field_accepted_date
field_name: field_accepted_date
entity_type: user
bundle: user
label: 'TOS Accepted Date'
description: 'The date and time when the user accepted the Terms of Service.'
required: false
translatable: true
default_value: { }
default_value_callback: ''
settings:
timezone_override: ''
field_type: datetime
21 changes: 21 additions & 0 deletions config/install/field.field.user.user.field_tos_acceptance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
langcode: en
status: true
dependencies:
config:
- field.storage.user.field_tos_acceptance
module:
- user
id: user.user.field_tos_acceptance
field_name: field_tos_acceptance
entity_type: user
bundle: user
label: 'Terms of Service Accepted'
description: 'Indicates whether the user has accepted the Terms of Service.'
required: false
translatable: true
default_value:
-
value: 0
default_value_callback: ''
settings: { }
field_type: boolean
19 changes: 19 additions & 0 deletions config/install/field.storage.user.field_accepted_date.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
langcode: en
status: true
dependencies:
module:
- user
- datetime
id: user.field_accepted_date
field_name: field_accepted_date
entity_type: user
type: datetime
settings:
datetime_type: datetime
module: core
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false
19 changes: 19 additions & 0 deletions config/install/field.storage.user.field_tos_acceptance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
langcode: en
status: true
dependencies:
module:
- user
id: user.field_tos_acceptance
field_name: field_tos_acceptance
entity_type: user
type: boolean
settings:
on_label: 'Accepted'
off_label: 'Not Accepted'
module: core
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false
102 changes: 102 additions & 0 deletions src/Controller/TosAcceptanceController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php

namespace Drupal\ucb_user_invite\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface;
use Drupal\user\UserStorageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

/**
* Controller for handling TOS acceptance.
*/
class TosAcceptanceController extends ControllerBase {

/**
* The current user.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $currentUser;

/**
* The user storage.
*
* @var \Drupal\user\UserStorageInterface
*/
protected $userStorage;

/**
* Constructs a TosAcceptanceController object.
*
* @param \Drupal\Core\Session\AccountProxyInterface $current_user
* The current user.
* @param \Drupal\user\UserStorageInterface $user_storage
* The user storage.
*/
public function __construct(AccountProxyInterface $current_user, UserStorageInterface $user_storage) {
$this->currentUser = $current_user;
$this->userStorage = $user_storage;
}

/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('current_user'),
$container->get('entity_type.manager')->getStorage('user')
);
}

/**
* Handles TOS acceptance.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The request object.
*
* @return \Symfony\Component\HttpFoundation\JsonResponse
* A JSON response.
*/
public function accept(Request $request) {
$user = $this->userStorage->load($this->currentUser->id());

if (!$user) {
return new JsonResponse([
'success' => FALSE,
'message' => 'User not found.',
], 404);
}

if (!$user->hasField('field_tos_acceptance')) {
return new JsonResponse([
'success' => FALSE,
'message' => 'TOS acceptance field not found.',
], 500);
}

// Set TOS accepted to TRUE.
$user->set('field_tos_acceptance', 1);

// Update the accepted_date field if it exists.
if ($user->hasField('field_accepted_date')) {
// Create a DrupalDateTime object in UTC timezone.
$date = new DrupalDateTime('now', DateTimeItemInterface::STORAGE_TIMEZONE);
// Format according to datetime storage format.
$formatted_date = $date->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT);
$user->set('field_accepted_date', $formatted_date);
}

$user->save();

return new JsonResponse([
'success' => TRUE,
'message' => 'Terms of Service accepted successfully.',
]);
}

}
112 changes: 112 additions & 0 deletions ucb_user_invite.install
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,115 @@ function ucb_user_invite_update_9502() {
$field_config->save();
}
}

/**
* Adds the 'field_tos_acceptance' and 'field_accepted_date' fields to the User entity.
*
* Introduced to support Terms of Service acceptance tracking.
*/
function ucb_user_invite_update_9503() {
$entity_type = 'user';
$bundle = 'user';

// Create field_tos_acceptance (boolean).
$tos_field_name = 'field_tos_acceptance';
$tos_field_storage = \Drupal::entityTypeManager()
->getStorage('field_storage_config')
->load($entity_type . '.' . $tos_field_name);

if (!$tos_field_storage) {
$tos_field_storage = \Drupal::entityTypeManager()
->getStorage('field_storage_config')
->create([
'field_name' => $tos_field_name,
'entity_type' => $entity_type,
'type' => 'boolean',
'settings' => [
'on_label' => 'Accepted',
'off_label' => 'Not Accepted',
],
]);
$tos_field_storage->save();
}

$tos_field_config = \Drupal::entityTypeManager()
->getStorage('field_config')
->load($entity_type . '.' . $bundle . '.' . $tos_field_name);

if (!$tos_field_config) {
$tos_field_config = \Drupal::entityTypeManager()
->getStorage('field_config')
->create([
'field_name' => $tos_field_name,
'entity_type' => $entity_type,
'bundle' => $bundle,
'label' => t('Terms of Service Accepted'),
'description' => t('Indicates whether the user has accepted the Terms of Service.'),
'required' => FALSE,
'default_value' => [
[
'value' => 0,
],
],
]);
$tos_field_config->save();
}

// Create field_accepted_date (datetime).
$date_field_name = 'field_accepted_date';
$date_field_storage = \Drupal::entityTypeManager()
->getStorage('field_storage_config')
->load($entity_type . '.' . $date_field_name);

if (!$date_field_storage) {
$date_field_storage = \Drupal::entityTypeManager()
->getStorage('field_storage_config')
->create([
'field_name' => $date_field_name,
'entity_type' => $entity_type,
'type' => 'datetime',
'settings' => [
'datetime_type' => 'datetime',
],
]);
$date_field_storage->save();
}

$date_field_config = \Drupal::entityTypeManager()
->getStorage('field_config')
->load($entity_type . '.' . $bundle . '.' . $date_field_name);

if (!$date_field_config) {
$date_field_config = \Drupal::entityTypeManager()
->getStorage('field_config')
->create([
'field_name' => $date_field_name,
'entity_type' => $entity_type,
'bundle' => $bundle,
'label' => t('TOS Accepted Date'),
'description' => t('The date and time when the user accepted the Terms of Service.'),
'required' => FALSE,
]);
$date_field_config->save();
}

// Set default value for all existing users to FALSE (0) for tos_acceptance.
$user_storage = \Drupal::entityTypeManager()->getStorage('user');
$query = $user_storage->getQuery()
->accessCheck(FALSE)
->condition('uid', 0, '>');
$uids = $query->execute();

if (!empty($uids)) {
$users = $user_storage->loadMultiple($uids);
foreach ($users as $user) {
if ($user->hasField('field_tos_acceptance')) {
$current_value = $user->get('field_tos_acceptance')->value;
if ($current_value === NULL) {
$user->set('field_tos_acceptance', 0);
$user->save();
}
}
}
}
}
50 changes: 50 additions & 0 deletions ucb_user_invite.module
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,53 @@ function ucb_user_invite_mail($key, &$message, $params) {
$message['body'] = ['#markup' => $tokenService->replace(strtr($template, $variables), $tokens, $options)];
}
}

/**
* Implements hook_preprocess_page().
*/
function ucb_user_invite_preprocess_page(&$variables) {
// Check if TOS acceptance is enabled in site configuration.
$site_config = \Drupal::config('ucb_site_configuration.settings');
$tos_enabled = $site_config->get('tos_acceptance_enabled');

// If TOS acceptance is not enabled (default is FALSE), don't show the modal.
if (empty($tos_enabled)) {
return;
}

// Only check for logged-in users on user pages.
$route_match = \Drupal::routeMatch();
$route_name = $route_match->getRouteName();

// Check if this is a user page route.
if (in_array($route_name, ['entity.user.canonical', 'user.page'])) {
$current_user = \Drupal::currentUser();

// Only show modal to authenticated users.
if ($current_user->isAuthenticated()) {
$user = \Drupal::entityTypeManager()
->getStorage('user')
->load($current_user->id());

// Check if user has accepted TOS.
if ($user && $user->hasField('field_tos_acceptance')) {
$tos_accepted = $user->get('field_tos_acceptance')->value;

// If TOS not accepted, attach the library to show modal.
if (empty($tos_accepted)) {
$variables['#attached']['library'][] = 'boulder_base/ucb-tos-acceptance';

// TOS URL from Web Central Website.
$tos_url = 'https://www.colorado.edu/webcentral';

// Pass settings to JavaScript.
$variables['#attached']['drupalSettings']['ucb_tos_acceptance'] = [
'show_modal' => TRUE,
'tos_url' => $tos_url,
'accept_url' => Url::fromRoute('ucb_user_invite.tos_acceptance')->toString(),
];
}
}
}
}
}
10 changes: 10 additions & 0 deletions ucb_user_invite.routing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,13 @@ ucb_user_invite.settings_form:
_permission: administer user invite
options:
_admin_route: true

ucb_user_invite.tos_acceptance:
path: '/ucb-user-invite/tos-acceptance/accept'
defaults:
_controller: '\Drupal\ucb_user_invite\Controller\TosAcceptanceController::accept'
requirements:
_user_is_logged_in: 'TRUE'
_format: 'json'
_csrf_request_header_token: 'TRUE'
methods: [POST]