Laravel Nova multiple resources for same user model - laravel

I have a laravel + nova project.
Currently I have a USER model, with 'admin' column, with values 0 or 1.
I use this model for nova dashboard login.
Now, I want to separate admin users and normal users in nova dashboard. Like showing two Resources 1 ) Admins 2 ) Users at left side in nova dashboard.
Can I user same User model for two resources?
Currently it is showing two resources with names Admins and Users, but both opens admin list all time. Not the users list at all.
Thanks

Since Admins and Users are not separate users in your case, consider using Filters instead for your User resource.
To answer your question, if you want to stick to your implementation of 2 Nova resources for Admin and User respectively, you can add override the index query that is made to your Nova resource. To override this behaviour, add the following code to the Nova resource:
App\Nova\Admin.php
/**
* Build an "index" query for the given resource.
*
* #param \Laravel\Nova\Http\Requests\NovaRequest $request
* #param \Illuminate\Database\Eloquent\Builder $query
* #return \Illuminate\Database\Eloquent\Builder
*/
public static function indexQuery(NovaRequest $request, $query)
{
return $query->where('admin', 1);
}
And the following code to
App\Nova\User.php
/**
* Build an "index" query for the given resource.
*
* #param \Laravel\Nova\Http\Requests\NovaRequest $request
* #param \Illuminate\Database\Eloquent\Builder $query
* #return \Illuminate\Database\Eloquent\Builder
*/
public static function indexQuery(NovaRequest $request, $query)
{
return $query->where('admin', 0);
}
Note: with the above solution users can still manually navigate to yourwebsite.test/nova/resource/admins/{id}. Consider adding Authorization, so users can't view admins for example (depending on your use case).

Related

How can I use Policies whithout User model?

Today I am facing a problem. I have several levels of authentication on my site, and on my nova, I connect with the Administrators table. How can I use it to declare Policies other than with User?
I tried to do it like this:
/**
* Determine whether the user can view any models.
*
* #param Administrator $admin
* #return mixed
*/
public function viewAny(Administrator $admin)
{
return $admin->superadmin == 1;
}
The problem being that I get an error telling me that I'm not using the User model when I'm waiting for it? How can I fix this problem? I would like to give access to a nova page only to administrators who have the "superadmin" column on 1...
My table looks like this. It's named "administrators".
I've been stuck for quite a long time on this problem without really finding solutions... Do I have to use the User model?
You can make use of Guest users
From laravel documentation
Guest Users
By default, all gates and policies automatically return false if the incoming HTTP request was not initiated by an authenticated user. However, you may allow these authorization checks to pass through to your gates and policies by declaring an "optional" type-hint or supplying a null default value for the user argument definition:
<?php
namespace App\Policies;
use App\Models\Post;
use App\Models\User;
class PostPolicy
{
/**
* Determine if the given post can be updated by the user.
*
* #param \App\Models\User $user
* #param \App\Models\Post $post
* #return bool
*/
public function update(?User $user, Post $post)
{
return optional($user)->id === $post->user_id;
}
}

how to set up and authentication system allowing admin to go the dashboard, and regular user to his profile?

I want to create a system login, that direct the regular users to their profiles, and direct the admin to the dashboard, using the same logging form is that possible in laravel??
i was looking for a solution for that problem, if any one have any idea how to do it??
Assuming you have used Laravel's default auth scaffolding, you can customize how the user is redirected after logging in by modifying the authenticated method in your LoginController :
/**
* The user has been authenticated.
*
* #param \Illuminate\Http\Request $request
* #param mixed $user
* #return mixed
*/
protected function authenticated(Request $request, $user)
{
if ($user->hasRole('admin')) { // If using spatie/laravel-permissions
return redirect()->route('dashboard');
}
return redirect()->route('profile', ['user' => $user]);
}

how to check whether a restaurant is verified in laravel

I am new to laravel and trying to make a panel for food delivery
I have used Laravel default Registration and Login for User Category--Restaurant
and then after user login , the user can Add restaurant details using route (/add_details)
once the user has added restaurant details the user should not be able to go to that route (/add_details)
this will depend on a column in restaurant table (is_verified)
how do i check that
I was thinking of using a Laravel middleware
but then i was stuck how laravel middleware $request variable works
how can i get column value in middleware and verify it
or if any other simple but effective solution
as
i will be using it in sidebar.blade.php as well
so that i can hide the menu
I made a middleware and added it to kernel.php and is using it in routes
Its working fine
but i want to ask is this the right way i have done it
Route::get('/manage_cuisines', 'RestaurantCuisineController#create')->name('manage-cuisines')->middleware('restaurant_verified');
<?php
namespace App\Http\Middleware;
use Closure;
use Auth;
use \App\User;
use \App\Restaurant;
class CheckRestaurantVerification
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$restaurant = Restaurant::find(User::find(Auth::id())->restaurant_id);
if($restaurant->is_verified == 0)
{
return redirect('home');
}
return $next($request);
}
}

Laravel only retrieve Model Records if they belong to authenticated user

I'm using Laravel 5.4 and have a Model called Order.
To test things I've created two users and two Orders, each user having one Order.
I've just seen that I'm able to retrieve the order of someone who is not my current user. I'm retrieving a list of user's own orders using Auth::user()->orders. But in order to show the details of a specific order I do this:
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
$order = CustomerOrder::findOrFail($id)->with('products')->get();
return view('order.show')
->with('order', $order);
}
What am I missing out here? Is there a middleware or something to tell the application to only allow access to orders associated with the authenticated user?
Edit: So I've tried to do it using a Policy OrderPolicy (CRUD).
The view() fucntion of the Policy:
/**
* Determine whether the user can view the customerOrder.
*
* #param \App\User $user
* #param \App\CustomerOrder $customerOrder
* #return mixed
*/
public function view(User $user, CustomerOrder $customerOrder)
{
return $user->id === $customerOrder->user_id;
}
And I've registered it in the AuthServiceProvider.php:
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
Adress::class => AdressPolicy::class, //Doesn't work either
Order::class => OrderPolicy::class
];
I can still check the Order for another user.
You have a few options. The best option in my option is the use Policies. The documentation for this can be found here:
https://laravel.com/docs/5.4/authorization
Alternatively do could do something like:
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
$user = request()->user();
$order = $user->orders()->with('products')->find($id)->get();
return view('order.show', compact('order'));
}
With an orders relationship function on your user model.
Updated Reply
With the policy you gave, and with your resource route, you should be able to do:
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show(CustomerOrder $order)
{
$this->authorize('view', $order);
return view('order.show', compact('order'));
}
Another way would be to use the defined relationship and tell it to only retrieve the one with id $id. Like this:
$customerOrder = auth()->user()->orders()->with('products')->find($id);
If you want to get orders which belong to authenticated user, do this:
CustomerOrder::where('user_id', auth()->user()->id)->with('products')->find($id);
Remember,
first you create policy.
second you register it.
third you use something like $this->authorize('view', $order); in your normal controller.
You are missing the third step, you can find the doc here:
[https://laravel.com/docs/5.8/authorization#authorizing-actions-using-policies][1]

Laravel 5.3 Auth block user

I have a question, I'm currently developing a little site with Laravel 5.3 and I'm using the Basic Auth from them for users to register and login.
Now I want the following: Everybody can register and login, but if I click on a button (as an admin), I can "block" one specific user (for example if he did something not allowed), I don't completely delete the row in the database, but somehow make sure that if the user tries to login he get's a message saying something like "you can't login any more, your account is blocked, contact admin for more info" or something similar. The question is: Whats the best way to do this? I didn't find something built in, correct me if I'm wrong...
Ofcourse, I could just alter the users table and add a column called "blocked", set to false normally, then with the button, set it to true and then when logging in somehow checking for this value and (if it's true) showing this message and not allowing log in. Is this the best way to do this? If yes, where would I have to check for this value and how can I show the message then? If not, whats the better way?
I would do what you're suggesting - use a blocked or active column to indicate if the user should be able to log in. When I've done something similar in the past, to check this value upon login, I moved the out-of-the-box login function into my LoginController and added to it a bit. My login method now looks like this:
/**
* Handle a login request to the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function login(Request $request)
{
$this->validateLogin($request);
$user = User::where('email', $request->email)->firstOrFail();
if ( $user && !$user->active ) {
return $this->sendLockedAccountResponse($request);
}
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
if ($this->attemptLogin($request)) {
return $this->sendLoginResponse($request);
}
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
I also added these functions to handle users who weren't active:
/**
* Get the locked account response instance.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
protected function sendLockedAccountResponse(Request $request)
{
return redirect()->back()
->withInput($request->only($this->loginUsername(), 'remember'))
->withErrors([
$this->loginUsername() => $this->getLockedAccountMessage(),
]);
}
/**
* Get the locked account message.
*
* #return string
*/
protected function getLockedAccountMessage()
{
return Lang::has('auth.locked')
? Lang::get('auth.locked')
: 'Your account is inactive. Please contact the Support Desk for help.';
}
You can use soft deleting feature.
In addition to actually removing records from your database, Eloquent can also "soft delete" models. When models are soft deleted, they are not actually removed from your database. Instead, a deleted_at attribute is set on the model and inserted into the database. If a model has a non-null deleted_at value, the model has been soft deleted.
step1:
add new field to the User table called ‘status’ (1:enabled, 0:disabed)
step2:
to block the web login , in app/Http/Controllers/Auth/LoginController.php add the follwoing function:
/**
* Get the needed authorization credentials from the request.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
protected function credentials(\Illuminate\Http\Request $request)
{
$credentials = $request->only($this->username(), ‘password’);
return array_add($credentials, ‘status’, ‘1’);
}
Step3:
to block the user when using passport authentication ( token ) , in the User.php model add the following function :
public function findForPassport($identifier) {
return User::orWhere(‘email’, $identifier)->where(‘status’, 1)->first();
}
refer to this link ( tutorial) will help you : https://medium.com/#mshanak/solved-tutorial-laravel-5-3-disable-enable-block-user-login-web-passport-oauth-4bfb74b0c810
There is a package which not only blocks users but also lets you to monitor them before making a decision to block them or not.
Laravel Surveillance : https://github.com/neelkanthk/laravel-surveillance
Solved: this link ( tutorial) will help you : https://medium.com/#mshanak/solved-tutorial-laravel-5-3-disable-enable-block-user-login-web-passport-oauth-4bfb74b0c810
step1:
add new field to the User table called ‘status’ (1:enabled, 0:disabed)
step2:
to block the web login , in app/Http/Controllers/Auth/LoginController.php add the follwoing function:
/**
* Get the needed authorization credentials from the request.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
protected function credentials(\Illuminate\Http\Request $request)
{
$credentials = $request->only($this->username(), ‘password’);
return array_add($credentials, ‘status’, ‘1’);
}
Step3:
to block the user when using passport authentication ( token ) , in the User.php model add the following function :
public function findForPassport($identifier) {
return User::orWhere(‘email’, $identifier)->where(‘status’, 1)->first();
}
Done :)

Resources