CluPilotCloud/app/Http/Responses/LandsWhereSignedIn.php

63 lines
2.6 KiB
PHP

<?php
namespace App\Http\Responses;
use App\Support\AdminArea;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
use Laravel\Fortify\Fortify;
use Symfony\Component\HttpFoundation\Response;
/**
* Where a completed sign-in lands, shared by both ways of completing one.
*
* Fortify has two exits: LoginResponse for an ordinary sign-in, and
* TwoFactorLoginResponse after a challenge. Binding only the first left every
* account with two-factor enabled on the old behaviour — landing in the
* customer portal, and on a console-only host landing on a 404. Whichever exit
* is taken, the decision has to be the same one.
*/
trait LandsWhereSignedIn
{
protected function landing($request, JsonResponse $success): Response
{
// Where they were heading counts as much as where they posted from: in
// shared mode everyone signs in at /login, so the request itself never
// looks like the console even when /admin is the destination.
$onConsole = AdminArea::isConsole($request)
|| AdminArea::pointsAtConsole($request->session()?->get('url.intended'));
// Authorization first, before any branch. Answering JSON early let a
// non-operator keep the session on the console host that a browser
// request would have had taken away.
if ($onConsole && ! $request->user()?->can('console.view')) {
// Taken away at the moment it was created: the session exists as
// soon as Fortify authenticates, and a guard that merely refuses
// each page afterwards leaves it sitting in the browser.
Auth::guard('web')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
if ($request->wantsJson()) {
return new JsonResponse(['message' => __('auth.not_an_operator')], 403);
}
return redirect()->to(AdminArea::home())->withErrors([
Fortify::username() => __('auth.not_an_operator'),
]);
}
// Fortify answers JSON to a JSON client. Replacing that with a redirect
// would break every caller that is not a browser.
if ($request->wantsJson()) {
// The caller supplies it: Fortify answers {"two_factor":false} to an
// ordinary sign-in and an empty 204 after a challenge, and a client
// keying off the status code breaks if the two are merged.
return $success;
}
return redirect()->intended($onConsole ? AdminArea::home() : Fortify::redirects('login'));
}
}