Skip to content

[Validator] Add AutoMapping constraint to enable or disable auto-validation #32107

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 30, 2019

Conversation

dunglas
Copy link
Member

@dunglas dunglas commented Jun 19, 2019

Q A
Branch? 4.4
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #32070, #32015
License MIT
Doc PR todo

As discussed in #32070 and #32015, it's sometimes mandatory to prevent some classes or properties to be auto mapped (auto-validated). This PR introduces a new constraint, @AutoMapping allowing to do exactly that. Examples:

Class:

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity
 * @Assert\AutoMapping(false)
 */
class DoctrineLoaderNoAutoMappingEntity
{
    /**
     * @ORM\Id
     * @ORM\Column
     */
    public $id;

    /**
     * @ORM\Column(length=20, unique=true)
     */
    public $maxLength;
}

Property:

namespace Symfony\Bridge\Doctrine\Tests\Fixtures;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity
 */
class DoctrineLoaderEntity extends DoctrineLoaderParentEntity
{
    /**
     * @ORM\Id
     * @ORM\Column
     */
    public $id;

    /**
     * @ORM\Column(length=10)
     * @Assert\AutoMapping(false)
     */
    public $noAutoMapping;
}

The rules are the following:

  • If the constraint is present on a property, and set to true, auto-mapping is always on, regardless of the config, and of any class level annotation
  • If the constraint is present on a property, and set to false, auto-mapping is always off, regardless of the config, and of any class level annotation
  • If the constraint is present on a class, and set to true, auto-mapping is always on except if a the annotation has been added to a specific property, and regardless of the config
  • If the constraint is present on a class, and set to false, auto-mapping is always off except if a the annotation has been added to a specific property, and regardless of the config

@dunglas dunglas requested a review from weaverryan June 19, 2019 22:11
@dunglas dunglas force-pushed the no-auto-mapping-constraint branch 2 times, most recently from 2113beb to de30553 Compare June 19, 2019 22:20
@noniagriconomie
Copy link
Contributor

Hi @dunglas, this means in sf 4.3 it is a default feature (doctrine field are alwas by default validated) ?
the dev need to optout to get rid off it? if yes, why not the other side?
thank you

@nicolas-grekas
Copy link
Member

@noniagriconomie see symfony/recipes#612

BTW, I think we also need an opt-in annotation
having both config enabling+exclusion list and annotations to enable/disable looks the most sensible to me. Every style covered, maximum flexibility.

@OskarStark
Copy link
Contributor

I agree with Nicolas here, Opt-In is definitely needed too 👍🏻

@noniagriconomie
Copy link
Contributor

thx for both answers @nicolas-grekas @OskarStark :)

@alanpoulain
Copy link
Contributor

IMHO it should be enabled by default in the recipes (and allow to opt-out some classes or properties) and having an opt-in feature is a nice to have.

@fabpot
Copy link
Member

fabpot commented Jun 20, 2019

As we experienced issues when we enabled it by default and side effects that are difficult to understand, I'm in favor of only supporting the opt-in mode and only for classes/properties.

@dunglas
Copy link
Member Author

dunglas commented Jun 20, 2019

Being opt-in only defects the purpose of this feature and decreases the security benefits it provides: #32070 (comment)

Most side effects are because this feature is young, this PR should be enough to prevent the last remaining ones.

The feature is already opt-in using the config file (it’s off by default). I don’t understand how the AutoMapping constraint would work? I mean, you must already opt in a specific directory using the config, and you can exclude some classes or properties using this new annotation. How the proposed annotation would integrate with this?

@nicolas-grekas
Copy link
Member

Opt-in can still be made the default in maker-bundle, so that the security you want @dunglas is still a thing.

@dunglas
Copy link
Member Author

dunglas commented Jun 20, 2019

Many people (including me) don't use maker bundle to create entities (for instance, almost all PHPStorm users, I guess). And it's one more annotation to not forget to add to every new class, for no reasons. Actually, I prefer the current situation (having to uncomment one time for all some lines in a config file) than having to add an annotation to all new entities.

@dunglas
Copy link
Member Author

dunglas commented Jun 20, 2019

Travis failures are expected (we'll have to bump the required Validator version or to add conflict rules when merged).

@nicolas-grekas
Copy link
Member

That's why I think we need config + annotation, opt-in/out + list/exclusion, to cover all styles.

@dunglas
Copy link
Member Author

dunglas commented Jun 20, 2019

Here is a new proposal that should satisfy everybody:

  • Change the constraint to @AutoMapping(true/false), true being the default value.
  • If the constraint is present on a property, and set to true, auto-mapping is always on, regardless of the config, and of any class level annotation
  • If the constraint is present on a property, and set to false, auto-mapping is always off, regardless of the config, and of any class level annotation
  • If the constraint is present on a class, and set to true, auto-mapping is always on except if a the annotation has been added to a specific property, and regardless of the config
  • If the constraint is present on a class, and set to false, auto-mapping is always off except if a the annotation has been added to a specific property, and regardless of the config
  • The config stays unchanged (with the new behavior, there is no need to a config for exclusions, it's already handled by the constraint) ; and is uncommented by default in the recipe

It should cover all use cases, the feature is still on by default for the users of the framework thanks to the recipe. Do you folks agree?

@nicolas-grekas
Copy link
Member

Annotations always win, looks sensible to me.
I would still like to have the exclusion list in the config, but someone else can provide it in another PR.

@nicolas-grekas nicolas-grekas added this to the 4.3 milestone Jun 23, 2019
@nicolas-grekas
Copy link
Member

Should target 4.4 to me, except the bug fix part of course.

@weaverryan
Copy link
Member

With this proposal, if no annotations are added (assuming we re-add the auto mapping config in the recipe in 4.4), then auto mapping would still be turned on, correct? We could then, in make:entity decide to always generate entities with AutoMapping(true) to be explicit and make it more obvious how to turn it off (or even answer the question “where is this validation coming from?”). I think that sensible... though we may debate later whether to have the default config be “always on without annotation” or “off, unless the annotation is present” (or an I misunderstanding how the config would work?)

Thanks for the conversation. This feature makes me a bit uncomfortable... but @dunglas may very well be correct that it’s just this that’s needed to make it shine. After all, the form fields themselves hav built-in, automatic “sanity” validation, and that’s never been a problem (not an exact comparison).

@spackmat
Copy link
Contributor

spackmat commented Jul 1, 2019

I think disabling all automatic constraints at once is a bit rough. Think, for example, of a decimal property type-hinted to float (or a Decimal object or whatever) instead of Doctrine's internal type string. At the moment, this leads to an invalid Type constraints. Disabling all automatic constraints for that property would mean to give up the wanted ones. This wouldn't be a big problem as the missing ones can easily be readded explicitly and as it is an Annotation, a dev will see that the automatic is disabled. But doing that the correct way requires devs to know about them all and keep track, when new ones will be added in the future.

Wouldn't it be less invasive to only disable the specifically problematic automatic constraints? Like @Assert\NoAutoMapping(['Type', 'NotNull'])?

@dunglas
Copy link
Member Author

dunglas commented Oct 28, 2019

This one should be ready to be merged now. The last decision to make is between this single annotation and EnableAutoMapping+DisableAutoMapping as suggested by @xabbuh. Ping @symfony/mergers

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Oct 29, 2019

I think I prefer Enable/DisableAutoMapping because it opens for better extensibility.
One idea I have in mind would be to handle an auto_mapper attribute on the validator.auto_mapper tag:

<tag name="validator.auto_mapper" auto_mapper="property_info" />

Then @Assert\DisableAutoMapping("property_info") would allow specifically disabling this auto mapper (or enable it with @Assert\EnableAutoMapping("property_info")).

@dunglas dunglas force-pushed the no-auto-mapping-constraint branch 2 times, most recently from 065a81c to a1764e8 Compare October 29, 2019 10:51
@dunglas
Copy link
Member Author

dunglas commented Oct 29, 2019

EnableAutoMapping and DisableAutoMapping added. It should be ready to be merged now. /cc @xabbuh

@nicolas-grekas nicolas-grekas modified the milestones: 4.3, 4.4 Oct 30, 2019
@xabbuh xabbuh added Feature and removed Bug labels Oct 30, 2019
@xabbuh xabbuh force-pushed the no-auto-mapping-constraint branch from a1764e8 to f6519ce Compare October 30, 2019 07:50
@xabbuh
Copy link
Member

xabbuh commented Oct 30, 2019

Thank you Kévin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.