Override bundle class silex authentification php - php

Here I began with Silex and I do not understand how to override a class.
I use a plugin to manage authentication.
Everything works, however I would like to change the checkPreAuth () method to verify the account from the user before authentication without change yhe bundle code.
To do this I made the steps below:
I created a class UserDAO to call the plugin which extends the native class.
But it doesn't work because I make a simple die('foo !') in the new method in UserDAO but apparently my method is not taken into account because the die('foo !') doesn't appear :-( someone there to help me :-)
Class UserDAO:
use MicroCMS\Domain\User;
use MicroCMS\PDO\PDOController as PDOController;
use PDO;
class UserDAO extends BaseUserChecker implements UserProviderInterface
{
public function __construct() {
}
/**
* {#inheritDoc}
*/
public function checkPreAuth(UserInterface $user){
die('je rentre dans cette fonction !');
}
public function checkPostAuth(UserInterface $user){
}
}
thanks in advance

Related

Register custom AttributeBag through CompilerPass

I am trying to tidy up my session variables by integrating custom AttributBags into the session. In Symfony < 6.0 you were able to inject a custom AttributBag into the session service.
See related questions
How to add extra bag to symfony session
Using Symfony AttributeBags in a Controller
However this approach does not work anymore in Symfony >= 6.0. This blog article explains that the session service is deprecated and must now be accessed over the request_stack service. For controllers this works fine.
My current (not working) approach looks like this: Define a custom AttributBag class.
class ShoppingCartBag extends AttributeBag {
public function __construct(string $storageKey = 'shoppingCart') {
parent::__construct($storageKey);
}
}
Add a custom CompilerPass in the Kernel class so that Symfony takes care of all changes while building the container.
class Kernel extends BaseKernel {
use MicroKernelTrait;
protected function build(ContainerBuilder $container): void {
$container->addCompilerPass(new AddShoppingCartBagToSessionService());
}
}
The custom CompilerPass looks like this.
class AddShoppingCartBagToSessionService implements CompilerPassInterface {
public function process(ContainerBuilder $container) {
$container->getDefinition('request_stack') //<- Works, but how to access the session?
->addMethodCall('getSession') // How to bridge the gap? This thought does not work. I assume it is because the session is not yet instantiated when the container is build.
->addMethodCall('registerBag', [new Reference('App\Session\CustomBag\ShoppingCartBag')]);
}
}
As you correctly assumed, the session does not exist yet when doing this via the compiler pass.
Symfony uses a so called SessionFactory to create the session. So what you can do instead, is decorating the existing session.factory service with your own implementation of the SessionFactoryInterface and add your attribute bag there:
An implementation of this decorated session factory might look like this:
namespace App;
use Symfony\Component\HttpFoundation\Session\SessionFactoryInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
class SessionFactoryWithAttributeBag implements SessionFactoryInterface
{
public function __construct(private SessionFactoryInterface $delegate)
{
}
public function createSession(): SessionInterface
{
$session = $this->delegate->createSession();
$session->registerBag(new ShoppingCartBag());
return $session;
}
}
And then you can decorate the session.factory via the services.yaml:
services:
App\SessionFactoryWithAttributeBag:
decorates: session.factory
arguments: ['#.inner']
Now, whenever a session is created, your custom bag is also registered
That was an important clue, thank you #Spea!
I adopted his idea and created a new decorator for the session service. After some trial and error I found an answer to my problem. The solution looks like this. Notice the actual syntax is slightly different from the answer given by Spea.
Create a custom AttributBag by extending the likewise named class. Be careful to set the name of the attribut bag, not the storage key in constructor. Otherwise Symfony will throw an error when you try to access the ShoppingCartBag.
namepsace App\Session;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
class ShoppingCartBag extends AttributeBag {
public function __construct() {
parent::__construct();
$this->setName('shoppingCart');
}
}
Create a decorator to change the session service's behaviour to get the desired result (include the ShoppingCartBag on each session).
namespace App\Decorator;
use App\Session\ShoppingCartBag;
use Symfony\Component\HttpFoundation\Session\SessionFactoryInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
class SessionFactoryShoppingCartBag implements SessionFactoryInterface {
public function __construct(private SessionFactoryInterface $delegate) {}
public function createSession(): SessionInterface {
$session = $this->delegate->createSession();
$session->registerBag(new ShoppingCartBag());
return $session;
}
}
Then decorate the session service in the services.yml by adding the following piece of code.
services:
App\Decorator\SessionFactoryShoppingCartBag:
decorates: session.factory
arguments: ['#.inner']

Override Laravel From Address on SendsPasswordResetEmails trait

How can I override the forgot password email from address field?
I'm using the SendsPasswordResetEmails trait.
It seems to be using the .env mail-from configuration
here is the trait vendor code SendsPasswordResetEmail Trait
sendResetLinkEmail method seems to be where the magic happens but i cannot determine how to override the mail send from the broker where is this function? sendResetLink
You can just copy the trait its code and past it in the PasswordBroker class to overwrite it if that's what you're asking.
I think you don't have to edit broker() just override sendResetLinkEmail() in your ForgetPasswordController. Then override $request->mail entry.
Anyway, the function you are looking for is at "\vendor\laravel\framework\src\Illuminate\Auth\Passwords\PasswordBroker.php" => sendResetLink()
I think what you are trying to do is set
MAIL_FROM_ADDRESS=sender#example.com
MAIL_FROM_NAME=Sender
in .env file and it should work fine, you do not need to override sendResetLinkEmail method.
There are a two methods I can think of that will achieve what you want.
1) In AppServiceProvider:
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
config()->set('mail.from.address', 'YOUR FROM ADDRESS HERE');
}
2) In Controller.php:
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function __construct()
{
config()->set('mail.from.address', 'YOUR FROM ADDRESS HERE');
}
}
Hope that helps!

Laravel "FatalErrorException in User.php line 8:"

What does this mean, and how do I fix it??
FatalErrorException in User.php line 8:
Class App\User contains 6 abstract methods and must therefore be declared abstract or implement the remaining methods (Illuminate\Contracts\Auth\Authenticatable::getAuthIdentifierName, Illuminate\Contracts\Auth\Authenticatable::getAuthIdentifier, Illuminate\Contracts\Auth\Authenticatable::getAuthPassword, ...)
It happened when I was trying to log into my dashboard for my laravel app.
This is about the interface implements. If you want to implement the interface, you need to mention all the methods which interface declared.
Illuminate\Contracts\Auth\Authenticatable
The interface definition:
interface Authenticatable {
public function getAuthIdentifierName();
public function getAuthIdentifier();
public function getAuthPassword();
public function getRememberToken();
public function setRememberToken($value);
public function getRememberTokenName();
}
So your User class must have the methods above.
class User implements Illuminate\Contracts\Auth\Authenticatable
{
public function getAuthIdentifierName() {}
public function getAuthIdentifier(){}
public function getAuthPassword(){}
public function getRememberToken(){}
public function setRememberToken($value){}
public function getRememberTokenName(){}
}
Even you do not want write code in those method, however, you still need to write empty method in your user class.
Solution:
The interface mainly used for Auth mechanism. If you do not want use for Auth, you just remove your Authenticatable interface from your User class.
If you need it use for Auth, you need to implement all the interface methods and get it right. More information please read the following websites:
Laravel doc: Custom User Provider and Authenticatable Class
How do I create a custom auth in laravel 5
Replacing the laravel authentication with a custom authentication

Laravel Use Eloquent model from custom UserServiceProvider

I'm new to Laravel, just toying with it and getting my head back into MVC.
I'm trying to make my own User auth provider (custom password hashing) as a service that implements the UserProviderInterface within Laravel.
Inside app/controllers/Account.php:
public function postCreate() {
Auth::attempt(Input::all());
}
I have my app routing Auth::attempt through my custom provider class, and passing me the Input::all from the form into a retrieveByCredentials method.
Inside app/services/PasswordHash/PasswordHashUserProvider.php:
public function retrieveByCredentials(array $credentials) {
// Why can't I do this?
//Error: PasswordHash/User not found
User::find($credentials['username']);
dd($credentials);
}
I am lost at this point on how to access my User eloquent models from within this service class. I tried namespaces but had no luck.
The boot method on service providers use the service container to inject dependencies. To that end, you should be able to do the following (not using Facades, but I don't use facades that often).
class PasswordHashUserProvider extends ServiceProvider
{
protected $user;
public function boot(User $user)
{
$this->user = $user;
}
}
You can then access user via $this->user
Source: https://laravel.com/docs/master/providers#the-boot-method

Symfony2 - How to use __construct() in a Controller and access Securty.Context?

I am having some trouble with Symfony2. Namely in how to use the __construct() function. the Official Documentation is shockingly bad!
I want to be able to use the following:
public function __construct()
{
parent::__construct();
$user = $this->get('security.context')->getToken()->getUser();
}
How ever I get the following error:
Fatal error: Cannot call constructor in /Sites/src/DEMO/DemoBundle/Controller/Frontend/HomeController.php on line 11
Line 11 is "parent::__construct();"
I removed it and got the following, new error
Fatal error: Call to a member function get() on a non-object in /Sites/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php on line 242
I think I might need to set up the ContainerInterface DIC, but I have no idea how to do this (I tried and failed, miserably)
Any ideas folks?
Update - Tried changing to extend ContainerAware and got this error:
Fatal error: Class DEMO\DemoBundle\Controller\Frontend\HomeController cannot extend from interface Symfony\Component\DependencyInjection\ContainerAwareInterface in /Sites/src/DEMO/DemoBundle/Controller/Frontend/HomeController.php on line 43
Using the following code in the controller:
<?php
namespace DEMO\DemoBundle\Controller\Frontend;
use Symfony\Component\DependencyInjection\ContainerAware;
class HomeController extends ContainerAwareInterface
{
protected $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
I'm assuming you are extending the default Symfony controller? If so, a look at the code will reveal the answer:
namespace Symfony\Bundle\FrameworkBundle\Controller;
use Symfony\Component\DependencyInjection\ContainerAware;
class Controller extends ContainerAware
{
Notice that there is no Controller::__construct defined so using parent::__construct will not get you anywhere. If we look at ContainerAware:
namespace Symfony\Component\DependencyInjection;
class ContainerAware implements ContainerAwareInterface
{
protected $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
}
Again, no constructor and the container is not available until setContainer is called. So override setContainer and put your logic there. Or else just make a stand alone controller that does not extend the base controller class and inject your dependencies directly into the constructor.
Update Aug 2017
Still getting a few hits on this. If you really want to execute something before each controller then use a kernel controller listener. If all you need is the user then of course use getUser(). And please don't override setContainer(). In some cases it would work but it would just convolute your code.
I also frequently want an instance of the current User in most of my controllers. I find it is easiest to just do something like this:
class SomeController extends Controller
{
protected $user;
public function getUser()
{
if ($this->user === null) {
$this->user = $this->get('security.context')->getToken()->getUser();
}
return $this->user;
}
}
However, this is an overly simplistic example case. If you want to do more work before a Controller action is started, I suggest you define your Controller as a Service.
Also take a look at this article: Moving Away from the Base Controller
I have to retrieve the 'facade' manager for my rest api's resource. Not using the constructor and using a private function seems the easiest and simplest for me.
/**
* Class ExchangesController
* #RouteResource("Exchange")
*/
class ExchangesController extends Controller
{
/**
* Get exchange manager
* #return ExchangeManager
*/
protected function getExchangeManager()
{
return $this->get('exchange_manager');
}
/**
* #ApiDoc(
* description="Retrieve all exchanges",
* statusCodes={
* 200="Successful"
* }
* )
*/
public function cgetAction()
{
return $this->getExchangeManager()->findAll();
}
PS It's ok for me to use private/protected functions in my controller as long as it contains zero conditionals
You cannot call getUser() or get() for services in controller constructors. If you remember that, you will save lots of debugging time.
I know the question is very old, but I didn't found an answer until now. So I'll share it.
The goal here, is to execute a code everytime a action in our controller is called.
The __construct method doesn't work, because it's called before anything else, so you can't access the service container.
The trick is to overload each method automatically when they are called :
<?php
namespace AppBundle\DefaultController;
class DefaultController extends Controller {
private function method1Action() {
return $this->render('method1.html.twig');
}
private function method2Action() {
return $this->render('method2.html.twig');
}
public function __call($method, $args) {
$user = $this->get('security.tokenStorage')->getToken()->getUser();
// Do what you want with the User object or any service. This will be executed each time before one of those controller's actions are called.
return call_user_func_array(array($this, $method), $args);
}
}
Warning ! You have to define each method as a private method ! Or the __call magic method won't be called.
There are only two solutions to this problem:
Use a private method as pointed out by #Tjorriemorrie here. But this is a dirty method for purists. (I'm using this! :D );
Define the controller as a service, but this way you will lose all the shortcuts provided by Symfony\Bundle\FrameworkBundle\Controller\Controller. Here is the article that shows how to do this.
As told, personally, in my situation, I prefere a solution like this:
class MyController extends Controller
{
/** #var AwesomeDependency */
private $dependency;
public function anAction()
{
$result = $this->getDependency();
}
/**
* Returns your dependency.
*/
private function getDependency()
{
if (null === $this->dependency)
$this->dependency = $this->get('your.awesome.dependency');
return $this->dependency;
}
}
This is typically a class that I call MyManager where I put the code that I use in more than one action in the controller or that unusefully occupies lines (for example the code to create and populate forms, or other code to do heavy tasks or tasks that require a lot of code).
This way I mantain the code in the action clear in its purposes, without adding confusion.
Maybe the use of a property to store the dependency is an overoptimization, but... I like it :)
As i see, Controller extends ContainerAware, and if we take a look of ContainerAware it implements ContainerAwareInterface. So, ContainerAware must have declared the exact methods in it's interface. Add this line
public function __construct();
to the ContainerAwareInterface definition and it will be solved.

Categories