From 67eab3a68a7f643be05c046d9a5834a532ae442f Mon Sep 17 00:00:00 2001 From: Md Nadim Hossain Date: Fri, 15 Nov 2024 10:49:52 +1100 Subject: [PATCH 1/4] [SD-375] bypass tfa during pass reset use prlp (#532) * [SD-375] Added class to override tfa function to bypass tfa during pass reset. --------- Co-authored-by: Md Nadim Hossain --------- Co-authored-by: Md Nadim Hossain * [SD-375] Added dependency injection for request stack. --- .../src/Controller/TideTfaUserController.php | 143 ++++++++++++++++++ .../src/Routing/TideTfaRouteSubscriber.php | 30 ++++ modules/tide_tfa/src/TideTfaOperation.php | 16 +- modules/tide_tfa/tide_tfa.module | 6 + modules/tide_tfa/tide_tfa.services.yml | 5 + 5 files changed, 195 insertions(+), 5 deletions(-) create mode 100644 modules/tide_tfa/src/Controller/TideTfaUserController.php create mode 100644 modules/tide_tfa/src/Routing/TideTfaRouteSubscriber.php create mode 100644 modules/tide_tfa/tide_tfa.services.yml diff --git a/modules/tide_tfa/src/Controller/TideTfaUserController.php b/modules/tide_tfa/src/Controller/TideTfaUserController.php new file mode 100644 index 000000000..7be18ee78 --- /dev/null +++ b/modules/tide_tfa/src/Controller/TideTfaUserController.php @@ -0,0 +1,143 @@ +requestStack = $container->get('request_stack'); + + return $instance; + } + + /** + * {@inheritdoc} + */ + public function doResetPassLogin($uid, $timestamp, $hash, $request = NULL) { + // Ensure a valid request object. + if (!$request) { + $request = $this->requestStack->getCurrentRequest(); + } + + // Check if the PRLP module is enabled. + if (!\Drupal::moduleHandler()->moduleExists('prlp')) { + // If PRLP is not enabled, call the parent method. + return parent::doResetPassLogin($uid, $timestamp, $hash, $request); + } + + // Create an instance of PrlpController. + $prlp_controller = new PrlpController( + \Drupal::service('date.formatter'), + \Drupal::entityTypeManager()->getStorage('user'), + \Drupal::service('user.data'), + \Drupal::service('logger.factory')->get('prlp'), + \Drupal::service('flood'), + \Drupal::service('event_dispatcher') + ); + + /** @var \Drupal\user\UserInterface $user */ + $user = $this->userStorage->load($uid); + $this->setUser($user); + + // Let Drupal core deal with the one-time login, + // if TFA is not enabled or + // current user can skip TFA while resetting password. + if ($this->isTfaDisabled() || $this->canSkipPassReset()) { + // Use PRLP's resetPassLogin instead of the core function. + return $prlp_controller->prlpResetPassLogin($request, $uid, $timestamp, $hash); + } + + // Whether the TFA Validation Plugin is set and ready for use. + $tfa_ready = $this->isReady(); + + // Check for authentication plugin. + if ($tfa_ready && $this->pluginAllowsLogin()) { + $this->messenger()->addStatus($this->t('You have logged in on a trusted browser.')); + return $prlp_controller->prlpResetPassLogin($request, $uid, $timestamp, $hash); + } + + // Borrow the following codes from the core function: + $current = \Drupal::time()->getRequestTime(); + + // Verify that the user exists and is active. + if ($user === NULL || !$user->isActive()) { + throw new AccessDeniedHttpException(); + } + + // Time out, in seconds, until login URL expires. + $timeout = $this->config('user.settings')->get('password_reset_timeout'); + if ($user->getLastLoginTime() && $current - $timestamp > $timeout) { + $this->messenger()->addError($this->t('You have tried to use a one-time login link that has expired. Please request a new one using the form below.')); + return $this->redirect('user.pass'); + } + elseif ($user->isAuthenticated() && ($timestamp >= $user->getLastLoginTime()) && ($timestamp <= $current) && hash_equals($hash, user_pass_rehash($user, $timestamp))) { + if ($tfa_ready) { + $this->session->migrate(); + $token = Crypt::randomBytesBase64(55); + $request->getSession()->set('pass_reset_' . $uid, $token); + + $this->logger->notice('User %name used one-time login link at time %timestamp.', [ + '%name' => $user->getDisplayName(), + '%timestamp' => $timestamp, + ]); + + $this->tempStoreUid($user->id()); + + return $this->redirect('tfa.entry', [ + 'uid' => $uid, + 'hash' => $this->getLoginHash($user), + ], [ + 'query' => ['pass-reset-token' => $token], + 'absolute' => TRUE, + ]); + } + else { + if ($this->canLoginWithoutTfa($this->getLogger('tfa'))) { + return $this->redirectToUserForm($user, $request, $timestamp); + } + else { + return $this->redirect(''); + } + } + } + + // Use PRLP's resetPassLogin instead of the core function. + return $prlp_controller->prlpResetPassLogin($request, $uid, $timestamp, $hash); + } + + /** + * Determines if the user can skip tfa on password reset. + * + * This function checks the TFA settings to see if the option to skip TFA + * during password reset is enabled. If enabled, users will not be required + * to complete two-factor authentication when resetting their password. + * + * @return bool + * TRUE if the user can skip TFA on password reset, FALSE otherwise. + */ + public function canSkipPassReset() { + return $this->tfaSettings->get('reset_pass_skip_enabled'); + } + +} diff --git a/modules/tide_tfa/src/Routing/TideTfaRouteSubscriber.php b/modules/tide_tfa/src/Routing/TideTfaRouteSubscriber.php new file mode 100644 index 000000000..fbf1d9760 --- /dev/null +++ b/modules/tide_tfa/src/Routing/TideTfaRouteSubscriber.php @@ -0,0 +1,30 @@ +get('user.reset.login')) { + $route->setDefault('_controller', '\Drupal\tide_tfa\Controller\TideTfaUserController::doResetPassLogin'); + } + } + +} diff --git a/modules/tide_tfa/src/TideTfaOperation.php b/modules/tide_tfa/src/TideTfaOperation.php index 922721979..281c7f2c8 100644 --- a/modules/tide_tfa/src/TideTfaOperation.php +++ b/modules/tide_tfa/src/TideTfaOperation.php @@ -56,11 +56,17 @@ public static function setupTfaSettings() { $roles = Role::loadMultiple(); // Initialize the $tfa_required_roles array. $tfa_required_roles = []; - // Iterate through the roles and map the role IDs. - foreach ($roles as $role) { - if ($role->id() !== 'authenticated') { - // Map the role ID to itself. - $tfa_required_roles[$role->id()] = $role->id(); + // Define the roles to exclude in a variable. + $excluded_roles = ['authenticated', 'previewer', 'secure_file_user']; + + if (!empty($roles)) { + // Iterate through the roles and map the role IDs. + foreach ($roles as $role) { + // Check if the current role is not in the excluded roles. + if (!in_array($role->id(), $excluded_roles)) { + // Map the role ID to itself. + $tfa_required_roles[$role->id()] = $role->id(); + } } } diff --git a/modules/tide_tfa/tide_tfa.module b/modules/tide_tfa/tide_tfa.module index e894ea473..f9771b950 100644 --- a/modules/tide_tfa/tide_tfa.module +++ b/modules/tide_tfa/tide_tfa.module @@ -11,6 +11,12 @@ use Drupal\Core\Form\FormStateInterface; * Implements hook_form_alter(). */ function tide_tfa_form_alter(&$form, FormStateInterface $form_state, $form_id) { + // [SD-375] Bypass tfa during reset pass for all users. + if ($form_id == 'tfa_settings_form') { + if (isset($form['reset_pass_skip_enabled'])) { + $form['reset_pass_skip_enabled']['#description'] = t('Allow TFA to be bypassed during password reset by the authenticated user.'); + } + } if ($form_id == 'tfa_entry_form') { // [SD-294] Change the label of the 'Send' button. if (isset($form['actions']['send'])) { diff --git a/modules/tide_tfa/tide_tfa.services.yml b/modules/tide_tfa/tide_tfa.services.yml new file mode 100644 index 000000000..fa90d9713 --- /dev/null +++ b/modules/tide_tfa/tide_tfa.services.yml @@ -0,0 +1,5 @@ +services: + tide_tfa.route_subscriber: + class: Drupal\tide_tfa\Routing\TideTfaRouteSubscriber + tags: + - { name: event_subscriber } From 6aa0baefd00ad9f83b7577f07fa241530022bc88 Mon Sep 17 00:00:00 2001 From: vincent-gao Date: Mon, 25 Nov 2024 13:12:28 +1100 Subject: [PATCH 2/4] [SD-416] Fixes placeholder issue for `Header links` (#542) * [SD-416] Fixes placeholder issue for `Header links` * Fix a coding standard issue. --- ...d.paragraph.key_journeys.field_paragraph_title.yml | 4 +--- modules/tide_landing_page/tide_landing_page.install | 11 ++++++++++- modules/tide_landing_page/tide_landing_page.module | 6 ++---- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/modules/tide_landing_page/config/install/field.field.paragraph.key_journeys.field_paragraph_title.yml b/modules/tide_landing_page/config/install/field.field.paragraph.key_journeys.field_paragraph_title.yml index 4ed3c4bc8..4b8e778a0 100644 --- a/modules/tide_landing_page/config/install/field.field.paragraph.key_journeys.field_paragraph_title.yml +++ b/modules/tide_landing_page/config/install/field.field.paragraph.key_journeys.field_paragraph_title.yml @@ -12,9 +12,7 @@ label: Title description: '' required: true translatable: true -default_value: - - - value: 'Want to know more about...' +default_value: { } default_value_callback: '' settings: { } field_type: string diff --git a/modules/tide_landing_page/tide_landing_page.install b/modules/tide_landing_page/tide_landing_page.install index 243e63264..de73d8b3d 100644 --- a/modules/tide_landing_page/tide_landing_page.install +++ b/modules/tide_landing_page/tide_landing_page.install @@ -185,7 +185,7 @@ function tide_landing_page_update_10106() { $form_configs = [ 'field.field.node.landing_page.field_landing_page_component', ]; - /** @var \Drupal\tide_core\TideEntityUpdateHelper $s */ + /** @var \Drupal\tide_core\TideEntityUpdateHelper $tide_update_helper */ $tide_update_helper = \Drupal::service('tide_core.entity_update_helper'); $tide_update_helper->configMergeDeep('tide_landing_page', TideEntityUpdateHelper::INSTALL_DIR, $form_configs); $result = $tide_update_helper->updateFromOptional('base_field_override', 'paragraphs_library_item.paragraphs_library_item.paragraphs'); @@ -194,3 +194,12 @@ function tide_landing_page_update_10106() { } } + +/** + * Update key_journeys.field_paragraph_title configs. + */ +function tide_landing_page_update_10107() { + /** @var \Drupal\tide_core\TideEntityUpdateHelper $tide_update_helper */ + $tide_update_helper = \Drupal::service('tide_core.entity_update_helper'); + $tide_update_helper->revert('field_config', 'paragraph.key_journeys.field_paragraph_title'); +} diff --git a/modules/tide_landing_page/tide_landing_page.module b/modules/tide_landing_page/tide_landing_page.module index 1cd98a751..fe1d0196b 100644 --- a/modules/tide_landing_page/tide_landing_page.module +++ b/modules/tide_landing_page/tide_landing_page.module @@ -82,10 +82,8 @@ function tide_landing_page_form_node_form_alter(&$form, FormStateInterface $form if (isset($form['title']['widget'][0]['value']['#description'])) { $form['title']['widget'][0]['value']['#description'] = t('Include a short unique title for your page and keywords.'); } - if (isset($form["field_landing_page_key_journeys"]["widget"][0]["subform"]["field_paragraph_title"]["widget"][0]["value"]["#default_value"])) { - $placeholder_value = $form["field_landing_page_key_journeys"]["widget"][0]["subform"]["field_paragraph_title"]["widget"][0]["value"]["#default_value"]; - $form["field_landing_page_key_journeys"]["widget"][0]["subform"]["field_paragraph_title"]["widget"][0]["value"]["#placeholder"] = $placeholder_value; - unset($form["field_landing_page_key_journeys"]["widget"][0]["subform"]["field_paragraph_title"]["widget"][0]["value"]["#default_value"]); + if (isset($form['field_landing_page_key_journeys']['widget'][0]['subform']['field_paragraph_title']['widget'][0])) { + $form['field_landing_page_key_journeys']['widget'][0]['subform']['field_paragraph_title']['widget'][0]['value']['#placeholder'] = t("Want to know more about..."); } // Change form layout. $form['#attached']['library'][] = 'tide_landing_page/landing_page_form'; From 8543a311decf8a352523965fe1b2bc3ac4099423 Mon Sep 17 00:00:00 2001 From: vincent-gao Date: Mon, 25 Nov 2024 13:35:56 +1100 Subject: [PATCH 3/4] [SD-482] Bug in Tide captcha blocking drush cim (#537) --- modules/tide_webform/tide_webform.install | 49 +++++++++++++++++++++++ modules/tide_webform/tide_webform.module | 38 +++++++++--------- 2 files changed, 68 insertions(+), 19 deletions(-) diff --git a/modules/tide_webform/tide_webform.install b/modules/tide_webform/tide_webform.install index 0370804dd..dff545b96 100644 --- a/modules/tide_webform/tide_webform.install +++ b/modules/tide_webform/tide_webform.install @@ -52,3 +52,52 @@ function tide_webform_update_10002() { } } } + +/** + * Update tide webform dependencies. + */ +function update_tide_webform_dependencies(array $dependencies, array $remove_modules = [], array $add_modules = []) { + if (isset($dependencies['module'])) { + $dependencies['module'] = array_values( + array_diff($dependencies['module'], $remove_modules) + ); + $dependencies['module'] = array_unique( + array_merge($dependencies['module'], $add_modules) + ); + sort($dependencies['module']); + } + return $dependencies; +} + +/** + * Update tide webform captcha settings. + */ +function update_tide_webform_captcha_settings(array $config) { + if (isset($config['tide_webform_captcha'])) { + $settings = $config['tide_webform_captcha']; + unset($config['tide_webform_captcha']); + $config['tide_webform'] = $settings; + } + return $config; +} + +/** + * Update webform dependencies and third party settings. + */ +function tide_webform_update_10003() { + $webform_storage = \Drupal::entityTypeManager()->getStorage('webform'); + $webforms = $webform_storage->loadMultiple(); + foreach ($webforms as $webform_id => $webform_entity) { + $config = \Drupal::configFactory()->getEditable('webform.webform.' . $webform_id); + $dependencies = $config->get('dependencies'); + $third_party_settings = $config->get('third_party_settings'); + if (!empty($dependencies)) { + $result = update_tide_webform_dependencies($dependencies, ['tide_webform_captcha'], ['tide_webform']); + $config->set('dependencies', $result)->save(); + } + if (!empty($third_party_settings)) { + $result = update_tide_webform_captcha_settings($third_party_settings); + $config->set('third_party_settings', $result)->save(); + } + } +} diff --git a/modules/tide_webform/tide_webform.module b/modules/tide_webform/tide_webform.module index 976647998..2ac1f487c 100644 --- a/modules/tide_webform/tide_webform.module +++ b/modules/tide_webform/tide_webform.module @@ -445,7 +445,7 @@ function tide_webform_webform_update(EntityInterface $entity) { */ function tide_webform_webform_third_party_settings_form_alter(array &$form, FormStateInterface $form_state) { $webform = $form_state->getFormObject()->getEntity(); - $third_party_settings = $webform->getThirdPartySettings('tide_webform_captcha'); + $third_party_settings = $webform->getThirdPartySettings('tide_webform'); $user_input = $form_state->getUserInput(); $taxonomy_storage = \Drupal::entityTypeManager()->getStorage('taxonomy_term'); $captcha_type = NULL; @@ -469,8 +469,8 @@ function tide_webform_webform_third_party_settings_form_alter(array &$form, Form if (isset($third_party_settings['captcha_type'])) { $captcha_type = $third_party_settings['captcha_type']; } - if (isset($user_input['third_party_settings']['tide_webform_captcha']['captcha_type'])) { - $captcha_type = $user_input['third_party_settings']['tide_webform_captcha']['captcha_type']; + if (isset($user_input['third_party_settings']['tide_webform']['captcha_type'])) { + $captcha_type = $user_input['third_party_settings']['tide_webform']['captcha_type']; } $query = $taxonomy_storage->getQuery() ->accessCheck(TRUE) @@ -482,19 +482,19 @@ function tide_webform_webform_third_party_settings_form_alter(array &$form, Form return $term->label() . ' (' . $term->id() . ')'; }, $terms); - $form['third_party_settings']['tide_webform_captcha'] = [ + $form['third_party_settings']['tide_webform'] = [ '#type' => 'fieldset', '#title' => t('Tide webform CAPTCHA'), '#open' => TRUE, ]; - $form['third_party_settings']['tide_webform_captcha']['enable_captcha'] = [ + $form['third_party_settings']['tide_webform']['enable_captcha'] = [ '#type' => 'checkbox', '#default_value' => !empty($third_party_settings['enable_captcha']) ? $third_party_settings['enable_captcha'] : NULL, '#title' => t('Enable captcha'), ]; - $form['third_party_settings']['tide_webform_captcha']['captcha_type'] = [ + $form['third_party_settings']['tide_webform']['captcha_type'] = [ '#type' => 'select', '#title' => t('Captcha type'), '#options' => [ @@ -502,7 +502,7 @@ function tide_webform_webform_third_party_settings_form_alter(array &$form, Form ] + $allowed_values, '#default_value' => !empty($third_party_settings['captcha_type']) ? $third_party_settings['captcha_type'] : NULL, '#ajax' => [ - 'callback' => '_tide_webform_captcha_type_dropdown_callback', + 'callback' => '_tide_webform_type_dropdown_callback', 'wrapper' => 'captcha-type-dropdown-container', ], ]; @@ -514,7 +514,7 @@ function tide_webform_webform_third_party_settings_form_alter(array &$form, Form $score_threshold = (string) $third_party_settings['score_threshold']; } - $form['third_party_settings']['tide_webform_captcha']['score_threshold'] = [ + $form['third_party_settings']['tide_webform']['score_threshold'] = [ '#type' => 'textfield', '#title' => t('Score threshold (reCAPTCHA v3)'), '#size' => 2, @@ -523,19 +523,19 @@ function tide_webform_webform_third_party_settings_form_alter(array &$form, Form '#element_validate' => ['_tide_webform_threshold_validate'], '#states' => [ 'visible' => [ - ':input[name="third_party_settings[tide_webform_captcha][captcha_type]"]' => ['value' => 'google_recaptcha_v3'], + ':input[name="third_party_settings[tide_webform][captcha_type]"]' => ['value' => 'google_recaptcha_v3'], ], ], '#default_value' => $score_threshold, '#description' => 'Enter a value between 0.0 and 1.0. Use only one decimal place (e.g., 0.0, 0.5, 1.0).', ]; - $form['third_party_settings']['tide_webform_captcha']['captcha_type_dropdown_container'] = [ + $form['third_party_settings']['tide_webform']['captcha_type_dropdown_container'] = [ '#type' => 'fieldset', '#attributes' => ['id' => 'captcha-type-dropdown-container'], ]; - $form['third_party_settings']['tide_webform_captcha']['captcha_type_dropdown_container']['captcha_details'] = [ + $form['third_party_settings']['tide_webform']['captcha_type_dropdown_container']['captcha_details'] = [ '#type' => \Drupal::moduleHandler()->moduleExists('select2') ? 'select2' : 'select', '#title' => ('Site key'), '#target_type' => 'taxonomy_term', @@ -553,14 +553,14 @@ function tide_webform_webform_third_party_settings_form_alter(array &$form, Form ], ]; - $form['#validate'][] = '_tide_webform_captcha_form_validate'; + $form['#validate'][] = '_tide_webform_form_validate'; } /** * Captcha form validate. */ -function _tide_webform_captcha_form_validate(&$form, FormStateInterface $form_state) { - $settings = &$form_state->getValue(['third_party_settings', 'tide_webform_captcha']); +function _tide_webform_form_validate(&$form, FormStateInterface $form_state) { + $settings = &$form_state->getValue(['third_party_settings', 'tide_webform']); $captcha_details = $settings['captcha_type_dropdown_container']['captcha_details'] ?? NULL; if (is_array($captcha_details) && isset($captcha_details[0]['target_id'])) { @@ -591,19 +591,19 @@ function _tide_webform_captcha_form_validate(&$form, FormStateInterface $form_st /** * Captcha options callback. */ -function _tide_webform_captcha_type_dropdown_callback($form, FormStateInterface $form_state) { - return $form['third_party_settings']['tide_webform_captcha']['captcha_type_dropdown_container']; +function _tide_webform_type_dropdown_callback($form, FormStateInterface $form_state) { + return $form['third_party_settings']['tide_webform']['captcha_type_dropdown_container']; } /** * Threshold element validation. */ function _tide_webform_threshold_validate($element, FormStateInterface $form_state) { - $number = $form_state->getUserInput()['third_party_settings']['tide_webform_captcha']['score_threshold']; + $number = $form_state->getUserInput()['third_party_settings']['tide_webform']['score_threshold']; if ($number === 0 || $number === '' || $number === NULL) { $form_state->setValue([ 'third_party_settings', - 'tide_webform_captcha', + 'tide_webform', 'score_threshold', ], NULL); return; @@ -611,7 +611,7 @@ function _tide_webform_threshold_validate($element, FormStateInterface $form_sta if (preg_match('/^(0(\.[0-9])?|1(\.0)?)$/', (string) $number)) { $form_state->setValue([ 'third_party_settings', - 'tide_webform_captcha', + 'tide_webform', 'score_threshold', ], (float) $number); } From d0a79d43c89fe8b7182e21e0b3457c37f5d280d6 Mon Sep 17 00:00:00 2001 From: Sahil Sharma Date: Mon, 25 Nov 2024 14:02:20 +1100 Subject: [PATCH 4/4] Ckedito5 patch for table cell resize (#533) * Ckedito5 patch for table cell resize * modules/tide_landing_page/src/Plugin/jsonapi/FieldEnhancer/BasicTextEnhancer.php * Chnages for col style * Ckeditor table resize fix for retaining styles * Changes to revert config * Update hook changes * Removed cosnole log * Updated col style in install and also loop through all tabled in DOM * Removed table inline styles --------- Co-authored-by: Sahil Sharma Co-authored-by: Sahil Sharma Co-authored-by: sharmasahil --- composer.json | 3 +- config/install/filter.format.rich_text.yml | 2 +- .../ckeditor_tablecol_resize/.gitignore | 2 + .../ckeditor_tablecol_resize.ckeditor5.yml | 20 + .../ckeditor_tablecol_resize.info.yml | 7 + .../ckeditor_tablecol_resize.libraries.yml | 5 + .../ckeditor_tablecol_resize/composer.json | 15 + .../js/build/tableColResize.js | 1 + .../tableColResize/src/index.js | 22 + .../src/tablecolresizeediting.js | 104 + .../ckeditor_tablecol_resize/package.json | 21 + .../Filter/FilterResizeTableColumns.php | 121 + .../webpack.config.js | 73 + .../ckeditor_tablecol_resize/yarn.lock | 2643 +++++++++++++++++ modules/tide_ckeditor/tide_ckeditor.install | 31 + .../FieldEnhancer/BasicTextEnhancer.php | 67 + patches/ckeditor_templates/.DS_Store | Bin 0 -> 6148 bytes 17 files changed, 3135 insertions(+), 2 deletions(-) create mode 100644 modules/tide_ckeditor/modules/ckeditor_tablecol_resize/.gitignore create mode 100644 modules/tide_ckeditor/modules/ckeditor_tablecol_resize/ckeditor_tablecol_resize.ckeditor5.yml create mode 100644 modules/tide_ckeditor/modules/ckeditor_tablecol_resize/ckeditor_tablecol_resize.info.yml create mode 100644 modules/tide_ckeditor/modules/ckeditor_tablecol_resize/ckeditor_tablecol_resize.libraries.yml create mode 100644 modules/tide_ckeditor/modules/ckeditor_tablecol_resize/composer.json create mode 100644 modules/tide_ckeditor/modules/ckeditor_tablecol_resize/js/build/tableColResize.js create mode 100644 modules/tide_ckeditor/modules/ckeditor_tablecol_resize/js/ckeditor5_plugins/tableColResize/src/index.js create mode 100644 modules/tide_ckeditor/modules/ckeditor_tablecol_resize/js/ckeditor5_plugins/tableColResize/src/tablecolresizeediting.js create mode 100644 modules/tide_ckeditor/modules/ckeditor_tablecol_resize/package.json create mode 100644 modules/tide_ckeditor/modules/ckeditor_tablecol_resize/src/Plugin/Filter/FilterResizeTableColumns.php create mode 100644 modules/tide_ckeditor/modules/ckeditor_tablecol_resize/webpack.config.js create mode 100644 modules/tide_ckeditor/modules/ckeditor_tablecol_resize/yarn.lock create mode 100644 patches/ckeditor_templates/.DS_Store diff --git a/composer.json b/composer.json index 5976ffb16..6c82c5535 100644 --- a/composer.json +++ b/composer.json @@ -464,7 +464,8 @@ }, "config": { "allow-plugins": { - "composer/installers": true + "composer/installers": true, + "oomphinc/composer-installers-extender": true } } } diff --git a/config/install/filter.format.rich_text.yml b/config/install/filter.format.rich_text.yml index cd834cdfb..479f5a7b9 100644 --- a/config/install/filter.format.rich_text.yml +++ b/config/install/filter.format.rich_text.yml @@ -47,7 +47,7 @@ filters: status: true weight: -49 settings: - allowed_html: '