I used the scaffolding tools to generate my authentication code for my laravel project. I created a UserController to make a profile page which works great but when I try to make a function that can be used on Auth::user() i get an error Call to undefined method Illuminate\Database\Query\Builder::admin()
Why isn't the admin function accessible on the Auth::user()? Doesn't that extend my UserController? Or am I mixing it up with the model? Is the the model a good place to check if my user is an admin?
Here is my user controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Auth;
use App\Http\Requests;
class UserController extends Controller
{
/**
* Create a new user controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* #return View with user data
*/
public function index() {
$user = Auth::user();
return view('users.index', compact('user'));
}
/**
* #return bool
* Returns bool if the user is an admin.
*/
public function admin() {
$user = Auth::user();
$authorized_users = [
'admin#test.com'
];
return array_key_exists($user->email, $authorized_users);
}
}
and I am calling it on a different route controller function
public function index() {
return Auth::user()->admin();
}
I am fairly new to laravel and php so any critique is valuable and wanted!
You could add a function or attribute to you User model, I prefer attributes:
//User.php
class User extends Model{
protected $appends = ['is_admin'];
public function getIsAdminAttribute()
{
$user = Auth::user();
$authorized_users = [
'admin#test.com'
];
return array_key_exists($user->email, $authorized_users);
}
...
}
//Then in your view
Auth::user()->is_admin
No, Auth::user() does not extends any Controller. It represents the instance of the currently logged in/authenticated user. It will allow you retrieve other attributes of the use such as id, name etc Auth::user()->admin(); does not make any sense. Auth::user() has nothing to do with the UserController or any other controller.
Related
In my Laravel project I want to authorize user via a Request like this:
<?php
namespace Domain\Contents\Http\Requests\Blog;
use Domain\Contents\Models\Blog\Post;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Gate;
class ReadPostRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
if (request('id') === null) {
abort(403);
}
$post = Post::whereId(request('id'))->first();
return Gate::allows('view-post', $this->user(), $post);
}
// ...
}
But I think here this part of my code is little bit messy:
if (request('id') === null) {
abort(403);
}
$post = Post::whereId(request('id'))->first();
Is there any simpler solution for accessing current Post model in the Request class?
The documentation for FormRequests suggests that the authorize() method supports type hinting.
If you are using route model binding you could therefore just type hint the post:
public function authorize(Post $post)
{
return Gate::allows('view-post', $this->user(), $post);
}
Alternative solution is that you can directly access your Models that are used with Model Binding.
return Gate::allows('view-post', $this->user(), $this->post);
For ease of use you can typehint it in the comments.
/**
* #property \App\Models\Post $post
*/
I am trying to show data related to user but unfortunately it's not working. Currently, when I submit order via my form, every account can see the data. How can I show data for only the specific person who submitted it?
Database
Table digitizing_orders table has
id | order_name | order_placement | user_id
Digitizingorder Model
class Digitizingorder extends Model
{
protected $table = "digitizing_orders";
public function user()
{
return $this->belongsTo('App\User');
}
}
User Model
class User extends Authenticatable
{
public function digitizing()
{
return $this->hasMany('App\Digitizingorder');
}
}
Controller
public function index()
{
$data = [
'digitizings' => Digitizingorder::with('user')->where('id', '!=', Auth::id())->get()
];
return view('front_end.Customerprofile.digitizing_view_order', $data);
}
Use Polices they can protect controller actions on a model from unauthorized users.
After generating and registering the policy you can use its methods like this:
class DigitizingorderPolicy
{
/**
* Determine if the given Model can be Viewed by the user.
*
* #param \App\User $user
* #param \App\Digitizingorder $digitizingorder
* #return bool
*/
public function view(User $user, Digitizingorder $digitizingorder)
{
return $user->id === $digitizingorder->user_id;
}
}
You can define what's inside the method to satisfy a condition for the user to view a model (e.g privileges or Role).
One of the ways to call it is in the controller:
public function show(Request $request, Digitizingorder $digitizingorder )
{
$this->authorize('view', $digitizingorder);
// The current user can view the digitizingorder ...
}
I suggest reading the docs about it, they're Multiple Ways/Methods to use Polices and might contain something useful for you.
use this in controller
$user = \Auth::guard('web')->user();
$data=
[
'digitizings'=> $user->digitizing
];
return view('front_end.Customerprofile.digitizing_view_order',$data);
I made a piece of middleware that is responsible to check the permission a user has. I implemented a hasPermission function in my User model. But when I try to use it via the auth()->user I get the following error, why is this happening?
I implemented this method in my User Model
public function hasPermission($permission)
{
return in_array($this->permissions(), $permission);
}
And this is the middleware
<?php
namespace App\Http\Middleware;
use Closure;
class VerifyPermission
{
public function handle($request, Closure $next, $permission)
{
if (auth()->check() && auth()->user()->hasPermission($permission)) {
return $next($request);
}
abort(401, 'Unauthorized');
}
}
It's because the user() method has a return type of \Illuminate\Contracts\Auth\Authenticatable|null which is an interface that your user class implements. This is because it might return different models based on the guard you're using but they all have to implement Authenticatable.
I'm not aware of an easy way to change this globally, but you could save the user in a variable and add a phpDoc block:
/** #var \App\User */
$user = auth()->user();
This should get picked up by intelephense and show the correct methods.
I create login and register function in Laravel 6 with scaffold function, and i got this LoginController:
<?php
...
...
class LoginController extends Controller
{
use AuthenticatesUsers;
protected $redirectTo = RouteServiceProvider::HOME;
public function __construct()
{
$this->middleware('guest')->except('logout');
}
}
I want to pass a data DB::table('terms_condition')->get() to login view, how should i do?
Put this method in LoginController
public function showLoginForm()
{
$terms_condition = DB::table('terms_condition')->get();
return view('auth.login',compact('terms_condition'));
}
showLoginForm() is from AuthenticatesUsers trait which is used by your LoginController. You have to put this method in LoginController.
Inside your login controller rewrite the function showLoginform
public function showLoginForm()
{
` $data = DB::table('terms_condition')->get();
return view('frontend.auth.login',compact('data'));
}
Or From your LoginController you can see that AuthenticateUsers
go to the Authenticate Users file and edit the showLoginForm as like this
public function showLoginForm()
{
` $data = DB::table('terms_condition')->get();
return view('frontend.auth.login',compact('data'));
}
And dont forget to use DB in the top
You can override the built-in showLoginForm() method in the LoginController
LoginController.php
use Illuminate\Support\Facades\DB;
class LoginController extends Controller
{
use AuthenticatesUsers;
protected $redirectTo = RouteServiceProvider::HOME;
public function __construct()
{
$this->middleware('guest')->except('logout');
}
public function showLoginForm()
{
return view('admin.login',['terms'=>DB::table('terms_condition')->get()]); //pass your data here as a second argument
}
}
You can then access this in your blade view as $terms
A different way to go about it: use a View Composer. This will run when the view is rendered so you can pass data to it this way:
view()->composer('auth.login', function ($view) {
$view->with('something', DB::table(...)->get());
});
// or View::composer(...) if you prefer
You can add that at a Service Provider's boot method. No overriding anything.
Laravel 6.x Docs - Views - View Composers View::composer()
All my code is working on Laravel 5.2. Now I try to upgrade to Laravel 5.3 it breaks on middleware.
// Verify Middleware
public function handle($request, Closure $next)
{
// I already make sure the data is exists
$user = User::find('abc');
if (!$user) {
return responseHandler()->unauthorized('Unauthorized');
}
$request->merge(['user_id' => $user->id, 'device' => $device]);
return $next($request);
}
// User Controller
public function __construct(Request $request)
{
var_dump($request->all());
$this->user_id = $request->user_id;
$this->device = $request->device;
}
public function getProfile(Request $request)
{
$data = User::find($this->user_id);
$result = Fractal::item($data, new UserTransformer)->getArray();
return responseHandler()->success(0, $result, 'user');
}
The problem is $this->user_id is always null. But if I request from getProfile function it return correctly.
var_dump result only the login info. it not received any merge request from middleware
On Laravel 5.2 this code is working properly. Any solution?.
Reference-: https://www.laravel.com/docs/5.3/upgrade#upgrade-5.3.0
Session In The Constructor
In previous versions of Laravel, you could access session variables or the authenticated user in your controller's constructor. This was never intended to be an explicit feature of the framework. In Laravel 5.3, you can't access the session or authenticated user in your controller's constructor because the middleware has not run yet.
As an alternative, you may define a Closure based middleware directly in your controller's constructor. Before using this feature, make sure that your application is running Laravel 5.3.4 or above:
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
class ProjectController extends Controller
{
/**
* All of the current user's projects.
*/
protected $projects;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware(function ($request, $next) {
$this->projects = Auth::user()->projects;
return $next($request);
});
}
}
Of course, you may also access the request session data or authenticated user by type-hinting the Illuminate\Http\Request class on your controller action:
It seems you can't access the session data in Controller constructor because the middleware not run yet.
Refer laravel change log here
you can't access the session or authenticated user in your
controller's constructor because the middleware has not run yet.
In your case you can call session with request object
public function getProfile(Request $request)
{
$data = User::find($request->session()->get('user_id'));
$result = Fractal::item($data, new UserTransformer)->getArray();
return responseHandler()->success(0, $result, 'user');
}