Where are these routes names set in Laravel? - laravel

Netbeans isn't showing where the Auth::routes(); is, ctrl+clicking on it, and I'm trying to see why this
<a href="{{ route('register') }}">
works but my own route in web.php does not work. Where is this file setting these? I assume this is a more proper way to set the url because /mynameroute could possibly not work if sites were within some sub directory in different environments?

Auth::routes() is Route::auth() which is Illuminate\Routing\Router#auth. It isn't setting these routes in any special way; you could define them yourself if you wanted to.
For generating URLs there are multiple functions you can use depending on what you need:
Laravel 6.x Docs - URL Generation

All Auth::routes() is declared or works from /vendor/laravel/framework/src/Illuminate/Routing/Router.php files's auth() method you can see there
public function auth()
{
// Authentication Routes...
$this->get('login', 'Auth\LoginController#showLoginForm')->name('login');
$this->post('login', 'Auth\LoginController#login');
$this->post('logout', 'Auth\LoginController#logout')->name('logout');
// Registration Routes...
$this->get('register', 'Auth\RegisterController#showRegistrationForm')->name('register');
$this->post('register', 'Auth\RegisterController#register');
// Password Reset Routes...
$this->get('password/reset', 'Auth\ForgotPasswordController#showLinkRequestForm')->name('password.request');
$this->post('password/email', 'Auth\ForgotPasswordController#sendResetLinkEmail')->name('password.email');
$this->get('password/reset/{token}', 'Auth\ResetPasswordController#showResetForm')->name('password.reset');
$this->post('password/reset', 'Auth\ResetPasswordController#reset');
}

Related

How to pass more than one gate in middleware? (Laravel)

I am creating a Learning Management System for my university final year project (only recently introduced to laravel). I have set up three different roles (admin, instructor and student). I have created two views which only the admin&instructor can access, 'user management' and 'course management'. Within each admin&instructor can create users/courses and delete as required.. a student cannot view these or has access to so that is working as desired. To do so I have created a gate 'manage-user' and then passed this into the middleware.
I have now created a calendar, which I would like all user roles to view.. again i created a gate for this.. due to my current middleware i am getting 'unauthorised access' when a student attempts to view the calendar.. is it possible to pass another gate within the middleware? I tried to do so with no success.. After many attempts of trial and error I have resulted to asking a question on here hoping i can figure this out...
i will paste my code below.. any help is appreciated.
AuthServiceProvider.php
public function boot()
{
$this->registerPolicies();
//User Management
Gate::define('manage-users', function($user){
return $user->hasAnyRoles(['admin', 'instructor']);
});
//Calendar
Gate::define('manage-calendar', function($event){
return $event->hasAnyRoles(['admin', 'instructor', 'student']);
});
web.php
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/home', 'HomeController#index')->name('home');
Route::namespace('Admin')->prefix('admin')->name('admin.')->middleware('can:manage-users')->group(function(){
//Users
Route::resource('/users', 'UsersController', ['except' => ['show']]);
//Courses
Route::resource('/courses', 'CoursesController', ['except' => ['show']]);
Route::get('events', 'EventsController#index')->name('events.index');
Route::post('/addEvents', 'EventsController#addEvent')->name('events.add');
});
I understand that the issue lays within the gate manage-users that I have defined.. I am not sure what way to go about it protect my other routes from students &instructors...
Thanks in advance :)
The manage-users Gate will not allow a user with student role to go through the middleware, even if the manage-calendar Gate does.
I suggest you regroup the routes to apply the middleware that corresponds to each route:
Route::namespace('Admin')->prefix('admin')->name('admin.')->group(function(){
Route::middleware('can:manage-users')->group(function(){
Route::resource('/users', 'UsersController', ['except' => ['show']]);
Route::resource('/courses', 'CoursesController', ['except' => ['show']]);
});
Route::middleware('can:manage-calendar')->group(function(){
Route::get('events', 'EventsController#index')->name('events.index');
Route::post('/addEvents', 'EventsController#addEvent')->name('events.add');
});
});

Laravel policies strangely not working

The point is simple: I have a UserPolicy method that checks if a user wants to edit his/her own profile. So I did like this:
public function update(User $user, User $model)
{
return $user->id === $model->id;
}
And this is called in a UserController as it follows:
public function edit(User $user)
{
$this->authorize('update', $user);
return view('users.edit')->with('user', $user);
}
Everything is the same in a PostController and a PostPolicy, meant to check if a user can edit his/her own post and it works. The only difference is in their signature, since one has two users (the first one is the currently authenticated user injected by Laravel and the other is the instance I want to check it with) and the other has the above seen automatically injected authenticated user and a post instance. Anyway, it throws:
Symfony \ Component \ HttpKernel \ Exception \ AccessDeniedHttpException
This action is unauthorized.
I tried to dd($model) but I got the same exception.
Why? Thanks in advance!
EDIT
In my AuthServiceProvider is all set up, too:
protected $policies = [
// 'App\Model' => 'App\Policies\ModelPolicy',
Post::class => PostPolicy::class,
User::class => UserPolicy::class,
];
And so is my routes.php:
// Authentication Routes...
$this->post('login', 'Auth\LoginController#login')->name('login');
$this->post('logout', 'Auth\LoginController#logout')->name('logout');
// Registration Routes...
$this->post('register', 'Auth\RegisterController#register')->name('register');
// Password Reset Routes...
$this->get('password/reset', 'Auth\ForgotPasswordController#showLinkRequestForm')->name('password.request');
$this->post('password/email', 'Auth\ForgotPasswordController#sendResetLinkEmail')->name('password.email');
$this->get('password/reset/{token}', 'Auth\ResetPasswordController#showResetForm')->name('password.reset');
$this->post('password/reset', 'Auth\ResetPasswordController#reset');
Route::get('/', 'HomeController#index')->name('home');
Route::resource('posts', 'PostController');
Route::resource('users', 'UserController')->except('index', 'create', 'store');
Everything above is called right here:
#if ($user->id == Auth::id())
<a class="btn btn-link float-right p-0"
href="{{ route('users.edit', Auth::id()) }}">
<i class="fas fa-cog"></i>
Edit profile
</a>
<br><br><br>
#endif
I'm giving an answer myself: I tried to write the model and policy's full paths instead of registering the policies by the classes' names and it works (I don't know why, of course).
I did like this:
protected $policies = [
// 'App\Model' => 'App\Policies\ModelPolicy',
'App\User' => 'App\Policies\UserPolicy',
'App\Post' => 'App\Policies\PostPolicy',
];
Anyway, thanks everyone for trying to help me. Hope it will help someone else one day!
I just solved the same issue after fighting a whole day. Using full paths for register did not work for me. I fixed it by modifying my routes. I post my solution here hoping it may help someone someday.
If your routes are not protected by the authentication middleware, an AccessDeniedException will be thrown before applying your policies. The reason is that if your request comes in directly, you will never be treated as a logged-in user, so that you will be kicked off when trying to call $this->authorize('update') within the controller.
Route::middleware("auth:sanctum")->group(function () {
Route::post('/member/{id}', [MembersController::class, 'update']);
// ... and other path.
});

Custom function in Controller with resource wont work

I have created my own custom function in my RoomsController
public function join($id){
return $id;
}
Then I want to pass variable to it and it says MethodNotAllowedHttpException
And my Form looks like this
{{Form::open(['action'=> ['RoomsController#join', $room->id], 'method' => 'POST' ])}}
{{Form::submit('Join', ['class' => 'btn btn-danger'])}}
{{Form::close()}}
Also have these routes
Route::get('/','PagesController#index');
Route::get('/about', 'PagesController#about');
Route::get('/services', 'PagesController#services');
Route::get('/register', 'PagesController#register');
Route::get('/logout', 'PagesController#logout');
Route::get('/rooms/join', 'RoomsController#join');
Route::resource('posts','PostsController');
Route::resource('rooms','RoomsController');
Auth::routes();
Route::get('/dashboard', 'DashboardController#index');
I have tried in many different ways i dont know why it is not working. All update edit destroy resource functions are working. Thank's for helping :)
You're submitting a POST request but the route is expecting a GET request. If you change your route to Route::post('/rooms/join', 'RoomsController#join'); it should work
change the method to post and put the route below the resource route
Route::resource('rooms','RoomsController');
Route::post('/rooms/join', 'RoomsController#join');

Cannot use Auth::routes(); outside default routes/web.php

I have a simple app with a Group in RouteServiceProvider..
// Web routes
protected function mapWebRoutes()
{
Route::group(['domain' => 'example.com']), function()
{
Route::middleware('web')
->namespace($this->namespace);
->group(base_path('routes/web.php'));
});
// Match any other domains or subdomains
Route::group(['domain' => '{domain}'], function()
{
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/org.php'));
});
}
In routes/web.php i can call Auth::routes(); fine;
but in routes/org.php i get a missing required parameters from my views that need the named auth routes (made by default laravel)
"Missing required parameters for [Route: login] [URI: login]. (View: .../resources/views/layouts/loginmenu.blade.php) (View: .."
Issue was not the Auth::routes function but the fact that the {domain} wildcard did not set a domain in the routes (as it would without the wildcard)
To use default auth routes naming conventions you must update the views to include the domain parameter next to the name.
example:
{{ route('login') }}
needs to be
{{ route('login', ['domain'=>$domain]) }}
Of couse you must make the Domain variable available in views. The easiest way (instead of passing it around the controller like a maniac is to simply share the domain variable with the view.
In my middleware in the constructor of my Controller i call:
view()->share('domain', $domain);

Laravel - passing route parameter to blade

I am using Laravel 5.6, with the default make:auth mechanism.
In the routes/web.php, I would like to add a language middleware as follow:-
Route::prefix('{lang}')->group(function () {
Route::get('password/reset', 'Auth\ForgotPasswordController#showLinkRequestForm')->name('password.request');
});
Now I wish to apply this in blade:-
<a href="{{ route('password.request') }}">
But debugger just say:-
Missing required parameters for [Route: password.request] [URI: {lang}/password/reset].
I believe the blade cannot not get the {lang} from route. How can it be achieved?
Try this
<a href="{{ url('en') }}/password/reset">
When you pass a prefix in the route it means that it is going to be included in the route, so when you say
Route::prefix('{lang}')->group(function () {
Route::get('password/reset' .......
Route::get('foo/bar' .......
it means the route will be like this "http://yourwebsite.com/{lang}/password/reset"
"http://yourwebsite.com/{lang}/foo/bar"
so each time you pass any route that falls in that group will need to have a variable called $lang so the link can be initialized.
so in your case
<a href="{{ route('password.request', ['lang' => 'en']) }}"> //you can change en to your preferred language.
if you want to add a middleware to specific route or route group, it is passed in this way
Route::get('/', function () {
//
})->middleware('first', 'second');
or
Route::group(['middleware' => ['first']], function () {
//
});
if you want to create another language, you can check the below links:
Laravel localization
spatie/laravel-translation-loader

Resources