-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Security] Ban \DateTime from Security component #47772
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
[Security] Ban \DateTime from Security component #47772
Conversation
@@ -39,7 +39,7 @@ public function deleteTokenBySeries(string $series); | |||
* | |||
* @throws TokenNotFoundException if the token is not found | |||
*/ | |||
public function updateToken(string $series, #[\SensitiveParameter] string $tokenValue, \DateTime $lastUsed); | |||
public function updateToken(string $series, #[\SensitiveParameter] string $tokenValue, \DateTimeInterface $lastUsed); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a BC break for implementors of the interface
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we remove the param from 6.2 and replace it with an @param
annotation? I think you said we cannot but I forgot the reasoning once again 😬
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't have a default value, which means removing the param is not allowed as that would mean the implementors are flagged as incompatible with the interface?
@@ -37,7 +37,7 @@ public function getTokenValue(): string; | |||
/** | |||
* Returns the time the token was last used. | |||
*/ | |||
public function getLastUsed(): \DateTime; | |||
public function getLastUsed(): \DateTimeInterface; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a BC breaks for consumers of the interface
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I try to do here is to use the covariance feature of PHP. I don't get why is it a BC breaks ? If someone consumes this interface with DateTime he still can because DateTime is a child of DateTimeInterface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a BC break for the caller, as they could rely on the method returning DateTime
before. E.g. this code works before this change, but breaks after:
$lastUsed = $token->getLastUsed();
$lastUsed->modify('+30 minutes');
if ($lastUsed < new \DateTimeImmutable('now')) {
throw new \RuntimeException('This token was last used 30 minutes ago');
}
(or simpler use-cases e.g. where this is passed in a function requiring DateTime
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The consumer of a return type is not choosing whether it uses DateTime or a DateTimeInterface. It has to handle everything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok thanks both of you. I understand your point. But I don't see any way to it without leading to a BC break. Maybe we should target the next major version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also next major versions cannot have BC breaks that didn't have a deprecation (and way to get out of deprecation) in the last minor before it.
We would have to create a new method with the new return type and deprecate the old method. But I'm personally not sure if that is worth is: What about delaying to remove mutable DateTime in user-facing code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nicolas-grekas I ping you here. I think you should be part of this discussion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've no perfect solution to this. We would document a way to detect all such uses of DateTime
and rewrite them automatically:
Before:
$lastUsed = $token->getLastUsed();
$lastUsed->modify('+30 minutes');
After:
$lastUsed = $token->getLastUsed();
$lastUsed = $lastUsed->modify('+30 minutes');
That'd make the code the same whether DateTime
or DateTimeImmutable
is used.
Can Rector do that? /cc @TomasVotruba
Should the PHP engine trigger a deprecation when the return value of one of DateTime's setters is not used? I'm not sure how this would be possible technically, but let's just dream a bit :) /cc @derickr
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nicolas-grekas If the type is known, Rector can handle it :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And regarding the widened type, we might need something like ReturnTypeWillChange
to indicate that this interface will change its return type in the future. But there is no userland solution for that.
I'm closing because I think we went as far as possible on the topic already. Thanks for the interest in pushing this forward 🙏 |
This PR is next to: #47730
The purpose here is to remove the use of \DateTime in the security component. I don't think we can remove it completely without leading any BC break. So I propose to use DateTimeInterface with a deprecation notice.
Feel free to discuss!