Quantcast
Channel: Issues for Drupal core
Viewing all 296540 articles
Browse latest View live

Deprecate Migration::set()

$
0
0

Problem/Motivation

Migration::set() was provided as a work-around for the inability to properly modify migration plugin configuration at run time (#2681869: Provide clean way to merge configuration into migration plugins) - once that is committed, set() should be deprecated. The only core usages remaining after that commit are in tests, which should be changed to use the plugin manager to merge configuration.

Note that set() is documented with {@inheritdoc}, yet is not in MigrationInterface and thus is not properly documented. This fix should properly document it in the Migration class.

Proposed resolution

Add individual setters to MigrationInterface and implement them in Migration. Setters added are

  • setDependencies(array $value)
  • setRequirements(array $value)

In MigrateTestBase, add an optional $configuration parameter to getMigration() and executeMigration(), where $configuration is an array of values to merge into the migration definition.

In MigrateTestBase and the traits for file migrations, remove prepareMigration(). Instead, the traits add fileConfiguration(). Tests that run file migrations pass that to executeMigration().

Change the use of Migration::set() in

  • MigrationPluginManager
  • d6/MigrateUploadTest
  • d6/FileMigrationTestTrait
  • d7/FileMigrationSetupTrait
  • ReferenceBase.php

Move test in MigrationTest to MigrationPluginConfigurationTest.php
Add doc bloc for Migration::set() and deprecate it.

Theses changes may require changes to migration tests in contrib.

Remaining tasks

If #2953111: Only migrate role permissions that exist on the destination is fixed before this issue, then update the test. See Comment #43.14 there.

Add follow-up issues for the following contrib modules (see #85 here):

  • media_migration
  • location_migration
  • migrate_tools
  • migrate_upgrade

User interface changes

API changes


Documentation about aggregator feed block incorrect

$
0
0

Problem/Motivation

The last sentence in the text information at the top of the admin/config/services/aggregator page still reads "For each feed, the latest items block may be enabled at the blocks administration page." This was correct for D7, but for D8, you place a 'Aggregator Feed' block and select which feed it is to show. I found this confusing, and I almost filed an issue saying that the latest items blocks weren't being created. This should be corrected.

Steps to reproduce

Enable aggregator.
Go to admin/config/services/aggregator.
Read the help text.

Proposed resolution

Change
For each feed, the latest items block may be enabled at the blocks administration page.
to
For each feed, the Aggregator feed block may be enabled at the block layout page.

Remaining tasks

User interface changes

Before

After

API changes

Data model changes

Release notes snippet

Authentication Provider Challenge cannot have multiple challenges

$
0
0

Problem
Drupal\Core\Authentication\AuthenticationManager::challengeException only allows one authentication provider to send the challenge. For example, Basic Auth uses it to set WWW-Authenticate and the exception to UnauthorizedHttpException. This limits it to one authentication provider, if another one wishes to send it's challenge alongside BasicAuth, it cannot do so.

Proposed Resolution
Allow authentication provider to return string so that the manager and collect challenges from all providers and create the UnauthorizedHttpException itself having WWW-Authenticate. If a provider returns an exception, pass that exception as it is back.

Remaining Tasks
* Tests
* Figure out a better solution, if any?

API Changes
* Drupal\Core\Authentication\AuthenticationProviderChallenegeInterface::challengeException() renamed to challenge() since it is no longer exclusive for exceptions

Migrate source ids allow constants

$
0
0

Problem/Motivation

I have the migration, where one constant value is overridden by the code before running the migration.
This constant needs to be a part of source ids, in the current implementation it's allowed to be set as a migration source ids, but the value couldn't be extracted from the row.

Steps to reproduce

Proposed resolution

Remaining tasks

Need more information about the use case.

User interface changes

API changes

Data model changes

Release notes snippet

base authentication class to make multiple and external authn methods easier to implement

$
0
0

I think having a drupal authentication base class (for "drupal" authentication") that could be extended by external authentication modules would save a lot of code and make implementing ldap, cas, etc. easier. If done right the user interface for admins could be more consistent and the login sequence more predictable.

Hooks could be used throughout the authentication process so non authentication modules could react to the process; but authentication modules would be expected to implement certain properties and methods. Simpletests would become easier to share for external auth modules also.

It might end up we need two base classes; one for drupal form based authentication and one for tools such as openid, cert based, and cas where you enter your credentials elsewhere.

something like:

Authentication Class Properties:

An instance of this class represents an authentication means such as an ldap server, cas, or drupal.

  • boolean enabled
  • string moduleName
  • string instanceID (instance identifier. for ldap it might be server id. needed for cases where a single module provides more than one authentication means)
  • boolean provisionDrupalAccounts signifies if successful authentication can lead to drupal user account creation.
  • boolean allowPasswordResetinDrupal signifies if password stored in external structure (ldap, shib, etc.) can be reset via drupal reset pwd interface.
  • string passwordResetURL
  • string accountHelpURL

Authentication Class Methods:

  • __construct($username)
  • authenticationDerivedUserAttributes($username, $uid = NULL); returns array of attributes such as mail, first name, last name, etc. that could be mapped to drupal profile, account, etc.
  • drupalAccountExists()
  • userCredentialTest($pwd)

Then instead of every external author module figuring out how to fit itself into the the authentication process, user_login_authenticate_validate() could look something like:

function user_login_authenticate_validate($form, &$form_state) {
  $name = $form_state['values']['name'];
  $password = trim($form_state['values']['pass']);
  $drupal_accnt = drupal_account_from_name($name);
  check flood issues given name

  $authn_providers = module_invoke_all('authentication_providers');
  $results = array();
  if ($drupal_acct->uid == 1) {
    // for user 1, only allow authentication on user module.
    $authn_providers = array('user__drupal' => $authn_providers['user__drupal']);
  }
  foreach ($authn_providers  as $instance_id => $instance_data {
    require_once($instance_data['class_path']);
    $authn = new {$instance_data['classname']}($instance_data, $name);
    $results[$instance_id]['authn_object'] = $authn;
    $result = $authn->userCredentialTest($password);
    if (!$result) {
      $results[$instance_id]['result'] = USER_AUTHN_CREDENTIAL_FAILED;
      continue;
    }

    if (!$drupal_accnt) {
      if (!$authn->provisionDrupalAccounts) {
        $results[$instance_id]]['result'] = USER_AUTHN_ACCT_MISSING;
        continue;
      }
      list($result, $user_data) = $authn->provisionAccount($name);
      if (!$result) {
        $results[$instance_id]['result'] = USER_AUTHN_FAILED_TO_CREATE_ACCT;
        continue;
      }
      else {
        user_external_login_register($name, $user_data, $authn);
      }
    }
    
    $results[$instance_id]['result'] = USER_AUTHN_SUCCESS;
    $user->authnObject = $authn;
    exit;
  }
if ($results[$instance_id]['result'] == USER_AUTHN_SUCCESS)) {
    user_login_finalize();
    user_module_invoke('login', $user_data, $user);
  }
  else {  // no authentications succeeded.  
    if (count($authn_providers) == 1) { // if only one authentication provider, allow it to generate error msg
       list($field, $message) = $authn->loginFormSetError();
       form_set_error($field, $message);
    }
    else {
      form_set_error('name', t('Sorry, unrecognized username or password. <a href="@password">Have you forgotten your password?</a>', array('@password' => url('user/password'))));
      watchdog('user', 'Login attempt failed for %user.', array('%user' => $form_state['values']['name']));
    }
  }
}

Fix leaky and brittle container serialization solution

$
0
0

Problem/Motivation

Our current container serialization solution adds the _serviceId property to every container service. This creates a number of problems.
1) It creates a dynamic property bypassing the zend engine's optimizations for predefined properties.
2) It leaks our container implementation on to every single service.
3) Being present on every service it can break their serialization requiring existing complexity on services unrelated to their actual purpose to work around Drupal.

Proposed resolution

Remove use of _serviceId and provide an API for mapping container services to persistent objects. Being as container persistence is managed through the Kernel that is the logical place for the implementation.

Remaining tasks

Figure out out if hashing the service identifier makes sense.

User interface changes

n/a

API changes

This creates an actual public API for accessing the same functionality. It removes internal properties that could be considered an "internal api" though they are not documented anywhere and are artifacts of the implementation only.

Data model changes

n/a

Original post

PHP 5.4 has an optimization where class properties are accessed as a fixed array if they are predefined instead of a Zend hashtable like an array (which it was previously). By adding _serviceId to every service we meticulously destroy this for our services.

Proposed resolution
I would recommend adding a method to Container returning the spl_object_hash of the existing services and then compare that in DependencySerializationTrait.

Since Container and ContainerBuilder both need this method, a trait is used containing the getHashes method. There's also a setHashes method because installing a module breaks the module form and the hashes need to be passed from the before-submit-handlers-rebuilding-the-container Container to the after-submit-handlers-rebuilt-the-container ContainerBuilder. The current user id is passed along similarly in the kernel.

Because of this hash passing the approach is not 100% bulletproof: the hash depends on name of the class and the number of instances alive for a class. So theoretically it is possible that a Foo instance lived in the Container, then the container was rebuilt and now both Container and this Foo instance are gone and the class using a DependencySerializationTrait creates a new Foo object which is not a service. I am not worried because in general I think that if a Foo is used as a service it's always used as a service and because this edge case only applies within the same request when the container is rebuilt.

Allow to change password through RPC endpoints through the reset password workflow

$
0
0

This is a follow up to #2847708: RPC endpoint to reset user password and just adding it for discussion.

I was hoping to submit a patch for this but I found that this will require a bit of rework as how _skipProtectedUserFieldConstraint is worked in the workflow will likely either need duplication or some proper planning on how to rework.

I wonder if the validation of a password reset token should be added to the actual ProtectedUserFieldConstraint instead of outside.

In the meantime, I worked on an alternative to this on https://www.drupal.org/sandbox/hanoii/2904436

It should work for both 8.3.x and 8.4.x.

Authentication manager provide incorrect provider id

$
0
0

When i am trying to use two different contributed module at the same time name "simple_auth" and "JWT", then authentication manager provide incorrect provider id. Authentication Manager provide provider_id based on priority not on request.


authentication providers can fail access on routes with _access: 'TRUE'

$
0
0

Problem/Motivation

A route with _access: 'TRUE' should always allow access.

However, it's possible for authentication to fail.

Steps to reproduce

1. Enable basic_auth module
2. Set up an image derivative
3. Go to the URI for the derived image, with an Authorization HTTP header which looks like "Basic something-that-will-fail"
4. Get a 403

This is because the Authorization causes the BasicAuth authentication provider to report that it applies to the request. It will then fail authentication.

Furthermore, the log message is unclear: it says 'The used authentication method is not allowed on this route' which isn't actually the problem.

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Exception trace cannot be serialized because of closure

$
0
0

Problem/Motivation

Probably something has changed recently either in PHPUnit or somewhere else and we started seeing different issues related to serialization in tests. This particular issue was reported by @quietone in #3192893: [META] Serialization issues in Migration tests, which is now a meta task.

The issue is the following:

If the test is failing with exception, then PHP is trying to serialize a stack trace, which contains functions, methods, classes that have been executed. One of these functions is recognized as Closure (in other words it's anonymous function) in the stack trace (see the screenshot).

exception trace

This happens because we have array_walk() inside array_walk(), so the deepest one is executed inside the closure.

Steps to reproduce

Change a query in any source plugin and run the relevant migration test.
For example,
In d6\Term.php change ->orderBy('td.tid'); to ->orderBy('td.foo');

Then run the d6 term test.

phpunit -c core --debug -v --colors=always core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTest.php

You'll see something like:

Drupal\Tests\taxonomy\Kernel\Migrate\d7\MigrateTaxonomyTermTest::testTaxonomyTerms
PHPUnit\Framework\Exception: PHP Fatal error:  Uncaught Exception: Serialization of 'Closure' is not allowed in Standard input code:80
Stack trace:
#0 Standard input code(80): serialize(Array)
#1 Standard input code(112): __phpunit_run_isolated_test()
#2 {main}
  thrown in Standard input code on line 80
Fatal error: Uncaught Exception: Serialization of 'Closure' is not allowed in Standard input code:80
Stack trace:
#0 Standard input code(80): serialize(Array)
#1 Standard input code(112): __phpunit_run_isolated_test()
#2 {main}
  thrown in Standard input code on line 80
  
/var/www/html/vendor/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php:254
/var/www/html/vendor/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php:171
/var/www/html/vendor/phpunit/phpunit/src/Framework/TestSuite.php:601
/var/www/html/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:633
/var/www/html/vendor/phpunit/phpunit/src/TextUI/Command.php:204
/var/www/html/vendor/phpunit/phpunit/src/TextUI/Command.php:163

Proposed resolution

It can be fixed by replacing array_walk with foreach loop.
There is no way to add a test here because the serialization happens when the test is already executed.

Remaining tasks

Review, commit.
Think about how we can prevent this in the future.

CSRF check always fails for users without a session

$
0
0

Problem/Motivation

Any route using the _csrf_token requirement doesn't work for users without session because the CSRF checker fails as the CSRF seed is not stored anywhere.

Proposed resolution

Only add a CSRF token if a session is started.

Remaining tasks

User interface changes

Flag supports anonymous users (and there was much rejoicing).

API changes

CsrfAccessCheck constructor requires a new argument but it's a service so noone should be constructing it anyways.

Data model changes

None.

Store the successful authentication plugin's ID on the request

$
0
0

Problem/Motivation

Issues such as #3055260: Disable CSRF token check for non-CSRF vulnerable authentication providers require the AuthenticationManager provide some way for other services to determine which authentication plugin "won" in authenticating the current request. Various other parts of the routing and even image derivative generation systems use the request's attributesParameterBag for storing computed data about the request. Let's do the same here.

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

[PP-1] Disable CSRF token check for non-CSRF vulnerable authentication providers

$
0
0

We have an App using simple_oath with Bearer tokens to authentication method. After updating core from 8.6.15 to 8.71 we started getting "X-CSRF-Token request header is missing" when doing something other than GET requests to REST or JSONAPI endpoints.

So why Drupal started to require X-CSRF-Token if the authentication is done by Bearer token which is not a browser? Also I am not sure if is the job of contrib simple_oath module to deal with CSRF-Token because of https://www.drupal.org/project/drupal/issues/2753681 ?

Screenshot explains the issue.

UserInterface::id(), AccountInterface::id() should return int to match typehints

$
0
0

Problem/Motivation

AccountInterface::id()'s typehint states it returns an integer, but this is not true in many (all?) cases. Weakly typed as PHP is, uids stored on AccountProxy, UserSession, UserInterface may return the uid as a string. This prevents strongly typed comparison, e.g. $currentUser->id() === $ownerIdAsInteger, if one is represented as an integer and the other a string. Or, it will fail strict type enforcement if passed to a method which expects an integer.

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

[JSON:API] Document ResourceTypeBuildEvent


Prefix block machine name suggestions with the theme machine name

$
0
0

Problem/Motivation

When placing block on a page, you can set the block machine name. But the configuration of this block depends on the theme you place your block in.

On the same websites, if there are multiple themes, you can't place the same block on another theme with the same machine name because it is already used.

Proposed resolution

A best practice would be to prefix block machine name by the machine name of the theme it is in.

For example: block.block.bartik_help.yml

Remaining tasks

Allow process plugins to flag a row to be skipped

$
0
0

Problem/Motivation

Currently a process plugin can declare a row to be skipped by throwing a MigrateSkipRowException. Using exceptions as signals in this manner is not ideal. The process plugins have access to the $row. They should simply be able to set a flag on the row and return rather than trying to pass an exception up through the executable.

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Log message if migration_lookup skips on empty

$
0
0

Problem/Motivation

Continuing from #2951715-30: Log message if static_map plugin skips the row.

Log message if migration_lookup skips on empty. The method skipOnEmpty was renamed skipInvalid in #2751825: MigrationLookup plugin should accept zero as a legitimate input and will skip for more cases that the original. It now skips when the input is NULL, FALSE, [] and "".

From original Issue Summary:

core/modules/migrate/src/Plugin/migrate/process/MigrationLookup.php:248:      
throw new MigrateSkipProcessException();

The skip occurs only in the case when there are multiple source_ids. What should be the text of the error message?

      if (isset($this->configuration['source_ids'][$migration_id])) {
        $configuration = ['source' => $this->configuration['source_ids'][$migration_id]];
        $value = $this->processPluginManager
          ->createInstance('get', $configuration, $this->migration)
          ->transform(NULL, $migrate_executable, $row, $destination_property);
      }
      if (!is_array($value)) {
        $value = [$value];
      }
      $this->skipOnEmpty($value);

Proposed resolution

Log an informational migrate message of the form, "Migration lookup in migration '%s' skipped migration '%s' with input value '%s'.

Remaining tasks

Review
Commit

User interface changes

N/A

API changes

N/A

Data model changes

N/A

Missing @var annotation for arrays that provide default values

Tests missing for custom field labels?

$
0
0

I'm looking for a single test that checks if a field label is properly shown in a view. Can someone give me a hint where such a test exists, please?

Viewing all 296540 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>