In my app I provided prefix e.g. en which my site loads as domain.xyz/en now this is working, but what I need to add is:
force redirect when user visits websites without any prefix:
e.g. user try to load domain.xyz this domain must redirect to domain.xyz/en (default prefix) for the first time in order to site loads, but later if user choose another lang it can be set to that. r.g. domain.xyz/es
Question
What should I write in my middleware to achieve that redirect?
I've tried to use:
1-$request->route().parameters();
and
2-$request->route().getPrefix();
no luck.
code
<?php
namespace App\Http\Middleware;
use Closure;
class PrefixMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
return $next($request);
}
}
Update
Here is how my web.php looks like:
$route_prefix = \Config::get('app.route_prefix');
Route::group(['middleware' => 'verified', 'prefix' => $route_prefix.'/'], function () use ($route_prefix){
Route::get('/', 'HomeController#welcome')->name('homepage');
});
Update 2
Based on comments suggestion now I have something like:
public function handle($request, Closure $next)
{
$prefix = \Config::get('app.route_prefix');
\App::setLocale($prefix);
return $next($request.'/'.$prefix);
}
and it returns:
Call to a member function setUserResolver() on string
Solved
I used this tutorial and it fixed my problem
Related
I'm trying to get settings from the database and put them in the config,
my function need the user id so it can bring his settings only,
in the service provider ( boot function ) there is no authentication yet, can you please advise me to the right place to run my function, please note that I need it to run before the view get rendered because there are settings for the layout inside it, this is my function :
// public static becouse it's inside Class//
public static function getAppSettings(){
if (!config('settings') && Auth::check()) {
$user_id = Auth::user()->id;
$settings = AppSettings::where('user_id', $user_id)->get()->all();
$settings = Cache::remember('settings', 60, function () use ($settings) {
// Laravel >= 5.2, use 'lists' instead of 'pluck' for Laravel <= 5.1
return $settings->pluck('value', 'key')->all();
});
config()->set('settings', $settings);
}else{
// this is for testing//
dd('no');
}
}
without the auth, it can work inside the service provider ( boot function ) but it will bring all settings for all the users.
You can create middleware for this.Middleware calls after routes and before controller
php artisan make:middleware Settings
This will create below class
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class Settings
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
// exicute your logic here
return $next($request);
}
}
You can call your method inside handle and before next
You can read more about this in
https://laravel.com/docs/8.x/middleware
I have a basic web page where I want the user to be able to click the login link, go through the login, and then be returned to that page (not the home page). The page has some features that can only be seen when the user is logged in.
I am having trouble with this, no matter what when I go to login it returns to the home page after authentication or whatever I have set as the constant, not the prior page.
Fortify.php has a home path that is a constant, so I can't update that with an expression either...
'home' => RouteServiceProvider::HOME,
Here is the middleware RedirectIfAuthenticated.php, it is the standard Laravel and I'm wondering what would need to be updated.
<?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 $next
* #param string|null ...$guards
* #return mixed
*/
public function handle(Request $request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
}
return $next($request);
}
}
I should note too, that if I add a middleware route to the page, as in the below example, then the process works correctly as far as returning the user back to the prior page.
Route::middleware(['auth:sanctum', 'verified'])->get('/agenda', function () {
return view('agenda');
})->name('agenda');
However, I need the user to be able to view the agenda page, even if they are a guest... but, once logged in, they will be returned to the agenda page which will have some additional features. I can't seem to find in the documentation anything about this, unfortunately.
In AuthenticatesUsers.php
protected function sendLoginResponse(Request $request)
{
$request->session()->regenerate();
$this->clearLoginAttempts($request);
if ($response = $this->authenticated($request, $this->guard()->user())) {
return $response;
}
return $request->wantsJson()
? new JsonResponse([], 204)
: redirect()->back();
}
Or You Can Do this in Your Default Login Controller in Line 31
protected $redirectTo = "/your-path";
When the auth middleware detects an unauthenticated user, it will redirect the user to the login named route. You may modify this behavior by updating the redirectTo function in your application's app/Http/Middleware/Authenticate.php file
https://laravel.com/docs/8.x/authentication#redirecting-unauthenticated-users
I am building a Laravel site for personal use and I would like to make the first user to register on the site be the only user. So with a fresh Laravel install with the ui installed, migration sorted and no users registered, I would like the register route to be reachable. But if there is a registered user, block the register route and only allow the login route to be reachable.
I could do something like this in the web.php
Route:get('/register', function () {...})->auth();
But I would have to do that after I first create a user. I'd rather do it in a more controllable fashion.
Edit
I don't doubt that #yves-kipondo's answer is the more correct option if I were to create this for someone else.
The solution I went with is a simple one. In my register controller I just add a check in the constructor, if there already is a user return a 404.
public function __construct() {
if (!User::all()) {
$this->middleware('guest');
} else {
abort(404);
}
}
You can create a Middleware which will be register on the register route
<?php
namespace App\Http\Middleware;
use Closure;
class RegisterOnce
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (User::count() !== 0) {
// you can redirect wherever you want
return redirect('home');
}
return $next($request);
}
}
After that you can register the middleware in the app/Http/Kernel.php by adding this line after all registered routes middleware like this
protected $routeMiddleware = [
\\ ... previous registered middleware
'once' => App\Http\Middleware\RegisterOnce::class,
];
and you can customize the register route like this in the routes/web.php file
which wille replace the default set by Auth::routes();
Route::get('register', [App\Controllers\Auth\RegisterController::class, 'showRegistrationForm'])
->name('register')
->middleware('once');
Hello in my project I am using the auto generated password from the admin side.And when the user try to login I am checking that user changed the password or not if password is not changes I want to redirect the user at the changepassword screen. I set changepasword middleware for it but middleware do not call the changepassword redirection Link.
changepasword middleware
use Closure;
use Auth;
class ChangePassword
{
/**
* 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()->isAutoPasswordChanged() )
{
return redirect('/change_password');
}
else
{
return redirect('/tests');
}
}
}
web.php
Route::group(['middleware' => 'auth', 'changepassword'], function () {
Route::resource('/tests', 'TestController');
Route::resource('/clients', 'ClientController');
});
Go to app\Http\Kernel.php
and add this to $routeMiddleware
'change_password' => \App\Http\Middleware\ChangePassword::class,
Then in your routes, replace the middle ware line with
Route::group(['middleware' => ['auth', 'changepassword']], function () {
And I also believe the logic written in ChangePassword is wrong...
It should be
if (!auth()->user()->isAutoPasswordChanged()) {
return redirect(route('auth.change.password.get'));
}
return $next($request);
First, please use the route() function instead of simple string... You will not have to change the url here, if you ever change the route from your web.php
Since you are already using the auth middleware, there is no need for you to do auth()->check().
Secondly, there should be a NOT in the condition. Because if the AutoPassword is NOT changed, only then redirect to the route, otherwise the use should be returned the next request and NOT redirected to /tests
Check registration of middleware app/Http/Kernel.php Doc
If you have a route middleware, compare the name provided in app/Http/Kernel.php
but my guess is:
'middleware' => 'auth', 'changepassword' should maybe changed in 'middleware' => ['auth', 'changepassword']
Debug if middleware itself is called
I have a two level resource in Laravel as below;
Route::resource("domains", "DomainsController");
Route::resource("domains/{domain}/subdomains", "SubDomainsController");
and I have two policies;
DomainPolicy.php
SubDomainPolicy.php
the problem is that these domains belong to different users, so I have to authorize these domains and subdomains. I can authorize DomainsController easily since all I have to do is Domain::class => DomainPolicy::class in AuthServiceProvider.php.
When it comes to authorizing SubDomainsController I can use the same policy input such as SubDomain::class => SubDomainPolicy::class, BUT when I access the /domains/1/subdomains/create link since there is no Domain::class delivered to the SubDomainPolicy::class it always prevents access to create page.
I use $this->authorizeResource(Domain::class) and $this->authorizeResource(SubDomain::class) in resource controller constructors without any arguments.
I need to pass Domain model to the SubDomainPolicy someway, thanks in advance.
I have found the solution not through a policy but a middleware. Since the models are binded on web.php Domain::class is always delivered to the SubDomainsController class, so I changed the constructor as;
public function __construct(Domain $domain) {
$this->middleware("domain-access");
}
or you can set it on web.php as a middleware group (eg. ['middleware' => 'domain-access']).
In middleware folder create a middleware named DomainAccess.php with this content;
namespace App\Http\Middleware;
use Closure;
use Illuminate\Auth\Access\AuthorizationException;
class DomainAccess
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
*
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = $request->user();
$domain = $request->domain;
if ($domain->user_id != $user->id) {
return redirect("/");
}
return $next($request);
}
}
And, voila! Everything is working perfectly.
Have a beautiful day.