feat: accept terms
CI / 🧪 Tests Laravel (push) Successful in 2m7s
CI / 🐳 Build & Push Image (push) Successful in 38s

This commit is contained in:
2026-08-07 16:10:25 +02:00
parent 68560655f3
commit 6b757c37be
5 changed files with 62 additions and 1 deletions
+1
View File
@@ -360,6 +360,7 @@ class AuthController extends Controller
$userAttributes['email'] = strtolower($data['email']);
$userAttributes['password'] = Hash::make($data['password']);
$userAttributes['avatar_url'] = $avatarPath;
$userAttributes['terms_accepted_at'] = now();
$trialDays = max(0, (int) config('billing.trial_days', 7));
if ($trialDays > 0) {
+1
View File
@@ -50,6 +50,7 @@ class RegisterRequest extends FormRequest
->symbols()
->uncompromised(),
],
'termsAccepted' => ['required', 'accepted'],
'avatar' => ['sometimes', 'nullable', 'image', 'max:2048'],
'bio' => ['nullable', 'string'],
'physicalActivityLevel' => ['sometimes', Rule::enum(PhysicalActivityLevel::class)],
+2
View File
@@ -58,6 +58,7 @@ class User extends Authenticatable implements FilamentUser, HasAvatar, HasLocale
'pace_preference',
'sex',
'date_of_birth',
'terms_accepted_at',
'suspended_at',
'suspended_by',
'suspended_reason',
@@ -95,6 +96,7 @@ class User extends Authenticatable implements FilamentUser, HasAvatar, HasLocale
'sex' => UserSex::class,
'role' => UserRole::class,
'date_of_birth' => 'immutable_date',
'terms_accepted_at' => 'datetime',
'suspended_at' => 'datetime',
'trial_ends_at' => 'datetime',
];
@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->timestampTz('terms_accepted_at')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('terms_accepted_at');
});
}
};
+30 -1
View File
@@ -27,6 +27,7 @@ it('sends a verification email when a user registers', function () {
'pacePreference' => PacePreference::NORMAL->value,
'sex' => UserSex::WOMAN->value,
'dateOfBirth' => '2003-04-24',
'termsAccepted' => true,
])
->assertCreated()
->assertJsonPath('user.email', 'leon@example.com')
@@ -45,7 +46,8 @@ it('sends a verification email when a user registers', function () {
expect($user->hasVerifiedEmail())->toBeFalse()
->and($user->trial_ends_at)->not->toBeNull()
->and($user->trial_ends_at->isFuture())->toBeTrue();
->and($user->trial_ends_at->isFuture())->toBeTrue()
->and($user->terms_accepted_at)->not->toBeNull();
$this->assertDatabaseHas('users', [
'id' => $user->id,
@@ -71,6 +73,7 @@ it('returns a temporary error when the verification email cannot be sent during
'email' => 'leon@example.com',
'password' => 'Motsdfdepasse123*',
'locale' => 'fr-FR',
'termsAccepted' => true,
])
->assertServiceUnavailable()
->assertJsonPath('message', __('api.auth.verification_email_failed'));
@@ -94,6 +97,7 @@ it('registers mobile users with a bearer token', function () {
'pacePreference' => PacePreference::NORMAL->value,
'sex' => UserSex::MAN->value,
'dateOfBirth' => '2003-04-24',
'termsAccepted' => true,
])
->assertCreated()
->assertJsonPath('user.email', 'mobile.leon@example.com')
@@ -111,6 +115,31 @@ it('registers mobile users with a bearer token', function () {
Notification::assertSentTo($user, VerifyEmail::class);
});
it('requires users to accept the terms during registration', function () {
Notification::fake();
$registrationData = [
'name' => 'TermsLeon',
'email' => 'terms.leon@example.com',
'password' => 'Motsdfdepasse123*',
'termsAccepted' => false,
];
$this->postJson('/api/auth/mobile/register', $registrationData)
->assertUnprocessable()
->assertJsonValidationErrors('termsAccepted');
unset($registrationData['termsAccepted']);
$this->postJson('/api/auth/mobile/register', $registrationData)
->assertUnprocessable()
->assertJsonValidationErrors('termsAccepted');
$this->assertDatabaseMissing('users', [
'email' => 'terms.leon@example.com',
]);
});
it('uses the custom account verification mailable', function () {
$user = User::factory()->unverified()->create([
'locale' => 'fr',