I'm learning Laravel, and I'm busy building a site (framework version 5.1.34). I installed Homestead in September last year, initially on Windows 7 and then upgraded to Windows 10. Everything was working fine on Windows 7 and later on Windows 10 also (I had some issues on Windows 10 which I managed to sort out), but then my routes started acting strange recently. All of my routes still work, except the one now comes up with a 404 error. The route is:
Route::get('projects/{project}/nodes/{node}/tasks/create',
['uses' => 'TaskController#taskCreateShow']);
The controller function is:
public function taskCreateShow(Project $project, Node $node){
return view('tasks.create')
->with('project',$project)
->with('user',$this->user)
->with('node',$node)
->with('all_projects',$this->all_projects);
} // taskCreateShow
If I run php artisan route:list the route still shows up like all the other routes. I can add new routes, which also work fine. The model binding is defined in the RouteServiceProvider.php class in the boot function:
public function boot(Router $router)
{
parent::boot($router);
// Route model binding
$router->model('project', 'resolved7\Project');
$router->model('user', 'resolved7\User');
$router->model('node', 'resolved7\Node');
$router->model('task', 'resolved7\Task');
$router->model('io', 'resolved7\Io');
}
The only way I've been able to get this to work, is to change the route to:
Route::get('projects_1/{project}/nodes/{node}/tasks/create',
['uses' => 'TaskController#taskCreateShow']);
I've looked at the .htaccess file, and it seems fine. Does anyone perhaps know what could cause this to happen? I appreciate any help or suggestions. Thanks.
*edit: here is the routes.php file:
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
*/
/*=========================================================================
* General routes
*/
Route::get('/', function(){
return redirect('index');
});
Route::get('dashboard', function(){
return 'dashboard';
});
Route::get('about', function(){
return view('about')->with('company_name', 'The Resolved 7<sup>th</sup>');
});
Route::get('index', function(){
return view('index');
});
// Route used to get images from non-public folder
Route::get('images/{filename}', function ($filename)
{
$path = storage_path() . '/profilepics/' . $filename;
$file = File::get($path);
$type = File::mimeType($path);
$response = Response::make($file, 200);
$response->header("Content-Type", $type);
return $response;
});
/* =========================================================================
* Project specific routes
* Use controller to re-use construct functions
*/
// Project specific dashboard
Route::get('projects/{project}', ['uses' => 'ProjectController#projectDashboard'])
->where('project','[0-9]+');
// Page from which to create new project
Route::get('projects/create', ['uses' => 'ProjectController#projectCreateShow']);
// Create a new project through post method
Route::post('projects', ['uses' => 'ProjectController#projectCreate']);
// Page from which to edit projects
Route::get('projects/{project}/edit', ['uses' => 'ProjectController#projectEditShow']);
// Update an existing project through put method
Route::put('projects/{project}', ['uses' => 'ProjectController#projectEdit']);
// Page from which a project deletion is confirmed
Route::get('projects/{project}/delete', ['uses' => 'ProjectController#projectDeleteShow']);
// Delete project
Route::delete('projects/{project}', ['uses' => 'ProjectController#projectDelete']);
// Page to show project details
Route::get('projects/{project}/detail', ['uses' => 'ProjectController#projectDetail']);
// Page from which to select users to add as members
Route::get('projects/{project}/members/invite', ['uses' => 'ProjectController#projectAddMembersShow']);
/* =========================================================================
* User specific routes
*/
// Page to test user
Route::get('users/{user}/test', ['middleware' => 'auth',
'uses' => 'UserController#test']);
// Page to show user
Route::get('users/{user}', ['middleware' => 'auth',
'uses' => 'UserController#show']);
// Page from which to edit user
Route::get('users/{user}/edit', ['middleware' => 'auth',
'uses' => 'UserController#showUserEdit']);
// Update an existing user through put method
Route::put('users/{user}', ['middleware' => 'auth',
'uses' => 'UserController#userEdit']);
/* =========================================================================
* Node specific routes
*/
// Page from which to view node
Route::get('projects/{project}/nodes/{node}',
['uses' => 'NodeController#nodeShow']);
// Page from which to create new node
Route::get('projects/{project}/nodes/create',
['uses' => 'NodeController#nodeCreateShow']);
// Create a new node through post method
Route::post('projects/{project}/nodes',
['uses' => 'NodeController#nodeCreate']);
// Page from which to edit nodes
Route::get('projects/{project}/nodes/{node}/edit',
['uses' => 'NodeController#nodeEditShow']);
// Update an existing node through put method
Route::put('projects/{project}/nodes/{node}',
['uses' => 'NodeController#nodeEdit']);
// Page from which a node deletion is confirmed
Route::get('projects/{project}/nodes/{node}/delete',['uses' => 'NodeController#nodeDeleteShow']);
// Delete node
Route::delete('projects/{project}/nodes/{node}', ['uses' => 'NodeController#nodeDelete']);
// Page from which a user is selected to be added to a node
Route::get('/projects/{project}/nodes/{node}/members/add',
['uses' => 'NodeController#nodeAddMember']);
// Add existing project member user to specific project node
Route::post('/projects/{project}/nodes/{node}/members/add',
['uses' => 'NodeController#nodeAddExistingMember']);
// Page to confirm node member removal
Route::get('/projects/{project}/nodes/{node}/members/{user}/remove',
['uses' => 'NodeController#nodeRemoveMemberShow']);
// Remove node member user from a specific project node
Route::post('/projects/{project}/nodes/{node}/members/{user}/remove',
['uses' => 'NodeController#nodeRemoveMember']);
/* =========================================================================
* Task specific routes
*/
// Page from which to view task
Route::get('projects/{project}/nodes/{node}/tasks/{task}',
['uses' => 'TaskController#show']);
// Page from which to create new task
// return 'dashboard' is a test.
Route::get('/projects/{project}/nodes/{node}/tasks/create', function(){
return 'dashboard';
});
/*Route::get('/projects/{project}/nodes/{node}/tasks/create',
['uses' => 'TaskController#taskCreateShow']);*/
// Create a new task through post method
Route::post('/projects/{project}/nodes/{node}/tasks',
['uses' => 'TaskController#taskCreate']);
// Page from which a task deletion is confirmed
Route::get('projects/{project}/nodes/{node}/tasks/{task}/delete',
['uses' => 'TaskController#taskDeleteShow']);
// Delete task
Route::delete('projects/{project}/nodes/{node}/tasks/{task}',
['uses' => 'TaskController#taskDelete']);
/* =========================================================================
* Io specific routes
*/
// Page from which to create new io
Route::get('/projects/{project}/nodes/{node}/tasks/{task}/ios/create',
['uses' => 'IoController#ioCreateShow']);
// Create a new io through post method
Route::post('/projects/{project}/nodes/{node}/tasks/{task}/ios/',
['uses' => 'IoController#ioCreate']);
// Page from which an io deletion is confirmed
Route::get('projects/{project}/ios/{io}/delete',
['uses' => 'IoController#ioDeleteShow']);
// Delete io
Route::delete('projects/{project}/ios/{io}',
['uses' => 'IoController#ioDelete']);
/* =========================================================================
* User authentication controllers
*/
Route::controllers([
'auth' => 'Auth\AuthController',
'password' => 'Auth\PasswordController',
]);
/* =========================================================================
* Community
*/
Route::get('/community', ['uses' => 'UserController#community']);
/* Testing routes
*
* =========================================================================
*
*/
// Page from which to test project
Route::get('projects/{project}/test', ['uses' => 'ProjectController#test']);
Thanks guys, I missed a route that was indeed taking precedence as mentioned in the comments. I changed the route from:
Route::get('projects/{project}/nodes/{node}/tasks/{task}',
['uses' => 'TaskController#show']);
to:
Route::get('projects/{project}/nodes/{node}/tasks/{task}',
['uses' => 'TaskController#show'])
->where('project','[0-9]+')
->where('node','[0-9]+')
->where('task','[0-9]+');
All is working well again. I'll perhaps change some of the other routes also to make them more robust.
Related
I'm trying to restrict the access of routes to only some types of users in my site that I'm writing with Laravel 5.7, right now I'm trying to do it with middlewares.
For each user's level I have a middleware with this code(with a variation on the type):
public function handle($request, Closure $next)
{
if(Auth::user()->type==3)
return $next($request);
else
return redirect()->route('dashboard');
}
And in the kernel.php file, I have them written like this:
protected $routeMiddleware = [
...
'teacher' => \App\Http\Middleware\RedirectIfTeacher::class,
...
]
In my application each user has a level, which starts from 1 to 5, but each level has individual views and some shared views, but I can't manage to redirect views for more than just one type of user because I can't make them work when I use more than one middlewares on a route (or routes) that are shared with more than two types of users.
When I try it justs ignores the second or more middlewares and redirects to the route dashboard which is the route for redirecting if the type of user can't enter the desired view.
Right now I've tried with this code:
Route::group(['middleware' => ['administrator','teacher','student']], function(){
And with this code:
Route::group(['middleware' => ['administrator' OR 'teacher' OR 'student']], function(){
Also I tried with this style:
Route::group(['middleware' => ['administrator|teacher|student']], function(){
Without getting any luck, is there anything what am I doing wrong? or is there a better way to do what I'm trying to achieve, thanks in advance!.
I'm using below code and it worked:
Route::group(['middleware' => ['administrator','teacher','student']], function() {});
1 In the kernel.php file, have you got all of the keys assigned with your middlewares ? For example:
protected $routeMiddleware = [
...
'administrator' => \App\Http\Middleware\RedirectIfAdmin::class,
'teacher' => \App\Http\Middleware\RedirectIfTeacher::class,
'student' => \App\Http\Middleware\RedirectIfStudent::class,
...
]
2 Try to check the user vars before the if in your handle().
dd(Auth::user()->type);
You need to pass an array to it I guess
Route::group(['middleware' => ['administrator','teacher','student']], function() {});
If that doesn't work you have to split them I guess
Route::group(['middleware' => 'administrator'], function () {
Route::group([ 'middleware' => 'teacher'], function() {
Route::group([ 'middleware' => 'student'], function() {
});
});
});
I am developing web application with laravel 5.2.
What i need is i have some off account that distinguished by role. and i have to role that can access 1 route but other role cannot access. i have browsing and i have done everything that i found like
Route::group(['prefix' => '/', 'middleware' => ['role:user_a','role:user_b']], function(){someroute}
Route::group(['prefix' => '/', 'middleware' => ['role:user_a|role:user_b']], function(){someroute}
Route::group(['prefix' => '/', 'middleware' => ['role:user_a,role:user_b']], function(){someroute}
no one work. i dont know how to make my single route can be accessed by 2 role but disable for other role
You can create a middleware named role, read more about middleware in docs here
The handle method of middleware will be as:
public function handle($request, Closure $next)
{
if (auth()->user()->role('b')) {
return redirect('home');
}
// else users of other roles can visit the page
return $next($request);
}
Then you can use it in your route file as:
Route::group(['middleware' => 'role'], function () {
// someroute
});
i think you cant do this, but you can use this way.
Route::group(['prefix'=>'/', 'middleware' =>['role:user_a','role:user_b']],function(){
Route::group(['prefix'=>'userAorB', 'middleware' =>['role:user_a|role:user_b']],function(){ Routes });
Route::group(['prefix'=>'userAANDB', 'middleware' =>['role:user_a,role:user_b']],function(){ Routes });
})
I have 2 user roles which is superadmin and admin
I don't want admin to access of Settings Page.
I am not sure if this is the proper way.
So, here's my SettingsController.php
class SettingsController extends Controller {
public function index() {
if(Auth::user()->roles == 0) {
return redirect(url()->previous());
} else {
return view('settings.index');
}
}
}
As you can see if the roles is 0. I redirect the user to the last page they're in. I also tried to use return back();
web.php (routes)
<?php
Route::get('/', ['uses' => 'UsersController#index']);
Route::post('login', ['uses' => 'UsersController#login']);
Route::group(['middleware' => ['auth']], function() {
Route::get('logout', ['uses' => 'UsersController#destroy']);
Route::get('upline', ['uses' => 'UplinesController#index']);
Route::get('upline/create', ['uses' => 'UplinesController#create']);
Route::post('upline', ['uses' => 'UplinesController#store']);
Route::delete('upline/destroy/{id}', ['uses' => 'UplinesController#destroy']);
Route::put('upline/update/{id}', ['uses' => 'UplinesController#update']);
Route::get('upline/getdownlines/{id}', ['uses' => 'UplinesController#getDownlines']);
Route::get('downline', ['uses' => 'DownlinesController#index']);
Route::post('downline', ['uses' => 'DownlinesController#store']);
Route::delete('upline/destroy/{id}', ['uses' => 'DownlinesController#destroy']);
Route::put('downline/update/{id}', ['uses' => 'DownlinesController#update']);
Route::get('bonus', ['uses' => 'BonusController#index']);
Route::post('bonus/csv', ['uses' => 'BonusController#fileUpload']);
Route::get('settings', ['uses' => 'SettingsController#index']);
});
I have a 2nd question. Can I limit admin using middleware? If yes, how?
Any help would be appreciated.
Maybe the second option, "Limiting admin with middleware".
So you can try something like;
Route::group(['prefix' => 'admin', 'middleware' => 'auth'], function () {
Route::get('/', 'DownlinesController#update');
});
Then
Route::group(['prefix' => 'super', 'middleware' => 'auth'], function () {
Route::get('/', 'UplinesController#index');
});
As #michael s answer suggests use middleware, his answer fails to demonstrate on how to do it (mine too, I just added more text).
Note: Laravel is big because of its documentation, USE IT!
You have 2 (or more options):
parameterized middleware
2 distinctive middlewares (one for admin, another for superadmin)
Note: use artisan to generate middleware from stubs, $ php artisan make:middleware MyNewShinyMiddleware
parametrized middleware (my pick)
Head to documentation and check out this.
Example shows exactly your problem.
public function handle($request, Closure $next, $role)
{
if (! $request->user()->hasRole($role)) { //implement hasRole in User Model
// Redirect...
// (use named routes to redirect or do 401 (unauthorized) because thats what is going on!
// abort(401) // create view in /views/errors/401.blade.php
// return redirect()->route('home');
}
//success user has role $role, do nothing here just go to another "onion" layer
return $next($request);
}
2 distinctive middlewares
simply create two middlewares and hardcode your checking routine of roles
(same as you do in your controller sample) except use $request->user()...
(routes) web.php
Route::group(['middleware' => 'role:admin'], function () {...} //parametrized
Route::group(['middleware' => 'checkRoleAdmin'], function () {...}
Route::group(['middleware' => 'checkRoleSuper'], function () {...}
Note: role, checkRoleAdmin and checkRoleSuper are "named" middlewares and you need to register them in kernel.php
Another way is yo use gates or policies which make the best sense, since you are trying to limit user. Read more here.
I use middleware based ACL for really simple projects (like one admin and no real users).
I use gates based ACL for medium projects (1-2 roles).
I use policies based ACL for "huge" projects (many roles, many users).
Also consider looking at https://github.com/Zizaco/entrust
I defined a resource route group
Route::group(['prefix' => 'api/v1'], function() {
Route::resource('words', 'WordController');
});
and I created a controller for all that routes. I want to set basic authentication for all requests so I added to the constructor of WordController: $this->beforeFilter('auth.basic'); But there is no effect. I still can get all words without any username and password provided. Does someone know why?
class WordController extends ApiController {
protected $wordTransformer;
function __construct(WordTransformer $wordTransformer)
{
$this->wordTransformer = $wordTransformer;
$this->beforeFilter('auth.basic');
//$this->middleware('auth.basic');
}
public function index()
{
$words = Word::all();
return $this->respond([
'words' => $this->wordTransformer->transformCollection($words->all())
]);
}
}
If you are using laravel 5, you can use middleware that replace filter. Using middleware is becoming the preferred practice and way of thinking about decorating your routes. Why your code not working because auth.basic is a type of middleware not filter.
You can attach the middleware in controller since you are using Route::group.
See the code below how to attach it.
Route::group(['prefix' => 'api/v1', 'middleware' => 'auth.basic'], function() {
Route::resource('words', 'WordController');
});
You can see at the above code use middleware name "auth.basic". How do you know the middleware. Before you can use the middleware, you must register the middleware by define the middleware in /app/Http/Kernel.php. If you open that file you can see the code below.
/**
* The application's route middleware.
*
* #var array
*/
protected $routeMiddleware = [
'auth' => 'App\Http\Middleware\Authenticate',
'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
'guest' => 'App\Http\Middleware\RedirectIfAuthenticated',
];
You can try something like below. authenticate user during the routing rather then controller.
Route::get('home', array('before' => 'auth', 'do' => function()
{
// your action here
}));
Route::filter('auth',function(){
if(Auth::guest())
return Redirect::to('login');
});
Im developing a basic aplication core, first im working with user/groups and & permissions access.
I choose Sentry 2 to work, and i want to limit the access to my.domain/admin to a users or groups that have admin permissions.
Im developing a filter to check if the user is admin and if hasAccess to a specific action, like users.index, or users.custom_fuction.
In my routes i have:
/**
* ADMIN ROUTES
*/
Route::group(array('before' => 'sentry'), function() {
Route::group(array('before' => 'admin'), function() {
Route::group(array('prefix' => 'admin'), function()
{
Route::get('/', function()
{
return View::make('admin');
});
Route::resource('groups', 'GroupController',
array('except' => array('show')));
Route::resource('users', 'UserController',
array('except' => array('show')));
Route::get('users/{id}/groups', 'UserController#groups');
Route::post('users/{id}/groups', 'UserController#store_groups');
Route::get('{table}/{id}/permissions',
'PermissionController#manage_entity');
Route::post('{table}/{id}/permissions',
'PermissionController#update_permissions');
});
});
});
The sentry filter only checks if is loged and rediret to login page, the admin filter is:
/*
* Sentry admin & hasAccess filter
*/
Route::filter('admin', function()
{
$user = Sentry::getUser();
if (!$user->hasAccess('admin')) return Redirect::to('/');
// Ask if user hasAccess to specific action
var_dump(Route::getCurrentRoute()->getPath());
var_dump(Route::getCurrentRoute()->getAction());
});
I have to make another check with the actual route, in the getAction array there are a
'as' => string 'admin.users.index' (length=17)
I can use that for Route::resource i define but, how i did for other functions like groups or permissions.
Maybe there is a better way to handle that, but i dont know it.
Thanks in advice.
I found the solution:
http://laravel.com/docs/routing#named-routes
And now i have:
Route::get('users/{id}/groups', array('as' => 'admin.users.groups', 'uses' => 'UserController#groups'));
Route::post('users/{id}/groups', 'UserController#store_groups');
Route::get('{table}/{id}/permissions', array('as' => 'admin.permissions.manage_entity', 'uses' => 'PermissionController#manage_entity'));
Route::post('{table}/{id}/permissions', 'PermissionController#update_permissions');
And the filters looks like:
Route::filter('admin', function()
{
$user = Sentry::getUser();
$action = Route::getCurrentRoute()->getAction();
if (!$user->hasAccess($action['as'])) return Redirect::to('/admin');
});
But now, all route inside that filter need a as declared or error will popup.
Hope this helps others.