I followed the documentation for creating a model observer here https://laravel.com/docs/5.5/eloquent#observers.
But when I try and access the authenticated user I get null.
How can I access the authenticated user in the model observer?
<?php
namespace App\Observers;
use App\Customer;
class CustomerObserver
{
public function created(Customer $customer)
{
dd(auth()->user());
}
public function updated(Customer $customer)
{
dd(auth()->user());
}
}
I've also tried this inside the Customer model and it returns null as well.
public static function boot()
{
parent::boot();
self::updated(function ($model) {
dd(auth()->user());
});
}
Ok, so stupid mistake on my end.
Thanks #fubar for the tip.
I was using a custom authentication provider so I needed to do this:
dd(auth()->guard('admin')->user());
Related
While using Laravel Actions Package the model is not binding and returning an empty array.
What am I missing?
namespace App\Actions\User;
use App\Models\User;
use Illuminate\Routing\Router;
use Lorisleiva\Actions\Concerns\AsAction;
class GetUserAction
{
use AsAction;
public static function routes(Router $router)
{
$router->get('users/{user}', static::class);
}
public function handle(User $user): User
{
return $user;
}
RouteServiceProvider
public function boot()
{
Actions::registerRoutes();
}
If I run
public function handle(ActionRequest $request, User $user): User
{
dd($request->route()->parameters());
}
on the handler it does return the id parameter.
I'd like to keep the declaration of the route inside the Action as suggested in the documentation
If I declare it in the routes file it works
Route::get('/users/{user}', GetUserAction::class);
Trying to implement simple access authorization with Lumen. It works when doing the update (PUT) action.
But I would also like to handle accessing for example all articles.
I also tried the viewAny or view policy method but no success.
Router
$router->group(['prefix' => 'api/v1'], function () use ($router) {
$router->get('articles', ['uses' => 'ArticleController#showAllArticles']);
$router->get('articles/{id}', ['uses' => 'ArticleController#showOneArticle']);
$router->post('articles', ['uses' => 'ArticleController#create']);
$router->delete('articles/{id}', ['uses' => 'ArticleController#delete']);
$router->put('articles/{id}', ['uses' => 'ArticleController#update']);
});
AuthServiceProvider
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
Gate::policy('App\Article', 'App\Policies\ArticlePolicy');
$this->app['auth']->viaRequest('api', function ($request) {
return app('auth')->setRequest($request)->user();
});
}
}
Policies
namespace App\Policies;
use App\User;
use App\Article;
class ArticlePolicy
{
public function showAllArticles(User $user, Article $post)
{
// not working
return true;
}
public function update(User $user, Article $post)
{
// this works
return true;
}
}
Controller
namespace App\Http\Controllers;
use App\Article;
use Illuminate\Http\Request;
class ArticleController extends Controller
{
public function __construct()
{
$this->middleware('auth:api');
}
public function showAllArticles()
{
$this->authorize('showAllArticles');
return response()->json(Article::all());
}
public function showOneArticle($id)
{
return response()->json(Article::find($id));
}
public function update($id, Request $request)
{
$article = Article::findOrFail($id);
$this->authorize('update', $article);
$article->update($request->all());
return response()->json($article, 200);
}
}
As per the Laravel documentation on Authorization:
"When defining policy methods that will not receive a model instance, such as a create method, it will not receive a model instance. Instead, you should define the method as only expecting the authenticated user:"
public function create(User $user)
So:
public function showAllArticles(User $user)
"As previously discussed, some actions like create may not require a model instance. In these situations, you should pass a class name to the authorize method. The class name will be used to determine which policy to use when authorizing the action:"
$this->authorize('create', Post::class);
So:
$this->authorize('showAllArticles', Article::class);
Laravel 7.x Docs - Authorization - Writing Policies - Methods without Models
Laravel 7.x Docs - Authorization - Authorizing Actions Using Policies - via Controller Helper authorize
No explanation needed.
I used laravel Auditor in a model and it works very well as following:
use Illuminate\Database\Eloquent\Model;
use OwenIt\Auditing\Contracts\Auditable;
class Contracts extends Model implements Auditable
{
use \OwenIt\Auditing\Auditable;
protected $fillable=['condatereceived'];
public function user()
{
return $this->belongsTo(User::class);
}
}
But I want to used it in the controller as :
public function updatecomplated(Request $request, $id,Contracts $contract ,Auditor $auditor)
{
Contracts::where('id', $id)
->update(['complated' => 50, 'conuploadby' => Auth::id(),'constatus' =>'Need To Active' ]);
if ($audit = $auditor->execute($contract)) {
$auditor->prune($contract);
}
return redirect()->back();
}
The code in controller give me error:
Call to undefined method OwenIt\Auditing\Facades\Auditor::execute()
any ideas to use auditor in the controller, please.
try this package its easy with good documentation
simply add this to your table
$table->auditable();
and this to your model
namespace App;
use Yajra\Auditable\AuditableTrait;
class User extends Model
{
use AuditableTrait;
}
thats it now simply get your auditor by calling
$user->creator // for who create
and
$user->updater //for who update data
for more information click here for check trait
Hope this helps
I have an admin gate defined in my AuthServiceProvider that is used to add global query scopes to some models. Suppose I had models A, that is observed by an Observer (registered in AppServiceProvider), and B, that makes use of the admin gate to add global query scopes.
// app/Providers/AuthServiceProvider.php
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
Gate::define('admin', [static::class, 'admin']);
}
public static function admin(User $user): bool
{
return $user->group->name === 'Admin';
}
}
// app/B.php
class B extends Eloquent
{
public static function boot()
{
parent::boot();
if (!Gate::allows('admin')) {
static::addGlobalScope('public', function ($query) {
$query->where('public', true);
});
}
}
}
Up to this point everything worked fine. Then I added a model C that has an Observer and uses the admin gate. As C::observe() fires C::boot() and the AppServiceProvider is registered before the AuthServiceProvider the gate was not defined and I extracted the Observer registration to a new ObserverServiceProvider that is registered after AuthServiceProvider.
// app/C.php
class C extends Eloquent
{
public static function boot()
{
parent::boot();
if (!Gate::allows('admin')) {
static::addGlobalScope('public', function ($query) {
$query->where('public', true);
});
}
}
}
// app/Providers/ObserverServiceProvider.php
class ObserverServiceProvider extends ServiceProvider
{
public function boot()
{
A::observe(AObserver::class);
C::observe(CObserver::class);
}
}
// config/app.php
'providers' => [
//...
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
//...
App\Providers\ObserverServiceProvider::class,
]
My problem:
The observers for A and C are still working, as well as the admin gate in B's boot() method, but Gate::allows('admin') in C always returns false without even calling the gate function.
Adding a var_dump(Gate::has('admin')) in C::boot() outputs true and using #can('admin') later in the View during the same request works fine as well, so the gate is definitely defined and working in principle.
The authorization gate cannot be called as the session data (and therefore the authenticated user) is made available by the StartSession middleware, which runs after the service providers.
The problem can be solved by putting the Gate::allows() check inside the anonymous function, so it is only executed when building a query:
// app/C.php
class C extends Eloquent
{
public static function boot()
{
parent::boot();
static::addGlobalScope('public', function ($query) {
if (!Gate::allows('admin')) {
$query->where('public', true);
}
});
}
}
Let say i have the following;
User Model;
class User extends Authenticatable
{
public function posts()
{
return $this->hasMany('App\Models\Socials\Post');
}
}
Post Model;
class Post extends Model
{
public function comments()
{
return $this->morphMany('App\Models\Socials\Comment', 'commentable');
}
Comment model;
class Comment extends Model
{
public function commentable()
{
return $this->morphTo();
}
When i used $user = User::find($id); and $user->posts(), it returns all the post of the user, but if i used this method $user->posts()->comments() It return this message Method Illuminate\Database\Query\Builder::comments does not exist.
The question is how can i get all the comments of the user on the said post?
Change:
$user->posts()->comments();
to:
$user->posts->pluck('comments')->collapse();
The method itself returns an instance of Eloquent's query builder allowing you to add to or edit the query if you want. However, if you don't want to edit the query you can access the relationships as properties and Laravel will handle to execution of the query.
Essentially, $user->posts is actually turning into $user->posts()->get() in the background.
Credit to #JonasStaudenmeir.