I'm creating an E-Commerce website using CakePHP 3
I need to create an Admin page that will allow the Admin to upload
products and possibly view a few KPI's etc..
Is there a way in Cake to have a User (general customer shopping on the site) and a Superuser (or Admin) at the same time? I have an 'is_admin' column in my Users table to differentiate between admin and user. Do I just need to have something like this in my addProducts function or is there a better way?:
public function addProducts(){
$user = $this->Auth->user();
if($user['is_admin']) {
//allow access
} else {
//throw anauthorised exception
}
}
Thanks in advance
You can manage it via different URL's for admin and front User. This can be managed via the routes and the APP Controller.
What I am using for one of my appplication is as below:
In the routes.php file
Router::prefix('admin', function ($routes) {
// All routes here will be prefixed with `/admin`
// And have the prefix => admin route element added.
$routes->fallbacks('DashedRoute');
$routes->connect('/', array('controller' => 'Users', 'action' => 'login'));
/* Here you can define all the routes for the admin */
});
Router::scope('/', function ($routes) {
$routes->connect('/', array('controller' => 'Users', 'action' => 'login', 'home'));
/* Here you can define all the routes for the frontend */
});
Please note for the Admin you need to create a directory in all /src/Controller, /src/Template named as "Admin" and within these directories you can use the same structure that we use in our code.
Now comes the code that needs to be written in /src/Controller/AppController.php
public $prefix = '';
public function initialize()
{
$this->prefix = (!empty($this->request->params['prefix'])?$this->request->params['prefix']:'');
$this->set('prefix',$this->prefix);
if( !empty($this->prefix) && $this->prefix==='admin' )
{
$this->loadComponent('Auth', [
'loginAction' => [
'controller' => 'Users',
'action' => 'login',
'prefix'=>'admin'
],
'loginRedirect' => [
'controller' => 'Users',
'action' => 'index',
'prefix'=>'admin'
],
'logoutRedirect' => [
'controller' => 'Users',
'action' => 'login',
'prefix'=>'admin'
],
'authError' => 'Did you really think you are allowed to see that?',
'authenticate' => [
'Form' => [
'finder' => 'admin',
'fields' => ['username' => 'email', 'password' => 'password']
]
],
'storage' => ['className' => 'Session', 'key' => 'Auth.Admin']
]);
}
else
{
$this->loadComponent('Auth', [
'loginAction' => [
'controller' => 'Users',
'action' => 'login'
],
'loginRedirect' => [
'controller' => 'Users',
'action' => 'myaccount'
],
'logoutRedirect' => [
'controller' => 'Users',
'action' => 'login'
],
'authError' => 'Did you really think you are allowed to see that?',
'authenticate' => [
'Form' => [
'finder' => 'user',
'fields' => ['username' => 'email', 'password' => 'password']
]
],
'storage' => ['className' => 'Session', 'key' => 'Auth.User']
]);
}
}
Here you can see that we are using different keys for the storage Auth.User and Auth.Admin
For the finder you need to write the below code in your user model table located at src\Model\Table\UsersTable.php
public function findAdmin(\Cake\ORM\Query $query, array $options)
{
$query
->select(array('Users.email', 'Users.password','Users.id','Users.role_id'))
->where(array('Users.role_id' => 1));
return $query;
}
public function findUser(\Cake\ORM\Query $query, array $options)
{
$query
->select(array('Users.email', 'Users.password','Users.id','Users.role_id'))
->where(array('Users.status' => 1,'Users.role_id' => 3));
return $query;
}
Note, Here I am keeping role_id "1" for Admin and "3" for front Users.
In this manner, even you can set the login for both in the same browser as key for both the user types is different.
Hope this helps you setup the structure accordingly.
Related
After logging a user in, I want to redirect them back to where they came from but It's not working properly in CakePHP 3.5. Here are the required info's to help me figure out this problem.
URL while login(session time out),
http://dev.scys.com/db/admin?redirect=%2Fadmin%2Fstatuses
This is my Auth config,
$this->loadComponent('Auth', [
'loginAction' => ['controller' => 'Admins', 'action' => 'login'],
'loginRedirect' => ['controller' => 'Admins', 'action' => 'index'],
'logoutRedirect' => ['controller' => 'Admins', 'action' => 'login'],
'unauthorizedRedirect' => $this->referer(),
'authenticate' => [
'Form' => [
'finder' => 'auth',
'userModel' => 'Admins',
'fields' => ['username' => 'username', 'password' => 'password']
]
]
]);
And in the Login method/action
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
}
More Points
I have also tried $this->redirect($this->request->getQuery('redirect'));
Am I missing anything or something else I have to add to work this out :(
I figured out my mistake,
Actually, I was using for action URL like,
$this->Form->create(NULL, ['url'=> ['controller' => 'Admins', 'action' => 'login'],'style'=>'display: block;');
Because of this, the URL became "admins/login" and the redirect query string get removed that's why the problem occurred, because "$this->redirect($this->Auth->redirectUrl());" didn't find any redirect query string(as per the case 1), so it uses $this->Auth->config('loginRedirect');(as per case 2).
Then I solve it by removing the URL key and value from the form create option parameter.
I'm trying to redirect to current page after logged in, using cakephp 3.4 but I'm getting like this
localhost page isn't working, locahost page redirecting you too many
times. Try clearing your cookies
for 2 sec after that it's redirecting to home page. Please help me out here.
Here my code
In appController.php
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Flash');
$this->loadComponent('Auth', [
'authorize' => ['Controller'],
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'email',
'password' => 'password'
],
'scope' => ['userStatus' => '1']
]
],
'loginAction' => [
'controller' => 'Users',
'action' => 'login'
],
'unauthorizedRedirect' => $this->referer(),
'logoutRedirect' => [
'controller' => 'Users',
'action' => 'login'
]
]);
}
In loginController.php
function login{
if ( $this->request->is( 'post' ) ) {
if ( $this->Auth->login() )
{
$this->redirect($this->referer());
}
else {
$this->Flash->error(__('Your username or password is incorrect.'));
}
}
}
Looks like you got some redirect loop here. You should use AuthComponent::redirectUrl().
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
} else {
$this->Flash->error(__('Username or password is incorrect'));
}
}
}
See the Redirecting Users After Login in the Documentation.
After logging a user in, you’ll generally want to redirect them back
to where they came from. Pass a URL in to set the destination a user
should be redirected to after logging in.
If no parameter is passed, the returned URL will use the following
rules:
Returns the normalized URL from the redirect query string value if it
is present and for the same domain the current app is running on.
Before 3.4.0, the Auth.redirect session value was used.
If there is no query string/session value and there is a config loginRedirect, the loginRedirect value is returned.
If there is no redirect value and no loginRedirect, / is returned.
Use $this->Auth->redirectUrl() instead of $this->referer().
After logging a user in, you’ll generally want to redirect them back to where they came from. Pass a URL in to set the destination a user should be redirected to after logging in.
Returns the normalized URL from the redirect query string value if it is present and for the same domain the current app is running on. Before 3.4.0, the Auth.redirect session value was used.
If there is no query string/session value and there is a config loginRedirect, the loginRedirect value is returned.
If there is no redirect value and no loginRedirect, / is returned.
Add to your AuthComponent configuration options:
loginRedirect
The URL (defined as a string or array) to the controller action users
should be redirected to after logging in. This value will be ignored
if the user has an Auth.redirect value in their session.
Your code should be like that:
In appController.php
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Flash');
$this->loadComponent('Auth', [
'authorize' => ['Controller'],
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'email',
'password' => 'password'
],
'scope' => ['userStatus' => '1']
]
],
'loginAction' => [
'controller' => 'Users',
'action' => 'login'
],
'unauthorizedRedirect' => $this->referer(),
'logoutRedirect' => [
'controller' => 'Users',
'action' => 'login'
],
'loginRedirect' => [
'controller' => 'Pages',
'action' => 'display'
]
]);
}
In loginController.php
function login{
if ( $this->request->is( 'post' ) ) {
if ( $this->Auth->login() )
{
$this->redirect($this->Auth->redirectUrl());
}
else {
$this->Flash->error(__('Your username or password is incorrect.'));
}
}
}
See also Redirecting Users After Login
I have cakephp 3 aplication with social login plugin, hybridauth.
Sometimes works login over face and over google but sometimes i get error like these:
In 'hybridauth' instructions there is line:
Note: When specifying loginRedirect URL for AuthComponent be sure to add 'plugin' => false (or appropiate plugin name) to the URL array.
Probably i did something wrong in my appcontroller. It looks like:
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'email',
'password' => 'password'
]
],
'ADmad/HybridAuth.HybridAuth' => [
// All keys shown below are defaults
'fields' => [
'provider' => 'provider',
'openid_identifier' => 'openid_identifier',
'email' => 'email'
],
'profileModel' => 'ADmad/HybridAuth.SocialProfiles',
'profileModelFkField' => 'user_id',
// The URL Hybridauth lib should redirect to after authentication.
// If no value is specified you are redirect to this plugin's
// HybridAuthController::authenticated() which handles persisting
// user info to AuthComponent and redirection.
'hauth_return_to' => null
]
],
'loginRedirect' => [
'controller' => 'Users',
'action' => 'index',
'ADmad/HybridAuth.HybridAuth' => 'false'
'plugin' => 'false'
],
'logoutRedirect' => [
'controller' => 'Users',
'action' => 'login',
'home'
]
]);
Like you can see i try to ad lines to main 'loginRedirect' but there is same problem again.
'ADmad/HybridAuth.HybridAuth' => 'false'
'plugin' => 'false'
any idea please?
Thank you.
Even i can login sometimes. randomly.
And every time when i push face or google login i get session-Auth. I am authenticated, but routing brings me to error screen.
And than i can change url to localhost/projectname/users/index and everything is ok, works.
i also tryed to add routes to routes.php:
$routes->connect('/Users/index', ['controller' => 'Users', 'action' => 'index']);
$routes->connect('/http://localhost/sebastus1/hybrid-auth/authenticated', ['controller' => 'Users', 'action' => 'index']);
SOLUTION
thanks to ndm.
(string)'false' != (boolean)false
Assume I'm in an admin\controller\action...
When a session times out and the user's next request to any controller/action is placed, I end up in my admin\users\login() function. Which is exactly what should happen based on the Auth component settings!
But, then a redirect to ['admin' => false, 'controller' => 'users', 'action' => 'login'] immediately comes back to the "admin\users\login"
The code:
$this->redirect(['admin' => false, 'controller' => 'users', 'action' => 'login'])
does NOT honor the admin=false at this point.
Actually, looking at my 'Auth' component initialization in AppController:
// Authentication
$this->loadComponent('Auth', [
'authorize' => array('Controller'),
'loginAction' => array('admin' => false, 'plugin' => NULL, 'controller' => 'users', 'action' => 'login'),
'loginRedirect' => array('admin' => false, 'plugin' => NULL, 'controller' => 'pages', 'action' => '/'),
'logoutRedirect' => array('admin' => false, 'plugin' => NULL, 'controller' => 'users', 'action' => 'login'),
'authError' => 'Authorization is Required!',
'authenticate' => [
'Form' => ['fields' => ['username' => 'name', 'password' => '
'passwordHasher' => 'Default'
]
]
]);
It looks to me as if the admin => false is being ignored. I'm sure that when the delayed (went for coffee) new request for some controller/action occurs that the request would be sent to the admin\users\login since the last one was an admin... but why shouldn't the actual redirect inside the admin\users\login or the Auth->loginRedirect shown here still enforce the admin route?
Is there something new in 3.0, or am I just missing something?
Regardless of the documentation, 'admin' => false will NOT remove the admin routing performed in the Auth component after session times out when the last request was an admin route.
I found issue #14904579 (dated 2013) that solved this very issue by changing the 'loginAction' => '/users/login'... leaving out the array syntax.
I don't have any idea if this issue existed once in 2013 and has reappeared in version cakphp 3.0.9. I did NOT have this issue when running 2.6.7
This is the correct way to remove any prefix from route (admin included):
$this->redirect(['prefix' => false, 'controller' => 'users', 'action' => 'login'])
$this->loadComponent('Auth', [
'loginAction' => [
'prefix' => false, //just add this if you wish to use the array format for urls
'controller' => 'Users',
'action' => 'login',
],
'authError' => 'Login to continue.',
'storage' => 'Session'
]);
According to the Docs, but no prefix in the LoginAction key in example code
I'm trying to make a simple login system for my users, but I can't figure out why it won't log me in, the Auth->login() method always returns FALSE (incorrect information) for some reason... might be something with password hashing.
I have cakePHP 2.5.2.
Here is a screenshot of my issue: ISSUE
My beforeSave() method in UsersController:
public function beforeSave($options = array()) {
$this->request->data['User']['password'] = Security::hash($this->request->data['User']['password']);
}
and the login() method:
function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
$this->Session->setFlash(__('You\'ve successfully logged in.' . ' <b>' . $this->Session->read('User.login') . '</b>'), 'alert', array(
'plugin' => 'BoostCake',
'class' => 'alert-success'
), 'success');
return $this->redirect($this->Auth->redirectUrl());
//// $this->redirect($this->Auth->redirectUrl());
} else {
// var_dump($this->Auth->user());
$this->Session->setFlash(__('Sorry, the information you\'ve entered is incorrect.'), 'alert', array(
'plugin' => 'BoostCake',
'class' => 'alert-danger'
), 'danger');
}
}
}
here's the Auth component:
public $components = array(
'Session',
'Auth' => array(
'loginRedirect' => array('controller' => 'pages', 'action' => 'home'),
'logoutRedirect' => array('controller' => 'pages', 'action' => 'home'),
'loginAction' => array('controller' => 'users', 'action' => 'login'),
'authError' => 'You are not authorized to access this page.',
'authenticate' => array(
'Form' => array(
'userModel'=>'User',
'fields' => array(
'username' => 'login',
'password'=>'password')
)
),
'flash' => array(
'element' => 'alert',
'key' => 'auth',
'params' => array(
'plugin' => 'BoostCake',
'class' => 'alert-danger'
)
),'authorize'=>array('Controller'),
)
,'DebugKit.Toolbar'
);
Yes it's incorrect I removed everything and it works I don't know how
Move your beforeSave method to your Model, not the Controller.
When saving data Cake looks for any functions that should run before inserting the data in your Model.
You will also need to create a new user (if you look in your database you should find that the password has been stored as plaintext because the hashing in the beforeSave would never have been called.
I think you should provide the Security::hash() function blowfish or set the app's internal salt to true.
Like this:
public function beforeSave($options = array()) {
$this->request->data['User']['password'] = Security::hash($this->request->data['User']['password'], null, true);
}
This is the way, the deprecated AuthComponent::password() function works.
Just tested it this way in my Cake App and it work's fine.
See http://api.cakephp.org/2.4/class-Security.html#_hash
Edit:
beforeSave() should be in the User's Model, not in the User's Controller