Skip to content

Commit

Permalink
hub: add option to verify users from social login (#2968)
Browse files Browse the repository at this point in the history
  • Loading branch information
emmachughes authored Feb 12, 2025
1 parent bfbb76b commit ad3e31c
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 10 deletions.
12 changes: 12 additions & 0 deletions docs/docs/hosting/hub-setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,15 @@ In `sourcecode/hub`, or the `hub` Docker container:
```sh
php artisan edlib:create-admin-user [email protected]
```

## Configuration settings

### `FEATURE_SOCIAL_USERS_ARE_VERIFIED`

If enabled, users logging in from "social login providers" (i.e. Facebook) will
automatically have their email addresses verified upon next login, without
having to go through the email verification process.

:::caution
Only enable this if you trust a login provider completely.
:::
1 change: 1 addition & 0 deletions sourcecode/hub/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ ASSET_URL=null
FEATURE_SIGNUP_ENABLED=true
FEATURE_RESET_PASSWORD_ENABLED=true
FEATURE_NOINDEX=false
FEATURE_SOCIAL_USERS_ARE_VERIFIED=false

LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
Expand Down
5 changes: 5 additions & 0 deletions sourcecode/hub/app/Configuration/Features.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,9 @@ public function isNoindexEnabled(): bool
{
return $this->enabled('noindex');
}

public function socialUsersAreVerified(): bool
{
return $this->enabled('social-users-are-verified');
}
}
27 changes: 17 additions & 10 deletions sourcecode/hub/app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace App\Models;

use App\Configuration\Features;
use App\Events\UserSaved;
use BadMethodCallException;
use Database\Factories\UserFactory;
Expand Down Expand Up @@ -153,25 +154,31 @@ public static function fromSocial(string $provider, SocialiteUser $details): sel
throw new InvalidArgumentException('Unknown social provider');
}

$features = app()->make(Features::class);

$user = self::firstWhere("{$provider}_id", $details->getId());

if ($user) {
return $user;
if (!$user) {
$user = self::firstWhere('email', $details->getEmail());
}

$user = self::firstWhere('email', $details->getEmail());

if ($user) {
$user->forceFill(["{$provider}_id" => $details->getId()]);
$user->save();
} else {
$user = self::forceCreate([
'name' => $details->getName(),
'email' => $details->getEmail(),
"{$provider}_id" => $details->getId(),
'email_verified' => $features->socialUsersAreVerified(),
]);
}

return $user;
if (!$user->email_verified && $features->socialUsersAreVerified()) {
$user->email_verified = true;
$user->save();
}

return self::forceCreate([
'name' => $details->getName(),
'email' => $details->getEmail(),
"{$provider}_id" => $details->getId(),
]);
return $user;
}
}
2 changes: 2 additions & 0 deletions sourcecode/hub/config/features.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@
'forgot-password' => (bool) env('FEATURE_RESET_PASSWORD_ENABLED', true),

'noindex' => (bool) env('FEATURE_NOINDEX', false),

'social-users-are-verified' => (bool) env('FEATURE_SOCIAL_USERS_ARE_VERIFIED', false),
];
35 changes: 35 additions & 0 deletions sourcecode/hub/tests/Feature/UserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Tests\Stub\SocialiteUser;
use Tests\TestCase;

use function config;
use function json_decode;

use const JSON_THROW_ON_ERROR;
Expand Down Expand Up @@ -72,6 +73,7 @@ public function testFindsSocialAccountById(): void
$user = User::factory()->create([
'name' => 'Not From Details',
'email' => 'something@different',
'email_verified' => false,
'google_id' => $details->getId(),
]);

Expand All @@ -81,6 +83,7 @@ public function testFindsSocialAccountById(): void
$this->assertSame($details->getId(), $found->google_id);
$this->assertSame('Not From Details', $found->name);
$this->assertSame('something@different', $found->email);
$this->assertFalse($found->email_verified);
}

public function testFindsSocialAccountByEmail(): void
Expand All @@ -90,6 +93,7 @@ public function testFindsSocialAccountByEmail(): void
$user = User::factory()->create([
'name' => 'Not From Details',
'email' => $details->getEmail(),
'email_verified' => false,
'facebook_id' => 'non-matching',
]);

Expand All @@ -99,6 +103,7 @@ public function testFindsSocialAccountByEmail(): void
$this->assertSame($details->getId(), $found->facebook_id);
$this->assertSame('Not From Details', $found->name);
$this->assertSame($details->getEmail(), $found->email);
$this->assertFalse($found->email_verified);
}

public function testCreatesSocialAccount(): void
Expand All @@ -111,5 +116,35 @@ public function testCreatesSocialAccount(): void
$this->assertSame($details->getId(), $created->auth0_id);
$this->assertSame($details->getName(), $created->name);
$this->assertSame($details->getEmail(), $created->email);
$this->assertFalse($created->email_verified);
}

public function testCreatedSocialAccountIsVerifiedWithSettingEnabled(): void
{
config(['features.social-users-are-verified' => true]);

$details = new SocialiteUser();

$created = User::fromSocial('auth0', $details);

$this->assertTrue($created->email_verified);
}

public function testFoundSocialAccountIsVerifiedWithSettingEnabled(): void
{
config(['features.social-users-are-verified' => true]);

$details = new SocialiteUser();

User::factory()->create([
'auth0_id' => $details->getId(),
'email' => $details->getEmail(),
'email_verified' => false,
]);

$found = User::fromSocial('auth0', $details);

$this->assertFalse($found->wasRecentlyCreated);
$this->assertTrue($found->email_verified);
}
}

0 comments on commit ad3e31c

Please sign in to comment.