Hash user password without User instance in symfony - symfony

As it can be read in the official documentation, the current procedure to manually hash a password in the Symfony framework, is the following:
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
public function register(UserPasswordEncoderInterface $encoder)
{
// whatever *your* User object is
$user = new App\Entity\User();
$plainPassword = 'ryanpass';
$encoded = $encoder->encodePassword($user, $plainPassword);
$user->setPassword($encoded);
}
The encodePassword method requires an User instance to be passed as its first argument. The User instance must therefore pre-exist when the method is called: this means that a 'User' must be instantiated without a valid hashed password. I'd like the password to be provided as a constructor argument instead, so that an User entity is in a valid state when it is created.
Is there an alternative way of hashing the password using Symfony?

Update for Symfony 5 and later. The Encoder stuff was renamed to Hasher. The answer still works but just replace EncoderFactoryInterface with PasswordHasherFactoryInterface and change your variable names to hasher.
The UserPasswordEncoder uses what is known as an EncoderFactory to determine the exact password encoder for a given type of user. Adjust your code to:
public function register(EncoderFactoryInterface $encoderFactory)
{
$passwordEncoder = $encoderFactory->getEncoder(User::class);
$hashedPassword = $passwordEncoder->encodePassword($plainPassword,null);
And that should work as desired. Notice that getEncoder can take either a class instance or a class name.
Also note the need to explicitly send null for the salt. For some reason, some of the Symfony encoder classes do not have default values for salt yet.

Related

User current Locale inside entity OR trait

How can we access to current user local inside entity or Trait ?
namespace App\Entity;
class Activities
{
use Translation;
public $locale;
public function __construct(**PUT User locale**)
{
$this->locale = **PUT User locale**
}
}
You can't do that, because the locale is stored into the Request object which should'nt be accessed from an entity.
So if you really need that locale, you should pass it as an argument.
I suggest you to look around the Doctrine extension documentation for translating entities.
You'll see that it's better than just passing the user locale each time.
In fact, it is using event listener to pass the locale to the Translation component.

Is it possible to validate a property using data-annotation asynchronously with ASP.NET Core?

I have an asp.net core 3.1 based project. I need to add a custom validation rule that will require a database call in ordered to determine the validity of the value.
For example, when creating a new user, I need to validate that there is no other username in the database with the same username before allowing the user to be created.
If I can create a custom attribute UniqueUsername, then I should be able to do something like this
public class UniqueUsername : ValidationAttribute
{
private readonly UserManager _manager = manager;
public UniqueUsername (UserManager manager)
{
_manager = manager;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
string username = value.ToString();
if(_manager.Exists(username))
{
return new ValidationResult("The username provided belong to a different user.");
}
return ValidationResult.Success;
}
}
But, _manager.Exists(username) is a synchronous call. I want to avoid blocking the main thread, so I want a way to call await _manager.ExistsAsync(username) instead to avoid blocking the main thread.
Is there a way to create an attribute that would validate a single property and write errors "if any" to the ModelState?
If this isn't possible using data-annotation, is there an different way to validate property while writting errors to ModelState so when ModelState.IsValid() or TryValidateModel(model) are called, the attribute is called?
The data-annotations you add in your model are meant to validate the data present within the model (although some can also be translated into your database). These are meant to be reused even if you were to use your models on a client framework.
You can use the ModelState functions you mentioned to make async calls to your database. If you want to remove the logic from your controller, you can create utility functions to do so.
If you are open to third-party libraries, there is a great and popular validations library called Fluent Validation. Here is a documentation on how you can make async calls with it: https://docs.fluentvalidation.net/en/latest/async.html

Get the user in a RouteProviderInterface implementation

Is it possible to get the user in a RouteProviderInterface implementation?
My RouteProviderInterface implementation loads a number of new Routes, nothing special. But I want to customize the Routes based on a user setting, if a user is logged in.
If I inject the TokenStorage, the user is not loaded and null:
public function __construct(TokenStorage $tokenStorage) {
$this->user = $tokenStorage->getToken()->getUser(); // is null
}
Is there another way to get the user?
Some edit based on comments:
I am trying this with a authenticated user. I also dump the user in the actual controller being used and the user does exists there
All firewalls have "stateless: true" in the config

sfUser equivalent in Symfony 2

What is the sfUser equivalent in Symfony 2?
sfUser allowed getting user session attributes using getAttribute() method.
Is Symfony\Component\Security\Core\User\User its equivalent? But it doesn't have getAttribute() method in it.
To get session attributes, get the session service from the container. This example is in a controller, where the session is available via a helper method:
public function fooAction()
{
$session = $this->getRequest()->getSession();
// Setting
$session->set("foo", "bar");
// Retrieving
$foo = $session->get("foo");
}
See the documentation for details. You can also retrieve the session explicitly from the container should you need it, via $container->get("session");
If you need the User object, you can get it via:
public function fooAction()
{
// Get user from security token (assumes logged in/token present)
$user = $this->get("security.context")->getToken()->getUser();
}
Again, see the documentation for further details.

How do I set query cache on a call issued by the seam engine

#In
Identity identity;
Boolean newValue = identity.hasPermission(target, action);
Any call to the above method also does a "select role from Role r" call, which is called from the underlying seam engine. How do I set the query cache for this call as a query hint (e.g. org.hibernate.cacheable flag) so that it doesn't get called again.
Note: Role information is never bound to change, hence I view this as a unnecessary sql call.
I am not in hibernate, but as this question is still unanswered: we extended the standard Identity class of seam for several reasons. You might want to extend it as well to help you caching the results.
As this cache is session scoped, it will have the possible benefit that it will be reloaded when the user logs on/off again - but this depends on your requirements.
Best regards,
Alexander.
/**
* Extended Identity to implement i.e. caching
*/
#Name("org.jboss.seam.security.identity")
#Scope(SESSION)
#Install(precedence = Install.APPLICATION)
#BypassInterceptors
#Startup
public class MyIdentity extends Identity {
// place a concurrent hash map here
#Override
public boolean hasPermission(Object name, String action) {
// either use the use the cached result in the hash map ...
// ... or call super.hasPermission() and cache the result
}
}

Resources