Set Locale when using Auth::loginUsingId for phpunit - laravel

I have several languages in my Laravel 5.2 app. Each locale is stored in DB in th User Model. So, each time a user log, the locale must update.
Thing is in my Test, I use a lot Auth::loginUsingId, because I need to test function with differents user profiles.
So, I don't want to append to each of those calls with a App::setLocale(Auth::user->locale), nor extract it to a function.
Any Idea how should I do it???

What I did to address this problem is creating a middleware with
public function handle($request, Closure $next)
{
if ($user = Auth::user()) {
App::setLocale($user->locale);
}
return $next($request);
}
By handling all routes through this middleware, you can have the locale set automatically at each request.

Related

Laravel - Controller dependency is injected before middleware is executed

So I created a middleware to limit the data a connected user has access to by adding global scopes depending on some informations:
public function handle(Request $request, Closure $next)
{
if (auth()->user()?->organization_id) {
User::addGlobalScope(new OrganizationScope(auth()->user()->organization));
}
return $next($request);
}
The middleware is added to the 'auth.group' middleware group in Kernel.php which is used in web.php:
Route::middleware(['auth.group'])->group(function () {
Route::resource('users', UserController::class);
});
Then in the controller, I would expect a user to get a 404 when trying to see a page of a user he has no rights to. But the $user is retrieved before the middleware applies the global scope!
public function show(User $user, Request $request) {
// dd($user); // <= This actually contains the User model! It shouldn't, of course.
// dd(User::find($user->id)); // <= null, as it should!
}
So, the dependency is apparently calculated before the middleware is applied. If I'm trying to move the middleware into the 'web' group in Kernel.php it's the same. And in the main $middleware array, the authenticated user's data is not available yet.
I found this discussion that seems to be on topic : https://github.com/laravel/framework/issues/44177 but the possible solutions (and Taylor's PR) seems to point to a solution in the controller itself. Not what I'm trying to do, or I can't see how to adapt it.
Before that I was applying the global scopes at the Model level, in the booted function (as shown in the docs). But I had lots of issues with that - namely, accessing a relationship from there to check what is allowed or not is problematic, as the relationship call will look for something in the Model itself, and said model is not ready (that's the point of the booted method, right...). For example, checking a relationship of the connected user on the User model has to be done with a direct query to the db, that will be ran every time the Model is called... Not good.
Anyway, I like the middleware approach as it is a clean way to deal with rights as well, I think. Any recommandation?
Not a recommendation, just my opinion.
This issue is just because of that Laravel allow you add middleware in controller constructor, and that's why it calculate before midddleware in your case.
I agree that middleware is a clean way to deal with auth, but i also think that you are not completely doing auth in your middleware, for example if you create a new route will you need to add something auth action into your new controller or just add auth middleware to route?
If does needs add something to controller, that means your auth middleware is just put some permissions info into global scope and you are doing the auth in controller which i think it's not right.
Controller should be only control the view logic, and you should do full auth in your auth middleware, once the request passed into your controller function that means user passed your auth.
For some example, if you auth permissions like below, you can just add auth middleware to new route without any action in your controller when you trying to create new route.
public function handle(Request $request, Closure $next)
{
if (auth()->user()->canView($request->route())) { // you should do full auth, not just add informations.
return $next($request);
}
else
abort(404);
}

Google2FALaravel Authenticator always return True in Laravel 6

There is a problem using the Google-Authenticator Module "PragmaRX\Google2FALaravel" in my Laravel6 project.
I installed it following the manual on the github page. Setting up 2FA-Users via QRcode works like a charm, but the authentication middleware always returns "True" for authenticated, regardless if the user has passed the 2fa challenge or not.
public function handle($request, Closure $next)
{
$authenticator = app(Google2FAAuthenticator::class)->boot($request);
if ($authenticator->isAuthenticated()) { **//always returns true**
return $next($request);
}
return $authenticator->makeRequestOneTimePasswordResponse();
}
I assume it has something to do with the "CARTALYST/Sentinel" package i am using (instead of the built-in laravel "Auth" Manager), someone experienced similar behaviour and knows how to fix this?

Laravel: SetLocale based on value in users table

Version:
Laravel Version: 5.4.*
PHP Version: 5.6.x
Description:
I have a locale variable stored in the users table. Now I want to change the language of the app based on the user's locale variable (when the user logs in).
Steps To Reproduce:
I created a new middleware file
public function handle($request, Closure $next)
{
App::setLocale(Session::has('lang') ? Session::get('lang') : Config::get('app.locale'));
return $next($request);
}
And called this file in the Kernel.php
In my LoginController I have:
protected function authenticated(Request $request, $user)
{
Session::put('lang', $user->lang);
}
But this does not work. No errors, no different language. Anyone can help me with this?
For me, I use this one it work fine for me.
Session::put('lang', Auth::user()->lang);
or with full path
Session::put('lang', \Illuminate\Support\Facades\Auth::user()->lang);
I was able to fix it using a Event listener. With some help of this topic I managed to set the session variable based on the user's property. If someone needs more help, let me know!

Is it possible to force logout using user id in Laravel?

I'm wondering if there is any simple way to force logout different users by their id? For example I need to block currently lodged in user so I want to log out him after I set his status to block.
P.S.
I cant use middleware for this to check on each request.
I do this inside the Authenticate middleware
if (!Auth::user()->isActive()) {
Auth::logout();
return Redirect::home();
}
The user is already loaded there, no additional database query is needed here.
I don't think that's a performance issue, you just do a little if statement and you do it only if the user needs to be authenticated.
It's super easy if you are using database session driver:
DB::table('sessions')->where('user_id', $userId)->delete();
#PerterPan666 thanks, ya i ended up creating a middleware and adding it to the web group.
public function handle($request, Closure $next)
{
if (Auth::check())
{
if (Auth::User()->is_active != 'Y')
{
Auth::logout();
return redirect()->to('/')->with('warning', 'Your session has expired because your account is deactivated.');
}
}
return $next($request);
}
For anyone using later Laravel 5.6+, there's a method available for this built in. Doesn't mention where to call logoutOtherDevices, but LoginController#authenticated looks to work well as you can pass through their password, as required by the method
https://laravel.com/docs/5.8/authentication#invalidating-sessions-on-other-devices
public function authenticated(Request $request, $throttles)
{
\Illuminate\Support\Facades\Auth::logoutOtherDevices($request->get('password'));

Laravel 5.0 pass variable to middleware

At the moment I have to check if job record, which is being edited, belongs to right person. My get job edit route:
/user/job-edit/{slug}
So I created JobEditMiddleware but the problems is I can't access {slug} variable in my middlewar. Is there any way to do it? Thanks.
You can use segment() method to retrieve various segments of your URI.
Try following in your middleware,
\Request::segment(3)
Read More
You can access to your slug parameter easier.
public function handle($request, Closure $next, $role) {
//
}
You have to call your slug parameter like this :
$request->slug;
I think it's a better way than segment if you'll need to change your route later.

Resources