FOSUserBundle register without password - symfony

I am creating an application where visitors can upload some stuff (it will be for invited people only). At the end, if they are not logged in, they are asked to log in or create a user. If they create a new user, I only want to ask them to fill in their name and email.
a password will be generated, and a mail will be sent to the user with the links to change their password if they want to (only to make the procedure as low level as possible).
I can't seem to remove the password fields from the registration form. Can someone help me out. I create a custom form type, service and registered it. I also put custom templates in the app/Resource folder etc. Although my custom Form type AND the templates are being used, the password still appears ...
class RegistrationFormType extends BaseType {
public function buildForm(FormBuilderInterface $builder, array $options) {
parent::buildForm($builder, $options);
// add your custom field
$builder->add('username');
$builder->add('email');
}
public function getName() {
return 'val_user_registration';
}
}

You don't need to extend your parent form ... and you're better off not doing it in this case.
just create a Username/Email form and create the new User entity yourself in a custom registration method then persisting it into database ( don't forget to set the usernameCanonical property on your newly created User ).
FOSUserBundle calls several password-related things during the registration process which you don't need and can't easily circumvent in this case.
You can pass the entity ( with newly created password ) to the update method of FOSUserBundle's UserManager service after you have completed the password/email step then.

Related

symfony extra user info to be persisted in session after authentication

I am trying to use a property called lastLoginOnReference in my User entity. This property is not linked to any column in my corresponding db table as I don't want to store it.
I use this property in order to display to the user some activity logs since the last time he logs in.
I also have a lastLoginOn property, also in the User entity, which has a dedicated column in my user table.
what am I doing at authentication is this one (in my GoogleAuthenticator class):
public function getUser($credentials, UserProviderInterface $userProvider)
{
$googleUser = $this->getGoogleClient()
->fetchUserFromToken($credentials);
$email = $googleUser->getEmail();
$user = $this->em->getRepository(User::class)
->findOneBy(['email' => $email]);
if ($user) {
$user->setLastLoginOnReference($user->getLastLoginOn());
$user->setLastLoginOn(new DateTime('now'));
} else {
(not important)
}
$this->em->persist($user);
$this->em->flush();
return $user;
}
so I store in my lastLoginOnReference property the value from the lastLoginOn User property.
I update the lastLoginOn User property in the User repository and it works.
But when in my controller I use
$this->getUser();
getLastLoginOnReference returns null
I read the documentation and found out the user is apparently refreshed between every request. So I suspect my user object to be refreshed and as the lastLoginOnReference not in db, it is set to null
Then I have implemented the Serializable interface in my User entity, specifying this property to be serialized as well but it doesn't change anything.
login/logout are working as expected, and I am using Symfony 5.1

Sonata bundle, how can I get current logged in user?

Lets say I have a Car Entity. Other than typical Car properties I have updatedBy attribute
In sonata I created a CRUD admin page using AppBundle\Admin\CarAdmin.php
Inside the class CarAdmin I have the required methods like configureListFields, configureFormFields, etc...
I'm guessing I need to add updatedBy using the method prePersist($object) but I'm facing that $this->getUser() is not available
The question is, how can I get the logged in user to populate updateBy attribute?
You can get logged user using $this->getConfigurationPool()->getContainer()->get('security.context')->getToken()->getUser(). In your case you need to do something like this:
public function setUpdatedByAttribute($car)
{
$user = $this->getConfigurationPool()->getContainer()->get('security.context')->getToken()->getUser();
$car->setUpdatedBy($user);
}
public function prePersist($car)
{
$this->setUpdatedByAttribute($car);
}
public function preUpdate($car)
{
$this->setUpdatedByAttribute($car);
}

Conditionally display form field in Symfony 3

I have an account (like company account) entity with a user association for the accountOwner.
Both account owner and users with ROLE_ADMIN can edit the account, but only users with ROLE_ADMIN can set the account owner.
Do I need 2 form types? or can I conditionally present the accountOwner field on the same form based on user role?
You can present accountOwner association conditionally.
When you want to modify form dynamically, you'll usually want to use form events.
However, since your form's fields do not depend on actual data bound to the form, but on security context, you can just inject authorization checker into your form type and check whether you want to add needed field:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('always_present_field');
$builder->add('another_always_present_field');
if ($this->authorizationChecker->isGranted('ROLE_ADMIN')) {
$builder->add('conditional_field_if_current_user_is_admin');
}
}

Updating an entity through Doctrine while it's persisted by a backend process

I've got an issue with Doctrine being somehow nasty with automagical tracking of entities and changes. I've got a UserManager which gets data for a new user from a form and sends the data to the backend which creates the corresponding database entries. As the backend is only inserting some basic data like username, I want to persist everything else like a collection of user roles given through the form.
So my method should look like this:
public function create(User $user)
{
$this->createUserInBackend($user);
$this->em->merge($user);
$this->em->persist($user);
$this->em->flush();
}
My issue now is that Doctrine either drops the data from the given $user and replaces it with the database content. This way I lose the chosen user roles. Without the merge() Doctrine tries an INSERT which is clearly not what I want.
I tried everything coming to my mind from fetching a managed copy before the merge, cloning or whatever. In all cases the objects are linked so I lose the data from the form (although their spl_object_hash differ).
Some more simplified details as requested:
class User
{
// Username is tracked by backend
private $username;
// Fullname is only tracked by frontend/Doctrine
private $fullname;
}
Variant 1:
public function create(User $user)
{
// The user entity gets passed to the backend, which does some stuff
// and also inserts the entity in the database.
$this->createUserInBackend($user);
// The entitiy is in the database, but not managed by the EM.
// Therefore Doctrine does an INSERT.
$this->em->persist($user);
$this->em->flush();
}
Variant 2:
public function create(User $user)
{
// The user entity gets passed to the backend, which does some stuff
// and also inserts the entity in the database.
$this->createUserInBackend($user);
// Now there's an entity in the db with ID and username, but not the fullname
$user = $this->em->merge($user);
// The merge finds the entry in the database and refreshes its data.
// This leads to $user->fullname which was given in the form to be emptied. :(
$this->em->persist($user);
$this->em->flush();
}
I also tried to put the return value from merge into an $otherUser variable, but the objects are linked and fullname still gets dropped.
I'd just need something to tell Doctrine that the new entity is managed, but it should not touch its data. I've looked into the underlying UnitOfWork, but couldn't find a trick to solve this.

What's the 'correct' way to include unrelated entities subset in a form?

Imagine three entities - Account, Address, Purchase. Account has a OneToMany relationship with Address. A Purchase is related to an Account, but not with an Address - it does however have a text field for the address (this is because addresses can change, I don't want the address directly related). On the users' account page they can add addresses. Whilst logged into the site, a Purchase id is stored in the session and used to retrieve the Purchase details when required.
What I want to do on the checkout page is display a list of all the addresses a user currently has in a <select>, allow them to pick one, and update the address in the current Purchase. $account->getAddresses() exists and will show the addresses relevant to the user.
I have read http://symfony.com/doc/current/reference/forms/types/collection.html and http://symfony.com/doc/current/cookbook/form/form_collections.html and can't see how to apply it to this situation, although an embedded form isn't really necessary - I don't want to change other details of the Purchase at that stage.
So my question is (at least one of): how do I pass the results of $account->getAddresses() to a form type? Or in the form type, should I use an entity field type, and if so, how do I get the custom query_builder to contain the current user in a form type? Or how else should I do this?
You need to pass the entity in to the Type's constructor and then use it to get the parameter.
Class YourType extends AbstractType
{
private $account;
public function __construct($account)
{
$this->account = $account;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$accountId = $account->getAccountId();
$builder->add('addressId',
'entity',
array('class' => 'YourBundle:Address',
'query_builder' => function(EntityRepository $er) use ($accountId) {
return $er->createQueryBuilder('a')
->where('a.accountId = ?1')
->setParameter(1, $accountId)));
}
}

Resources