diff --git a/.env.example b/.env.example index ae67487f..d0ab8297 100644 --- a/.env.example +++ b/.env.example @@ -53,6 +53,10 @@ REVERB_SERVER_PORT=8080 GITHUB_CLIENT_ID= GITHUB_CLIENT_SECRET= +### GITLAB AUTH ### +GITLAB_CLIENT_ID= +GITLAB_CLIENT_SECRET= + ### DEVICE ENDPOINT ### ENABLE_DEVICE_AUTH_ENDPOINT=false diff --git a/app/Http/Controllers/Auth/GitLabSocialiteController.php b/app/Http/Controllers/Auth/GitLabSocialiteController.php new file mode 100644 index 00000000..d5fc3871 --- /dev/null +++ b/app/Http/Controllers/Auth/GitLabSocialiteController.php @@ -0,0 +1,96 @@ +with('loginError', 'GitLab login is not enabled.'); + } + + return Socialite::driver('gitlab')->redirect(); + } + + /** + * Handle the callback from GitLab after authentication. + */ + public function handleProviderCallback(): RedirectResponse + { + try { + $gitlabUser = Socialite::driver('gitlab')->user(); + $localUser = $this->findUserByEmail($gitlabUser->getEmail()); + + if (! $localUser instanceof User) { + $localUser = $this->createUser($gitlabUser); + } + + Auth::login($localUser); + + Log::debug('Logging GitLab user in.', ['email' => $gitlabUser->getEmail()]); + + Toaster::success(__('Successfully logged in via GitLab!')); + + return Redirect::route('overview'); + } catch (Exception $exception) { + Log::error('GitLab OAuth login error: ' . $exception->getMessage() . ' from ' . $exception::class); + + return Redirect::route('login')->with('loginError', 'Authentication failed. There may be an error with GitLab. Please try again later.'); + } + } + + /** + * Find a user by email and return the user's object if any. + * + * @param null|string $email The email of the user + */ + private function findUserByEmail(?string $email): ?User + { + return User::where('email', $email)->first(); + } + + /** + * Create a new user with GitLab data and return the user's object. + */ + private function createUser(SocialiteUser $socialiteUser): User + { + $user = User::create([ + 'name' => $socialiteUser->getName(), + 'email' => $socialiteUser->getEmail(), + ]); + + Mail::to($user->email)->queue(new WelcomeMail($user)); + + Log::debug('Creating new user from GitLab data.', ['email' => $socialiteUser->getEmail()]); + + return $user; + } +} diff --git a/config/services.php b/config/services.php index 4485b2cc..b56b33f8 100644 --- a/config/services.php +++ b/config/services.php @@ -32,4 +32,10 @@ 'client_secret' => env('GITHUB_CLIENT_SECRET'), 'redirect' => config('app.url') . '/auth/github/callback', ], + + 'gitlab' => [ + 'client_id' => env('GITLAB_CLIENT_ID'), + 'client_secret' => env('GITLAB_CLIENT_SECRET'), + 'redirect' => config('app.url') . '/auth/gitlab/callback', + ], ]; diff --git a/resources/views/components/icons/gitlab.blade.php b/resources/views/components/icons/gitlab.blade.php new file mode 100644 index 00000000..b753656b --- /dev/null +++ b/resources/views/components/icons/gitlab.blade.php @@ -0,0 +1,56 @@ + +{{----}} diff --git a/resources/views/livewire/pages/auth/login.blade.php b/resources/views/livewire/pages/auth/login.blade.php index c48669eb..3c90511f 100644 --- a/resources/views/livewire/pages/auth/login.blade.php +++ b/resources/views/livewire/pages/auth/login.blade.php @@ -99,6 +99,23 @@ public function login(): void @endif + @if (config('services.gitlab.client_id') && config('services.gitlab.client_secret')) +