Многопользовательская многопользовательская база данных не может войти в поддомен

#php #laravel #pdo

Вопрос:

У меня есть приложение с несколькими клиентами / несколькими базами данных, и у каждого клиента есть свой собственный поддомен с Laravel 7.2

Когда я иду в rootdomain.com/super-admin Я могу войти в систему.

Когда я иду в demo.rootdomain.com/login Я могу войти в систему (база данных по умолчанию).

Когда я иду в tenant1.rootdomain.com/login Я НЕ могу войти в систему.

Я использую строительные леса Laravels Auth.

Я сузил его до признака ValidatesRequests. Если я добавлю адрес электронной почты/пароль вручную, я смогу войти в tenant1.rootdomain.com/login

Итак, это выглядит так:

 public function validate(Request $request, array $rules,
                             array $messages = [], array $customAttributes = [])
    {
     return [
              "email" => "tenant1@rootdomain.com",
              "password" => "#Abc123"
            ];
      
        return $this->getValidationFactory()->make(
            $request->all(), $rules, $messages, $customAttributes
        )->validate();
    }
 

Вот мой поставщик услуг аренды для переключения подключения для каждой БД

 public function register()
    {
      
      if($this->app->runningInConsole()){
        return;
      }
      
      $host = request()->getHttpHost();
      $new_host = explode('.',   str_replace('www.', '', $host));
      
      //host must contain at least 3 
      if(count($new_host) == 3 amp;amp; $new_host[0] != 'dev'){

          config(['database.connections.mysql.database' => 'c4_'.$new_host[0].'_app']);
          DB::purge('mysql');
          DB::reconnect('mysql');
           try {
                DB::connection()->getPdo();
                if(!DB::connection()->getDatabaseName()){
                       //reset to default
                    config(['database.connections.mysql.database' => 'c4_app']);
                    DB::purge('mysql');
                    DB::reconnect('mysql');
                    die("Could not find the database OR Subdomain. Please check your configuration.");
                }
            } catch (Exception $e) {
             //reset to default
                config(['database.connections.mysql.database' => 'c4_app']);
                DB::purge('mysql');
                DB::reconnect('mysql');
                die("Could not open connection to database server.  Please check your configuration OR subdomain.");
            }  
      }
      
//       dump('DB Connected...ready to go c4_mvp_app ',DB::connection()->getDatabaseName());

    }//end function
 

И мой ЛогинКонтроллер

 
namespace AppHttpControllersAuth;

use AppModelsGlobalSetting;
use AppHttpControllersFrontFrontBaseController;
use AppModelsSocial;
use AppTraitsSocialAuthSettings;
use AppModelsUser;
use CarbonCarbon;
use FroidenEnvatoTraitsAppBoot;
use GuzzleHttpClient;
use IlluminateFoundationAuthAuthenticatesUsers;
use IlluminateHttpRequest;
use IlluminateHttpResponse;
use IlluminateSupportFacadesLang;
use IlluminateSupportStr;
use IlluminateValidationRule;
use IlluminateValidationValidationException;
use LaravelSocialiteFacadesSocialite;

class LoginController extends FrontBaseController
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers, AppBoot, SocialAuthSettings;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = '/admin/dashboard';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
//       dd('Base Login', $this->redirectTo);
        parent::__construct();
        $this->middleware('guest', ['except' => 'logout']);

    }

    public function showLoginForm()
    {
        if (!$this->isLegal()) {
           // return redirect('verify-purchase');
        }

        if ($this->setting->front_design == 1 amp;amp; $this->setting->login_ui == 1) {
            return view('saas.login', $this->data);
        }
        $this->pageTitle = 'Login Page';
        return view('auth.login', $this->data);
    }

    protected function validateLogin(IlluminateHttpRequest $request)
    {
        $setting = GlobalSetting::first();

        $rules = [
            $this->username() => 'required|string',
            'password' => 'required|string'
        ];

        // User type from email/username
          $user_email = $request->{$this->username()};
          $user = User::where('email', $user_email)->first();

        if (!is_null($setting->google_recaptcha_key) amp;amp; (is_null($user) || ($user amp;amp; !$user->super_admin))) {
            $rules['g-recaptcha-response'] = 'required';
        }

        if (module_enabled('Subdomain')) {
            $rules = $this->rulesValidate($user);
        }

        $this->validate($request, $rules);
    }

    public function googleRecaptchaMessage()
    {
        throw ValidationException::withMessages([
            'g-recaptcha-response' => [trans('auth.recaptchaFailed')],
        ]);
    }

    public function companyInactiveMessage()
    {
        throw ValidationException::withMessages([
            $this->username() => [trans('auth.companyStatusInactive')],
        ]);
    }

    public function validateGoogleRecaptcha($googleRecaptchaResponse)
    {
        $setting = GlobalSetting::first();

        $client = new Client();
        $response = $client->post(
            'https://www.google.com/recaptcha/api/siteverify',
            [
                'form_params' =>
                [
                    'secret' => $setting->google_recaptcha_secret,
                    'response' => $googleRecaptchaResponse,
                    'remoteip' => $_SERVER['REMOTE_ADDR']
                ]
            ]
        );

        $body = json_decode((string) $response->getBody());

        return $body->success;
    }

    public function login(IlluminateHttpRequest $request)
    {
        $setting = GlobalSetting::first();
        $this->validateLogin($request);

        // User type from email/username
        $user = User::where($this->username(), $request->{$this->username()})->first();
// dd('LoginController login 140', $user);
        if ($user amp;amp;  !$user->super_admin amp;amp; $user->company->status == 'inactive' amp;amp; !$user->hasRole('client')) {
            return $this->companyInactiveMessage();
        }

        // Check google recaptcha if setting is enabled
        if (!is_null($setting->google_recaptcha_key) amp;amp; (is_null($user) || ($user amp;amp; !$user->super_admin))) {
            // Checking is google recaptcha is valid
            $gRecaptchaResponseInput = 'g-recaptcha-response';
            $gRecaptchaResponse = $request->{$gRecaptchaResponseInput};
            $validateRecaptcha = $this->validateGoogleRecaptcha($gRecaptchaResponse);
            if (!$validateRecaptcha) {
                return $this->googleRecaptchaMessage();
            }
        }

        // If the class is using the ThrottlesLogins trait, we can automatically throttle
        // the login attempts for this application. We'll key this by the username and
        // the IP address of the client making these requests into this application.
        if (
            method_exists($this, 'hasTooManyLoginAttempts') amp;amp;
            $this->hasTooManyLoginAttempts($request)
        ) {
            $this->fireLockoutEvent($request);

            return $this->sendLockoutResponse($request);
        }

        if ($this->attemptLogin($request)) {
            return $this->sendLoginResponse($request);
        }

        // If the login attempt was unsuccessful we will increment the number of attempts
        // to login and redirect the user back to the login form. Of course, when this
        // user surpasses their maximum number of attempts they will get locked out.
        $this->incrementLoginAttempts($request);

        return $this->sendFailedLoginResponse($request);
    }
  

    protected function credentials(IlluminateHttpRequest $request)
    {
        //return $request->only($this->username(), 'password');
//       dd('credentials 185',$request->{$this->username()});
        return [
            'email' => $request->{$this->username()},
            'password' => $request->password,
            'status' => 'active',
            'login' => 'enable'
        ];
    }

    protected function redirectTo()
    {
        $user = auth()->user();
        if ($user->super_admin == '1') {
            return 'super-admin/dashboard';
        } elseif ($user->hasRole('admin')) {
            $user->company()->update([
                'last_login' => Carbon::now()->format('Y-m-d H:i:s')
            ]);
            return 'admin/dashboard';
        }

        if ($user->hasRole('employee')) {
            return 'member/dashboard';
        }

        if ($user->hasRole('client')) {
            return 'client/dashboard';
        }
    }

    /**
     * Log the user out of the application.
     *
     * @param  IlluminateHttpRequest  $request
     * @return IlluminateHttpResponse
     */
    public function logout(Request $request)
    {
        $user = auth()->user();
        $this->guard()->logout();

        $request->session()->invalidate();
        if (module_enabled('Subdomain')) {
            if ($user->super_admin == 1) {
                return $this->loggedOut($request) ?: redirect(route('front.super-admin-login'));
            }
        }

        return $this->loggedOut($request) ?: redirect('/login');
    }

    private function rulesValidate($user)
    {

        if (Str::contains(url()->previous(), 'super-admin-login')) {
            $rules = [
                $this->username() => [
                    'required',
                    'string',
                    Rule::exists('users', 'email')->where(function ($query) {
                        $query->where('super_admin', '1');
                    })
                ],
                'password' => 'required|string',
            ];
        } else {
            $company = getCompanyBySubDomain();
            $client = false;
            $companies = [];

            if ($user amp;amp; User::isClient($user->id)) {
                $client = true;
                foreach ($user->client as $item) {
                    $companies[] = $item->company_id;
                }
            }

            $rules = [
                $this->username() => [
                    'required',
                    'string',
                    Rule::exists('users', 'email')->where(function ($query) use ($company, $companies, $client) {
                        if ($client) {
                            $query->whereIn('company_id', $companies);
                        } else {                          
                            $query->where('company_id', $company->id);
                        }
                    })
                ],
                'password' => 'required|string',

            ];
        }
//             dd('rulesValidate 281',$rules);
        return $rules;
    }


    public function redirect($provider)
    {
        $this->setSocailAuthConfigs();
        return Socialite::driver($provider)->redirect();
    }

    public function callback(Request $request, $provider)
    {
        $this->setSocailAuthConfigs();
        $redirectRoute = module_enabled('Subdomain') ? 'front.workspace' : 'login';

        try {
            if ($provider != 'twitter') {
                $data = Socialite::driver($provider)->stateless()->user();
            } else {
                $data = Socialite::driver($provider)->user();
            }
        } catch (Exception $e) {


            if ($request->has('error_description') || $request->has('denied')) {
                return redirect()->route($redirectRoute)->withErrors([$this->username() => 'The user cancelled ' . $provider . ' login']);
            }

            throw ValidationException::withMessages([
                $this->username() => [$e->getMessage()],
            ])->status(Response::HTTP_TOO_MANY_REQUESTS);
        }


        $user = User::where('email', '=', $data->email)->first();
        if ($user) {
            // User found
            DB::beginTransaction();

            Social::updateOrCreate(['user_id' => $user->id], [
                'social_id' => $data->id,
                'social_service' => $provider,
            ]);

            if ($user->super_admin == 1) {
                Auth::login($user);
                return redirect()->intended($this->redirectPath());
            }

            DB::commit();

            $user->social_token = Str::random(60);
            $user->save();

            if (module_enabled('Subdomain')) {
                return redirect()->to(str_replace(request()->getHost(), $user->company->sub_domain, route('login')) . '?token=' . $user->social_token);
            }

            Auth::login($user);
            return redirect()->intended($this->redirectPath());
        }

        if (module_enabled('Subdomain')) {
            return redirect()->route($redirectRoute)->withErrors(['sub_domain' => Lang::get('auth.sociaLoginFail')]);
        }

        throw ValidationException::withMessages([
            $this->username() => [Lang::get('auth.sociaLoginFail')],
        ])->status(Response::HTTP_TOO_MANY_REQUESTS);
    }
}
 

Дайте мне знать, если вам понадобится какой-либо другой код…спасибо!

Ответ №1:

Код работает нормально…. оказывается, это была проблема с кэшированием.