I am brand new to laravel and am setting up admin panel authorization on my first application. The way I have my files setup currently setup is:
controllers/
admin/
dashboard.php
settings.php
non-admin-controller1.php
non-admin-controller1.php
views/
admin/
dashboard.blade.php
login.blade.php
template.blade.php
non-admin-view1.php
non-admin-view1.php
non-admin-view1.php
...and these are my routes
Route::get('admin/login', function()
{
return View::make('admin.login');
});
Route::get('admin/logout', function()
{
return Auth::logout();
return Redirect::to('admin/login');
});
Route::post('admin/login', function()
{
$userdata = array('username' => Input::get('username'),
'password' => Input::get('password'));
if (Auth::attempt($userdata))
{
return Redirect::to('admin');
}
else
{
return Redirect::to('admin/login')->with('login_errors',true);
}
});
Route::controller('admin.dashboard');
Route::get('admin', array('before' => 'auth', function() {
return Redirect::to_action('admin#dashboard');
}));
Route::filter('auth', function()
{
if (Auth::guest()) return Redirect::to('admin/login');
});
When I go to /admin I am redirected to admin/login and asked to login which is exactly how I need it to work. Upon logging in I am redirected to admin/dashboard and it all looks good there too. I am having 2 problems however.
When I go to admin/logout I am logged out but greeted with a blank page (it's not redirecting to admin/login)
When logged out, if I go to admin/dashboard I am greeted with the error
Error rendering view: [admin.dashboard]
Trying to get property of non-object
What am I doing wrong here? What am I doing right? Would it make more sense to create a separate bundle for admin? Thanks!
So I was able to solve my problem a slightly different way. I created an (base) Admin_Controller in the root of the controllers folder, with a constructor calling the auth filter before execution:
class Admin_Controller extends Base_Controller {
public function __construct()
{
$this->filter('before', 'auth');
}
}
and then made all my admin related controllers in /controllers/admin extend Admin_Controller and call the parent constructor:
class Admin_Dashboard_Controller extends Admin_Controller {
public function __construct()
{
parent::__construct();
}
public function action_index()
{
return View::make('admin.dashboard');
}
}
This might not be the most eloquent solution, but it does the job!
In your admin/login route you have an unnecessary return before the Auth::logout() call, nuke that and it should fix it up.
Another issue here is that only your one 'admin' route is getting filtered. You could wrap all of your admin routes with a Route::group() and apply the 'auth' before filter or you could use Route::filter('pattern: admin/*', 'auth') too.
Check out:
http://laravel.com/docs/routing#filters
For the second issue, is your Admin Dashboard controller class named Admin_Dashboard_Controller and if so, do you have an action_index() or get_index() function in there returning a view?
Check out:
http://laravel.com/docs/controllers#nested-controllers
(I'm assuming you're using L3 here btw.)
For future readers, a very clean way to handle this is using Laravel's Route Groups:
Route groups allow you to share route attributes, such as middleware or namespaces, across a large number of routes without needing to define those attributes on each individual route.
Route::group(['middleware' => 'auth'], function () {
Route::get('/', function () {
// Uses Auth Middleware
});
Route::get('user/profile', function () {
// Uses Auth Middleware
});
});
They can be used not only for authentication, but also Namespaces, Sub-Domains, and more.
Related
What I'm trying to test is to access some routes but these routes are in laratrust role middleware this role is the auth user must be super admin to go in this routes my problem is I don't know how to write this function.
I tried to make the user super admin in the test function like this
public function Test()
{
$user = factory(User::class)->create();
$user->attachRole('superadministrator');
$this->actingAs($user, 'api');
$response = $this->json('GET', 'api/users');
$response->assertStatus(200);
}
but it didn't work even I checked the data base this user is superadministrator and the test give like I'm not super admin
This is my api routes:
Route::group(['middleware' => ['auth:api', 'role:superadministrator']],
function()
{
Route::apiResource('users', 'UserController');
}
This is my index function in UserController:
public function index()
{
return Response()->json(User::all, 200);
}
What I'm expect is a function can access this route because there is more routes in this group and the rest of the tests depends on this function
I've never used Laratrust, but after a quick look at its source code, it looks like the issue is that you need to specify the api guard on your role middleware check. Add ,guard:api to your role middleware:
Route::group(['middleware' => ['auth:api', 'role:superadministrator,guard:api']], function() {
Route::apiResource('users', 'UserController');
}
In the role middleware check, if you don't specify the guard, it will use the default guard defined in your auth config (which is web if you haven't changed it). So, the middleware will be looking for the user from the web auth guard, which doesn't exist.
The good news is, your test worked! It found a bug in your route definition.
I use Laravel 5.3 and I have the following problem.
[UPDATE]
My initial trouble was the appearance of an error when performing actions on the site when the user was not logged in the system.
This happened when the browser is started, where cached information is displayed by default on the page. Site interface displayed for logged users, and in his system was not. At the same time, producing some action, I get an error that the user is not authorized.
I also have group auth middleware for all my routes. When I reboot page of the site, the middleware is activated and redirectedme to the login page. The main problem is the browser shows the cached information.
So, in addition to middleware for routes I decided to make auth check in controllers.
[/UPDATE]
I want to check user's auth in every controller's action. Making the auth check in every controllers' action manually isn't a solution, because there are many controllers and actions.
So I decided to make it globally.
As all controllers extends Main Controller (App\Http\Controllers\Controller.php), I decided write the
auth()->check() in constructor:
function __construct()
{
if(auth()->check()) dd('success');
}
But... nothing happened((( Then I found the callAction method in BaseController which Main Controller extends and made checking here:
public function callAction($method, $parameters)
{
if(auth()->check()) dd('success');
return call_user_func_array([$this, $method], $parameters);
}
This time everything's OK, but I don't like this solution, because editing the core files isn't good.
Finally, I redeclared callAction method in Main Controller with auth checking, but I don't like this way too.
Is any solution?
You should use middleware:
Route::get('profile', ['middleware' => 'auth', 'uses' => 'UserController#showProfile']);
Or:
Route::get('profile', 'UserController#show')->middleware('auth');
Or using middleware groups:
Route::group(['middleware' => ['auth']], function () {
// Controllers here.
});
Or using controller's construct:
public function __construct()
{
$this->middleware('auth');
}
You can use auth middleware in your controller
public function __construct()
{
$this->middleware('auth');
}
check here : https://laravel.com/docs/5.3/authentication
if there is a group of routes this would be the easiest way
Route::group(['middleware' => ['auth']], function()
{
// here all of the routes that requires auth to be checked like this
Route::resource('user','UsersController');
}
another ways
function __construct()
{
$this->middleware('auth');
}
another way is specified on controller routes
Route::get('profile', [
'middleware' => 'auth',
'uses' => 'UserController#showProfile'
]);
see documentation
https://laravel.com/docs/5.0/controllers#controller-middleware
(I have asked this question before, and did find a way around which worked for a while, but soon got out of hand. So now I am looking for a perfect solution to achieve this, the Laravel way.)
The problem is pretty simple, when admin goes to http://example.com/dashboard they should see the admin dashboard and when manager goes to the same link he should see the managers dashboard.
The way around that I used before was to call the pagecontroller and then depending on the user role call the relevant admin's or manager's dashboard controller.
// ROUTES.php
Route::group(['middleware' => 'auth'], function () {
Route::get('dashboard', 'PagesController#dashboard');
Route::get('users', 'PagesController#manageUsers');
});
// PagesController
public function dashboard(){
if($this->user->isAdmin()){
return $controller = app()->make('App\Http\Controllers\Admin\dashboard')->index();
}
if($this->user->isManager()){
return $controller = app()->make('App\Http\Controllers\Manager\dashboard')->index();
}
}
Now the problem with this approach is that I can no longer call the middleware on the dashboard controller because the process doesn't involve calling the kernel.
I am pretty sure there must be a way to achieve such a basic feature, I would be really grateful if someone can sort this out.
I think the reason this isn't a Laravel default feature because it kinda goes counter to what routes are supposed to represent. In other words, this isn't the Laravel Way. Why not redirect the user depending on their role?
// ROUTES.php
Route::group(['middleware' => 'auth'], function () {
Route::get('dashboard', function() {
if($this->user->isAdmin())
return redirect('/dashboard/admin');
if($this->user->isManager())
return redirect('/dashboard/manager');
return redirect('/home');
});
Route::get('dashboard/admin', 'Admin\dashboard#index');
Route::get('dashboard/manage', 'Manager\dashboard#index');
Route::get('users', 'PagesController#manageUsers');
});
I am using code that is below for admin routing in laravel.
Route::group(['prefix' => 'admin'], function() {
Route::get('/', 'Admin\AdminController#home');
Route::get('/users/userList', 'Admin\UserController#userList');
Route::get('/users/detail', 'Admin\UserController#detail');
Route::get('/posts/view', 'Admin\PostController#view');
Route::get('/posts/edit', 'Admin\PostController#edit');
Route::get('/posts/add', 'Admin\PostController#add');
});
This is working fine for me. But when I add new functions in code for that I have to write routing in routes file. For example: If I want to add edit functionality in users controller, for that I have to add new route like .
Route::get('/users/edit', 'Admin\UserController#edit');
So I have to add routing for each function.
I want to know How to use wild card for admin routing so that I have to write routing only for controller not for each function for example.
Route::group(['prefix' => 'admin'], function() {
Route::get('/', 'Admin\AdminController#home');
Route::get('/users/:any', 'Admin\UserController#:any');
Route::get('/posts/:any', 'Admin\PostsController#:any');
});
wild card replace the function name, and auto ridirect to that function.
You could use implicit controllers that will do what you need.
First declare a route for your implicit controller
Route::controller('users', 'UserController');
Then, on your controller, you have to follow a convention for naming your routes with HTTP verbs used to access them (get for GET, post for POST, any for both)
class UserController extends Controller {
public function getIndex()
{
//
}
public function postProfile()
{
//
}
public function anyLogin()
{
//
}
}
A note about composed method name from documentation
If your controller action contains multiple words, you may access the action using "dash" syntax in the URI. For example, the following controller action on our UserController would respond to the users/admin-profile URI:
public function getAdminProfile() {}
Looking for some insight on this.
I am trying to define a route controller in a Laravel 4 application that does the following things.
Handles the route user/{userid}
Handles the route user/new
I cannot figure out a way to make both happen simultaneously.
My controller and route look like this:
Route::controller('user', 'UserController');
class UserController extends BaseController {
public function getIndex($user_id) {
$user = User::find($user_id);
return View::make('user')
->with('user', $user);
}
public function getNew() {
return View::make('create_user');
}
}
To me, that should work, but I get a 404 when trying to go to user/1. Oddly enough, user/new still takes me to create_user as it should. The user.blade.php view and create_user.blade.php view both exist in the root of views, so that isn't the problem either. What am I doing wrong?
Instead of doing Route::controller('user', 'UserController'); you can do the following in your routes:
Route::get('user/new', 'UserController#getNew');
Route::get('user/{user_id}', 'UserController#getIndex');
OR you can also do the following:
Route::get('user/{user_id}', 'UserController#getIndex');
Route::controller('user', 'UserController');