Laravel Policies not stopping delete action - laravel

I have just started using Policies within Laravel 5.4 to handle my authorization. I have been following the official documentation and created a PostPolicy.
<?php
namespace App\Policies;
use App\User;
use App\Post;
use Illuminate\Auth\Access\HandlesAuthorization;
class PostPolicy
{
use HandlesAuthorization;
public function delete(User $user, Post $post)
{
return false;
//return $user->id === $post->user_id;
}
}
My goal is to stop the ability to delete a post using Policies.
I am currently still able to delete and cannot find a way to implement these Policy rules.

You need to authorize actions. For example, you could do that:
if ($user->can('delete', $post)) {
Or in controller:
$this->authorize('delete', $post);
https://laravel.com/docs/5.5/authorization#authorizing-actions-using-policies

Related

basic authorization with livewire and laravel

I have a method in my postpolicy that only current authenticated user can delete his own posts. I try to put this method in my delete method, but it returns that the method does not exist. I have included authroizerequest in the controller, so I'm confused why I get this error.
Method App\Http\Livewire\Posts::authorize does not exist.
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
public $postId = null;
public function deletePost($id)
{
$this->authorize('delete', $this->postId);
$post = Post::find($id);
Storage::delete('public/photos/', $post->image);
$post->delete();
session()->flash('flash.banner', 'Post Deleted Successfully');
}
the policy:
namespace App\Policies;
use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
public function delete(User $user, Post $post){
return $user->id === $post->user_id;
}
You are just importing use AuthorizesRequests trait not including this trait inside your class you need to use this trait inside your controller
class ControllerName extends Controller {
use AuthorizesRequests;
}
Using this way you can use AuthorizesRequest traits method inside your class.

Laravel override Login controller, login(). How do i retrieve logged in user data if i overwrite the login controller. I tried to get auth() data

I used laravel like 4 years ago. Had to work on a project on laravel and tried using my own authentication methods but mybad forgot there was already inbuilt better security authentication. I understand if my question seem to be basic.
As you can see the commented line "$userID = Auth::user()->userID;" the auth() is null therefore, userID cannot get its id from null. I am unable to get user session data in any other controllers as well.
Any kind of help or suggestions is appreciated.
P.S. i have used the default login and registration inbuilt function only required function like login is override code. I am using laravel v 4.2.3. I tried passing the userid as url parameter but then discarded it as inbuilt session data makes it more secure and easier
the login function of my controller looks like this
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
use AuthenticatesUsers;
protected $redirectTo = RouteServiceProvider::HOME;
public function __construct()
{
$this->middleware('guest')->except('logout');
}
protected function login(Request $request){
$user = new User(); //my model User
$result=$user->login($request); //result has the id of the user
if ($result) {
//$userID = Auth::user()->userID;
return redirect()->route('homepage');
}else{
return redirect()->route('login');
}
}
}
model for user login()
//Auth user then let them login
public function login($request){
$email = $request->input('email');
$password = $request->input('password');
$result=DB::table('users')
->where('email', $email)
->where('password', $password)
->get();
return $result;
}
My Routes.. its default route of "Auth::routes();"
Route::get('/homepage/{userID?}', function($userID = null){
return view('index', ['userID' => $userID]);
})->name('homepage');
Route::get('/evaluate/{userID?}', function ($userID = null) {
return view('evaluate', ['userID' => $userID]);
})->name('evaluate');
I installed a fresh new laravel and tried my code again and somehow it worked. Must have made some errors when trying to override the codes. Thank you

Laravel sharing data with all views

I'm trying to run a user-related query to fetch data to appear in the top bar of my site on every view.
I've created a new BaseController according to the first answer here:
How to pass data to all views in Laravel 5?
and that's working for a simple test (just sharing a typed-out variable), but when I try and use Auth::user()->id in the __construct method of BaseController (which in my other controllers always returns the ID of the currently logged in user), I get Trying to get property 'id' of non-object.
I've tried adding use App\User at the top of BaseController (even though it isn't usually needed) and also tried adding in the bits for Spatie laravel-permission plugin, but neither has any effect.
I tried dd on Auth::user() and just get 'null'. My feeling is that the user details maybe haven't been loaded at this stage, but BaseController extends Controller same as MyWorkingController extends Controller so I'm not sure why Auth::user()->id doesn't work here when it does normally?
Create a Base Controller which has all the information that you want to share too all controllers/pages/views and let your others controllers extend it.
open file AppServiceProvider.php from folder Providers and write below code in boot function
view()->composer('*', function ($view)
{
$view->with('cartItem', $cart );
});
And now go to your view page and write :
{{ $cartItem }}
You cannot access Auth in constructors because middleware has not been run yet. You can use either View composer or give try this way though i haven't tested.
class BaseController extends Controller {
protected $userId;
public function __construct() {
$this->middleware(function ($request, $next) {
$this->userId= Auth::user()->id;
return $next($request);
});
}
}
Write this in AppServiceProvider.php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;
use DB;
use Auth;
use App\Cart;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Schema::defaultStringLength(191);
view()->composer('*', function ($view)
{
view()->composer('*', function($view)
{
if (Auth::check()) {
$cart = Cart::where('user_id', Auth::user()->user_id)->count();
$view->with('cartItem', $cart );
}else {
$view->with('cartItem', 0);
}
});
});
}
}
In you view simply write
{{ $cartItem }}
For anyone interested, I just encountered the same problem and I've solved it with ServiceProvider:
Define your custom ServiceProvider with the command
php artisan make:provider CustomServiceProvider
Add a reference to your service provider in the config\app.php file, specifically in the providers array, adding this item to it:
\App\Providers\CustomServiceProvider::class,
Declare the variables you want to share in your provider's boot() method and share them by using the view()->share method:
public function boot()
{
$shared_variable = "Hello";
view()->share('shared_variable', $shared_variable);
}
You can now reference your variable in your blade files with the standard notation:
{{ $shared_variable }}

Laravel - Notifications Controller can't use method user()

I'm trying to add notification system to my Laravel project. I' watched this video to understand the system : https://www.youtube.com/watch?v=iDDUxqpNgSc
Notification table, model et controller are created. Also, i have created the view with Vue.JS and Pusher. It's work well !
However, in the notification controller, when i try to user Auth::user() method it's return null. I read somewhere it's because the middleware 'auth' is not already load when the controller is.
This is my NotificationsController file :
<?php
namespace App\Http\Controllers;
use App\Notification;
use Illuminate\Http\Request;
use App\Idea;
use App\User;
use Illuminate\Support\Facades\Auth;
class NotificationsController extends Controller
{
public function __construct()
{
}
function get(){
$notification = Auth::user()->unreadNotifications()->get();
return $notification;
}
function read(Request $request){
Auth::user()->unreadNotifications()->find($request->id)->markAsRead();
}
}
Do you have any idea how to solve this ?
Thank's for your time !
The answer was not about the Auth::user (It's accessible). I just baldy defined the notifiable_type in my model. It was App\Idea, it should be App\User

Best way to define global variables from database in laravel

I want to define some variables from database to take them in any place of the app (controllers and views at least).
I found a way to do this in Http/Controllers/Controller.php:
namespace App\Http\Controllers;
use Session;
use Request;
use View;
use App\Http\Requests;
use Log;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function __construct()
{
$this->middleware(function ($request, $next) {
$t = array();
$translations = \App\Translation::all();
foreach ($translations as $translation) {
$t[$translation->code] = $translation->text;
}
View::share('t', $t);
});
}
}
It works fine - I can access {{$t['something'}} in my app, but there is a problem with Auth route /register or /login, in these pages $t variable is not defined.
I think because Auth performs some actions before this my __construct, how to fix it?
Or maybe there is a better way to set dynamic variables from database reachable in all app views and controllers?
(laravel 5.3) I'm new to laravel, so can't feel the architecture yet.
I would go with setting a custom Config like this:
Config::set('translations', your_array_from_database);
You can even define your own helper function for fast retrieving, ie.
function t($name)
{
return Config::get('translations.'.$name);
You can set your own translations Config in a middleware, so you can decide the exact order in the request-response cycle you want to load it from database.
I haven't used Laravel for some time but my guess is, based on the 5.3 docs, is you can just call your middleware from those Auth controllers that are missing it. In the Auth Register controller you can add middleware, for example:
app/Http/Controllers/Auth/RegisterController.php
public function __construct()
{
$this->middleware('guest');
$this->middleware(function ($request, $next) {
// Add your middleware logic here
// or put it in it's own file and reference like 'guest' above.
return $next($request);
});
}
Try your logic directly in the closure above first. Then shift to its own class file and add it to the routeMiddleware array in the kernel.
Alternatively, you could include the middleware in your base controller you extend from: https://github.com/laravel/laravel/blob/5.3/app/Http/Controllers/Controller.php
Try using compact function in Laravel. Something like this:
//function to fetch data
//$t = \App\Translation::all();
return View::make('gameworlds.mygame', compact(['t']));
Then on the view you can access it like:
{{$t}}

Resources