laravel9 middleware not loaded when frontend and admin are seperated - laravel

I am doing the separation of frontend and admin. After several days of studying, It seems ok now. My github: https://github.com/ronrun/laravel-multiauth
Currently there are 4 versions.
There are 3 branches, the branch 9.x_two-tables has two version.
commit: frontend and admin login can login separately
The structure:
app\Http\Controller\Admin\Auth\LoginController.php
app\Http\Controller\Admin\DashboardController.php
app\Http\Controller\Auth\LoginController.php
app\Http\Controller\HomeController.php
commit: more seperation!
app\Admin\Console
app\Admin\Exceptions
app\Admin\Http\Controllers
app\Admin\Http\Middleware
app\Admin\Providers
app\Frontend\Console
app\Frontend\Exceptions
app\Frontend\Http\Controllers
app\Frontend\Http\Middleware
app\Frontend\Providers
app\Models
In short, it's
app\Admin
app\Frontend
app\Models
During the studying process, lots of questions I want to ask. Now all seems working fine. But I still have questions about the final commit: more seperation!
Question: Many files inside app\Frontend not loaded, only app\Admin's files are used.
The two files:
app\Admin\Http\Middleware\Authenticate.php
app\Frontend\Http\Middleware\Authenticate.php
I expected that when I am not logged in, but visite a page should login, the Authenticate's redirectTo() should do the redirect work. But only Admin's Authenticate.php is loaded. I clear the content of Frontend's Authenticate.php, make it compeletly empty, NO ERRORS. But If I clear the content of Admin's Authenticate.php, it says this class cannot found.
I found the RedirectIfAuthenticated.php is the same. Then I delete frontend's middleware folder, still working fine, no errors.
Then I delete app\Frontend\Console, Exceptions, no errors. The login functions of Frontend and Admin both working. But app\Frontend\Providers cannot be deleted, or error shows.
bootstrap\app.php
$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Frontend\Http\Kernel::class
);
$app->singleton(
Illuminate\Contracts\Console\Kernel::class,
App\Frontend\Console\Kernel::class
);
$app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Frontend\Exceptions\Handler::class
);
$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Admin\Http\Kernel::class
);
$app->singleton(
Illuminate\Contracts\Console\Kernel::class,
App\Admin\Console\Kernel::class
);
$app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Admin\Exceptions\Handler::class
);
Why does it only loads files inside app\Admin ?
Why no errors, login logout functions still work, when many Frontend files are deleted?
Any suggestions to improve the codes, I'd appreciate it.

To keep the frontend and admin separate, basically need:
separate routes file (say web.php, api.php & admin.php)
separate redirectTo routes in RedirectIfAuthenticated
separate redirectTo routes in Authenticate
To achieve that keep all default middleware & providers under app folder -
|-app
|-Http
|-Middleware
-Authenticate.php
-EncryptCookies.php
-PreventRequestsDuringMaintenance.php
-RedirectIfAuthenticated.php
-TrimStrings.php
-TrustHosts.php
-TrustProxies.php
-VerifyCsrfToken.php
|-Providers
-AppServiceProvider.php
-AuthServiceProvider.php
-BroadcastServiceProvider.php
-EventServiceProvider.php
-RouteServiceProvider.php
|-Frontend
|-Http
|-Controllers
|-FrontendControllers
|-Middleware
|-FrontendSpecificMiddleware (if any)
|-Requests
|-FrontendFormRequests (if any)
|-Languages
|-Other
|-Admin
|-Http
|-Controllers
|-AdminControllers
|-Middleware
|-AdminSpecificMiddleware (if any)
|-Requests
|-AdminFormRequests (if any)
|-Languages
|-Other
|-routes
|-web.php
To load routes, in App\Providers\RouteServiceProvider
$this->routes(function () {
Route::middleware('api')
->prefix('api')
->group(base_path('routes/api.php'));
Route::middleware('web')
->group(base_path('routes/web.php'));
Route::middleware('web')
->prefix('admin')
->as('admin.')
->group(app_path('Admin/routes/web.php'));
});
To set the redirect route for successful authentication
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* #param string|null ...$guards
* #return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
$prefix = $request->route()->getPrefix();
return $prefix == '/admin' ? redirect(route('admin.home') : redirect(RouteServiceProvider::HOME);
}
}
return $next($request);
}
}
To set redirect route for unsuccessful authentication
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* #param \Illuminate\Http\Request $request
* #return string|null
*/
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
$prefix = $request->route()->getPrefix();
return $prefix == '/admin' ? route('admin.login') : route('login);
}
}
}
You can also have App\Frontend\FrontendServiceProvider and App\Admin\AdminServiceProvider if you want and register them under providers array in config/app.php
To summarise, take cue from Domain Driven Design (DDD) approach. You can read about DDD at:
Stitcher - Laravel Beyond Crud - Domain Oriented Laravel
Conciliating Laravel and DDD

Related

After giving client expire date middleware validation return redirect to dashboard not working properly

I have created a middleware, the middleware name is expireDateCheck
This middleware class I have kept to Kernel.php and I've added to this class protected $routeMiddleware.
Inside Kernel.php code is:
protected $routeMiddleware = [ 'expireDateCheck' => \App\Http\Middleware\expireDateCheck::class, ]
Then I've given a condition inside middleware expireDateCheck.php for redirecting to the dashboard, this condition working fine but the main problem is it's redirecting to the dashboard two times which means after showing dashboard then it's showing again dashboard page it seems like dashboard page loading multiple time.
How can I fix this problem?
Inside middleware expireDateCheck.php code is:
<?php
namespace App\Http\Middleware;
use Closure;
use App\User;
use App\Client;
use Auth;
use Redirect;
class expireDateCheck
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (Auth::check() && Auth::user()){
$currentDate = date('Y-m-d H:i:s');
$userExpireDate = Client::where('expire_date', '<' , $currentDate)->first();
if($userExpireDate){
return Redirect::to('dashboard');
}
return $next($request);
}
}
}
Here are my routes:#Nikolay
Route::group(['middleware' => 'expireDateCheck'],function(){
-------------------------------
-------------------------------
});
Route::get('dashboard','DashboardController#index')->middleware('admin');
The middleware is run on all urls, therefor also on the request when loading the dashboard. You can remove the middlewares when defining the routes, this will avoid it from loading twice, and since the logic is to return them to the dashboard it does not makes sense running it on the dashboard.
Route::get('dashboard', 'DashboardController#index')->withoutMiddleware(['expireDateCheck']);
Or by grouping multiple.
Route::group([
'excluded_middleware' => ['expireDateCheck'],
], function () {});

Prevent user from accessing some routes in Laravel

Working on a Laravel application and I have some routes, the routes are of a multi step form. I need to prevent the user from accessing the last route (which directs to last page of the form) before accessing or filling in the previous routes.
Routes
Route::get( '/first', 'TrController#payQuote')->name('b2c.payquote');
Route::get( '/second', 'TrController#emailQuote')->name('b2c.sendquote');
Route::get( '/receipt', 'TrController#getReceipt')->name('b2c.receipt');
Route::get( '/success', 'TrController#getSuccess')->name('b2c.success');
You could create a middleware class and then use the middleware directly in your routes file.
Example:
<?php
namespace App\Http\Middleware;
use Closure;
class CheckPermission
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
// TODO: Add your logic here.
if ($request->age <= 200) {
return redirect('home');
}
return $next($request);
}
}
Then in your routes file:
Route::get('admin/profile', function () {
//
})->middleware(CheckPermission::class);
There are multiple ways to do it. One way could be that you can check http-referrer on the last page and if it is the route previous to the last one then you allow it otherwise redirect it to the previous page. This can be implemented for every page.
Other way could be database driven. For every page visit you can have an entry in the database and check on the next page if there is an entry otherwise redirect him to wherever you want.

New registered user to be redirected to the password reset screen

I'm quite new to Laravel and have been stumped on a problem for 2 days - I'd be grateful for some guidance.
I'm using the default out-of-the-box User authentication system with Laravel 5.3. A new user is created automatically behind the scenes by an existing Admin user - I will in time hide the user registration page. I have also successfully set up middleware to check if a user is newly registered (by looking for a null 'last_logged_in_date' that I've added to the migration).
All I want to happen is for a new registered user to be redirected to the password reset screen that ships with Laravel (again, in time I will create a dedicated page). I would like this to happen within the middleware file. So far, my middleware looks like this:
<?php
namespace App\Http\Middleware;
use Closure;
use App\Http\Controllers\Auth;
class CheckIfNewUser
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = $request->user();
if (! is_null($user->last_logged_in_date )) {
return $next($request);
}
// This is where I'm stuck!!!
}
}
I'm not sure what code to enter at the location indicated by the comments above. I've tried sendResetLinkEmail($request); etc and have imported what I though were the correct classes but I always end up with a Call to undefined function App\Http\Middleware\sendResetLinkEmail() message irregardless of what I 'use' at the top of my class.
Where am I going wrong? Thanks!
Well that happens because you have not defined your sendResetLinkEmail($request) function yet. You can do it like this, or you can create a new class with that and then call the class.
Call the trait SendsPasswordResetEmails and then access it with $this since traits are not classes and you cannot access their members directly.
<?php
namespace App\Http\Middleware;
use Closure;
use App\Http\Controllers\Auth;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
class CheckIfNewUser
{
use SendsPasswordResetEmails;
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = $request->user();
if (! is_null($user->last_logged_in_date )) {
return $next($request);
}
// This is where I'm stuck!!!
//EDIT
//return $this->SendsPasswordResetEmails->sendResetLinkEmail($request);
return $this->sendResetLinkEmail($request);
}
}

How to get Larvel5.3 session data or Authentication data from public directory?

I wrote some php function in public directory because I have to use external library.
Then I can't retrieve any session data and authentication data from the controller I have tested with below php script
session_start();
var_dump($_SESSION['user']);
I have initial Session data from AdminMiddlware already
It awesome for using it in Resource->view directories but can not in public.
namespace App\Http\Middleware;
use App\User;
use Closure;
use Illuminate\Support\Facades\Auth;
class AdminMiddleware
{
/**
* Handle an incoming request. User must be logged in to do admin check
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = User::find(\Auth::user()->id);
if ((int) $user->is_admin == (int) config('auth.guards.is_admin')) {
$collection = collect(Auth::user());
$thisdata = $collection->toArray();
$request->session()->put('user', $thisdata);
return $next($request);
}
return redirect()->guest('/');
}}
Ok, the simplest way that I can see to get this to work with Laravel is:
(If you haven't done so already) Copy
public/gallery/scripts/filemanager.config.default.json
to
public/gallery/scripts/filemanager.config.json
Then set "fileConnector"(line 25) to "/authenticate-filemanager", e.g
"fileConnector": "/authenticate-filemanager",
This will tell your Filemanager application to load through the route /authenticate-filemanager.
Next, go to public/gallery/connectors/php/application/FmApplication.php and at the bottom change if(!auth()) to if(!auth()->check()) this will tell the application to use the built-in auth in Laravel.
Then you will need to set up the actual route (this is essentially the contents of filemanager.php without the auth() function):
Route::match(['GET', 'POST'], 'authenticate-filemanager', function () {
require_once(public_path('gallery/connectors/php/application/Fm.php'));
require_once(public_path('gallery/connectors/php/application/FmHelper.php'));
$config = [];
$fm = Fm::app()->getInstance($config);
$fm->handleRequest();
});
Because both GET and POST calls are made to the same endpoint match is used. Make sure you don't put this route behind the auth middleware.
Lastly, you just need to to go to app/Http/Middleware/VerifyCsrfToken.php and add 'authenticate-filemanager' to the $except array to disable csrf for the route.
Hope this helps!
Update for RichFilemanger ver. 2.7.6 and Laravel 5.6
I use RichFilemanager in HTML text editor in admin panel. So check for admin user is logged in.
in public/../RichFilemanager/config/filemanager.config.json
"connectorUrl": "/admin/authenticate-filemanager",
in route/web.php
Route::match(['GET', 'POST'], '/admin/authenticate-filemanager', function () {
//Here check is admin or user is authenticated. Can use: auth()->check()
$isAuth = \App\Libraries\Admin\AdminBLL::isAuth();
if(!$isAuth){
return 'Not authenticated';
}
return require_once(public_path('assets/plugins/RichFilemanager/connectors/php/filemanager.php'));
});
As was wrote before by Ross Wilson: Lastly, you just need to to go to app/Http/Middleware/VerifyCsrfToken.php and add 'admin/authenticate-filemanager' to the $except array to disable csrf for the route.
Last one - setup files folder location in public/../RichFilemanager/connectors/php/filemanager.php
$local->setRoot('userfiles/filemanager', true, true);

How to prevent Laravel Routes from being accessed directly (i.e. non-ajax requests)

In my project, I am using Laravel purely as a backend api and all frontend is handled by Angular javascript. At the moment, the Laravel routes can be accessed directly and it will cough out all the data in Json that shows in the browser. I want to put a restriction on it so Laravel only responds to Ajax requests and nothing else.
I read this post here which has a solution for Laravel 4 that is by adding a restriction in filter.php. But as of Laravel 5.1, filters are no longer used and I believe Middleware can be used to do the same. However, I am not sure how to go ahead changing the Laravel 4 solution in that SO answer from filter to Middleware.
Can someone share your ideas on how to prevent Laravel 5.1 routes from being accessed directly please?
Laravel 4 solution using filter.php:
In filter.php declare this filter:
Route::filter('isAJAX', function()
{
if (!Request::AJAX()) return Redirect::to('/')->with(array('route' => Request::path()));
});
Then put all your routes that you only want accessible via AJAX into a group. In your routes.php:
Route::group(array('before' => 'isAJAX'), function()
{
Route::get('contacts/{name}', ContactController#index); // Or however you declared your route
... // More routes
});
Create the middleware file app/Http/Middleware/OnlyAjax.php with this content:
<?php
namespace App\Http\Middleware;
class OnlyAjax
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, \Closure $next)
{
if ( ! $request->ajax())
return response('Forbidden.', 403);
return $next($request);
}
}
Then register your middleware in the file app/Http/Kernel.php
<?php namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* #var array
*/
protected $middleware = [
//... your original code
];
/**
* The application's route middleware.
*
* #var array
*/
protected $routeMiddleware = [
//... your original code
'ajax' => \App\Http\Middleware\OnlyAjax::class,
];
}
And finally attach the middleware to any route or group of routes you want to make only accessible via AJAX. i.e:
/// File: routes/web.php
// Single route
Route::any('foo', 'FooController#doSomething')->middleware('ajax');
// Route group
Route::middleware(['ajax'])->group(function () {
// ...
});

Resources