laravel auth middleware: one route, two views - php

I am building a store so i could learn laravel.
Like most stores, users can add items to a cart but cannot checkout until they register.
How do i have the same route return a user name when authorized and a nothing when an authorized.
This seemed very easy to me at first:
#if(Auth::guest())
Nothing || or login/register buttons
#else
{{ Auth::user()->name }}
#endif
That works well when you have content that should only be visible to loyal users but for a store, you need users to see whats there to offer.
The problem is that, in my home controller, i need to add middleware auth in the constructor function so that Route::get('/',HomeController#index); returns a view and in the view use #if(Auth::guest()) ..., but adding this middleware means this route is not accessible if the user is not Authenticated and without it you get this issue.
So how do i have the same root route with Authenticated user data(if authenticated) without blocking the route from unauthenticated users?

If i am understanding what you are asking (Though i believe i dont quite fully get what you mean).
You want to use the Auth::user() or Auth::check() throughout your views? This should be available out of the box especially when you have used php artisan make:auth.
One way to achieve this would be to use view->share() in a service provider on the boot method, This will then make the $user variable or $isSignedIn variable available in all views.
For example in your App\Providers\AppServiceProvider
namespace App\Providers;
use App\User;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Auth;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
view()->share('isSignedIn', Auth::check());
view()->share('user', Auth::user() ?: new User());
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
}
If this is not going to help let me know and i can help towards getting the outcome you need.
- Update
On your HomeController can you try:
use App\User;
use Illuminate\Support\Facades\Auth;
and in your index() method can you add:
if(Auth::user()){
$user = Auth::user();
}else{
$user = new User();
// or you can use:
$user = Auth::guest();
// If you use $user = Auth::guest() you can remove the Use App\User;
}
return view('home', compact('user'));
See if that does anything for you?

Related

Laravel 7 redirects to login Page

I have a code in HomeController.php in the Laravel framework, but I could not access the index/homepage it redirects to the login page. what is the blunder I am committing?
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$users = User::get();
return view('home', compact('users'));
}
public function user($id){
$user = User::find($id);
return view('user', compact('user'));
}
public function ajax(Request $request){
$user = User::find($request->user_id);
$response = auth()->user()->toggleFollow($user);
return response()->json(['success'=> $response]);
}
}
The answer is simple. In the __construct() method, you specified that every function under this controller must use the auth middleware. This will redirect to login page is the user is not logged in.
There are a number of ways to work around this, the first being to remove the __construct entirely. However, this is not so recommended.
Another would be to add an except() function
public function __construct()
{
$this->middleware('auth')->except('index');
}
This will allow the condition to apply anywhere else other than the index function.
Based on the code you posted, the homepage route is protected by the 'auth' middleware, which means users have to login to access the resource page (Home page), so you should first login and then it will direct you to the intended page. If you don't want the page to be protected, then you could either remove the $this->middleware('auth') in your constructor, or you could put the index() function separately in a different Controller file and leave it unprotected
you can also control it in the routes (routes/web.php).
Or as already mentioned with middleware: Assigning Middleware To Routes
Route Group
Use route grouping in your web.php file
This way you can determine middleware for specific routes, you can also use grouping inside route group also
And don't use middleware in controller, use it in web.php so you can have a proper idea that how many routes are using middleware

Laravel policies: no usages in project, only 403

I am trying to use laravel policies to check if a story is "visible" and if it isn't, if the authenticated user ownes the story (in which case he can still view it). I set up my policy using
php artisan make:policy StoryPolicy --model=Story
There I set up the checks required to see if the authenticated user can see the Story or not
<?php
namespace App\Policies;
use App\User;
use App\Story;
use Illuminate\Auth\Access\HandlesAuthorization;
class StoryPolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can view the story.
*
* #param \App\User $user
* #param \App\Story $story
* #return mixed
*/
public function view(User $user, Story $story)
{
if ($story->visibility == 'visible') {
return true;
} else {
return $story->user_id == $user->id;
}
}
}
I register the policy in my AuthServiceProvider
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* #var array
*/
protected $policies = [
'App\Story' => 'App\Policies\StoryPolicy'
];
/**
* Register any authentication / authorization services.
*
* #return void
*/
public function boot()
{
$this->registerPolicies();
}
}
As I understand it, I should be able to use this policy in my controller. That is what I did.
<?php
namespace App\Http\Controllers;
use App\Storyblock;
use App\User;
use Illuminate\Http\Request;
use App\Category;
use App\Story;
class StoryController extends Controller
{
public function __construct(){
$this->middleware('auth')->except('show');
}
// GET shows the story page
public function show(Story $story) {
$this->authorize('view',$story);
return view('story.show', compact('story'));
}
}
this however always result in a 403
I've tried many things, changing up the way the policies are set, changing the logic dd'ing if all is correct. After 4 hours of lookign online I failed to come up with an answer.
Also, in my phpStorm I noticed that my policy files are indicated red with no usages over the entire project. This makes me think that I somehow fail to import them in my AuthServiceProvider
i don't see all your code but you get this message when you want to access of lavarel resouce and you don't have the scrf token make sure all your view or on the app view header you have this
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
i think you just try to get a resource without this then it just tell you don't have access of this one.
You have specified that the show method isn't going to have the auth middleware assigned, so there may not be an authenticated User. From the Policy documentation:
"By default, all gates and policies automatically return false if the incoming HTTP request was not initiated by an authenticated user"
You will need to continue reading the Policy documentation for how to handle the lack of an authenticated user, guest.
Laravel 5.7 Docs - Authorization - Writing Policies - Guest Users

Laravel 5.2 default auth, how to register when authenticated

I need to be able to do a post method to the default "/register" from a form even when im already authenticated.
Currently its not possible, I get no errors but I don't get a record in my database.
My form and code works when im not logged in.
Where do i need to make changes so it will work?
I think its near the registersusers.php but that code is completely new to me.
By default you cannot do this because the guest middleware stops logged in users from accessing the registration page.
In your AuthController (provided by Laravel in app/Http/Controllers/Auth) you can specify which methods should remain accessible to non-guests (or authenticated users).
By default only the logout method is available to logged in users, however you can add anymore you wish.
public function __construct()
{
$this->middleware($this->guestMiddleware(), ['except' => ['logout', 'showRegistrationForm', 'register']]);
}
showRegistrationForm is responsible for showing the login page and form, register is responsible for processing the registration and persisting it.
Technically, it's working as intended. A logged in user shouldn't be able to register a user, that doesn't make sense.
However, you can simply use the RegistersUsers trait within your own Controller in order to attempt to register a user. It's as simple as this:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class RegistrationController extends Controller {
uses RegistersUsers;
public function create(Request $request){
return $this->postRegister($request);
}
}
The ->postRegister() method is provided by the RegistersUsers trait. It accepts an \Illuminate\Http\Request object and is injected as a dependency, so you must only pass an instance of \Illuminate\Http\Request. You can easily display the registration form as well by simply just calling $this->showRegistrationForm();, such as this:
public function show(){
return $this->getRegister();
}
Now just attach your routes accordingly.

As correctly use policies in laravel 5.2? I can not

I have a problem, I can not use policies in laravel 5.2.
I have 2 tables, students and tasks.
I try to apply a policy to prevent editing of a task by changing the url, but I always get the message This action is unauthorized although the task is the correct user.
Policy Code:
<?php
namespace App\Policies;
use App\Models\Student;
use App\Models\Task;
class TasksPolicy
{
public function edit(Student $student, Task $tasks)
{
return $student->id === $tasks->student_id;
}
}
Code in AuthServiceProvider.php
<?php
namespace App\Providers;
use App\Models\Task;
use App\Policies\TasksPolicy;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* #var array
*/
protected $policies = [
Task::class => TasksPolicy::class
];
And then the call in the TaskController.php file:
public function edit($id)
{
$tasks = Task::findOrFail($id);
$this->authorize('edit', $tasks);
return view('tasks.edit', compact('tasks'));
}
I think the code is good because I've revised several times, but as I said earlier I always get the message This action is unauthorized although the task is to edit the user.
http://i.imgur.com/2q6WFb3.jpg
What am I doing wrong? As I can use the policy correctly?
you are using "===" which means that both side data and datatype will match.May be your data are matched,not datatype,you may try using "=="
public function edit(Student $student, Task $tasks)
{
return $student->id == $tasks->student_id;
}
Two things: one is the name of the method and the other is the order of parameters. The method name should be 'update', not 'edit' - these are predefined, at least in later versions of Laravel. You might be getting the authorization error because the name 'edit' is not recognized by Laravel, so the policy for update is never defined.
The order of arguments also matters. When there are parameters passed to policy methods, the User model has to be the first parameter, followed by all the others.
public function update(User $user, [... other objects...])
So, you'd have
update(User $user, Student $student, Task $tasks)
Laravel will inject the Authenticated User Model but other objects have to be passed directly.
$this->authorize('edit', $student, $tasks);
Hopefully that will work.
If your Student class extends User Class, you may be thinking that you can substitute Student for User in the method prototype. You can't do that - that's a different method altogether.

How to validate credentials in laravel 5 for logging in features?

I am new to Laravel and I am using tutorial for web app. Tutorial uses Laravel 4 whereas I am using Laravel 5. I solved register issue but when I set down to test for login following errors shown up:
ErrorException in EloquentUserProvider.php line 111: Argument 1 passed to Illuminate\Auth\EloquentUserProvider::validateCredentials() must be an instance of Illuminate\Contracts\Auth\Authenticatable, instance of App\user given, called in C:\Users\Pujan\Desktop\projectlaravel\vendor\laravel\framework\src\Illuminate\Auth\Guard.php on line 390 and defined.
I'm not able to figure out the issue here. What actually means credentials. I know Laravel 5 has inbuilt login features but couldn't use it so I tried out different ways but this problem out of my focus.
My usercontroller is:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use View;
use App\user;
use Input;
use App\Http\Requests\YourFormRequest;
use Auth;
//use Illuminate\Support\Facades\Auth;
class UserController extends Controller
{
public $restful = true;
public function index()
{
return View::make('users.new')->with('title', 'Make it snappy Q&A - Register');
}
public function create(YourFormRequest $request)
{
User::create($request->all());
return redirect('/')->with('message','Thanks for registering!');
}
public function getlogin()
{
// return \Auth::user();
return View::make('users.login')->with('title','Make it snappy Q&A - Login ');
}
public function createlogin()
{
$user = array(
'username'=>Input::get('username'),
'password'=>Input::get('password')
);
if (Auth::attempt($user))
{
return redirect('/')->with('message','You are logged in:');
}else{
return redirect('login')
->with('message','Your username or password are incorrect pls chk it out')
->with_input();
}
}
I have my routes:
Route::get('/','Questions#index');
Route::get('register','UserController#index');
Route::get('login','UserController#getlogin');
Route::post('register','UserController#create');
Route::post('login','UserController#createlogin');
My login layout is working properly but as I try to login above errors show up. I think this error belongs to inbuilt Laravel 5 features but I am not able to match the setting inbuilt and my created login functionality.
The error you're seeing isn't related to your login code. Your User entity should implement the Illuminate\Contracts\Auth\Authenticatable interface. An interface is a contract, it lists methods/functions that a class must have. The class definition should look like this:
class User extends Model implements Authenticatable
{
On a quick glance of your code, there are other things you can do to clean it up:
public function createlogin()
{
if (Auth::attempt(Input::only('username', 'password'))) {
return redirect('/')->with('message','You are logged in:');
}
return redirect('login')
->with('message','Your username or password are incorrect pls chk it out')
->with_input();
}
And on a final note, I'd stop using the tutorial you're following. Laravel's latest documentation has a quick start guide that covers authentication, there are two versions, beginnner and intermediate.
What #Logan has suggested is true, and you should follow that.
I'll just go with cleaning of your code a bit.
Whenever you are dealing with validations, you should treat it as a separate stuff and for that you need to create the FormRequest object.
Refer this document on how to create the form request.
Then update the authorize and rules method with the following:
/**
* Authorize the request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'username' => 'required|exists:users|alpha_dash|min:4',
'password' => 'required'
];
}
Now in your createLogin method
/**
* Log in the user.
*
* #param \App\Http\Requests\YourFileRequest $request
* #return \Illuminate\Http\RedirectResponse
*/
public function createlogin(YourFileRequest $request)
{
$credentials = $request->only('username', 'password');
if (Auth::attempt($credentials)) {
return redirect('/')->with('message','You are logged in:');
}
return redirect('login')
->with('message', 'Invalid credentials')
->with_input();
}
Now you see how your code is simple and readable when you visit after 6 months from now ? It has to be like that. Validation logic in separate file and your Login logic in the controller. According to me, this helps a lot when you are testing via phpUnit, phpSpec or any other testing tool you are using.
Me and Logan have also replaced your if statement block. That is because, you should avoid the else block as far as possible when you are returning something from both if and else block.
Just a side note:
You should always try to follow 3 principles while programming / coding: SOLID, KISS, and DRY.
Kindly document your code whenever you are done with that part of the code. This is will again help future programmers and also for future reference to know what that piece of code is doing.
Hope this helps you out. Cheers.
Not sure whether you have solved this issue or not but I'm putting my experience here, maybe it could help someone else looking for a solution to this problem which happened exactly with me.
Your App/User model class should extends Illuminate\Foundation\Auth\User and not the Eloquent Model.
So change your User model to this:
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
Instead of
class User extends Model
It did resolve this same error for me. Hope this helps.

Categories