diff --git a/css/ckeditor_overrides.css b/css/ckeditor_overrides.css index aa63e9dfe..5d18aee63 100644 --- a/css/ckeditor_overrides.css +++ b/css/ckeditor_overrides.css @@ -14,3 +14,10 @@ button.ck.ck-button[data-cke-tooltip-text="Media"] svg { .ck.ck-content.ck-editor__editable { min-height: 200px; } + +.ck-link-form { + .ck-reset_all-excluded { + background-color: rgba(265, 256, 257, 21.4) !important; + } +} + diff --git a/drush.services.yml b/drush.services.yml new file mode 100644 index 000000000..f7fa3f647 --- /dev/null +++ b/drush.services.yml @@ -0,0 +1,6 @@ +services: + drush.command.tide_core: + class: Drupal\tide_core\Command\AuditLogCleanupCommand + arguments: ['@config.factory'] + tags: + - { name: drush.command } \ No newline at end of file diff --git a/modules/tide_site/tide_site.install b/modules/tide_site/tide_site.install index dde975183..8907fde62 100644 --- a/modules/tide_site/tide_site.install +++ b/modules/tide_site/tide_site.install @@ -89,3 +89,12 @@ function tide_site_update_10002() { } } } + +/** + * Enable linkset. + */ +function tide_site_update_10003() { + $system_feature_flags = \Drupal::configFactory()->getEditable('system.feature_flags'); + $system_feature_flags->set('linkset_endpoint', TRUE) + ->save(); +} diff --git a/modules/tide_tfa/src/TideTfaOperation.php b/modules/tide_tfa/src/TideTfaOperation.php index 31da59282..d9b329b6a 100644 --- a/modules/tide_tfa/src/TideTfaOperation.php +++ b/modules/tide_tfa/src/TideTfaOperation.php @@ -103,7 +103,7 @@ public static function setupTfaSettings() { 'code_validity_period' => '600', 'email_setting' => [ 'subject' => 'Single Digtial Presence CMS two-factor authentication code', - 'body' => '[user:display-name],\r\n\r\nThis code is valid for [length] minutes. \r\n\r\nYour code is: [code]\r\n\r\nThis code will expire once you have logged in.', + 'body' => 'Hi [user:display-name],\r\n\r\nYour two-factor authentication code is: [code]\r\n\r\nThis code is valid for [length] minutes. \r\n\r\nThis code will expire when you have logged in.\r\n\r\nFrom the SDP team\r\n\r\nRead more about 2FA: https://digital-vic.atlassian.net/servicedesk/customer/article/2439479507', ], ], ]; diff --git a/src/Command/AuditLogCleanupCommand.php b/src/Command/AuditLogCleanupCommand.php new file mode 100755 index 000000000..d693d00bd --- /dev/null +++ b/src/Command/AuditLogCleanupCommand.php @@ -0,0 +1,106 @@ +configFactory = $config_factory; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('config.factory') + ); + } + + /** + * Removes log entries older than the configured retention period. + * + * @command tide_core:auditlog-cleanup + * @aliases tcl + * @description Cleans up audittrail logs older than the configured retention period. + * + * @option force-cleanup Skip confirmation and run the cleanup immediately. + */ + public function cleanupLogs($options = ['force-cleanup' => FALSE]) { + // Check if the user passed the --force-cleanup option. + if (!$options['force-cleanup']) { + // If the force-cleanup flag isn't passed, ask for confirmation. + $confirmation = $this->confirmCleanup(); + if (!$confirmation) { + $this->output()->writeln('Cleanup operation cancelled.'); + return; + } + } + + $config = $this->configFactory->get('tide_core.settings'); + define('DEFAULT_LOG_RETENTION_DAYS', 30); + $log_retention_days = $config->get('log_retention_days') ?: DEFAULT_LOG_RETENTION_DAYS; + // Get current date and time. + $current_time = new DateTime(); + $current_time->sub(new DateInterval("P{$log_retention_days}D")); + $threshold_timestamp = $current_time->getTimestamp(); + // Connect to the database. + $database = Database::getConnection(); + $deleted = $database->delete('admin_audit_trail') + ->condition('created', $threshold_timestamp, '<') + ->execute(); + + // Output the result. + $this->output()->writeln("Deleted $deleted log entries older than $log_retention_days days."); + // Run a database optimization command to recover space. + $this->optimizeDatabase(); + } + + /** + * Ask for confirmation before proceeding with the cleanup. + * + * @return bool + * TRUE if the user confirms, FALSE if the user cancels. + */ + private function confirmCleanup() { + $question = 'Are you sure you want to delete log entries older than the configured retention period? (y/n): '; + $confirmation = $this->io()->ask($question, 'n'); + $confirmation = strtolower($confirmation); + // Return TRUE if the user answers 'y' or 'yes'. + return in_array($confirmation, ['y', 'yes']); + } + + /** + * Run database optimization (optional). + * + * @return void + * TRUE write the message. + */ + private function optimizeDatabase() { + $database = Database::getConnection(); + $database->query('OPTIMIZE TABLE {admin_audit_trail}'); + $this->output()->writeln("Database optimized to recover space."); + } + +} diff --git a/src/Form/AuditTrailSettingsForm.php b/src/Form/AuditTrailSettingsForm.php new file mode 100644 index 000000000..79d5679c5 --- /dev/null +++ b/src/Form/AuditTrailSettingsForm.php @@ -0,0 +1,62 @@ +config('tide_core.settings'); + + // Add a text field to specify the number of days for log retention. + $form['log_retention_days'] = [ + '#type' => 'number', + '#title' => $this->t('Log retention days'), + '#description' => $this->t('Enter the number of days after which logs should be deleted.'), + // Default to 30 if not set. + '#default_value' => $config->get('log_retention_days', 30), + '#min' => 1, + '#required' => TRUE, + ]; + + return parent::buildForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $this->config('tide_core.settings') + ->set('log_retention_days', $form_state->getValue('log_retention_days')) + ->save(); + + $this->messenger()->addMessage($this->t('The log retention days have been updated.')); + parent::submitForm($form, $form_state); + } + +} diff --git a/tide_core.install b/tide_core.install index a60005191..79171eb9a 100644 --- a/tide_core.install +++ b/tide_core.install @@ -5,6 +5,7 @@ * Installation functions for Tide Core. */ +use Drupal\field\Entity\FieldConfig; use Drupal\tide_core\TideCoreOperation; use Drupal\user\Entity\Role; use Drupal\user\Entity\User; @@ -316,3 +317,44 @@ function tide_core_update_10010() { $module_installer->install(['tide_tfa']); } } + +/** + * Enabled tide_data_driven_component module. + */ +function tide_core_update_10011() { + $moduleHandler = \Drupal::service('module_handler'); + $moduleInstaller = \Drupal::service('module_installer'); + // Enable tide_data_driven_component. + if (!$moduleHandler->moduleExists('tide_data_driven_component')) { + $moduleInstaller->install(['tide_data_driven_component']); + } + if ($moduleHandler->moduleExists('tide_landing_page')) { + // Define the fields to be updated. + $fields_to_update = [ + 'field_landing_page_component', + 'field_landing_page_header', + ]; + $new_component = 'data_driven_component'; + + foreach ($fields_to_update as $field_name) { + $field_config = FieldConfig::loadByName('node', 'landing_page', $field_name); + + if ($field_config) { + // Get the current handler settings. + $handler_settings = $field_config->getSetting('handler_settings'); + + // Ensure 'target_bundles' exists in handler settings. + if (isset($handler_settings['target_bundles'])) { + // Add the new component if it does not already exist. + if (!array_key_exists($new_component, $handler_settings['target_bundles'])) { + $handler_settings['target_bundles'][$new_component] = $new_component; + + // Update the field configuration with the new handler settings. + $field_config->setSetting('handler_settings', $handler_settings); + $field_config->save(); + } + } + } + } + } +} diff --git a/tide_core.links.menu.yml b/tide_core.links.menu.yml index 3379177e4..766f1b9f0 100644 --- a/tide_core.links.menu.yml +++ b/tide_core.links.menu.yml @@ -4,3 +4,9 @@ tide_core.moderated_content: parent: system.admin_content route_name: content_moderation.admin_moderated_content weight: 100 + +audit_trail_settings.admin: + title: 'Audit Trail Settings' + description: 'Change audit trail log clean time' + parent: admin_audit_trail.report_form + route_name: audit_trail_settings.admin \ No newline at end of file diff --git a/tide_core.routing.yml b/tide_core.routing.yml index 785595880..3e98bb11d 100644 --- a/tide_core.routing.yml +++ b/tide_core.routing.yml @@ -36,3 +36,11 @@ tide_core.package_version: methods: ['GET'] requirements: _access: 'TRUE' + +audit_trail_settings.admin: + path: '/admin/reports/audit-trail/audit-trail-settings' + defaults: + _form: '\Drupal\tide_core\Form\AuditTrailSettingsForm' + _title: 'Audit Trail Settings' + requirements: + _permission: "access admin audit trail"