Verified Commit b3ddfca1 authored by Dave Long's avatar Dave Long
Browse files

fix: #3575821 locale.check_translation route is not protected against CSRF

By: prudloff
By: smustgrave
(cherry picked from commit 474d7c36)
parent 1db960a1
Loading
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ locale.check_translation:
    _controller: '\Drupal\locale\Controller\LocaleController::checkTranslation'
  requirements:
    _permission: 'translate interface'
    _csrf_token: 'TRUE'

locale.translate_page:
  path: '/admin/config/regional/translate'
+5 −2
Original line number Diff line number Diff line
@@ -63,7 +63,8 @@ public function testConfigTranslationImport(): void {

    // Check and update the translation status. This will import the Afrikaans
    // translations of locale_test_translate module.
    $this->drupalGet('admin/reports/translations/check');
    $this->drupalGet('admin/reports/translations');
    $this->clickLink('Check manually');

    $this->drupalGet('admin/reports/translations');
    $this->submitForm([], 'Update translations');
@@ -92,7 +93,9 @@ public function testConfigTranslationImport(): void {

    $this->configImporter()->import();

    $this->drupalGet('admin/reports/translations/check');
    $this->drupalGet('admin/reports/translations');
    $this->clickLink('Check manually');
    $this->checkForMetaRefresh();
    $this->drupalGet('admin/reports/translations');
    $this->submitForm([], 'Update translations');

+15 −6
Original line number Diff line number Diff line
@@ -50,17 +50,26 @@ protected function setUp(): void {
    $this->submitForm($edit, 'Save configuration');

    // Check for available translations and update them via the UI.
    $this->drupalGet('admin/reports/translations/check');
    $this->checkTranslations();
    $this->assertSession()->addressEquals('admin/reports/translations');
    $this->submitForm([], 'Update translations');
  }

  /**
   * Check for translation updates via the UI.
   */
  protected function checkTranslations(): void {
    $this->drupalGet('admin/reports/translations');
    $this->clickLink('Check manually');
    $this->checkForMetaRefresh();
  }

  /**
   * Tests that modifying a file produces a different hash, detected by the UI.
   */
  public function testModifiedFileProducesDifferentHash(): void {
    // Check for translation updates via the UI.
    $this->drupalGet('admin/reports/translations/check');
    $this->checkTranslations();
    // The translation status page should show no updates are available.
    $this->assertSession()->addressEquals('admin/reports/translations');
    $this->assertSession()->pageTextNotContains('Updates for:');
@@ -76,7 +85,7 @@ public function testModifiedFileProducesDifferentHash(): void {
    touch($uri, time() + 20000);

    // Run check again via the UI.
    $this->drupalGet('admin/reports/translations/check');
    $this->checkTranslations();
    // The translation status page should show no updates are available.
    $this->assertSession()->addressEquals('admin/reports/translations');
    $this->assertSession()->pageTextNotContains('Updates for:');
@@ -89,7 +98,7 @@ public function testModifiedFileProducesDifferentHash(): void {
    touch($uri, filemtime($uri));

    // Run check again via the UI.
    $this->drupalGet('admin/reports/translations/check');
    $this->checkTranslations();
    // The translation status page should show an update is available.
    $this->assertSession()->addressEquals('admin/reports/translations');
    $this->assertSession()->pageTextContains('Updates for: Contributed module two');
@@ -105,7 +114,7 @@ public function testModifiedFileProducesDifferentHash(): void {
    $this->assertHashes($expected_hash, $expected_hash, 'contrib_module_two', 'de');

    // Check for translation updates via the UI.
    $this->drupalGet('admin/reports/translations/check');
    $this->checkTranslations();
    // The translation status page should show no updates are available.
    $this->assertSession()->addressEquals('admin/reports/translations');
    $this->assertSession()->pageTextNotContains('Updates for:');
@@ -120,7 +129,7 @@ public function testModifiedFileProducesDifferentHash(): void {
    \Drupal::keyValue('locale.translation_status')->set('contrib_module_two', $status['contrib_module_two']);

    // Test fallback to mtime if the hash is not available.
    $this->drupalGet('admin/reports/translations/check');
    $this->checkTranslations();
    // The translation status page should show no updates are available.
    $this->assertSession()->addressEquals('admin/reports/translations');
    $this->assertSession()->pageTextContains('Updates for: Contributed module two');
+3 −1
Original line number Diff line number Diff line
@@ -53,7 +53,9 @@ public function testUpdateCron(): void {
    $this->config('locale.settings')->set('translation.default_filename', '%project-%version.%language._po')->save();

    // Update translations using batch to ensure a clean test starting point.
    $this->drupalGet('admin/reports/translations/check');
    $this->drupalGet('admin/reports/translations');
    $this->clickLink('Check manually');
    $this->checkForMetaRefresh();
    $this->drupalGet('admin/reports/translations');
    $this->submitForm([], 'Update translations');

+22 −6
Original line number Diff line number Diff line
@@ -86,7 +86,9 @@ public function testUpdateCheckStatus(): void {
    $this->submitForm($edit, 'Save configuration');

    // Get status of translation sources at local file system.
    $this->drupalGet('admin/reports/translations/check');
    $this->drupalGet('admin/reports/translations');
    $this->clickLink('Check manually');
    $this->checkForMetaRefresh();
    $result = \Drupal::service(LocaleSource::class)->loadSources();
    $this->assertEquals(LOCALE_TRANSLATION_LOCAL, $result['contrib_module_one']['de']->type, 'Translation of contrib_module_one found');
    $this->assertEquals($this->timestampOld, $result['contrib_module_one']['de']->timestamp, 'Translation timestamp found');
@@ -103,7 +105,9 @@ public function testUpdateCheckStatus(): void {
    $this->submitForm($edit, 'Save configuration');

    // Get status of translation sources at both local and remote locations.
    $this->drupalGet('admin/reports/translations/check');
    $this->drupalGet('admin/reports/translations');
    $this->clickLink('Check manually');
    $this->checkForMetaRefresh();
    $result = \Drupal::service(LocaleSource::class)->loadSources();
    $this->assertEquals(LOCALE_TRANSLATION_REMOTE, $result['contrib_module_one']['de']->type, 'Translation of contrib_module_one found');
    $this->assertEquals($this->timestampNew, $result['contrib_module_one']['de']->timestamp, 'Translation timestamp found');
@@ -113,6 +117,10 @@ public function testUpdateCheckStatus(): void {
    $this->assertEquals($this->timestampOld, $result['contrib_module_three']['de']->timestamp, 'Translation timestamp found');
    $this->assertEquals(LOCALE_TRANSLATION_LOCAL, $result['locale_test']['de']->type, 'Translation of locale_test found');
    $this->assertEquals(LOCALE_TRANSLATION_LOCAL, $result['custom_module_one']['de']->type, 'Translation of custom_module_one found');

    // Tests that the check route is protected against CSRF.
    $this->drupalGet('admin/reports/translations/check');
    $this->assertSession()->statusCodeEquals(403);
  }

  /**
@@ -139,7 +147,9 @@ public function testUpdateImportSourceRemote(): void {
    $this->submitForm($edit, 'Save configuration');

    // Get the translation status.
    $this->drupalGet('admin/reports/translations/check');
    $this->drupalGet('admin/reports/translations');
    $this->clickLink('Check manually');
    $this->checkForMetaRefresh();

    // Check the status on the Available translation status page.
    $this->assertSession()->responseContains('<label for="edit-langcodes-de" class="visually-hidden">Update German</label>');
@@ -209,7 +219,9 @@ public function testUpdateImportSourceLocal(): void {
    $this->submitForm($edit, 'Save configuration');

    // Execute the translation update.
    $this->drupalGet('admin/reports/translations/check');
    $this->drupalGet('admin/reports/translations');
    $this->clickLink('Check manually');
    $this->checkForMetaRefresh();
    $this->drupalGet('admin/reports/translations');
    $this->submitForm([], 'Update translations');

@@ -268,7 +280,9 @@ public function testUpdateImportModeNonCustomized(): void {
    $this->submitForm($edit, 'Save configuration');

    // Execute translation update.
    $this->drupalGet('admin/reports/translations/check');
    $this->drupalGet('admin/reports/translations');
    $this->clickLink('Check manually');
    $this->checkForMetaRefresh();
    $this->drupalGet('admin/reports/translations');
    $this->submitForm([], 'Update translations');

@@ -308,7 +322,9 @@ public function testUpdateImportModeNone(): void {
    $this->submitForm($edit, 'Save configuration');

    // Execute translation update.
    $this->drupalGet('admin/reports/translations/check');
    $this->drupalGet('admin/reports/translations');
    $this->clickLink('Check manually');
    $this->checkForMetaRefresh();
    $this->drupalGet('admin/reports/translations');
    $this->submitForm([], 'Update translations');