diff --git a/app/Actions/ConnectGitHubAccount.php b/app/Actions/ConnectGitHubAccount.php
new file mode 100644
index 000000000..a05eb80d0
--- /dev/null
+++ b/app/Actions/ConnectGitHubAccount.php
@@ -0,0 +1,21 @@
+update([
+ 'github_id' => $socialiteUser->getId(),
+ 'github_username' => $socialiteUser->getNickname(),
+ ]);
+
+ dispatch(new UpdateUserIdenticonStatus($user));
+ }
+}
diff --git a/app/Actions/DisconnectGitHubAccount.php b/app/Actions/DisconnectGitHubAccount.php
new file mode 100644
index 000000000..15373a9ad
--- /dev/null
+++ b/app/Actions/DisconnectGitHubAccount.php
@@ -0,0 +1,17 @@
+update([
+ 'github_id' => null,
+ 'github_username' => null,
+ 'github_has_identicon' => false,
+ ]);
+ }
+}
diff --git a/app/Http/Controllers/Auth/GitHubController.php b/app/Http/Controllers/Auth/GitHubController.php
index cb8fa20d0..849779859 100644
--- a/app/Http/Controllers/Auth/GitHubController.php
+++ b/app/Http/Controllers/Auth/GitHubController.php
@@ -2,6 +2,7 @@
namespace App\Http\Controllers\Auth;
+use App\Actions\ConnectGitHubAccount;
use App\Http\Controllers\Controller;
use App\Jobs\UpdateProfile;
use App\Models\User;
@@ -28,7 +29,7 @@ public function redirectToProvider()
/**
* Obtain the user information from GitHub.
*/
- public function handleProviderCallback()
+ public function handleProviderCallback(ConnectGitHubAccount $connectGitHubAccount)
{
try {
$socialiteUser = $this->getSocialiteUser();
@@ -42,6 +43,27 @@ public function handleProviderCallback()
return $socialiteUser;
}
+ $isConnectingAttempt = session()->pull('settings.github.connect.intended', false);
+
+ if ($isConnectingAttempt) {
+ $currentUser = auth()->user();
+
+ // Check if the GitHub account is already connected to another user.
+ $existingUser = User::where('github_id', $socialiteUser->getId())
+ ->where('id', '!=', $currentUser->id)
+ ->first();
+
+ if ($existingUser) {
+ $this->error('This GitHub account is already connected to another user.');
+ } else {
+ $connectGitHubAccount($currentUser, $socialiteUser);
+
+ $this->success('Your GitHub account has been connected.');
+ }
+
+ return redirect(route('settings.profile'));
+ }
+
try {
$user = User::findByGitHubId($socialiteUser->getId());
} catch (ModelNotFoundException $exception) {
diff --git a/app/Http/Controllers/Settings/GitHubAccountController.php b/app/Http/Controllers/Settings/GitHubAccountController.php
new file mode 100644
index 000000000..8465b62f1
--- /dev/null
+++ b/app/Http/Controllers/Settings/GitHubAccountController.php
@@ -0,0 +1,40 @@
+middleware(Authenticate::class);
+ }
+
+ public function connect(): RedirectResponse
+ {
+ session()->put('settings.github.connect.intended', true);
+
+ return redirect(route('login.github'));
+ }
+
+ public function disconnect(DisconnectGitHubAccount $disconnectGitHubAccount): RedirectResponse
+ {
+ $user = auth()->user();
+
+ if (! $user->password) {
+ $this->error('You must set a password before disconnecting your GitHub account, otherwise, you will not be able to log in again.');
+
+ return redirect(route('settings.profile'));
+ }
+
+ $disconnectGitHubAccount($user);
+
+ $this->success('Your GitHub account has been disconnected.');
+
+ return redirect(route('settings.profile'));
+ }
+}
diff --git a/app/Models/User.php b/app/Models/User.php
index 1914dbf3f..87e841cfc 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -118,6 +118,11 @@ public function githubUsername(): string
return $this->github_username ?? '';
}
+ public function hasConnectedGitHubAccount(): bool
+ {
+ return ! is_null($this->githubId());
+ }
+
public function hasIdenticon(): bool
{
return (bool) $this->github_has_identicon;
diff --git a/resources/views/users/settings/github.blade.php b/resources/views/users/settings/github.blade.php
new file mode 100644
index 000000000..bbe4f3523
--- /dev/null
+++ b/resources/views/users/settings/github.blade.php
@@ -0,0 +1,61 @@
+@title('GitHub')
+
+
+ Connect your GitHub account to keep your profile for easy login and avatar sync.
+
+ You must set a password before disconnecting your GitHub account, otherwise, you will not be able to log in again.
+
+ Connecting your GitHub account will automatically populate your GitHub username and use your
+ GitHub profile image.
+
+ GitHub Account
+
+
+