fix(auth): scope email uniqueness to active users
This commit is contained in:
parent
ddb8c3743f
commit
0baad641d5
|
|
@ -19,7 +19,7 @@ use Illuminate\Notifications\Notifiable;
|
|||
use Laravel\Sanctum\HasApiTokens;
|
||||
|
||||
#[Fillable(['nombre_apellido', 'email', 'password', 'dni', 'telefono', 'google_id', 'rol_codigo', 'tenant_codigo'])]
|
||||
#[Hidden(['password', 'remember_token'])]
|
||||
#[Hidden(['password', 'remember_token', 'active_email'])]
|
||||
class User extends Authenticatable
|
||||
{
|
||||
/** @use HasFactory<UserFactory> */
|
||||
|
|
|
|||
|
|
@ -21,7 +21,13 @@ class RegisterUserRequest extends FormRequest
|
|||
return [
|
||||
'tenant_codigo' => ['nullable', 'string', Rule::exists('tenants', 'codigo')],
|
||||
'nombre_apellido' => ['required', 'string', 'max:255'],
|
||||
'email' => ['required', 'string', 'email', 'max:255', Rule::unique('users', 'email')],
|
||||
'email' => [
|
||||
'required',
|
||||
'string',
|
||||
'email',
|
||||
'max:255',
|
||||
Rule::unique('users', 'email')->whereNull('deleted_at'),
|
||||
],
|
||||
'password' => ['required', 'string', 'confirmed', Password::min(8)->mixedCase()->symbols()],
|
||||
'dni' => ['nullable', 'string', 'max:255'],
|
||||
'telefono' => ['nullable', 'string', 'max:255'],
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace App\Domains\Auth\Requests;
|
|||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\Rules\Password;
|
||||
|
||||
class UpdateProfileRequest extends FormRequest
|
||||
{
|
||||
|
|
@ -19,11 +20,13 @@ class UpdateProfileRequest extends FormRequest
|
|||
'email' => [
|
||||
'required',
|
||||
'email',
|
||||
Rule::unique('users', 'email')->ignore($this->user()->id),
|
||||
Rule::unique('users', 'email')
|
||||
->whereNull('deleted_at')
|
||||
->ignore($this->user()->id),
|
||||
],
|
||||
'dni' => ['nullable', 'string', 'regex:/^[0-9]{7,8}$/'],
|
||||
'telefono' => ['nullable', 'string', 'regex:/^\+?[0-9\s\-]+$/'],
|
||||
'password' => ['nullable', 'string', \Illuminate\Validation\Rules\Password::min(8)->mixedCase()->symbols()],
|
||||
'password' => ['nullable', 'string', Password::min(8)->mixedCase()->symbols()],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,12 @@ class StoreStaffRequest extends FormRequest
|
|||
return [
|
||||
'nombre_apellido' => ['required', 'string', 'max:255'],
|
||||
'dni' => ['required', 'string', 'max:50'],
|
||||
'email' => ['required', 'email', 'max:255', 'unique:users,email'],
|
||||
'email' => [
|
||||
'required',
|
||||
'email',
|
||||
'max:255',
|
||||
Rule::unique('users', 'email')->whereNull('deleted_at'),
|
||||
],
|
||||
'category_ids' => $categoryRules,
|
||||
'category_ids.*' => ['integer', 'distinct', Rule::exists('categorias', 'id')],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@ class UpdateStaffRequest extends FormRequest
|
|||
'required',
|
||||
'email',
|
||||
'max:255',
|
||||
Rule::unique('users', 'email')->ignore($staffId),
|
||||
Rule::unique('users', 'email')
|
||||
->whereNull('deleted_at')
|
||||
->ignore($staffId),
|
||||
],
|
||||
'category_ids' => $categoryRules,
|
||||
'category_ids.*' => ['integer', 'distinct', Rule::exists('categorias', 'id')],
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table): void {
|
||||
$table->dropUnique(['email']);
|
||||
$table->string('active_email')
|
||||
->nullable()
|
||||
->storedAs('CASE WHEN `deleted_at` IS NULL THEN LOWER(`email`) ELSE NULL END');
|
||||
$table->unique('active_email');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table): void {
|
||||
$table->dropUnique(['active_email']);
|
||||
$table->dropColumn('active_email');
|
||||
$table->unique('email');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -121,6 +121,11 @@ class StaffControllerTest extends TestCase
|
|||
|
||||
$this->deleteJson("/api/v1/adminapp/tenant/staff/{$staffId}")->assertNoContent();
|
||||
$this->assertSoftDeleted('users', ['id' => $staffId]);
|
||||
$this->assertDatabaseHas('users', [
|
||||
'id' => $staffId,
|
||||
'email' => 'ada@example.test',
|
||||
'active_email' => null,
|
||||
]);
|
||||
$this->assertDatabaseMissing('personal_access_tokens', ['id' => $accessTokenId]);
|
||||
$this->assertDatabaseHas('category_scanners', [
|
||||
'user_id' => $staffId,
|
||||
|
|
@ -133,6 +138,24 @@ class StaffControllerTest extends TestCase
|
|||
->assertOk()
|
||||
->assertJsonCount(0, 'data');
|
||||
|
||||
$replacementResponse = $this->postJson('/api/v1/adminapp/tenant/staff', [
|
||||
'nombre_apellido' => 'Nueva Ada',
|
||||
'dni' => '11223344',
|
||||
'email' => 'ADA@example.test',
|
||||
'category_ids' => [$firstCategory->id],
|
||||
])->assertSuccessful()
|
||||
->assertJsonPath('data.email', 'ada@example.test');
|
||||
|
||||
$replacementStaffId = $replacementResponse->json('data.id');
|
||||
$this->assertNotSame($staffId, $replacementStaffId);
|
||||
$this->assertSame('Ada Byron', $ticket->fresh()->scannerUser?->nombre_apellido);
|
||||
$this->assertDatabaseHas('users', [
|
||||
'id' => $replacementStaffId,
|
||||
'email' => 'ada@example.test',
|
||||
'active_email' => 'ada@example.test',
|
||||
'deleted_at' => null,
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
public function test_admin_cannot_assign_another_tenants_category(): void
|
||||
|
|
|
|||
Loading…
Reference in New Issue