digitalbiblesociety/dbp

View on GitHub
app/Http/Controllers/User/SocialController.php

Summary

Maintainability
A
35 mins
Test Coverage
<?php

namespace App\Http\Controllers\User;

use App\Models\User\ProjectMember;
use App\Models\User\Role;
use Illuminate\Encryption\Encrypter;
use Illuminate\Http\JsonResponse;
use App\Http\Controllers\APIController;

use App\Models\User\ProjectOauthProvider;
use App\Models\User\Account;
use App\Models\User\User;

use Laravel\Socialite\Two\BitbucketProvider;
use Laravel\Socialite\Two\FacebookProvider;
use Laravel\Socialite\Two\GithubProvider;
use Laravel\Socialite\Two\GoogleProvider;

use Socialite;
use Illuminate\Support\Str;

class SocialController extends APIController
{

    public function redirect($provider = null)
    {
        $project_id = checkParam('project_id');
        $provider   = checkParam('provider', true, $provider);

        $oAuthDriver = $this->getOauthProvider($project_id, $provider);
        if (!$oAuthDriver) {
            return $this->setStatusCode(404)->replyWithError('Socialite Provider not found');
        }

        return $this->reply([
            'data' => [
                'provider_id'  => $provider,
                'redirect_url' => urldecode($oAuthDriver->stateless()->redirect()->getTargetUrl()),
            ]
        ]);
    }

    /**
     * @param $provider
     *
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    public function callback($provider)
    {
        $project_id = checkParam('project_id', true);

        $driver = ProjectOauthProvider::where('project_id', $project_id)->where('name', $provider)->first();
        $oAuthDriver = $this->getOauthProvider($project_id, $provider);
        if (!$oAuthDriver) {
            return $this->setStatusCode(404)->replyWithError('Socialite Provider not found');
        }

        $user = $this->createOrGetUser($oAuthDriver->user(), $provider, $project_id);
        return redirect($driver->redirect_url.'?code='.base64_encode("$user->id,$user->email,$user->first_name $user->last_name"), 302);
    }

    private function getOauthProvider($project_id, $provider)
    {
        $driver = ProjectOauthProvider::where('project_id', $project_id)->where('name', $provider)->first();
        switch ($provider) {
            case 'bitbucket':
                $providerClass = BitbucketProvider::class;
                break;
            case 'facebook':
                $providerClass = FacebookProvider::class;
                break;
            case 'github':
                $providerClass = GithubProvider::class;
                break;
            case 'google':
                $providerClass = GoogleProvider::class;
                break;
            default:
                $providerClass = null;
        }

        if (!$providerClass || !$driver) {
            return null;
        }

        return Socialite::buildProvider($providerClass, [
            'client_id'     => $driver->client_id,
            'client_secret' => $driver->client_secret,
            'redirect'      => $driver->callback_url.'?project_id='.$project_id,
        ])->stateless();
    }

    private function createOrGetUser($providerUser, $provider, $project_id)
    {
        $account = Account::where('provider_id', $provider)->where('provider_user_id', $providerUser->getId())->first();
        if (!$account) {
            $user = User::where('email', $providerUser->getEmail())->first();
            if (!$user) {
                $user = User::create([
                    'id'        => Str::random(24),
                    'email'     => $providerUser->getEmail(),
                    'name'      => $providerUser->getName(),
                    'password'  => bcrypt(Str::random(16)),
                    'token'     => Str::random(10),
                    'activated' => 1,
                ]);
            }

            Account::create([
                'user_id'          => $user->id,
                'provider_user_id' => $providerUser->getId(),
                'provider_id'      => $provider,
                'project_id'       => $project_id
            ]);

            ProjectMember::create([
               'user_id'    => $user->id,
               'project_id' => $project_id,
               'role_id'    => Role::where('slug','user')->first()->id
            ]);

            return $user;
        }
        return $account->user;
    }
}