Laravel - middleware on routes in controller - laravel-5

I have a route resource
Route::resource('campaign', 'CampaignController');
I want to restrict some of these routes to the users.
For example the index page lists all the campaigns and they should not see this only their own ones.
I have a custom middleware that simply checks the if the user is an admin
However I cannot apply this to individual methods.
public function index()
{
$this->middleware('checkuser');
}
Just the constructor
public function __construct()
{
$this->middleware('checkuser');
}
How do I get around this and apply to individual route in the controller

Sorry my mistake I should have read the docs you can add exceptions or allowed.
$this->middleware('auth');
$this->middleware('log', ['only' => ['fooAction', 'barAction']]);
$this->middleware('subscribed', ['except' => ['fooAction', 'barAction']]);
}

Related

Adding custom function to Policy

I want to create a custom function for my Policy but I don't know how to use it in the route as middleware or something. Basically below is the code for my policy
class DepartmentPolicy
{
use HandlesAuthorization;
public function list(User $user, Department $department)
{
return true;
}
}
Now I want to call this in my Route something like this
Route::prefix('/departments')->group(function () {
Route::get('/list', [App\Http\Controllers\DepartmentController::class, 'list'])
->middleware('can:list,department');
});
But I always get a 403 function. When I remove this middleware I can access the url. But with this I get a 403.
Note: I already created the policies in the AuthServiceProvider like below
protected $policies = [
'\App\Models\User' => 'App\Policies\UserPolicy',
'\App\Models\Department' => 'App\Policies\DepartmentPolicy',
];
Can anyone tell me how to use this custom function in my custom route? Basically I know that by default if I access the index in the controller it will call the viewAny function in my DepartmentPolicy but what about the custom function in the policy and the custom route? how can I call that or link each other?

Set username as prefix in URIs Laravel

I want to set prefix in all of the authenticated URIs in Laravel 5.3 app. If I use Route::group(['prefix' => {username}]), then how can I get the username in web.php file.
Assuming you have defined routes like this:
Route::group(['prefix' => '/{user}'], function() {
Route::get('/profile', 'UserController#showProfile')->name('user.profile');
});
You can use Laravel's route-model binding to pass an User instance directly into your routes:
View Profile
Then in the controller , you can easily grab that model instance:
class UserController extends Controller
{
public function showProfile(User $user)
{
return view('user.profile.index', compact('user'));
}
}
Check out the documentation here.
EDIT: By default, Laravel uses the id column when retrieving a given model class. You can change that to any column, in your case username , easily by overriding the getRouteKeyName() method on your User model.
public function getRouteKeyName()
{
return 'username';
}
You can't and you shouldn't hardcore routes with usernames. If you have 100 users, do you plan to create 100 route groups for each user? Assuming each user has 2 routes that's 200 routes.
What you need to do is generate routes with username segment and detect the user on the fly based on the user name.
Route::group(['prefix' => '{username}'], function () {
Route::get('profile', 'UserController#profile');
Route::get('setting', 'UserController#setting');
});
The routes generated would be like
http://example.app/{username}/profile
http://example.app/{username}/setting
So a user with username adam with get the links.
http://example.app/adam/profile
http://example.app/adam/setting
Similarly you can have username based links for all your users and you need to detect them in your controller using route model binding or the standard way.
Edit
For closure based routes you can get the url segment like so
Route::get('{username}/profile', function ($username) {
return 'Username is '.$username;
});
With controllers you get them as the parameters.
public function profile($username)
{
return $username;
}

Laravel 5 Authentication: make Controller decides which methods are public

This is a very long question for (I think) a very simple answer, but I am a total newbie in Laravel and I need to know if I am addressing it the right way.
What I did
I followed the Intermediate Tutorial and modified it just a little bit, and now I have a simple task list that uses authentication. I had this in my TaskController constructor:
public function __construct(TaskRepository $tasks)
{
$this->middleware('auth');
}
This checks if the user is logged in before launching any methods, so I just need to call them like this in my routes file:
Route::get('/home', 'TaskController#index');
Route::get('/tasks', 'TaskController#indexUser');
Then I wanted to remove the authentication requirement for the index method, so that all users can see the /home page (where I list all the tasks), and only authenticated users can see the /tasks page (where I list only the user tasks and allow to delete them). I managed to do it like this:
1) I removed $this->middleware('auth') from the TaskController constructor
2) I modified my routes file to look like this:
Route::get('/home', 'TaskController#index');
Route::get('/tasks', [
'middleware' => 'auth',
'uses' => 'TaskController#indexUser'
]);
Ok, this works, but:
What I want to achieve
I don't want to have this logic in my routes file, I want that my Controller decides which methods are public and which not. But I got stuck. I think it should be something like this:
class TaskController extends Controller
{
/**
* Display a list of all current tasks
*/
public function index()
{
return view('tasks.index', [
'tasks' => Task::orderBy('created_at', 'asc')->get()
]);
}
/**
* Display a list of all of the logged user's task.
*
*/
public function indexUser(Request $request)
{
if (Auth::check() {
return view('tasks.index_user', [
'tasks' => $this->tasks->forUser($request->user()),
]);
} else {
//This is what I don't know how to do:
redirect_to_login
}
}
}
How can I achieve this?
You can decide which controller method should execute the middleware:
public function __construct()
{
$this->middleware('auth', ['only' => ['indexUser', 'update'] ];
}
just add in only the method you want to protect.
When a user try to access a method will automatically redirect to the login page.
Here you can find the documentation: https://laravel.com/docs/5.1/controllers#controller-middleware
You can do the following if you want this logic in your controller:
if (!Auth::check()) {
return redirect('/path/to/login/page');
}
This way you don't have giant if else statement in your controller. (Handy if your controller contains more logic then the sample above)
I personally would go for the answer Christian Giupponi provided. Cause it makes much more sense to handle this logic in the construct function then in your controller.

Laravel 5 Auth Register After Login

I am trying to create users after login in Laravel 5. Register route is
get('auth/register', 'Auth\AuthController#getRegister');
It should be accessible with or without login as I have not used any middleware in it. But when I try to navigate to auth/register if logged in then It redirects me to /home. I can only access it before login.
How can I make it accessible after login?
The middleware is set in the App\Http\Controllers\Auth\AuthController.php class constructor.
If your using Laravels boilerplate authentication controller, it will probably look something like this:
class AuthController extends Controller
{
...
public function __construct()
{
$this->middleware('guest', ['except' => 'getLogout']);
}
...
}
You could remove the $this->middleware() line entirely to prevent the middleware being applied to all your login and register routes.
Alternatively you could add any route exceptions to the array passed as the second parameter to prevent the middleware being applied to just those methods.
$this->middleware('guest', ['except' => ['getLogout', 'getRegister', 'postRegister']]);
You need to simply comment the line.
public function __construct(Guard $auth, Registrar $registrar)
{
$this->auth = $auth;
$this->registrar = $registrar;
//$this->middleware('guest', ['except' => 'getLogout', 'getRegister', 'postRegister']);
}

Bind middleware to controller in laravel 5

I want to use middleware in my controller , but I don't know route beforehand, as I take slug from my DB.
Is it possible in laravel 5?
Thank you in advance
Inside your controller's constructor, do the following:
public function __construct()
{
//This will apply to every method inside the controller
$this->middleware('auth');
//This will apply only to the methods listed inside the array
$this->middleware('log', ['only' => ['fooAction', 'barAction']]);
//This will apply only to the methods except the ones listed inside the array
$this->middleware('subscribed', ['except' => ['fooAction', 'barAction']]);
}
You can read about that here

Resources