I am making a system using CakePHP in which the users can be either A, B or C. Like student, teacher and some other role. Is it possible to let them all login via 1 link? so not /students/login and /teachers/login, but something like www.somewebsite/login for all of them?
Read this tutorial, it exactly covers what you're asking for. Also read this section.
It does not make any sense at all to have different controllers for different types of users, you'll just duplicate code. If you need to take different actions based on the role you can do that within your login method by calling another method like afterStudentLogin() from within your login() method and do role specific things there. The reason for that is that a single method should always just do one task, so you decouple the role specific code from it in a separate method.
public function login() {
if ($this->Auth->user()) {
/* ... */
$callback = 'after' . $this->Auth->user('role') . 'Login');
$this->{$callback}($this->Auth->user());
/* ... */
}
}
Even if the user types are very different, they all will share a common thing: The login. In this case have an users table and for example student_profils table and teacher_profiles table. If the difference is just a few fields I would put them all in one table like profiles.
If you want to have /login instead of /users/login you should use routing.
Router::connect(
'/login',
array(
'controller' => 'users',
'action' => 'login'
)
);
You can also take a look at this Users plugin which covers a lot of the usual user related tasks. And here is a simple multi-role authorization adapter.
A simple basic login function depending on user group would look like as given below
<?php
public function login() {
//if user already logged in call routing function...
if($this->Session->read('Auth.User')) {
$this->routing();
}
if ($this->request->is('post')) {
if ($this->Auth->login()) {
//if user status is active...
if ($this->Auth->user('status') == 1){
//redirect users based on his group id...
if($this->Auth->User('group_id')==1){
$this->redirect($this->Auth->redirect('/admins/dashboard'));
}
else if($this->Auth->User('group_id')==2){
$this->redirect($this->Auth->redirect('/teachers/dashboard'));
}
else if($this->Auth->User('group_id')==3){
$this->redirect($this->Auth->redirect('/students/dashboard'));
}
}
else{
$this->Session->delete('User');
$this->Session->destroy();
$this->Session->setFlash('Your account is not yet activated. Please activate your account to login.', 'warning');
}
}
else {
$this->Session->setFlash('Your username or password was incorrect.', 'error');
}
}
}
//just route the loggedin users to his proper channel...
public function routing() {
if($this->Session->read('Auth.User.Group.id') == 1) {
$this->redirect('/admins/dashboard');
}
else if($this->Session->read('Auth.User.Group.id') == 2) {
$this->redirect('/teachers/dashboard');
}
else if($this->Session->read('Auth.User.Group.id') == 3) {
$this->redirect('/students/dashboard');
}
else {
$this->Session->destroy();
$this->redirect('/');
}
}
?>
Related
I have a database that in this: Admin has True isAdmin property, but other users have false isAdmin property.
I want to check if the user who logged in is an Admin or not by redirecting them to different pages in my app. My code in Controller is:
public function store(User $user)
{
if (auth()->attempt(request(['email', 'password']))) {
if ($user->isAdmin == 1) {
return redirect('/ShowUser');
}
{
return redirect('/lo');
}
}
return back()->withErrors(
[
'message' => 'Error'
]
);
}
But this code doesn't work; it sends the users to '/lo' all the time. How can I fix it?
You're missing an else keyword.
Right here:
if ($user->isAdmin == 1) {
return redirect('/ShowUser');
}
{ // <-- right here
return redirect('/lo');
}
add the else keyword.
if ($user->isAdmin == 1) {
return redirect('/ShowUser');
}
else { // <-- right here
return redirect('/lo');
}
anyway, your code will still run fine even after the edit above. But I have questions for you:
Is the user assumed to be in the database already?
What is the default value of isAdmin in the database?
Are you passing the isAdmin attribute as an input from a form or something?
And why is it a store request when you're just trying to log a user in?
It's a bit confusing. I can tell from your code that you're trying to log a user in, but you're doing it in a store method (nothing wrong with that, just convention), the store method is usually used in storing data (how coincidental!)
I have created a log in form for my admin pages and it works, but for now everyone who logs in can access those pages.
My users are also belong to usergroups and my users table in the database has a group_id column. The admin group has an id of 1.
What I'd like to do is that if someone who belongs to the admin group logs in can access the admin pages, but if the user belongs to a different group and tries to log in be redirected to main page or anywhere.
What I'm trying to do is add a similar code to the admin pages controllers
class Dashboard extends MY_Controller {
public function __construct() {
parent::__construct();
// Access control
if(!$this->session->userdata('logged_in')) {
redirect('admin/login');
}
}
}
My model
class Authenticate_model extends CI_Model {
public function login_user($username, $password){
//Secure password
$enc_password = md5($password);
//Validate
$this->db->where('username',$username);
$this->db->where('password',$enc_password);
$result = $this->db->get('users');
if($result->num_rows() == 1){
return $result->row();
} else {
return false;
}
}
}
You can do it yourself, provide validation and set $SESSION variable to retrieve if the user is logged in. But this is too much work, and error prone.
I recommend you to use this popular library: https://github.com/benedmunds/CodeIgniter-Ion-Auth. It is really easy to set up, you just need to copy some files and you are ready to go.
If you really want to do it your self(thats the question) then you need to store in SESSION two variables - logged_in and is_admin.
I would recomend two create library with function:
function is_logged_in($admin = FALSE){
$is_logged = $this->session->userdata('logged_in');
if($admin){
$is_logged = $this->session->userdata('is_admin')
}
return $is_logged;
}
This assumes that you store two booleans "logged_in" and "is_admin" in SESSION.(If user has group_id = 1 then you would store TRUE in is_admin)
Then you can protect your site members only pages
if(!$this->your_authenticatation_library->is_logged_in()){redirect('notMembersControler')}
and admin page:
if(!$this->your_authenticatation_library->is_logged_in(TRUE)){redirect('notMembersControler')}
Thats the basic idea, you need to work around depending on what you are up to. Hope this helps!
I'm currently trying to route as follows:
If user GETs /account/
If session has account_id, user is logged in; show his account information
If not, user is not logged in; show login/create form
If user POSTs /account/
If input has create, user wants to create account; create it
If not, user wants to login; find his account and go again to /account/
My routes are set this way:
Route::get('account', function() {
if (Session::has('account_id'))
return 'AccountsController#show';
else
return 'AccountsController#index';
});
Route::post('account', function() {
if (Input::has('create')) {
return 'AccountsController#create';
else
return 'AccountsController#login';
)};
This is somewhat how I would do with Rails, but I don't know how to point to the controller method. I just get the returned string as a result. I didn't find it in Laravel documentation (which I found really poor, or have I searched wrong?) neither in any other web tutorial.
Try the following:
Route::get('account', function() {
if (Session::has('account_id')) {
$action = 'show';
return App::make('AccountsController')->$action();
}
else {
$action = 'index';
return App::make('AccountsController')->$action();
}
});
Route::post('account', function() {
if (Input::has('create')) {
$action = 'create';
return App::make('AccountsController')->$action();
}
else {
$action = 'login';
return App::make('AccountsController')->$action();
}
)};
So, you want to put all your logic in the controllers.
You would want to do
Route::get('account', 'AccountsController#someFunction');
Route::get('account', 'AccountsController#anotherFunction');
Then, in the respective controllers, you would want to make your tests, then do, for example,
if (Session::has('account_id')){
return Redirect::action('AccountsController#show');
}
else{
return Redirect::action('AccountsController#index');
}
However, make sure you define a route for each action, so your application can detect a URL.
For example, if you want to have
Redirect::action('AccountsController#show')
you will need to define this action like:
Route::get('/account/show', 'AccountsController#show')
I have one user class which consists of two types of users and want to allow different users to go to different pages.
I have created a filter as follows
Route::filter('isExpert', function()
{
$userIsExpert = 0;
$userIsLoggedIn = Auth::check();
if ($userIsLoggedIn && Auth::user()->role == 'expert') {
$userIsExpert = 1;
}
Log::info('Logged in: ' . $userIsLoggedIn . ' && Expert: ' . $userIsExpert);
if ($userIsExpert == 0)
{
Log::info('should be logging out now.');
Auth::logout();
return Auth::basic();
}
});
And routing like so
Route::get('/winners', array('before' => 'isExpert', function()
{
$winners = DB::select('select * from winners');
return View::make('winners.index')->with('winners',$winners);
}));
The thought is this: If it's not an expert, it will logout and redirect to login page. If it is, it will simply continue.
However, Auth::logout(); doesn't ever log out the user.
Question
Why is not Auth::logout() working? I've tried placing it anywhere in the app to no avail.
cheers
I had the same problem, I really couldn't logout the current user... And the answer is simple: Laravel doesn't support logout() with Auth::basic().
There are ways to fix it, but it's not very clean; https://www.google.nl/search?q=logout+basic
This is not a limitation to Laravel, HTTP Basic Authorization is not designed to handle logging out. The client will remain logged in until the browser is closed.
HTTP Basic Authorization really shouldn't be used in any public production environment. Here are some reasons why:
No way to give users a "remember me"-option on the login form.
Password managers have no or lacking support for HTTP Basic Auth, as it is not rendered HTML but a native popup.
Terrible user experience. Putting together a proper login form is well worth the little time it takes.
The only valid case I can think of is to protect public development-subdomains like dev.example.com, but there are better ways to solve that as well.
The easiest way that I've found for that is to redirect to invalid username/password on logout route. Example:
Route::get('admin/logout', function() {
return Redirect::to(preg_replace("/:\/\//", "://log-me-out:fake-pwd#", url('admin/logout')));
});
If you implemented these methods in User.php
/**
* Get the e-mail address where password reminders are sent.
*
* #return string
*/
public function getReminderEmail()
{
return $this->email;
}
public function getRememberToken()
{
return $this->remember_token;
}
public function setRememberToken($value)
{
$this->remember_token = $value;
}
public function getRememberTokenName()
{
return 'remember_token';
}
add new column with name 'remember_token' to your table 'users' in mysql database, and then log out, finally it solved successfully.
to alternate you table use this SQL Command:
ALTER TABLE users ADD remember_token TEXT;
and then press 'Go' button.
I'm trying to make a blogging system but obviously certain users in certain groups should only be able to edit/delete their own posts/comments. How would I go about doing this in CakePHP? I followed the manual's basic Acl guide to setup my current Auth system.
Assuming you have a Post and Comment model and the user_id is present via the $this->Auth->... object, you could define a generic method in your model:
function allowUserPost($user_id, $post_id) {
// Then check if this $user_id owns the $post_id
// if true, return true, if false, return false
}
In your controller:
function deletePost($post_id) {
if($this->Post->allowUserPost($user_id, $post_id) {
// Go ahead, delete
} else {
// Deny
}