How to structure a good controller with Laravel Socialite?

Asked

Viewed 348 times

1

I’m using the Socialite to provide authentication via account providers (Facebook, Twitter, Linkedin...).

In my application, when authenticating via provider, if there is already an association of the current account of the user with the account of the provider it will be logged in, if there is no current link with the account of the provider, an association will be made with the current registration, if you do not have registration it will be created (user redirected to a view for the purpose of confirming only its name).

Routes/web.php

Route::get('auth-socialite/{provider}', 'Auth\SocialiteController@redirectToProvider');
Route::get('auth-socialite/{provider}/callback', 'Auth\SocialiteController@handleProviderCallback');
Route::post('auth-socialite/criar-usuario', 'Auth\SocialiteController@createUser');

Socialitecontroller.php

<?php

namespace App\Http\Controllers\Auth;

use Auth;
use Socialite;
use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\ProvedoresServicoContas;

class SocialiteController extends Controller
{
    /**
     * Endereço para onde o usuário será redirecionado após o login
     *
     * @var string
     */
    protected $redirectTo = '/home';

    /**
     * Chama a página de autenticação do provedor (Facebook, Linkedin, Twitter...)
     *
     * @param $provedor
     * @return mixed
     */
    public function redirectToProvider($provedor)
    {
        return Socialite::driver($provedor)->redirect();
    }

    /**
     * Autentica o usuário via callback do provedor (Facebook, Linkedin, Twitter...)
     *
     * @param $provedor
     * @return \Illuminate\Http\RedirectResponse
     */
    public function handleProviderCallback($provedor)
    {
        $userProvedor = Socialite::driver($provedor)->user();

        $authUsuario = $this->findOrCreateUser($userProvedor, $provedor);

        if (!$authUsuario)
            return view('auth.socialite-novo-user', compact('userProvedor', 'provedor'));

        Auth::login($authUsuario, true);

        return redirect($this->redirectTo);
    }

    /**
     * Se o usuário já existe o mesmo será retornado, do contrário será criado
     *
     * @param $userProvedor
     * @param $provedor
     * @return \App\Models\User
     */
    public function findOrCreateUser($userProvedor, $provedor)
    {
        $conta = ProvedoresServicoContas::whereProvedor($provedor)
            ->whereProvedorUserId($userProvedor->getId())
            ->first();

        if ($conta)
            return $conta->user;

        $usuario = User::whereEmail($userProvedor->getEmail())->first();

        if (!$usuario) {
            session(['userProvedor' => $userProvedor, 'provedor' => $provedor]);
            return false;
        }

        return $this->associarProvedorUsuario($usuario, $userProvedor, $provedor);
    }

    public function createUser(Request $request)
    {
        $userProvedor = session('userProvedor');
        $provedor = session('provedor');

        $usuario = User::create([
            'name' => $request->name,
            'email' => $userProvedor->email,
            'password' => bcrypt(str_random(20)),
        ]);

        $this->associarProvedorUsuario($usuario, $userProvedor, $provedor);

        Auth::login($usuario, true);

        return redirect($this->redirectTo);
    }

    public function associarProvedorUsuario($usuario, $userProvedor, $provedor)
    {
        $criarConta = new ProvedoresServicoContas([
            'provedor_user_id' => $userProvedor->getId(),
            'provedor' => $provedor
        ]);

        $criarConta->user()->associate($usuario);
        $criarConta->save();

        return $usuario;
    }
}

migrate:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateProvedoresServicoContasTable extends Migration
{
    /**
     * Run the migrations.


 *
     * @return void
     */
    public function up()
    {
        Schema::create('provedores_servico_contas', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id');
            $table->string('provedor');
            $table->string('provedor_user_id');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('provedores_servico_contas');
    }
}

Currently working, however, I think my controller is confused. Any suggestions for improvement in terms of organization and efficiency?

1 answer

-2

Try to separate into layers of responsibility .

Let the controller only receive the view request and pass on the processed content. Create services with all encapsulated business logic, handling business errors, validations, etc. I also suggest you create repositories that should be responsible for interpreting what is read and formatting the output of the data in a way that makes sense to the business, never undefined objects like Jsons or Dtos.

Creating the layers, at first, gives a job but is much more organized and easier to maintain.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.