I'm trying to use different user levels at my system. I have at data base my users and their levels (master, portais, chaves, etc)
So, what I want is different routes for each user, so each one will access just a part of the system.
I can easily check in each page of the system his AUTH and dont show to him the page if he is logged in a account witch he shouldn't see that page. BUT, there's a easy way to do it with middleware / Routes no?!
I tried something like this on my routes.php:
Route::group(['middleware' => 'Master'], function()
{
Route::any('/vendedor/produtos/removeProduto', 'AjaxController#vendedorRemoveProduto');
Route::any('/vendedor/produtos/editaPrecoProduto', 'AjaxController#editaPrecoProduto');
Route::any('/vendedor/produtos/alterarestadoproduto', 'AjaxController#alterarestadoumproduto');
Route::any('/vendedor/produtos/listaProdutos', 'AjaxController#listaProdutos');
Route::any('/vendedor/produtos/adicionaProdutoCliente', 'AjaxController#adicionaProdutoCliente');
Route::any('/', 'DashboardController#home'); });
Route::group(['middleware' => 'portais'], function()
{
Route::any('/cadastrarobjedu/criartema', 'AjaxController#criartemaobjedu');
Route::any('/cadastrarobjedu/cadastrar', 'AjaxController#cadastraobjedu');
Route::any('/cadastrarobjedu', 'DashboardController#cadastrarobjedu');
Route::any('/listarobjedu', 'DashboardController#listarobjedu');
Route::any('/editarobjeto/{id}', 'DashboardController#editarobjeto');
Route::any('/apagarobjeto/{id}', 'AjaxController#apagarobjeto');
Route::any('/', 'DashboardController#home'); });
But this didn't work, hgive me a error saying the "MASTER" class dosen't exist. I have change anything more?
You need to implement a middleware that would check if current user has given level.
Laravel 5.0
//app/Http/Kernel.php - register middleware classes
protected $routeMiddleware = [
'levelMaster' => 'App\Http\Middleware\LevelMasterMiddleware',
'levelPortais' => 'App\Http\Middleware\LevelPortaisMiddleware'
];
//app/Http/Middleware/LevelMiddleware.php - base middleware class that checks if user has level stored in $level;
namespace App\Http\Middleware;
use Closure;
use App;
use Auth;
abstract class LevelMiddleware
{
protected $level;
public function handle($request, Closure $next)
{
if (Auth::user() && Auth::user()->level !== $this->level) {
return App::abort(Auth::check() ? 403 : 401, Auth::check() ? 'Forbidden' : 'Unauthorized');
}
return $next($request);
}
}
//app/Kernel/Middleware/LevelMasterMiddleware.php - checks if user has level Master
namespace App\Http\Middleware;
class LevelMasterMiddleware extends LevelMiddleware
{
protected $level = 'master';
}
//app/Kernel/Middleware/LevelPortaisMiddleware.php - checks if user has level Portais
namespace App\Http\Middleware;
class LevelPortaisMiddleware extends LevelMiddleware
{
protected $level = 'portais';
}
//config/routes.php - configure routes for different levels
Route::group(['middleware' => 'levelMaster'], function()
{
//here add routes for users with level=master
}
Route::group(['middleware' => 'levelPortais'], function()
{
//here add routes for users with level=portais
}
Laravel 5.1
The latest version of Laravel introduces middleware parameters which lets simplify the above code a bit, as only one middleware class will be needed:
//app/Http/Kernel.php - register middleware class
protected $routeMiddleware = ['level' => 'App\Http\Middleware\LevelMiddleware'];
//app/Http/Middleware/LevelMiddleware.php - check if current user has given level
namespace App\Http\Middleware;
use Closure;
use App;
use Auth;
class LevelMiddleware
{
public function handle($request, Closure $next, $level)
{
if (Auth::user() && Auth::user()->level !== $level) {
return App::abort(Auth::check() ? 403 : 401, Auth::check() ? 'Forbidden' : 'Unauthorized');
}
return $next($request);
}
}
//config/routes.php - configure routes for different levels and pass level as middleware parameter
Route::group(['middleware' => 'level:master'], function()
{
//here add routes for users with level=master
}
Route::group(['middleware' => 'level:portais'], function()
{
//here add routes for users with level=portais
}
Related
I created a custom middleware to redirect short urls to other urls, I have a Url model that has this information:
{
"id":1,
"original_url":"http://www.google.com",
"short_url":"http://127.0.0.1:8000/wGjxw",
"updated_at":"2023-02-08T21:05:39.000000Z",
"created_at":"2023-02-08T21:05:39.000000Z"
}
so I have created a middleware:
<?php
namespace App\Http\Middleware;
use App\Models\Url;
use Closure;
use Illuminate\Http\Request;
class RedirectMiddleware
{
public function handle(Request $request, Closure $next)
{
//dd('here'); // is not reaching this code
$url = Url::where('short_url', $request->fullUrl())->first();
if ($url) {
return response()->redirectTo($url->original_url);
}
return $next($request);
}
}
app/Http/Kernel.php
....
....
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\RedirectMiddleware::class,
...
...
But, when I hit the url http://127.0.0.1:8000/wGjxw I get a 404 error,
This is the web.php
Route::get('/', function () {
return view('main');
});
Route::post('/urls', [UrlsController::class, 'store'] );
These routes are for showing the page with the form, and for creating the short url and those are working properly, the problem is that it looks like the middleware is not registered or I don't know what is happening, what I want is the short_url gets redirected to the original_url, what can I do? thanks
If the middleware approach isn't working, you could make a route specifically for it using route model binding with short_url as the key.
https://laravel.com/docs/9.x/routing#customizing-the-key
Route::get('/{url:short_url}', fn (Url $url) => redirect()->away($url->original_url));
My error was that the middleware was in the $middlewareGroups property, and it should be in the $middleware property, now it is working properly
I am trying to add newrelic to my laravel site. I found this repo. But couldn't use it properly.
Where should I put this code?
App::after( function() {
Newrelic::setAppName( 'MyApp' );
} );
Or maybe other ways to add routes response time to newrelic...
App::after does not exists anymore.
You can register a middleware that is executed after the request to do what you need:
<?php
namespace App\Http\Middleware;
use Closure;
class AfterMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);
Newrelic::setAppName( 'MyApp' );
return $response;
}
}
and register it as usually in app/Http/Kernel.php:
protected $middleware = [
...,
\App\Http\Middleware\AfterMiddleware::class
];
I'm building a Laravel-app and I have a route where I need to include a third-party script/iframe. I want to protect that route with a simple access code without setting up the laravel-authentication.
Is that possible? If so, how can I achieve that?
All solutions I give below suggest you are trying to access your route with code=X URI/GET parameter.
Simple Route
You can simply check for the given code to be correct in each route's method, and redirect somewhere if that's not the case.
web.php
Route::get('yourRouteUri', 'YourController#yourAction');
YourController.php
use Request;
class YourController extends Controller {
public function yourAction(Request $request) {
if ($request->code != '1234') {
return route('route-to-redirect-to')->redirect();
}
return view('your.view');
}
}
Route with middleware
Or you can use middlewares for avoiding to repeat the condition-block in each route if you have many of them concerned by your checking.
app/Http/Middleware/CheckAccessCode.php
namespace App\Http\Middleware;
use Request;
use Closure;
class CheckAccessCode
{
public function handle(Request $request, Closure $next)
{
if ($request->code != '1234') {
return route('route-to-redirect-to')->redirect();
}
return $next($request);
}
}
app/Http/Kernel.php
// Within App\Http\Kernel Class...
protected $routeMiddleware = [
// Other middlewares...
'withAccessCode' => \App\Http\Middleware\CheckAccessCode::class,
];
web.php
Route::get('yourRouteUri', 'YourController#yourAction')->middleware('withAccessCode');
You can create your own middleware.
Register the middleware in the $routesMiddleware of your app/Http/Kernel.php file.
Then use it like this:
Route::get('script/iframe', 'YourController#index')->middleware('your_middleware');
-- EDIT
You can access the route like this:
yoururl.com/script/iframe?code=200
Then in the middleware handle method:
if ($request->code !== 200) {
// you don't have access redirect to somewhere else
}
// you have access, so serve the requested page.
return $next($request);
Im still fairly new to Laravel and have worked through some of the fundamental laracasts. Now I'm starting my first laravel project but I am stuck on how to use my first package "Landlord". Basically I need a setup for Multi-Tenants in my application. I have a company table and a user table, the user table has a company_id column. When a company registers it successfully creates the company and attaches the company_id to the user.
I assume Landlord is the best way to implement a multi-tenant application so I worked through the installation instructions and now I have it included in my app.
However the first line in the USAGE section says:
IMPORTANT NOTE: Landlord is stateless. This means that when you call addTenant(), it will only scope the current request.
Make sure that you are adding your tenants in such a way that it
happens on every request, and before you need Models scoped, like in a
middleware or as part of a stateless authentication method like OAuth.
And it looks like I need to attach a the Landlord::addTenant('tenant_id', 1); facade.
This may be a pretty simple answer I am overlooking but where is the best place to to use addTenant and do I have to redeclare it with every controller or model? Should I attach it when the user signs in, use it in my routes or use as a middleware? If it is a middleware is the following correct in order to pull the company_id from the current user and use it with addTenant?
Middleware:
public function handle($request, Closure $next){
$tenantId = Auth::user()->tenant_id;
Landlord::addTenant('tenant_id', $tenantId);
return $next($request);
}
UPDATE
Here is my middleware (MultiTenant.php)
<?php
namespace App\Http\Middleware;
use Closure;
use App\User;
use Illuminate\Support\Facades\Auth;
class MultiTenant
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (Auth::check()) {
$tenantId = Auth::user()->company_id;
Landlord::addTenant('company_id', $tenantId); // Different column name, but same concept
}
return $next($request);
}
}
My routes/web.php
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| This file is where you may define all of the routes that are handled
| by your application. Just tell Laravel the URIs it should respond
| to using a Closure or controller method. Build something great!
|
*/
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::group(['middleware' => ['multitenant']], function () {
Route::get('/home', 'HomeController#index');
//Clients
Route::resource('clients', 'ClientController');
});
My Client.php Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use HipsterJazzbo\Landlord\BelongsToTenants;
class Client extends Model
{
use BelongsToTenants;
//
protected $fillable = [
'organization',
];
}
https://github.com/HipsterJazzbo/Landlord#user-content-usage
While just one option, I also went the middleware route. I saw it as an easy way to implement it.
I added the middleware to my routes/web.php file:
Route::group(['middleware' => ['landlord']], function () {
// Your routes
});
And my landlord middleware looks like this:
public function handle($request, Closure $next)
{
if (Auth::check()) {
$tenantId = Auth::user()->company_id;
Landlord::addTenant('company_id', $tenantId); // Different column name, but same concept
}
return $next($request);
}
Then I just add the trait to the models that I want scoped:
use HipsterJazzbo\Landlord\BelongsToTenant;
class User extends Authenticatable
{
use BelongsToTenant;
}
Update
Also, make sure in your config/app.php file you have added landlord to the providers array:
'providers' => [
// ...
HipsterJazzbo\Landlord\LandlordServiceProvider::class
// ...
],
And to the aliases array:
'aliases' => [
// ...
'Landlord' => HipsterJazzbo\Landlord\Facades\Landlord::class,
// ...
],
Then finally composer dump-autoload when completed to refresh the autoloading.
I follow this tutorial : https://www.youtube.com/watch?v=kmJYVhG6UzM Currently I can check in my blade if user is a admin or not like this:
{{ Auth::user()->roles->toArray()[0]['role'] }}
HI ADMIN
#endif
How can I make my route only available for admin user?
You need to create a middleware for your route.
Use: php artisan make:middleware AdminMiddleware.
You will find in your middleware folder a new file with this name.
Put your logic in your middleware, e.g.
public function handle($request, Closure $next)
{
if(Auth::check())
{
return $next($request);
}
else
{
return view('auth.login')->withErrors('You are not logged in');
}
}
Once you have done your logic in your middleware, you can either call it in the route or make the middleware apply to all routes.
If you want to add it to all routes, go to Kernel.php and add it to the $middleware array, e.g.
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',
'App\Http\Middleware\AdminMiddleware',
];
If you want to add it to specific routes only, add it to the $routeMiddleware variable and add the alias to the route. E.g.
protected $routeMiddleware = [
'auth' => 'App\Http\Middleware\Authenticate',
'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
'guest' => 'App\Http\Middleware\RedirectIfAuthenticated',
'admin' => 'App\Http\Middleware\AdminMiddleware',
];
You can then add it to a route, as a filter, e.g.
Route::get('admin/profile', ['middleware' => 'admin', function()
{
}]);
For additional info visit the docs:
http://laravel.com/docs/master/middleware
EDIT
An improvement on this would be to use variadic functions which was introduced in PHP 5.6
http://php.net/manual/en/migration56.new-features.php
Instead of having to make a middleware for each permission set you can do the following
PermissionMiddleware
namespace App\Http\Middleware;
use Closure;
use \App\Models\Role;
class PermissionMiddleware
{
// Pass parameters to this middleware
public function handle($request, Closure $next, ...$permitted_roles)
{
//Get a users role
$role = new Role;
$role_name = $role->getUserRoleByName();
foreach($permitted_roles as $permitted_role) {
if($permitted_role == $role_name) {
return $next($request);
}
}
return redirect()->back()->withErrors('You do not have the required permission');
}
}
Notice the ...$permitted_roles
Route::get('admin/profile', ['middleware' => 'PermissionMiddleware:Admin,Marketing', function()
{
}]);
You can now specify as many roles as required for one middleware rather than creating multiple by using middleware parameters
Docs
https://laravel.com/docs/5.3/middleware#middleware-parameters
Let's assume you have a column in your users table with isAdmin name which has a default value of 0 (false)
You can give special access using middleware in laravel like you give access to logged in users using auth middleware in laravel.
Now you need to create a middleware using the command :
php artisan make:middleware AdminMiddleware
In your Kernel.php you need to add this line to protected $routeMiddleware
'admin' => \App\Http\Middleware\AdminMiddleware::class,
In your middleware folder you have the AdminMiddleware file.
In that you need to put your logic
In this case this is how it might look like depending upon you
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RoleMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(Auth::user()->isAdmin == '1') // is an admin
{
return $next($request); // pass the admin
}
return redirect('/'); // not admin. redirect whereever you like
}
}
Now in your route you have to pass the url using this middleware
Here is how it might look like
Route::get('/iamanadmin', ['middleware' => 'admin', function() {
return view('iamanadmin');
}]);
use middleware and check for admin user.
Route::get('admin', ['middleware' => 'checkadmin', function()
{
}]);
now create middleware and validate admin user.