Skip to content
Snippets Groups Projects
Verified Commit 87bf1eef authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3401255 by znerol, smustgrave, borisson_, phenaproxima, penyaskito,...

Issue #3401255 by znerol, smustgrave, borisson_, phenaproxima, penyaskito, kunal.sachdev:  Tighten config validation schema of system.mail mailer_dsn
parent 257fa315
Branches
Tags
27 merge requests!12227Issue #3181946 by jonmcl, mglaman,!11131[10.4.x-only-DO-NOT-MERGE]: Issue ##2842525 Ajax attached to Views exposed filter form does not trigger callbacks,!9470[10.3.x-only-DO-NOT-MERGE]: #3331771 Fix file_get_contents(): Passing null to parameter,!8736Update the Documention As per the Function uses.,!8528Issue #3456871 by Tim Bozeman: Support NULL services,!8513Issue #3453786: DefaultSelection should document why values for target_bundles NULL and [] behave as they do,!8126Added escape fucntionality on admintoolbar close icon,!5423Draft: Resolve #3329907 "Test2",!3878Removed unused condition head title for views,!3818Issue #2140179: $entity->original gets stale between updates,!3742Issue #3328429: Create item list field formatter for displaying ordered and unordered lists,!3731Claro: role=button on status report items,!3651Issue #3347736: Create new SDC component for Olivero (header-search),!3478Issue #3337882: Deleted menus are not removed from content type config,!3355Issue #3209129: Scrolling problems when adding a block via layout builder,!3154Fixes #2987987 - CSRF token validation broken on routes with optional parameters.,!3133core/modules/system/css/components/hidden.module.css,!2964Issue #2865710 : Dependencies from only one instance of a widget are used in display modes,!2812Issue #3312049: [Followup] Fix Drupal.Commenting.FunctionComment.MissingReturnType returns for NULL,!2378Issue #2875033: Optimize joins and table selection in SQL entity query implementation,!2062Issue #3246454: Add weekly granularity to views date sort,!10223132456: Fix issue where views instances are emptied before an ajax request is complete,!877Issue #2708101: Default value for link text is not saved,!617Issue #3043725: Provide a Entity Handler for user cancelation,!579Issue #2230909: Simple decimals fail to pass validation,!560Move callback classRemove outside of the loop,!555Issue #3202493
Pipeline #210560 passed
Pipeline: drupal

#210565

    Showing
    with 641 additions and 39 deletions
    ......@@ -1010,3 +1010,145 @@ entity_reference_selection.default:
    # providing a specific schema.
    entity_reference_selection.default:*:
    type: entity_reference_selection.default
    # Schema for the configuration of mailer transport DSN.
    mailer_dsn:
    type: mapping
    label: 'Symfony mailer transport DSN'
    mapping:
    scheme:
    type: string
    label: 'Scheme'
    constraints:
    NotBlank:
    message: 'The mailer DSN must contain a scheme.'
    Regex:
    # https://datatracker.ietf.org/doc/html/rfc3986#appendix-A
    pattern: '/^[a-z][a-z0-9+\-\.]*$/i'
    message: 'The mailer DSN scheme must start with a letter followed by zero or more letters, numbers, plus (+), minus (-) or periods (.)'
    host:
    type: string
    label: 'Host'
    constraints:
    NotBlank:
    message: 'The mailer DSN must contain a host (use "default" by default).'
    UriHost:
    message: 'The mailer DSN host should conform to RFC 3986 URI host component.'
    user:
    type: string
    nullable: true
    label: 'User'
    password:
    type: string
    nullable: true
    label: 'Password'
    port:
    type: integer
    nullable: true
    label: 'Port'
    constraints:
    Range:
    min: 0
    max: 65535
    notInRangeMessage: 'The mailer DSN port must be between 0 and 65535.'
    options:
    type: mailer_dsn.options.[%parent.scheme]
    label: 'Options'
    mailer_dsn.options.*:
    type: sequence
    label: 'Options'
    sequence:
    type: string
    label: Option
    constraints:
    NotNull: []
    mailer_dsn.options.null:
    type: mapping
    label: 'Null transport options'
    mapping: {}
    mailer_dsn.options.native:
    type: mailer_dsn.options.null
    mailer_dsn.options.sendmail:
    type: mapping
    label: 'Sendmail transport options'
    mapping:
    command:
    type: string
    nullable: true
    label: 'Command to be executed by sendmail transport'
    constraints:
    Regex:
    # Forbid any kind of control character.
    # @see https://stackoverflow.com/a/66587087
    pattern: '/([^\PC])/u'
    match: false
    message: 'The command option is not allowed to span multiple lines or contain control characters.'
    mailer_dsn.options.sendmail+smtp:
    type: mailer_dsn.options.sendmail
    label: 'Sendmail transport options'
    mailer_dsn.options.smtp:
    type: mapping
    label: 'SMTP options'
    mapping:
    verify_peer:
    type: boolean
    nullable: true
    label: 'TLS Peer Verification (defaults to true)'
    peer_fingerprint:
    type: string
    nullable: true
    label: 'TLS Peer Fingerprint (no default)'
    constraints:
    Regex:
    pattern: '/^[a-fA-F0-9]+$/'
    message: 'The peer_fingerprint option requires an md5, sha1 or sha256 certificate fingerprint in hex with all separators (colons) removed.'
    local_domain:
    type: string
    nullable: true
    label: 'Domain name or IP address that represents the identity of the client when establishing the SMTP session (defaults to 127.0.0.1)'
    constraints:
    Regex:
    # Forbid any kind of control character.
    # @see https://stackoverflow.com/a/66587087
    pattern: '/([^\PC])/u'
    match: false
    message: 'The local_domain is not allowed to span multiple lines or contain control characters.'
    restart_threshold:
    type: integer
    nullable: true
    label: 'Maximum number of messages to send before re-starting the transport (defaults to 100 messages)'
    constraints:
    Range:
    min: 0
    restart_threshold_sleep:
    type: float
    nullable: true
    label: 'Number of seconds to sleep between stopping and re-starting the transport (defaults to no delay)'
    constraints:
    Range:
    min: 0
    ping_threshold:
    type: integer
    nullable: true
    label: 'The minimum number of seconds between two messages required to ping the server (defaults to 100 seconds)'
    constraints:
    Range:
    min: 0
    max_per_second:
    type: integer
    nullable: true
    label: 'The number of messages to send per second (defaults to no limit)'
    constraints:
    Range:
    min: 0
    mailer_dsn.options.smtps:
    type: mailer_dsn.options.smtp
    label: 'Secure SMTP options'
    <?php
    declare(strict_types=1);
    namespace Drupal\Core\Validation\Plugin\Validation\Constraint;
    use Drupal\Core\StringTranslation\TranslatableMarkup;
    use Drupal\Core\Validation\Attribute\Constraint;
    use Symfony\Component\Validator\Constraint as SymfonyConstraint;
    /**
    * Checks if a string conforms to the RFC 3986 host component.
    */
    #[Constraint(
    id: 'UriHost',
    label: new TranslatableMarkup('URI host', [], ['context' => 'Validation']),
    )]
    class UriHostConstraint extends SymfonyConstraint {
    /**
    * The error message if validation fails.
    *
    * @var string
    */
    public string $message = 'This value should conform to RFC 3986 URI host component.';
    }
    <?php
    declare(strict_types=1);
    namespace Drupal\Core\Validation\Plugin\Validation\Constraint;
    use Symfony\Component\Validator\Constraint;
    use Symfony\Component\Validator\ConstraintValidator;
    use Symfony\Component\Validator\Exception\UnexpectedTypeException;
    /**
    * Validates if a string conforms to the RFC 3986 host component.
    */
    class UriHostConstraintValidator extends ConstraintValidator {
    /**
    * {@inheritdoc}
    */
    public function validate($value, Constraint $constraint): void {
    assert($constraint instanceof UriHostConstraint);
    if ($value === NULL || $value === '') {
    return;
    }
    if (!is_string($value)) {
    throw new UnexpectedTypeException($value, 'string');
    }
    if (!$this->isValid($value)) {
    $this->context->addViolation($constraint->message);
    }
    }
    /**
    * Return TRUE if value is a valid hostname or IP address literal.
    */
    protected function isValid(string $value): bool {
    if (filter_var($value, \FILTER_VALIDATE_DOMAIN, \FILTER_FLAG_HOSTNAME) !== FALSE) {
    return TRUE;
    }
    if (str_starts_with($value, '[') && str_ends_with($value, ']')) {
    $address = substr($value, 1, strlen($value) - 2);
    if (filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6) !== FALSE) {
    return TRUE;
    }
    }
    return FALSE;
    }
    }
    ......@@ -608,6 +608,7 @@ skiptags
    slatkin
    smacss
    smalldatetime
    smtps
    somecompany
    sortablejs
    specialchars
    ......
    ......@@ -7,3 +7,4 @@ giraffe:
    hum2: hum2
    uuid: '7C30C50E-641A-4E34-A7F1-46BCFB9BE5A3'
    string__not_blank: 'this is a label'
    host: 'localhost'
    ......@@ -296,3 +296,8 @@ config_test.validation:
    type: string
    constraints:
    NotBlank: {}
    host:
    type: string
    constraints:
    UriHost: ~
    ......@@ -361,6 +361,8 @@ system.image.gd:
    system.mail:
    type: config_object
    label: 'Mail system'
    constraints:
    FullyValidatable: ~
    mapping:
    interface:
    type: sequence
    ......@@ -373,45 +375,8 @@ system.mail:
    manager: plugin.manager.mail
    interface: 'Drupal\Core\Mail\MailInterface'
    mailer_dsn:
    type: mapping
    type: mailer_dsn
    label: 'Symfony mailer transport DSN'
    mapping:
    scheme:
    type: string
    label: 'Scheme'
    constraints:
    NotBlank:
    message: 'The mailer DSN must contain a scheme.'
    host:
    type: string
    label: 'Host'
    constraints:
    NotBlank:
    message: 'The mailer DSN must contain a host (use "default" by default).'
    user:
    type: string
    nullable: true
    label: 'User'
    password:
    type: string
    nullable: true
    label: 'Password'
    port:
    type: integer
    nullable: true
    label: 'Port'
    constraints:
    Range:
    min: 0
    max: 65535
    options:
    type: sequence
    label: 'Options'
    sequence:
    type: string
    label: Option
    constraints:
    NotNull: []
    system.theme.global:
    type: theme_settings
    ......
    ......@@ -96,7 +96,7 @@ public function testTypedDataAPI(): void {
    $typed_config_manager = \Drupal::service('config.typed');
    $typed_config = $typed_config_manager->createFromNameAndData('config_test.validation', \Drupal::configFactory()->get('config_test.validation')->get());
    $this->assertInstanceOf(TypedConfigInterface::class, $typed_config);
    $this->assertEquals(['_core', 'llama', 'cat', 'giraffe', 'uuid', 'string__not_blank'], array_keys($typed_config->getElements()));
    $this->assertEquals(['_core', 'llama', 'cat', 'giraffe', 'uuid', 'string__not_blank', 'host'], array_keys($typed_config->getElements()));
    $this->assertSame('config_test.validation', $typed_config->getName());
    $this->assertSame('config_test.validation', $typed_config->getPropertyPath());
    $this->assertSame('config_test.validation.llama', $typed_config->get('llama')->getPropertyPath());
    ......
    <?php
    declare(strict_types=1);
    namespace Drupal\KernelTests\Core\Config;
    use Drupal\Core\Config\TypedConfigManagerInterface;
    use Drupal\KernelTests\KernelTestBase;
    /**
    * Tests validation of mailer dsn config.
    *
    * @group config
    * @group Validation
    */
    class MailerDsnConfigValidationTest extends KernelTestBase {
    /**
    * {@inheritdoc}
    */
    protected static $modules = ['system'];
    /**
    * Config manager service.
    */
    protected TypedConfigManagerInterface $configManager;
    /**
    * {@inheritdoc}
    */
    protected function setUp(): void {
    parent::setUp();
    $this->installConfig('system');
    $this->configManager = $this->container->get(TypedConfigManagerInterface::class);
    }
    public function testMailerSchemeValidation(): void {
    $config = $this->config('system.mail');
    $this->assertFalse($config->isNew());
    $data = $config->get();
    // If the scheme is NULL, it should be an error.
    $data['mailer_dsn']['scheme'] = NULL;
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(1, $violations);
    $this->assertSame('mailer_dsn.scheme', $violations[0]->getPropertyPath());
    $this->assertSame('This value should not be null.', (string) $violations[0]->getMessage());
    // If the scheme is blank, it should be an error.
    $data['mailer_dsn']['scheme'] = '';
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(1, $violations);
    $this->assertSame('mailer_dsn.scheme', $violations[0]->getPropertyPath());
    $this->assertSame('The mailer DSN must contain a scheme.', (string) $violations[0]->getMessage());
    // If the scheme doesn't start with a letter, it should be an error.
    $data['mailer_dsn']['scheme'] = '-unexpected-first-character';
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(1, $violations);
    $this->assertSame('mailer_dsn.scheme', $violations[0]->getPropertyPath());
    $this->assertSame('The mailer DSN scheme must start with a letter followed by zero or more letters, numbers, plus (+), minus (-) or periods (.)', (string) $violations[0]->getMessage());
    // If the scheme contains unexpected characters, it should be an error.
    $data['mailer_dsn']['scheme'] = 'unexpected_underscore';
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(1, $violations);
    $this->assertSame('mailer_dsn.scheme', $violations[0]->getPropertyPath());
    $this->assertSame('The mailer DSN scheme must start with a letter followed by zero or more letters, numbers, plus (+), minus (-) or periods (.)', (string) $violations[0]->getMessage());
    // If the scheme is valid, it should be accepted.
    $data['mailer_dsn']['scheme'] = 'smtp';
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(0, $violations);
    // If the scheme is valid, it should be accepted.
    $data['mailer_dsn']['scheme'] = 'sendmail+smtp';
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(0, $violations);
    // If the scheme is valid, it should be accepted.
    $data['mailer_dsn']['scheme'] = 'drupal.test-capture';
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(0, $violations);
    }
    public function testMailerHostValidation(): void {
    $config = $this->config('system.mail');
    $this->assertFalse($config->isNew());
    $data = $config->get();
    // If the host is NULL, it should be an error.
    $data['mailer_dsn']['host'] = NULL;
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(1, $violations);
    $this->assertSame('mailer_dsn.host', $violations[0]->getPropertyPath());
    $this->assertSame('This value should not be null.', (string) $violations[0]->getMessage());
    // If the host is blank, it should be an error.
    $data['mailer_dsn']['host'] = '';
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(1, $violations);
    $this->assertSame('mailer_dsn.host', $violations[0]->getPropertyPath());
    $this->assertSame('The mailer DSN must contain a host (use "default" by default).', (string) $violations[0]->getMessage());
    // If the host contains a newline, it should be an error.
    $data['mailer_dsn']['host'] = "host\nwith\nnewline";
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(1, $violations);
    $this->assertSame('mailer_dsn.host', $violations[0]->getPropertyPath());
    $this->assertSame('The mailer DSN host should conform to RFC 3986 URI host component.', (string) $violations[0]->getMessage());
    // If the host contains unexpected characters, it should be an error.
    $data['mailer_dsn']['host'] = "host\rwith\tcontrol-chars";
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(1, $violations);
    $this->assertSame('mailer_dsn.host', $violations[0]->getPropertyPath());
    $this->assertSame('The mailer DSN host should conform to RFC 3986 URI host component.', (string) $violations[0]->getMessage());
    // If the host is valid, it should be accepted.
    $data['mailer_dsn']['host'] = 'default';
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(0, $violations);
    // If the host is valid, it should be accepted.
    $data['mailer_dsn']['host'] = 'mail.example.com';
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(0, $violations);
    // If the host is valid, it should be accepted.
    $data['mailer_dsn']['host'] = '127.0.0.1';
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(0, $violations);
    // If the host is valid, it should be accepted.
    $data['mailer_dsn']['host'] = '[::1]';
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(0, $violations);
    }
    public function testMailerUserPasswordValidation(): void {
    $config = $this->config('system.mail');
    $this->assertFalse($config->isNew());
    $data = $config->get();
    // If the user is valid, it should be accepted.
    $data['mailer_dsn']['user'] = "any😎thing\ngoes";
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(0, $violations);
    // If the password is valid, it should be accepted.
    $data['mailer_dsn']['password'] = "any😎thing\ngoes";
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(0, $violations);
    }
    public function testMailerPortValidation(): void {
    $config = $this->config('system.mail');
    $this->assertFalse($config->isNew());
    $data = $config->get();
    // If the port is negative, it should be an error.
    $data['mailer_dsn']['port'] = -1;
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(1, $violations);
    $this->assertSame('mailer_dsn.port', $violations[0]->getPropertyPath());
    $this->assertSame('The mailer DSN port must be between 0 and 65535.', (string) $violations[0]->getMessage());
    // If the port greater than 65535, it should be an error.
    $data['mailer_dsn']['port'] = 655351 + 1;
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(1, $violations);
    $this->assertSame('mailer_dsn.port', $violations[0]->getPropertyPath());
    $this->assertSame('The mailer DSN port must be between 0 and 65535.', (string) $violations[0]->getMessage());
    // If the port is valid, it should be accepted.
    $data['mailer_dsn']['port'] = 587;
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(0, $violations);
    }
    public function testMailerTransportDefaultOptionsValidation(): void {
    $config = $this->config('system.mail');
    $this->assertFalse($config->isNew());
    $data = $config->get();
    // Set scheme to an unknown schema.
    $data['mailer_dsn']['scheme'] = 'drupal.unknown-scheme+https';
    // If there is no more specific type for a scheme, options with any key
    // should be accepted.
    $data['mailer_dsn']['options'] = [
    'any_bool' => TRUE,
    'any_int' => 42,
    'any_string' => "any😎thing\ngoes",
    ];
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(0, $violations);
    }
    public function testMailerTransportNativeOptionsValidation(): void {
    $config = $this->config('system.mail');
    $this->assertFalse($config->isNew());
    $data = $config->get();
    // Set scheme to native.
    $data['mailer_dsn']['scheme'] = 'native';
    // If the options contain an invalid key, it should be an error.
    $data['mailer_dsn']['options'] = ['invalid_key' => 'Hello'];
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(1, $violations);
    $this->assertSame('mailer_dsn.options.invalid_key', $violations[0]->getPropertyPath());
    $this->assertSame("'invalid_key' is not a supported key.", (string) $violations[0]->getMessage());
    // If options is an empty map, it should be accepted.
    $data['mailer_dsn']['options'] = [];
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(0, $violations);
    }
    public function testMailerTransportNullOptionsValidation(): void {
    $config = $this->config('system.mail');
    $this->assertFalse($config->isNew());
    $data = $config->get();
    // Set scheme to null.
    $data['mailer_dsn']['scheme'] = 'null';
    // If the options contain an invalid key, it should be an error.
    $data['mailer_dsn']['options'] = ['invalid_key' => 'Hello'];
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(1, $violations);
    $this->assertSame('mailer_dsn.options.invalid_key', $violations[0]->getPropertyPath());
    $this->assertSame("'invalid_key' is not a supported key.", (string) $violations[0]->getMessage());
    // If options is an empty map, it should be accepted.
    $data['mailer_dsn']['options'] = [];
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(0, $violations);
    }
    public function testMailerTransportSendmailOptionsValidation(): void {
    $config = $this->config('system.mail');
    $this->assertFalse($config->isNew());
    $data = $config->get();
    // Set scheme to sendmail.
    $data['mailer_dsn']['scheme'] = 'sendmail';
    // If the options contain an invalid command, it should be an error.
    $data['mailer_dsn']['options'] = ['command' => "sendmail\t-bs\n"];
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(1, $violations);
    $this->assertSame('mailer_dsn.options.command', $violations[0]->getPropertyPath());
    $this->assertSame('The command option is not allowed to span multiple lines or contain control characters.', (string) $violations[0]->getMessage());
    // If the options contain an invalid key, it should be an error.
    $data['mailer_dsn']['options'] = ['invalid_key' => 'Hello'];
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(1, $violations);
    $this->assertSame('mailer_dsn.options.invalid_key', $violations[0]->getPropertyPath());
    $this->assertSame("'invalid_key' is not a supported key.", (string) $violations[0]->getMessage());
    // If the options contain a command, it should accepted.
    $data['mailer_dsn']['options'] = ['command' => 'sendmail -bs'];
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(0, $violations);
    // If options is an empty map, it should be accepted.
    $data['mailer_dsn']['options'] = [];
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(0, $violations);
    }
    public function testMailerTransportSMTPOptionsValidation(): void {
    $config = $this->config('system.mail');
    $this->assertFalse($config->isNew());
    $data = $config->get();
    // Set scheme to smtps.
    $data['mailer_dsn']['scheme'] = 'smtps';
    // If the options contain an invalid peer_fingerprint, it should be an error.
    $data['mailer_dsn']['options'] = [
    'verify_peer' => FALSE,
    'peer_fingerprint' => 'BE:F7:B9:CA:0F:6E:0F:29:9B:E9:B4:64:99:35:D6:27',
    ];
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(1, $violations);
    $this->assertSame('mailer_dsn.options.peer_fingerprint', $violations[0]->getPropertyPath());
    $this->assertSame('The peer_fingerprint option requires an md5, sha1 or sha256 certificate fingerprint in hex with all separators (colons) removed.', (string) $violations[0]->getMessage());
    // If the options contain a valid peer_fingerprint, it should be accepted.
    $data['mailer_dsn']['options'] = [
    'verify_peer' => FALSE,
    'peer_fingerprint' => 'BEF7B9CA0F6E0F299BE9B4649935D627',
    ];
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(0, $violations);
    // If the options contain a valid peer_fingerprint, it should be accepted.
    $data['mailer_dsn']['options'] = [
    'verify_peer' => TRUE,
    'peer_fingerprint' => '87abbc4d1c3f23146362c6a1168fb7e90a56569c4c97275c69c0630dc06e526d',
    ];
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(0, $violations);
    // If the options contain a local_domain with a newline, it should be an error.
    $data['mailer_dsn']['options'] = ['local_domain' => "host\nwith\nnewline"];
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(1, $violations);
    $this->assertSame('mailer_dsn.options.local_domain', $violations[0]->getPropertyPath());
    $this->assertSame('The local_domain is not allowed to span multiple lines or contain control characters.', (string) $violations[0]->getMessage());
    // If the options contain a local_domain with unexpected characters, it should be an error.
    $data['mailer_dsn']['options'] = ['local_domain' => "host\rwith\tcontrol-chars"];
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(1, $violations);
    $this->assertSame('mailer_dsn.options.local_domain', $violations[0]->getPropertyPath());
    $this->assertSame('The local_domain is not allowed to span multiple lines or contain control characters.', (string) $violations[0]->getMessage());
    // If the options contain a valid local_domain, it should be accepted.
    $data['mailer_dsn']['options'] = ['local_domain' => 'www.example.com'];
    $violations = $this->configManager->createFromNameAndData($config->getName(), $data)
    ->validate();
    $this->assertCount(0, $violations);
    }
    }
    ......@@ -44,4 +44,48 @@ public function testUuid(): void {
    $this->assertCount(1, $typed_config->validate());
    }
    /**
    * @see \Drupal\Core\Validation\Plugin\Validation\Constraint\UriHostConstraint
    */
    public function testUriHost() {
    $typed_config_manager = \Drupal::service('config.typed');
    /** @var \Drupal\Core\Config\Schema\TypedConfigInterface $typed_config */
    $typed_config = $typed_config_manager->get('config_test.validation');
    // Test valid names.
    $typed_config->get('host')->setValue('example.com');
    $this->assertCount(0, $typed_config->validate());
    $typed_config->get('host')->setValue('example.com.');
    $this->assertCount(0, $typed_config->validate());
    $typed_config->get('host')->setValue('default');
    $this->assertCount(0, $typed_config->validate());
    // Test invalid names.
    $typed_config->get('host')->setValue('.example.com');
    $this->assertCount(1, $typed_config->validate());
    // Test valid IPv6 literals.
    $typed_config->get('host')->setValue('[::1]');
    $this->assertCount(0, $typed_config->validate());
    $typed_config->get('host')->setValue('[2001:DB8::]');
    $this->assertCount(0, $typed_config->validate());
    $typed_config->get('host')->setValue('[2001:db8:dd54:4473:bd6e:52db:10b3:4abe]');
    $this->assertCount(0, $typed_config->validate());
    // Test invalid IPv6 literals.
    $typed_config->get('host')->setValue('::1');
    $this->assertCount(1, $typed_config->validate());
    // Test valid IPv4 addresses.
    $typed_config->get('host')->setValue('127.0.0.1');
    $this->assertCount(0, $typed_config->validate());
    $typed_config->get('host')->setValue('192.0.2.254');
    $this->assertCount(0, $typed_config->validate());
    }
    }
    0% Loading or .
    You are about to add 0 people to the discussion. Proceed with caution.
    Please register or to comment