Laravel 5.5, routing depend of session - php

I'm starting to learn laravel 5.5 and I'm trying to create routes depending on the session
My code in web.php is:
if(session()->has("user")){
Route::any('/profile/view',"ProfileController#view");
}
if(session()->has("admin")){
Route::any('/game/new', "gameController#new");
}
but it donĀ“t works, it show me "page not found".
How i can do that?

RouteServiceProvider are booted before the StartSession middleware, so you cannot access session in route files. Use middleware to check instead.
Route::middleware('session.has.user')->group(function () {
Route::any('/profile/view',"ProfileController#view");
});
Route::middleware('session.has.admin')->group(function () {
Route::any('/game/new', "gameController#new");
});
To create middlewares:
php artisan make:middleware SessionHasUser
php artisan make:middleware SessionHasAdmin
Update middlewares to check the session, if it does not have corresponding session, abort the request:
app/Http/Middleware/SessionHasUser.php
public function handle($request, Closure $next)
{
if(session()->has("user")) {
return $next($request);
}
return abort(404);
}
Install Middlewares, so routing can use the middlewares
app/Http/Kernel.php
protected $middlewareGroups = [
'web' => [
...
'session.has.user' => , \App\Http\Middleware\SessionHasUser::class,
'session.has.admin' => \App\Http\Middleware\SessionHasAdmin::class,
...
],

Related

Laravel 6: remove register route using User model in routes

I would like to remove the register route from my Auth::routes() when a user with an admin role is registered without using App\User in my routes file.
use App\User;
if (User::where("role","=", "admin")->exists())
Auth::routes(['register' => false, 'verify' => true]);
else
Auth::routes(['verify' => true]);
Why would I want this?
This code causes a mysql error when i run php artisan without any tables in my database. I haven't found any solution on how to solve this yet and it would be great if you can suggest me solutions on how to achieve this.
I suggest use Middleware .Use:
use Illuminate\Support\Facades\Route;
public function handle($request, Closure $next)
{
$user=User::where("role","=", "admin")->first();
$route = Route::getRoutes()->match($request);
$currentroute = $route->getName();
if($currentroute == "/register"){
if(User::where("role","=", "admin")->count()>0){
return $next($request);
}
else{
abort(404)
}
}
}

Sentinel::check() always return FALSE in middleware

This is my route:
Route::group(['middleware' => ['web']], function () {
Route::get('/xx', 'xx\yy#zz');
This is my modification in Kernel.php:
protected $middlewareGroups = [
'web' => [
\Keevitaja\Linguist\LocalizeUrls::class,
LocalizeUrls.php:
public function handle($request, Closure $next)
{
if ($this->linguist->hasDefaultSlug() && $this->linguist->isDefaultDenied()) {
abort(404);
}
if (Sentinel::check())
{
dd("logged in");
}
dd("NOT logged in");
I am using Sentinel and Linguist for authentication and localisation.
I would like to get 'system_language' from the User model: check if the user is logged in and if he is, I would like to get his preferred language from the DB and then pass it to Linguist:
$this->linguist->localize('fr');
Unfortunately, Sentinel:check() always returns FALSE in this middleware. In my own middleware it is working well.
For sure, I am using the right Facade of Sentinel, because $sentinel = Sentinel::findById(1); returns a valid result.
The problem was caused because of the order in the Kernel.php $middlewareGroups where \Keevitaja\Linguist\LocalizeUrls::class was on first position.

Laravel 5.2 Session flash not working even with web middleware

I am trying to implement flash messaging using sessions but am unable to do so.
In my controller I have:
public function store(Request $request) {
session()->flash('donald', 'duck');
session()->put('mickey', 'mouse');
return redirect()->action('CustomerController#index')->with('bugs', 'bunny');
}
But when I check the session variables in the view, I can only see the values from session()->put('mickey', 'mouse').
Session:
{"_token":"F6DoffOFb17B36eEJQruxvPe0ra1CbyJiaooDn3F","_previous":{"url":"http:\/\/localhost\/customers\/create"},"flash":{"old":[],"new":[]},"mickey":"mouse"}
A lot of people encountered this problem by not having the relevant routes inside the web middleware. I made sure to do this as well but it still wouldn't work.
In routes.php:
Route::group(['middleware' => ['web']], function () {
Route::get('/', function () {
return view('welcome');
});
Route::get('/customers', 'CustomerController#index');
Route::get('/customers/create', 'CustomerController#create');
Route::post('/customers', 'CustomerController#store');
});
In Kernel.php:
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,
],
'api' => [
'throttle:60,1',
],
];
Can anyone let me know what I could be doing wrong here? Thanks!
Fixed the issue by replacing
Route::group(['middleware' => ['web']], function () {
...
});
with
Route::group(['middlewareGroups' => ['web']], function () {
...
});
No idea why this works though when all the documentation suggests that we use ['middleware' => ['web']]
This is more than likely because of a change that was made to the Laravel framework (v5.2.27) that all routes by default are part of the "web" middleware, so assigning it again in your routes.php file ends up assigning it twice.
The solution is either to remove the "web" middleware from your routes OR remove the automatic assignment from the RouteServiceProvider.
Before the Laravel update:
// RouteServiceProvider.php
$router->group(['namespace' => $this->namespace], function ($router) {
require app_path('Http/routes.php');
});
After the Laravel update:
// RouteServiceProvider.php
$router->group([
'namespace' => $this->namespace, 'middleware' => 'web',
], function ($router) {
require app_path('Http/routes.php');
});
Notice how the new update automatically applies the "web" middleware to all routes. Simply remove it here if you wish to continue using Laravel 5.2 as you have before (manually assigning "web" middleware in your routes.php).
Build your Session flash info by using this code:
<?php
Session::flash("Donald", "Duck")
// Or in your code style.
$request->session()->flash("Donald", "Duck")
?>
Check it in your view with:
#if(Session::has("Donald")
{{Session::get("Donald")}}
#endif
You forget to use $request :)
In Controller:
use Session,Redirect;
public function store(Request $request)
{
Session::flash('donald', 'duck');
Session::put('mickey', 'mouse');
return Redirect::to('/customers')->with('bugs', 'bunny');
}
In 'view' check the data is getting or not:
<?php
print_r($bugs);die;
?>
Good Luck :)
I use the following:
In my controller:
public function xyz(){
// code
// This
return redirect()->action('homeController#index')->with('success', 'Check! Everything done!');
// Or this
return redirect('/index')->with('success', 'Check! Everything done!');
}
In my view:
#if(session('success'))
{{ session('success') }}
#endif
Nothing else. The web-middleware is assigned to every route.
I dont know why but on Windows you need changes in your routes: middleware to middlewareGroups, like that:
So, in your app\Kernel.php, you need put the StartSession at first on array of middleware group web:

Laravel 5 : Restrict access to controllers by User group

I've started learning Laravel 5.1 and so far I'm liking it! But there is one thing I don't get yet..
In my previous project I had 2 specific controllers (eg: "normal", "extended") which , after a successfull login, were called based on the Users user_group from the database.
If "Foo.Bar" enters his valid credentials and has the group normal he is redirected to NormalControler. Since I wasn't using any framework I restricted access to the other group by setting a $_SESSION with the group and checking it. So if another group tried to access that controller he got redirected.
How would this be achievable in Laravel 5? So far I have a controller which is callable without an Authentication and one restricted by this code in routes.php :
// All routes in the group are protected, only authed user are allowed to access them
Route::group(array('before' => 'auth'), function() {
// TO-DO : Seperate Controller access
});
And the login looks like this :
public function performLogin()
{
$logindata = array(
'username' => Input::get('user_name'),
'password' => Input::get('user_pass')
);
if( Auth::attempt( $logindata ) ){
// return \Redirect::to( check group and access this controller based on it);
}
else {
// TO-DO : Redirect back and show error message
dd('Login failed!');
}
}
----- EDIT -----
I've run the artisan command and made this middleware as you suggested :
namespace App\Http\Middleware;
use Closure;
use Request;
class GroupPermissions
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, $group)
{
// Check User Group Permissions
if( $request->user()->group === $group ){
// Continue the request
return $next($request);
}
// Redirect
return redirect('restricted');
}
}
and edited this line into Kernel.php into $routeMiddleware :
'group.perm' => \App\Http\Middleware\GroupPermissions::class
I think this is done right so far, correct me if I'm wrong! Could I then do something like this to restrict the controllers?
Route::group(array('before' => 'auth'), function() {
Route::group( ['middleware' => 'group.perm', 'group' => 'normal'], function(){
Route::get('/normal/index', 'DummyNormalController#index');
});
Route::group( ['middleware' => 'group.perm', 'group' => 'extended'], function(){
Route::get('/extended/index', 'DummyExtendedController#index');
});
});
Ok, here is what you might do. Once user is logged in, you would check his credentials, get his user_group and decide what controller he should be redirected to.
if( Auth::attempt( $logindata ) ){
$user = Auth::user();
if ($user->inGroup('normal')) {
return redirect()->route('normal_controllers_named_route');
}
return redirect()->route('extended_controllers_named_route');
}
return redirect()->back()->withFlashMessage('don\'t get me wrong');
This will handle right routing after logging in.
The next portion where you need to protect you routes from unwanted user groups may be achieved with middlewares.
do an artisan command php artisan make:middleware ShouldBeInGroup
go to app/http/Kernel.php and add your new middleware to the routeMiddleware array. Key of the item might be anything you like. Let's call in inGroup. So: 'inGroup' => 'App\Http\Middleware\ShouldBeInGroup'
Now, in your controller, in constructor, you are able to call this middleware
$this->middleware('inGroup:extended'); //we also passing the name of the group
at lastly, work on the our middleware. Open newly created ShouldBeInGroup class and edit the handle method.
public function handle($request, Closure $next, $groupName)
{
if (Auth::check() && Auth::user()->inGroup($groupName)) {
return $next($request);
}
return redirect('/');
}
And finally you should work on inGroup method, that should return true of false. I assume that you have user_group field your users table. Then in your User eloquent model add the method
public function inGroup($groupName) {
return $this->user_group == $groupName;
}
Edit
if you want to use this middleware in your routes, you can do the following
Route::group(array('before' => 'auth'), function() {
Route::get('/normal/index', ['middleware' => 'group.perm:normal', 'uses' =>'DummyNormalController#index']);
}
But generally it's better to put all your middlewares into your Controller's constructor
public function __construct(){
$this->middleware('group.perm:normal'); // you can also pass in second argument to limit the methods this middleware is applied to : ['only' => ['store', 'update']];
}
And also on this note, Laravel provides built in auth middleware that you can use
public function __construct(){
$this->middleware('auth');
$this->middleware('group.perm:normal');
}
so then your routes would become much cleaner, just:
Route::get('normal/index', 'DummyNormalController#index');
I think the best way to do that is using middlewares. See the doc here
You can easily create a middleware using the following artisan command:
php artisan make:middleware ExtendedMiddleware
If you can't or don't want to use artisan, you need to create a class in The App/Http/Middleware folder.
In this class you'll need the following method to handle the request. In the method you can check for the user group.
public function handle($request, Closure $next)
{
// check user group
if( user_group_ok )
return $next($request); // Continue the request
return redirect('restricted'); // Redidrect
}
You can then use this middleware in your route.php file:
Route::group(['middleware' => 'auth'], function()
{
// Logged-in user with the extended group
Route::group(['middleware' => 'extended'], function()
{
// Restricted routes here
});
// Normal routes here
});
You can create a Middleware called : PermissionFilter
In PermissionFilter, you check if requesting user is in the group or not.
I can't provide a demo for now, but if you want I can make a demo later.
L5 middleware: http://laravel.com/docs/5.1/middleware

method post, put, delete route not work on laravel 5

I try test api rest on laravel 5 but I have problems with method post, put, delete.
In my route.php file I have code:
Route::group(['prefix' => 'api'], function()
{
Route::group(['prefix' => 'user'], function()
{
Route::get('', ['uses' => 'UserController#allUsers']);
Route::get('{id}', ['uses' => 'UserController#getUser']);
Route::post('', ['uses' => 'UserController#saveUser']);
Route::put('{id}', ['uses' => 'UsercCntroller#updateUser']);
Route::delete('{id}', ['uses' => 'UserController#deleteUsers']);
});
});
Route::get('/', function()
{
return 'Enjoy the test...';
});
and in UserController.php have code:
public function allUsers()
{
return 'test';
}
public function getUser($id)
{
return 'test get user';
}
public function saveUser()
{
return 'test save user';
}
public function updateUser($id)
{
return 'test update user';
}
public function deleteUsers($id)
{
return 'test delete user';
}
When I run with method get it works good but with method post, put and delete it does not work.
Why is this?
If you want to make REST APIs then use laravel's generators.
Use php artisan make:controller UserController
Laravel automatically creates RESTful controller class for you with all required methods.
Then just put one line in your routes.php
Route::group(['prefix' => 'api'], function()
{
Route:resource('user', 'UserController');
});
And that's it, now you can access get, post, put, and delete requests very easily.
If you want to see what route I should use for what method then simply fire php artisan route:list from commandline.
And because of laravel comes with built in csrf token verification middleware, you must have to pass _token with your post data request. Or either you can access those routes without csrf token verification by doing this:
Go to kernel.php in Http folder under the app directory, and comment the csrfToken line.
protected $middleware = [
'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',
];

Categories