159 lines
6.9 KiB
PHP
159 lines
6.9 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Staff;
|
|
|
|
use App\Domains\Core\Auth\Models\User;
|
|
use App\Domains\Core\Auth\Services\ResetPasswordAttemptService;
|
|
use Illuminate\Database\Schema\Blueprint;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Laravel\Sanctum\Sanctum;
|
|
use Mockery\MockInterface;
|
|
use Tests\TestCase;
|
|
|
|
class StaffEventScopeTest extends TestCase
|
|
{
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
// Exercise HTTP authorization on SQLite without the incompatible legacy migrations.
|
|
Schema::create('tenants', function (Blueprint $table): void {
|
|
$table->id();
|
|
$table->string('codigo');
|
|
$table->boolean('scanner_category_validation_enabled')->default(false);
|
|
});
|
|
Schema::create('roles', function (Blueprint $table): void {
|
|
$table->id();
|
|
$table->string('codigo');
|
|
$table->string('nombre');
|
|
});
|
|
Schema::create('users', function (Blueprint $table): void {
|
|
$table->id();
|
|
$table->string('rol_codigo');
|
|
$table->string('tenant_codigo');
|
|
$table->unsignedBigInteger('event_id')->nullable();
|
|
$table->string('nombre_apellido');
|
|
$table->string('dni');
|
|
$table->string('email');
|
|
$table->string('active_email')->nullable();
|
|
$table->string('password')->nullable();
|
|
$table->timestamps();
|
|
$table->softDeletes();
|
|
});
|
|
Schema::create('categorias', function (Blueprint $table): void {
|
|
$table->id();
|
|
$table->string('nombre');
|
|
$table->string('tenant_code')->nullable();
|
|
$table->unsignedBigInteger('categoria_id')->nullable();
|
|
});
|
|
Schema::create('catalog_items', function (Blueprint $table): void {
|
|
$table->id();
|
|
$table->unsignedBigInteger('category_id');
|
|
$table->string('tenant_code');
|
|
$table->softDeletes();
|
|
});
|
|
Schema::create('category_scanners', function (Blueprint $table): void {
|
|
$table->unsignedBigInteger('user_id');
|
|
$table->unsignedBigInteger('categoria_id');
|
|
$table->timestamps();
|
|
});
|
|
Schema::create('personal_access_tokens', function (Blueprint $table): void {
|
|
$table->id();
|
|
$table->string('tokenable_type');
|
|
$table->unsignedBigInteger('tokenable_id');
|
|
});
|
|
|
|
DB::table('tenants')->insert(['codigo' => 'onticket']);
|
|
foreach (['adminapp', 'scanner'] as $role) {
|
|
DB::table('roles')->insert(['codigo' => $role, 'nombre' => $role]);
|
|
foreach ([10, 20, null] as $eventId) {
|
|
$this->insertUser($role, 'onticket', $eventId);
|
|
}
|
|
$this->insertUser($role, 'other', 10);
|
|
}
|
|
Sanctum::actingAs(User::query()->findOrFail(1));
|
|
}
|
|
|
|
public function test_lists_and_searches_are_restricted_to_the_authenticated_event(): void
|
|
{
|
|
foreach (['administrators' => 1, 'staff' => 5] as $path => $id) {
|
|
foreach (['', '?search=Persona&event_id=20'] as $query) {
|
|
$this->getJson("/api/v1/adminapp/tenant/{$path}{$query}")
|
|
->assertOk()->assertJsonCount(1, 'data')
|
|
->assertJsonPath('data.0.id', $id)->assertJsonPath('data.0.event_id', 10);
|
|
}
|
|
}
|
|
}
|
|
|
|
public function test_creation_inherits_the_actor_event_even_if_the_client_supplies_another(): void
|
|
{
|
|
$this->mock(ResetPasswordAttemptService::class, function (MockInterface $mock): void {
|
|
$mock->shouldReceive('createForAdminAppEmail')->once();
|
|
$mock->shouldReceive('createForScannerEmail')->once();
|
|
});
|
|
foreach (['administrators' => 'adminapp', 'staff' => 'scanner'] as $path => $role) {
|
|
$this->postJson("/api/v1/adminapp/tenant/{$path}", [
|
|
...$this->payload("new-{$role}@example.com"), 'event_id' => 20,
|
|
])->assertSuccessful()->assertJsonPath('data.event_id', 10);
|
|
$this->assertDatabaseHas('users', ['email' => "new-{$role}@example.com", 'event_id' => 10, 'rol_codigo' => $role]);
|
|
}
|
|
}
|
|
|
|
public function test_foreign_and_unassigned_staff_cannot_be_edited_deleted_or_inspected(): void
|
|
{
|
|
foreach (['administrators' => [2, 3, 4], 'staff' => [6, 7, 8]] as $path => $ids) {
|
|
foreach ($ids as $id) {
|
|
$this->putJson("/api/v1/adminapp/tenant/{$path}/{$id}", $this->payload("update-{$id}@example.com"))->assertNotFound();
|
|
$this->deleteJson("/api/v1/adminapp/tenant/{$path}/{$id}")->assertNotFound();
|
|
$this->assertDatabaseHas('users', ['id' => $id, 'deleted_at' => null, 'email' => "person-{$id}@example.com"]);
|
|
if ($path === 'staff') {
|
|
$this->getJson("/api/v1/adminapp/tenant/staff/{$id}/scan-attempts")->assertNotFound();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public function test_own_staff_can_be_edited_and_deleted_without_changing_its_event(): void
|
|
{
|
|
$adminId = $this->insertUser('adminapp', 'onticket', 10);
|
|
foreach (['administrators' => $adminId, 'staff' => 5] as $path => $id) {
|
|
$this->putJson("/api/v1/adminapp/tenant/{$path}/{$id}", [
|
|
...$this->payload("updated-{$id}@example.com"), 'event_id' => 20,
|
|
])->assertOk()->assertJsonPath('data.event_id', 10);
|
|
$this->deleteJson("/api/v1/adminapp/tenant/{$path}/{$id}")->assertNoContent();
|
|
$this->assertSoftDeleted('users', ['id' => $id]);
|
|
}
|
|
}
|
|
|
|
public function test_unscoped_actor_keeps_tenant_lists_and_creates_without_an_event(): void
|
|
{
|
|
Sanctum::actingAs(User::query()->findOrFail(3));
|
|
$this->mock(ResetPasswordAttemptService::class, function (MockInterface $mock): void {
|
|
$mock->shouldReceive('createForAdminAppEmail')->once();
|
|
$mock->shouldReceive('createForScannerEmail')->once();
|
|
});
|
|
foreach (['administrators', 'staff'] as $path) {
|
|
$this->getJson("/api/v1/adminapp/tenant/{$path}")->assertOk()->assertJsonCount(3, 'data');
|
|
$this->postJson("/api/v1/adminapp/tenant/{$path}", $this->payload("legacy-{$path}@example.com"))
|
|
->assertSuccessful()->assertJsonPath('data.event_id', null);
|
|
}
|
|
}
|
|
|
|
private function insertUser(string $role, string $tenant, ?int $eventId): int
|
|
{
|
|
$id = DB::table('users')->count() + 1;
|
|
|
|
return DB::table('users')->insertGetId([
|
|
'id' => $id, 'rol_codigo' => $role, 'tenant_codigo' => $tenant,
|
|
'event_id' => $eventId, 'nombre_apellido' => 'Persona', 'dni' => '12345678',
|
|
'email' => "person-{$id}@example.com", 'active_email' => "person-{$id}@example.com",
|
|
]);
|
|
}
|
|
|
|
private function payload(string $email): array
|
|
{
|
|
return ['nombre_apellido' => 'Persona editada', 'dni' => '87654321', 'email' => $email];
|
|
}
|
|
}
|