Silex default_target_path not working after successful login - forms

I've got a problem ith redirect after successful login.
App.php file (part of it):
<?php
use Silex\Application;
/** ... */
use Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder;
$app = new Application();
/** ... */
$app['security.encoder.digest'] = $app->share(function ($app) {
return new PlaintextPasswordEncoder();
});
$app['security.firewalls'] = array(
'secured' => array(
'pattern' => '^/admin/',
'form' => array(
'login_path' => '/login',
'check_path' => '/admin/login_check',
'default_target_path' => '/admin/news',
'always_use_default_target_path' => true,
),
'logout' => array(
'logout_path' => '/admin/logout',
),
'users' => array(
'admin' => array('ROLE_ADMIN', 'test'),
),
),
);
My controllers.php file:
<?php
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
$app->get('/login', function(Request $request) use ($app) {
return $app['twig']->render('login.html.twig', array(
'error' => $app['security.last_error']($request),
'last_username' => $app['session']->get('_security.last_username'),
));
});
$app->get('/admin/news', function(Request $request) use ($app) {
if ($app['security.authorization_checker']->isGranted('ROLE_ADMIN')) {
echo 'admin';
}
});
I am logged in (after passing correct login data in form), I have access to /admin/news route, but I have to go to that address manually. I'd like to be redirected there automatically after successful login. Now I'm kept in /login page. When I change default_target_path to 'http://google.com', it works properly.
I use homestead (vagrant) with nginx. Silex 1.3.0.
I'll appreciate any help.

The solution (or rather workaround) which worked was:
change 'default_target_path' to '/admin';
add new route:
$app->get('/admin', function() use ($app) {
return $app['twig']->render('admin/loggedIn.html.twig');
});
in admin/loggedIn.html.twig template I've added js redirect to admin/news
I don't have any idea why wasn't it working. If anyone knows - please leave a comment.

Related

Laravel 5.3 - redirect after login

I am trying to redirect user to /admin/magazines after login instead of to /. I have tried with changing the $redirect variable in Auth\LoginController, tried with also changing the function handle in Middleware\RedirectIfAuthenticated, and also with putting the function into LoginController like this:
public function authenticate()
{
if (Auth::attempt(['email' => $email, 'password' => $password])) {
// Authentication passed...
return redirect()->intended('/admin/magazines');
}
}
But nothing worked, every time after a login I have been redirected to /
This is my routes file:
Route::get('/', ['as' => 'home', 'middleware' => 'auth', 'uses' => 'HomeController#index']);
Auth::routes();
//Backend admin routes...
Route::group(['middleware' => 'auth', 'prefix' => 'admin', 'namespace' => 'Admin'], function() {
Route::resource('magazines', 'MagazinesController');
});
in Auth/LoginController there is protected $redirectTo = '/home';
just change '/home' to '/admin/magazine'. and with this every time a user login it will redirect him to this URL.

Symfony2 form refresh same page after submit

I have a form whose content is created from a DB.
in my controller i have:
/**
* #Route("/HR/manage/{projectID}", name="hr_manage")
*/
public function manageHRAction(Request $request, $projectID)
{
//here I get all the data from DB and create the form
if ($form->isValid())
{
//here I do all the relevant changes in the DB
return $this->render('HR/show.html.twig', array('hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
return $this->render('HR/show.html.twig', array('hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
It updates the info on the DB properly, but it does not build again the form with updated data. Instead of the return inside the "isValid()" I simply need a refresh on the current page.
I assume it's possible and easy to accomplish, but I failed to find how to do it :/
EDIT - here comes more relevant code:
/**
* #Route("/HR/manage/{projectID}", name="hr_manage")
*/
public function manageHRAction(Request $request, $projectID)
{
$user = $this->container->get('security.context')->getToken()->getUser(); //get current user
$em = $this->getDoctrine()->getManager(); //connect to DB
$prj = $this->getDoctrine()->getRepository('AppBundle:Project')->findOneById($projectID);
[...]
// here comes some code to generate the list of $HRsInThisProject and the list of roles ($rolesListForForm)
[...]
foreach ($HRsInThisProject as $key => $HR)
{
$form->add('roleOf_'.$key, 'choice', array('choices' => $rolesListForForm, 'required' => true, 'data' => $HR['role'], 'label' => false, ));
$form->add('isActive_'.$key, 'choice', array('choices' => [0 => 'Inactive', 1 => 'Active'] , 'required' => true, 'data' => $HR['is_active'], 'label' => false, ));
}
[...]
// here there is some code to get the $HRsInMyDomainForForm
[...]
$form->add('HRid', 'choice', array('choices' => $HRsInMyDomainForForm,'required' => false, 'placeholder' => 'Choose a resource', 'label' => false, ));
$form->add('role', 'choice', array('choices' => $rolesListForForm,'required' => false, 'placeholder' => 'Choose a role', 'label' => false, ));
$form->add('save', 'submit', array('label' => 'Save'));
$form->handleRequest($request);
if ($form->isValid())
{
{
[...] here there is a huge portion of code that determines if I need to generate a new "event" to be stored, or even multiple events as I can change several form fields at once
// If I needed to create the event I persist it (this is inside a foreach)
$em->persist($newHREvent);
}
$em->flush();
return $this->render('HR/show.html.twig', array('projectID' => $prj->getId(), 'hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
return $this->render('HR/show.html.twig', array('projectID' => $prj->getId(), 'hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
I also include a screenshot of the form:
If a user selects to add a new resouce, I need to persist it to DB (and that is done properly) but then I need to see it in the list of available HRs, without the need for the user to reload the page.
More dynamic way would be:
$request = $this->getRequest();
return $this->redirectToRoute($request->get('_route'), $request->query->all());
or simply
return $this->redirect($request->getUri());
I managed to solve it in a simple (and I hope correct) way.
I simply substituted the "render" inside the isValid() with the following:
return $this->redirect($this->generateUrl('hr_manage', array('projectID' => $prj->getId())));
I works, but does anybody foresee problems with this solution?
You have to link the form to the request.
$entity = new Entity();
$form = $this->createFormBuilder($entity)
->add('field1', 'text')
->add('field2', 'date')
->add('save', 'submit', array('label' => 'Submit'))
->getForm();
$form->handleRequest($request); // <= this links the form to the request.
only after that you test $form->isValid() and pass this form when rendering the template. If you already did this and haven't included in the code above please show more code for better help.
Here is the right way to do it. Event though you have $projectId slug, in Action you can pass whole Object, in this case Project. Symfony will take care for the rest (fetching right Project entity for you.
/**
* #Route("/HR/manage/{projectID}", name="hr_manage")
*/
public function manageHRAction(Request $request, Project $project)
{
$form = $this->createForm(new ProjectType(), $project);
$form->handleRequest($request);
// ... your business logic or what ever
//here I get all the data from DB and create the form
if ($form->isValid() && $form->isSubmitted()) {
$em->persist($project);
// no need to flush since entity already exists
// no need to redirect
}
// here $form->createView() will populate fields with data since you have passed Poroject $project to form
return $this->render('HR/show.html.twig', array('hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'project' => $prj, ));
}
Update
According to your edit, you need to use javascript for client-side dom manipulation. Check this link from Symfony official document embedded forms. Here you'll find an example of what you're trying to accomplish.

Zend Framework 2 - Gobal Variable that are accessible to controller/model that are initialize in local.php or global.php

Hello everyone please someone help me how to create a global variable in zend framework 2 to be use in table prefix that are accessible in controller and model.
Thanks and regards to all.
In your config/database.local.php you can define which you want globally
<?
return array(
'service_manager' => array(
'factories' => array(
//'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
'Zend\Db\Adapter\Adapter' => function ($serviceManager) {
$adapterFactory = new Zend\Db\Adapter\AdapterServiceFactory();
$adapter = $adapterFactory->createService($serviceManager);
\Zend\Db\TableGateway\Feature\GlobalAdapterFeature::setStaticAdapter($adapter);
return $adapter;
}
),
),
'db' => array(
'driver' => 'pdo',
'dsn' => 'mysql:dbname=testdb;host=localhost',
'username' => 'root',
'password' => '',
),
'msg' => array(
'add' => 'Data Inserted Successfully',
'edit' => 'Data Updated Successfully',
'delete' => 'Data Deleted Successfully',
),
);
?>
Controller File:
DemoController.php
<?php
namespace Demo\Controller;
use Zend\Mvc\Controller\AbstractActionController;
class DemoController extends AbstractActionController
{
public function indexAction($cms_page_name='whyus')
{
/*Call config file to fetch current cms page id-- fetch config file from database.local.php*/
$config = $this->getServiceLocator()->get('Config');
$all_msg = $config['msg'];
}
}
?>

Can't get Auth login to work with CakePHP 2.0

I'm trying to get a simple login form to work using CakePHP 2.0... just Auth, no ACLs for now.
I'm able to see the form and enter the email and password as they are in the database, but I just get returned to the form and the flash error message is displayed. Here is my code:
AppController:
class AppController extends Controller
{
function beforeFilter()
{
$this->Auth->userModel = 'Users';
$this->Auth->fields = array('username' => 'email', 'password' => 'password'); //have to put both, even if we're just changing one
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'hotels', 'action' => 'dashboard');
$this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
}
}
login.ctp:
<?php
echo $this->Form->create('User', array('action' => 'login'));
echo $this->Form->input('email');
echo $this->Form->input('password');
echo $this->Form->end('Login');
?>
UsersController:
class UsersController extends AppController
{
var $name = 'Users';
var $helpers = array('Html','Form');
var $components = array('Auth','Session');
function beforeFilter()
{
$this->Auth->allow("logout");
parent::beforeFilter();
}
function index() { } //Redirects to login()
function login()
{
if ($this->Auth->login())
{
$this->redirect($this->Auth->redirect());
} else
{
$this->Session->setFlash(__('Invalid username or password, try again'));
}
}
function logout()
{
$this->redirect($this->Auth->logout());
}
}
?>
I appreciate any help with this. Thanks!
The "Invalid username or password, try again" error is displayed after you hit login?
There are a few things you should check:
• Is the output of $this->Auth->login() identical to the information in your database? Put debug($this->Auth->login()) to see the output in your login method after the form is submitted.
• Are the passwords correctly hashed in the database?
• Try making the AuthComponent available to all your controllers not just the UsersController.
• Not sure if this makes a difference, but call parent::beforeFilter(); before anything else in your controller's beforeFilter method.
EDIT:
Is see that you're trying to validate based on email and password. As a default AuthComponent expects a username and password. You have to explicitly state that you want the email and password to be validated by $this->Auth->login(). This comes from the 2.0 documentation:
public $components = array(
'Auth'=> array(
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'email')
)
)
)
);
The fact that you're not seeing any SQL output is to be expected, I believe.
Also you must check if your field "password" in database is set to VARCHAR 50.
It happens to me that I was truncating the hashed password in DB and Auth never happened.
if you are not using defalut "username", "password" to auth, you cant get login
e.g., you use "email"
you should edit component declaration in your controller containing your login function:
$component = array('Auth' => array(
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'email', 'password' => 'mot_de_passe')
)
)
));
Becareful with cakephp's conventions. You should change this "$this->Auth->userModel = 'Users';" to "$this->Auth->userModel = 'User';" because User without plural is the Model's convention in cake. That worked for me and also becareful with the capital letters. it almost drived me crazy. Good luck.
public $components = array(
'Session',
'Auth' => array(
'loginRedirect' => array(
'controller' => 'Events',
'action' => 'index'
),
'logoutRedirect' => array(
'controller' => 'Users',
'action' => 'login',
'home'
),
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'username','password' => 'password')
)
)
)
);
Editing the component declaration in AppController did the trick for me. If you have the fields named other than "username" and "password" you should always specify them. In your case it would be
public $components = array(
'Auth' => array(
'authenticate' => array(
'Form' => array(
'passwordHasher' => 'Blowfish',
'fields' => array('username' => 'email','password' => 'password')
)
)
)
);
There is a bug in the cakephp tutorial.
$this->Auth->login() should be changed to
$this->Auth->login($this->request->data)

Building a modular Website with Zend Framework: Am I on the right way?

I´m a little bit confused by reading all the posts and tutorials about starting with Zend, because there a so many different ways to solve a problem.
I just need some feedback about my code to know if I am on the right track.
To simply get a (hard coded) Navigation for my site (depending on who is logged in) I build a Controller Plugin with a postDispatch method:
public function postDispatch(Zend_Controller_Request_Abstract $request)
{
$menu = new Menu();
//Render menu in menu.phtml
$view = new Zend_View();
//NEW view -> add View Helper
$prefix = 'My_View_Helper';
$dir = dirname(__FILE__).'/../../View/Helper/';
$view->addHelperPath($dir,$prefix);
$view->setScriptPath('../application/default/views/scripts/menu');
$view->menu = $menu->getMenu();
$this->getResponse()->insert('menu', $view->render('menu.phtml'));
}
Is it right that I need to set the helper path again?
I did this in a Plugin Controller named ViewSetup. There I do some setup for the view like doctype, headlinks, and helper paths (This step is from the book: Zend Framework in Action).
The Menu class which is initiated looks like this:
class Menu
{
protected $_menu = array();
/**
* Menu for notloggedin and logged in
*/
public function getMenu()
{
$auth = Zend_Auth::getInstance();
$view = new Zend_View();
//check if user is logged in
if(!$auth->hasIdentity()) {
$this->_menu = array(
'page1' => array(
'label' => 'page1',
'title' => 'page1',
'url' => $view->url(array('module' => 'pages','controller' => 'my', 'action' => 'page1'))
),
'page2' => array(
'label' => 'page2',
'title' => 'page2',
'url' => $view->url(array('module' => 'pages','controller' => 'my', 'action' => 'page2'))
),
'page3' => array(
'label' => 'page3',
'title' => 'page3',
'url' => $view->url(array('module' => 'pages','controller' => 'my', 'action' => 'page3'))
),
'page4' => array(
'label' => 'page4',
'title' => 'page4',
'url' => $view->url(array('module' => 'pages','controller' => 'my', 'action' => 'page4'))
),
'page5' => array(
'label' => 'page5',
'title' => 'page5',
'url' => $view->url(array('module' => 'pages','controller' => 'my', 'action' => 'page5'))
)
);
} else {
//user is vom type 'client'
//..
}
return $this->_menu;
}
}
Here´s my view script:
<ul id="mainmenu">
<?php echo $this->partialLoop('menuItem.phtml',$this->menu) ?>
</ul>
This is working so far. My question is: is it usual to do it this way; is there anything to improve?
I´m new to Zend and I've seen deprecated tutorials on the web which often are not obvious. Even the book is already deprecated where the autoloader is mentioned.
You shouldn't be creating a new view. Since you have already created the View object in your Boostrap (and used it to render the rest of the site) you should fetch the already created view object.
If you are using Zend_Application_Resource to setup your view in the bootstrap you can fetch it like this:
$view = Zend_Controller_Front::getInstance()
->getParam('bootstrap')
->getResource('view');
This way there is no need to set the view helper path again and create another view object.
If you are not using the Zend_Application to boostrap your app you could try something like this:
$view = Zend_Layout::getMvcInstance()->getView();
Unless you are working on a relatively small side, I wouldn't do this in the controller,
since you will have to add this to many controllers.
Why not check in the bootstrap or even checking in your layout would make more sense to me although it wouldn't be proper.