I have a route for destroying a Post, how can I make so that the one who can access the route is only the Post creator? For example, I have a Post with id number 3 and the user id is 5, so the only one who can delete number 3 is only user id 5. I've tried messing with middleware but not lucky enough to get it to work.
CekStatus.php (Middleware)
class CekStatus
{
public function handle($request, Closure $next)
{
$userId = $request->id;
$user = Post::where('id', $userId)->select('user_id')->pluck('user_id')->first();
if ($user === Auth::id()) {
return $next($request);
}
return redirect('/'); //redirect anyware.
}
}
Route
Route::get('/hapus/{id}','PostController#destroy')->middleware('cekstatus');
Kernel.php
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
'cekstatus' => \App\Http\Middleware\CekStatus::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
Output:
ERR_TOO_MANY_REDIRECTS
You should be using Policy here, the middleware is not used for authorization purposes. More on this in the docs here.
The docs use your example as well, instead of update you can create a delete function and then to use it in your controller you can add this:
if (auth()->user()->can('delete', $post)) {
// delete it code here.
}
Related
I'm working on Laravel 5.8 and php 7.1.3. using csrf_token() return value in controller function but not return any value in controllers/api controller. how to used csrf_token in api controller function.
Api controller :- Http/Controllers/Api/TestConroller.php
class TestConroller extends Controller
{
public function __construct()
{
}
public function getToken(Request $request){
echo csrf_token();
}
}
Routes:- routes/api.php
Route::get('getToken', 'Api\TestConroller#getToken');
url:-
http://localhost/laravel/api/getToken
if csrf token() not work in api controller then how to used token for verification in api.
Csrf token only works in web.php not in api.php .Api's are stateless
if you check kernal.php
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Laravel\Jetstream\Http\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\HandleInertiaRequests::class,
],
'api' => [
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
web middleware uses session .So For testing purpose if you comment below middleware
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
then it will return null on web.php
if you want to use in api.php just add these 2 lines in kernel.php
\Illuminate\Session\Middleware\StartSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
in
'api' => [
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
section
want edit my Kernel.php file and disabled some Middleware in on place in aplication (I want my header response was shortly, here is my stack subject)
I have some idea but i don't know what is the next step:
class Kernel extends HttpKernel
{
public function __construct(Application $app, Router $router)
{
$url = \Illuminate\Http\Request::capture()->url();
if($url == 'http://autoservie.test/save'){
//HERE i want set protected $middlewareGroup and remove session
middleware from 'web'
}else{
// HERE set another protected $middlewareGroup
}
parent::__construct($app, $router);
}
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
The question is, how set dynamic protected $middlewareGroups array in constructor? Or is there any other solution ?
You can do something like
$index = array_search(\Illuminate\Session\Middleware\StartSession::class, $middlewareGroups['web']);
unset($middlewareGroups['web'][$index]);
I have laravel 5.0 . and set sessions drivers to database . I have some link that no require to insert new row in sessions table . how i can disable inserting new row only for www.site.com/download .
Create a new route/middleware type for sessionless access. Do this by adding a new middleware group in your Http/Kernel that doesn't include the StartSession middleware, then adding a new route file to hold all your download links, and then registering your new route file in your RouteServiceProvider.
Edit the $middlewareGroups array in app/Http/Kernel.php to look like the following:
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
'sessionless' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
Then edit your app/Providers/RouteServiceProvider to map your newly-created route file:
Route::group([
'middleware' => 'sessionless',
'namespace' => $this->namespace,
'prefix' => 'download',
], function ($router) {
require base_path('routes/downloads.php');
});
Now add a file in your /routes directory named downloads.php, and add your downloadable routes there. If you want to use a wildcard to parse what file they're looking for, you can, or you can explicitly list what routes will trigger a download:
Route::get('test', function(){
$file = '/path/to/test/file';
return response()->download($file);
});
Route::get('{fileName}', function($fileName){
$file = '/path/to/' . $fileName;
return response()->download($file);
});
This doesn't address using headless authorization, which you would need if you didn't want unauthorized access to all of your sessionless routes.
this solution is good for laravel 5.0
first must define two middleware in app/http/kernel.php .first middleware is lesssession . lesssession is for route that do not need session .and second is hasssession middleware .hassession is good for route that need session :
<?php namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel {
/**
* The application's global HTTP middleware stack.
*
* #var array
*/
/**
* The application's route middleware.
*
* #var array
*/
protected $routeMiddleware = [
'auth' => 'App\Http\Middleware\Authenticate',
'hassession' => [
'Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode',
'Illuminate\Cookie\Middleware\EncryptCookies',
'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
'Illuminate\Session\Middleware\StartSession',
'Illuminate\View\Middleware\ShareErrorsFromSession',
'App\Http\Middleware\VerifyCsrfToken',
],
'lesssession' => [] ,
'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
'guest' => 'App\Http\Middleware\RedirectIfAuthenticated',
];
}
step 2:
put route in two group by edit app/http/route.php:
<?php
Route::group(['middleware' => ['lesssession']], function()
{
Route::get('download', function(){
// do some stuff for download file
});
});
Route::group(['middleware' => ['hassession']], function()
{
// all other route that need session
});
?>
I'm trying to pass to all templates current user object like this:
class Controller extends BaseController
{
public function __construct()
{
view()->share('usr', Auth::guard('user'));
}
}
Every controller is extended by Controller. But if i try to dump Auth::guard('user')->user() Laravel returns null, although I am logged in. Moreover when i pass this variable into template, {{ $usr->user() }} returns current user. What I've done wrong?
my config/auth.php
'defaults' => [
'guard' => 'user',
'passwords' => 'users',
],
'guards' => [
'user' => [
'driver' => 'session',
'provider' => 'user',
],
],
'providers' => [
'user' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
],
Kernel.php
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
];
/**
* The application's route middleware groups.
*
* #var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
//\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* #var array
*/
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];
my own function to log in:
public function authorizes(Request $request)
{
$this->validate($request, [
'login' => 'required|max:50',
'password' => 'required|max:50'
]);
$credentials = $request->only(['login', 'password' ]);
$remember = $request->get('remember', false) == 1 ? true : false;
if ($this->guard->attempt( $credentials, $remember)) {
$user = $this->guard->user();
$user->last_login = date('Y-m-d H:i:s');
$user->save();
return redirect()->route( 'homepage' )->withSuccess(trans('app.login.success'));
}
return redirect()->back()->withErrors(trans('app.wrong.credentials'));
}
In Laravel 5.3 you should change your controller constructor like so to make this work (assuming you use at least Laravel 5.3.4):
public function __construct()
{
$this->middleware(function ($request, $next) {
view()->share('usr', Auth::guard('user'));
return $next($request);
});
}
You can see this change described in Upgrade guide:
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
Try to do this:
view()->share('usr', Auth::user());
Or this:
view()->share('usr', auth()->user());
Frist check if user is logged or not, then share the current user as:
public function __construct()
{
if (auth()->check()) {
$this->currentUser = auth()->user();
View::share('currentUser', $this->currentUser);
} else {
// you can redirect the user to login page.
}
}
In your case there are two things to consider
To get actual user model you should do Auth::guard('user')->user()
Auth::user() is actually not yet initialized when view()->share() is called, see https://github.com/laravel/framework/issues/6130
Therefore you could rather use view composer. In boot method of your AppServiceProvider add:
\View::composer('*', function ($view) {
$view->with('usr', \Auth::guard('user')->user());
});
I am trying to use oauth for google in laravel 5 but i am getting the error. Can any one help me to sort out this problem.
Followings are my files please check out
.env
GOOGLE_ID = 'mygoogleId'
GOOGLE_SECRET = 'mysecretID'
GOOGLE_REDIRECT = http://localhost:8090/users
services.php
'google' => [
'client_id' => env('GOOGLE_ID'),
'client_secret' => env('GOOGLE_SECRET'),
'redirect' => env('GOOGLE_REDIRECT'),
],
AuthController
public function redirectToProvider() {
return Socialite::driver('google')->redirect();
}
public function handleProviderCallback() {
$user = Socialite::driver('google')->user();
console.log($user);
}
routes.php
Route::get('google', 'Auth\AuthController#redirectToProvider');
Route::get('google/callback', 'Auth\AuthController#handleProviderCallback');
//I have set the providers and aliases in app.php.
Here is the code where i am getting an error
//on set() method
public function redirect()
{
$state = str::random(40);
if ($this->usesState()) {
$this->request->getSession()->set('state', $state);
}
return new RedirectResponse($this->getAuthUrl($state));
}
Thanks in advance..
Hey If you are using laravel 5.2, this is worked for me.
Put your controllers in 'web' middleware. like,
Route::group(['middleware' => 'web'], function() {
Route::get('google', 'Auth\AuthController#redirectToProvider');
Route::get('google/callback', 'Auth\AuthController#handleProviderCallback');
});
and Make sure Kernel file has middleware classes registered.
/**
* The application's route middleware groups.
*
* #var array
*/
protected $middlewareGroups = [
'web' => [
\Perkweb\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\Perkweb\Http\Middleware\VerifyCsrfToken::class,
],
'api' => [
'throttle:60,1',
],
];