143 lines
5.1 KiB
PHP
143 lines
5.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Feature\Api\Transaction;
|
|
|
|
use App\Enums\TransactionStatus;
|
|
use App\Models\Customer;
|
|
use App\Models\Transaction;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Http\UploadedFile;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Str;
|
|
use Tests\TestCase;
|
|
|
|
class ManualDepositProofTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
private function actingAsCustomer(Customer $customer): static
|
|
{
|
|
return $this->actingAs($customer, 'client')
|
|
->withHeaders(['x-access-token' => $this->buildClientAccessToken()]);
|
|
}
|
|
|
|
public function test_confirm_rejects_proof_path_belonging_to_another_customer(): void
|
|
{
|
|
Storage::fake('local');
|
|
|
|
$owner = Customer::factory()->create();
|
|
$attacker = Customer::factory()->create();
|
|
|
|
$ownerPath = UploadedFile::fake()->image('proof.jpg')->store('deposit-proofs/' . $owner->id, 'local');
|
|
|
|
$transaction = Transaction::create([
|
|
'uuid' => Str::uuid()->toString(),
|
|
'public_code' => 'MAN-TEST-' . Str::random(6),
|
|
'trans' => 'MANTEST' . time(),
|
|
'amount' => 100000,
|
|
'customer_id' => $attacker->id,
|
|
'type' => 'manual',
|
|
'status' => TransactionStatus::PENDING->value,
|
|
]);
|
|
|
|
$response = $this->actingAsCustomer($attacker)->postJson('/v1/transaction/manual-deposit/confirm', [
|
|
'uuid' => $transaction->uuid,
|
|
'proof_image' => $ownerPath,
|
|
]);
|
|
|
|
$response->assertStatus(422)->assertJsonPath('error', true);
|
|
$this->assertNull($transaction->fresh()->proof_image);
|
|
}
|
|
|
|
public function test_confirm_rejects_traversal_and_reused_proof_paths(): void
|
|
{
|
|
Storage::fake('local');
|
|
|
|
$customer = Customer::factory()->create();
|
|
$other = Customer::factory()->create();
|
|
$otherPath = UploadedFile::fake()->image('proof.jpg')->store('deposit-proofs/' . $other->id, 'local');
|
|
$usedPath = UploadedFile::fake()->image('old.jpg')->store('deposit-proofs/' . $customer->id, 'local');
|
|
|
|
$newTransaction = fn () => Transaction::create([
|
|
'uuid' => Str::uuid()->toString(),
|
|
'public_code' => 'MAN-TEST-' . Str::random(6),
|
|
'trans' => 'MANTEST' . Str::random(8),
|
|
'amount' => 100000,
|
|
'customer_id' => $customer->id,
|
|
'type' => 'manual',
|
|
'status' => TransactionStatus::PENDING->value,
|
|
]);
|
|
|
|
$newTransaction()->update(['proof_image' => $usedPath, 'status' => TransactionStatus::COMPLETED->value]);
|
|
|
|
foreach (["deposit-proofs/{$customer->id}/../{$otherPath}", $usedPath] as $path) {
|
|
$transaction = $newTransaction();
|
|
|
|
$this->actingAsCustomer($customer)->postJson('/v1/transaction/manual-deposit/confirm', [
|
|
'uuid' => $transaction->uuid,
|
|
'proof_image' => $path,
|
|
])->assertStatus(422);
|
|
|
|
$this->assertNull($transaction->fresh()->proof_image);
|
|
}
|
|
}
|
|
|
|
public function test_confirm_without_proof_is_rejected(): void
|
|
{
|
|
$customer = Customer::factory()->create();
|
|
|
|
$transaction = Transaction::create([
|
|
'uuid' => Str::uuid()->toString(),
|
|
'public_code' => 'MAN-TEST-' . Str::random(6),
|
|
'trans' => 'MANTEST' . time(),
|
|
'amount' => 100000,
|
|
'customer_id' => $customer->id,
|
|
'type' => 'manual',
|
|
'status' => TransactionStatus::PENDING->value,
|
|
]);
|
|
|
|
$response = $this->actingAsCustomer($customer)->postJson('/v1/transaction/manual-deposit/confirm', [
|
|
'uuid' => $transaction->uuid,
|
|
]);
|
|
|
|
$response->assertStatus(422)->assertJsonPath('error', true);
|
|
}
|
|
|
|
public function test_upload_then_confirm_binds_proof_to_owner(): void
|
|
{
|
|
Storage::fake('local');
|
|
|
|
$customer = Customer::factory()->create();
|
|
|
|
$transaction = Transaction::create([
|
|
'uuid' => Str::uuid()->toString(),
|
|
'public_code' => 'MAN-TEST-' . Str::random(6),
|
|
'trans' => 'MANTEST' . time(),
|
|
'amount' => 100000,
|
|
'customer_id' => $customer->id,
|
|
'type' => 'manual',
|
|
'status' => TransactionStatus::PENDING->value,
|
|
]);
|
|
|
|
$upload = $this->actingAsCustomer($customer)->post('/v1/transaction/manual-deposit/upload-proof', [
|
|
'file' => UploadedFile::fake()->image('proof.jpg'),
|
|
]);
|
|
|
|
$upload->assertStatus(200);
|
|
$path = $upload->json('path');
|
|
|
|
$this->assertStringStartsWith('deposit-proofs/' . $customer->id . '/', $path);
|
|
Storage::disk('local')->assertExists($path);
|
|
|
|
$confirm = $this->actingAsCustomer($customer)->postJson('/v1/transaction/manual-deposit/confirm', [
|
|
'uuid' => $transaction->uuid,
|
|
'proof_image' => $path,
|
|
]);
|
|
|
|
$confirm->assertStatus(200)->assertJsonPath('error', false);
|
|
$this->assertSame($path, $transaction->fresh()->proof_image);
|
|
}
|
|
}
|