-
Notifications
You must be signed in to change notification settings - Fork 1
No entities in messages #59
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
base: main
Are you sure you want to change the base?
Conversation
Prevent errors when serializing the message. See https://symfony.com/doc/current/messenger.html#doctrine-entities-in-messages
Reviewer's GuideRefactors user-related Messenger messages to carry user IDs instead of User entities, and updates all handlers, controllers, validation, and tests to load entities from the repository using those IDs for safer serialization and transport. Sequence diagram for user message dispatch and handling with userIdsequenceDiagram
actor UserActor
participant Controller
participant MessageBus
participant SendConfirmationMessage as SendConfirmation
participant SendConfirmationHandler
participant UserRepository
participant User
UserActor->>Controller: trigger confirmation resend
Controller->>MessageBus: dispatch SendConfirmation(userId, locale)
MessageBus->>SendConfirmationHandler: __invoke(SendConfirmation)
SendConfirmationHandler->>UserRepository: find(message.userId)
UserRepository-->>SendConfirmationHandler: User
SendConfirmationHandler->>User: requestConfirmation()
SendConfirmationHandler->>UserRepository: save()
UserRepository-->>SendConfirmationHandler: void
SendConfirmationHandler-->>MessageBus: return User
Class diagram for updated user messages and handlers using userIdclassDiagram
class User {
+int id
+string email
+array roles
+void confirm()
+void disable()
+void enable()
+void update(string email, array roles)
+void requestPassword()
+void requestConfirmation()
+void setPassword(string password)
+int getId()
+string getEmail()
+array getRoles()
}
class UserRepository {
+User find(int id)
+void add(User user)
+void save()
}
class UpdateUser {
+int userId
+string email
+array roles
+__construct(User user)
}
class ConfirmUser {
+int userId
+__construct(int userId)
}
class DisableUser {
+int userId
+__construct(int userId)
}
class EnableUser {
+int userId
+__construct(int userId)
}
class SendConfirmation {
+int userId
+string locale
+__construct(int userId, string locale)
}
class ChangePassword {
+int userId
+string password
+__construct(int userId)
}
class ResetPassword {
+int userId
+string password
+__construct(int userId)
}
class ConfirmUserHandler {
+__construct(UserRepository userRepository)
+__invoke(ConfirmUser message) void
}
class DisableUserHandler {
+__construct(UserRepository userRepository)
+__invoke(DisableUser message) void
}
class EnableUserHandler {
+__construct(UserRepository userRepository)
+__invoke(EnableUser message) void
}
class UpdateUserHandler {
+__construct(UserRepository userRepository)
+__invoke(UpdateUser message) void
}
class ChangePasswordHandler {
+__construct(UserRepository userRepository, PasswordEncoder passwordEncoder)
+__invoke(ChangePassword message) void
}
class ResetPasswordHandler {
+__construct(UserRepository userRepository, PasswordEncoder passwordEncoder)
+__invoke(ResetPassword message) void
}
class SendConfirmationHandler {
+__construct(UserRepository userRepository)
+__invoke(SendConfirmation message) User
}
class UniqueEmailValidator {
+void validate(mixed value, Constraint constraint)
}
class UserDataTransferObject {
+string email
+array roles
}
class PasswordEncoder {
+string hashPassword(User user, string password)
}
UserDataTransferObject <|-- UpdateUser
ConfirmUserHandler --> ConfirmUser
ConfirmUserHandler --> UserRepository
ConfirmUserHandler --> User
DisableUserHandler --> DisableUser
DisableUserHandler --> UserRepository
DisableUserHandler --> User
EnableUserHandler --> EnableUser
EnableUserHandler --> UserRepository
EnableUserHandler --> User
UpdateUserHandler --> UpdateUser
UpdateUserHandler --> UserRepository
UpdateUserHandler --> User
ChangePasswordHandler --> ChangePassword
ChangePasswordHandler --> UserRepository
ChangePasswordHandler --> User
ChangePasswordHandler --> PasswordEncoder
ResetPasswordHandler --> ResetPassword
ResetPasswordHandler --> UserRepository
ResetPasswordHandler --> User
ResetPasswordHandler --> PasswordEncoder
SendConfirmationHandler --> SendConfirmation
SendConfirmationHandler --> UserRepository
SendConfirmationHandler --> User
UniqueEmailValidator --> UpdateUser
UniqueEmailValidator --> UserRepository
UniqueEmailValidator --> User
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
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.
Hey - I've found 1 issue, and left some high level feedback:
- Now that handlers load the User via
$this->userRepository->find($message->userId), there’s no guarantee a user will be found; consider adding explicit handling (exception, early return, or validation) for anullresult to avoid hidden failures. - In
SendConfirmationHandler::__invoke,$this->userRepository->find($message->userId)can returnnullwhile the method still declares aUserreturn type; it would be good to either enforce non-null lookup (e.g.findOrFail-style) or adjust the return type/behavior to reflect the possibility of a missing user.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Now that handlers load the User via `$this->userRepository->find($message->userId)`, there’s no guarantee a user will be found; consider adding explicit handling (exception, early return, or validation) for a `null` result to avoid hidden failures.
- In `SendConfirmationHandler::__invoke`, `$this->userRepository->find($message->userId)` can return `null` while the method still declares a `User` return type; it would be good to either enforce non-null lookup (e.g. `findOrFail`-style) or adjust the return type/behavior to reflect the possibility of a missing user.
## Individual Comments
### Comment 1
<location> `src/MessageHandler/User/ChangePasswordHandler.php:21-23` </location>
<code_context>
{
- $encodedPassword = $this->passwordEncoder->hashPassword($message->user, $message->password);
- $message->user->setPassword($encodedPassword);
+ $user = $this->userRepository->find($message->userId);
+ $encodedPassword = $this->passwordEncoder->hashPassword($user, $message->password);
+ $user->setPassword($encodedPassword);
$this->userRepository->save();
}
</code_context>
<issue_to_address>
**issue:** Handle the case where the user cannot be found by the provided userId.
`find()` may return `null`, so if the user was deleted or the ID is invalid, both `hashPassword()` and `setPassword()` will fail on a `null` value. Add a guard for a missing user (e.g. throw a domain-specific exception, early return, or use a `getOrFail`-style method), and apply the same handling in the other handlers that call `find($message->userId)`.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
jonasdekeukelaere
left a comment
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.
- Meeste van die messages kunnen readonly op class-niveau krijgen
- Zou je in de handlers niet nog een check steken als user niet gevonden wordt?
Should not happen, so we want to know if it does.
Pass entity id in message instead of object.
Prevent errors when serializing the message.
See https://symfony.com/doc/current/messenger.html#doctrine-entities-in-messages
Summary by Sourcery
Replace Doctrine user entity instances in messenger messages with scalar user IDs and adjust handlers, controllers, validation, and tests accordingly.
Bug Fixes:
Enhancements:
Tests: