chore: align account lifecycle

This commit is contained in:
Andras Bacsai
2026-09-24 16:56:38 +02:00
parent 87685d1e09
commit c8dea4badc
5 changed files with 10 additions and 30 deletions
-1
View File
@@ -58,7 +58,6 @@ class CreateNewUser implements CreatesNewUsers
'password' => Hash::make($input['password']),
]);
$user->save();
$user->markEmailAsVerified();
$team = $user->teams()->first() ?? Team::find(0);
if ($team !== null && ! $user->teams()->where('team_id', $team->id)->exists()) {
$user->teams()->attach($team, ['role' => 'owner']);
+6 -24
View File
@@ -3,7 +3,6 @@
namespace App\Services\Auth;
use App\Auth\Oidc\OidcUser;
use App\Jobs\SendVerificationEmailJob;
use App\Models\OauthIdentity;
use App\Models\OauthSetting;
use App\Models\Team;
@@ -210,7 +209,7 @@ class OauthLoginService
throw new HttpException(403, 'Registration is disabled');
}
$user = $this->createUser($oauthUser->name ?: $email, $email, $oauthSetting, $emailVerified);
$user = $this->createUser($oauthUser->name ?: $email, $email, $oauthSetting);
}
OauthIdentity::create([
@@ -235,7 +234,7 @@ class OauthLoginService
return instanceSettings()->is_registration_enabled || $oauthSetting->allow_registration;
}
private function createUser(string $name, string $email, OauthSetting $oauthSetting, bool $emailVerified = true): User
private function createUser(string $name, string $email, OauthSetting $oauthSetting): User
{
if (User::count() === 0) {
$user = (new User)->forceFill([
@@ -245,7 +244,6 @@ class OauthLoginService
'password' => Hash::make(Str::random(64)),
]);
$user->save();
$this->verifyOrNotifyNewUser($user, $emailVerified);
$team = $user->teams()->first() ?? Team::find(0);
if ($team !== null && ! $user->teams()->where('team_id', $team->id)->exists()) {
@@ -258,23 +256,19 @@ class OauthLoginService
}
if ($oauthSetting->auto_join_root_team) {
return $this->createRootTeamOnlyUser($name, $email, $emailVerified);
return $this->createRootTeamOnlyUser($name, $email);
}
$user = User::create([
return User::create([
'name' => $name,
'email' => $email,
'password' => Hash::make(Str::random(64)),
]);
$this->verifyOrNotifyNewUser($user, $emailVerified);
return $user;
}
private function createRootTeamOnlyUser(string $name, string $email, bool $emailVerified): User
private function createRootTeamOnlyUser(string $name, string $email): User
{
return DB::transaction(function () use ($name, $email, $emailVerified) {
return DB::transaction(function () use ($name, $email) {
$rootTeam = Team::find(0);
if ($rootTeam === null) {
throw new HttpException(403, 'Root team is not available for OAuth user provisioning');
@@ -285,22 +279,10 @@ class OauthLoginService
'email' => $email,
'password' => Hash::make(Str::random(64)),
]));
$this->verifyOrNotifyNewUser($user, $emailVerified);
$user->teams()->attach($rootTeam, ['role' => 'member']);
return $user;
});
}
private function verifyOrNotifyNewUser(User $user, bool $emailVerified): void
{
if ($emailVerified) {
$user->markEmailAsVerified();
return;
}
SendVerificationEmailJob::dispatch($user)->afterCommit();
}
}
+1
View File
@@ -216,6 +216,7 @@ it('registers a new user from a verified provider identity', function () {
], OauthSetting::where('provider', 'google')->firstOrFail());
expect($user->email)->toBe('verified@example.com');
expect($user->email_verified_at)->toBeNull();
$this->assertAuthenticatedAs($user);
$this->assertDatabaseHas('oauth_identities', [
'user_id' => $user->id,
@@ -48,5 +48,6 @@ it('allows password registration when no oauth provider is enabled', function ()
'password_confirmation' => 'password',
]);
expect($user->email)->toBe('password@example.com');
expect($user->email)->toBe('password@example.com')
->and($user->email_verified_at)->toBeNull();
});
+1 -4
View File
@@ -1,7 +1,6 @@
<?php
use App\Auth\Oidc\OidcUser;
use App\Jobs\SendVerificationEmailJob;
use App\Models\InstanceSettings;
use App\Models\OauthIdentity;
use App\Models\OauthSetting;
@@ -13,7 +12,6 @@ use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Once;
use Laravel\Socialite\Facades\Socialite;
@@ -223,6 +221,7 @@ it('creates the root user when oidc provisions the first account', function () {
$response->assertRedirect('/');
$this->assertDatabaseHas('users', ['id' => 0, 'email' => 'root@example.com']);
expect(User::whereEmail('root@example.com')->firstOrFail()->email_verified_at)->toBeNull();
$this->assertDatabaseHas('team_user', ['team_id' => 0, 'user_id' => 0, 'role' => 'owner']);
expect(InstanceSettings::find(0)->is_registration_enabled)->toBeFalse();
});
@@ -295,7 +294,6 @@ it('logs callback failures with diagnostic context', function () {
});
it('does not mark a newly provisioned oidc account verified without a verified email claim', function () {
Queue::fake();
User::factory()->create(['email' => 'existing@example.com']);
OauthSetting::where('provider', 'oidc')->update(['allow_registration' => true, 'require_email_verified' => false]);
@@ -305,5 +303,4 @@ it('does not mark a newly provisioned oidc account verified without a verified e
$user = User::whereEmail('unverified@example.com')->firstOrFail();
expect($user->email_verified_at)->toBeNull();
Queue::assertPushed(SendVerificationEmailJob::class);
});