You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wx.sstbc.com/tests/Unit/Services/AdminSmsChallengeServiceTes...

134 lines
5.0 KiB

<?php
namespace Tests\Unit\Services;
use App\Models\Admin;
use App\Services\AdminSmsChallengeService;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Hash;
use Tests\TestCase;
class AdminSmsChallengeServiceTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();
config([
'app.key' => 'test-key',
'admin-sms.cache_store' => 'array',
]);
Cache::store('array')->flush();
}
public function test_challenge_is_six_digits_hashed_and_single_use(): void
{
$service = app(AdminSmsChallengeService::class);
$sentCode = null;
$challengeId = $service->issueChallenge('13800138000', '127.0.0.1', function ($code) use (&$sentCode) {
$sentCode = $code;
return true;
});
$this->assertNotNull($challengeId);
$this->assertMatchesRegularExpression('/^\d{6}$/', $sentCode);
$stored = Cache::store('array')->get($service->challengeKey($challengeId));
$this->assertArrayNotHasKey('code', $stored);
$this->assertNotSame($sentCode, $stored['code_hash']);
$this->assertTrue(Hash::check($sentCode, $stored['code_hash']));
$admin = new Admin();
$admin->forceFill(['id' => 7, 'mobile' => '13800138000']);
$success = $service->verify($challengeId, '13800138000', $sentCode, '127.0.0.1', $admin);
$replay = $service->verify($challengeId, '13800138000', $sentCode, '127.0.0.1', $admin);
$this->assertTrue($success['ok']);
$this->assertFalse($replay['ok']);
}
public function test_fifth_failed_attempt_locks_and_invalidates_challenge(): void
{
$service = app(AdminSmsChallengeService::class);
$challengeId = $service->issueChallenge('13800138000', '127.0.0.1', fn () => true);
$admin = new Admin();
$admin->forceFill(['id' => 7, 'mobile' => '13800138000']);
$result = null;
for ($attempt = 0; $attempt < 5; $attempt++) {
$result = $service->verify($challengeId, '13800138000', '000000', '127.0.0.1', $admin);
}
$this->assertFalse($result['ok']);
$this->assertTrue($result['locked']);
$this->assertNull(Cache::store('array')->get($service->challengeKey($challengeId)));
}
public function test_phone_send_limit_allows_one_request_per_minute(): void
{
$service = app(AdminSmsChallengeService::class);
$this->assertTrue($service->canSend('13800138000'));
$this->assertFalse($service->canSend('13800138000'));
}
public function test_ip_limit_applies_across_multiple_mobile_numbers(): void
{
config([
'admin-sms.ip_max_failures' => 2,
'admin-sms.phone_max_failures' => 10,
]);
$service = app(AdminSmsChallengeService::class);
$admin = new Admin();
$admin->forceFill(['id' => 7, 'mobile' => '13800138000']);
foreach (['13800138000', '13900139000'] as $mobile) {
$challengeId = $service->issueChallenge($mobile, '127.0.0.1', fn () => true);
$result = $service->verify($challengeId, $mobile, '000000', '127.0.0.1', $mobile === $admin->mobile ? $admin : null);
$this->assertFalse($result['ok']);
}
$third = $service->issueChallenge('13700137000', '127.0.0.1', fn () => true);
$result = $service->verify($third, '13700137000', '000000', '127.0.0.1', null);
$this->assertTrue($result['locked']);
}
public function test_account_lock_applies_across_challenges(): void
{
config([
'admin-sms.account_max_failures' => 2,
'admin-sms.phone_max_failures' => 10,
'admin-sms.ip_max_failures' => 30,
]);
$service = app(AdminSmsChallengeService::class);
$admin = new Admin();
$admin->forceFill(['id' => 8, 'mobile' => '13800138000']);
for ($attempt = 0; $attempt < 2; $attempt++) {
$challengeId = $service->issueChallenge('13800138000', '127.0.0.' . ($attempt + 1), fn () => true);
$result = $service->verify($challengeId, '13800138000', '000000', '127.0.0.' . ($attempt + 1), $admin);
}
$this->assertTrue($result['locked']);
$third = $service->issueChallenge('13800138000', '127.0.0.3', fn () => true);
$result = $service->verify($third, '13800138000', '000000', '127.0.0.3', $admin);
$this->assertTrue($result['locked']);
}
public function test_production_sms_sending_is_restricted_to_configured_ips(): void
{
config([
'admin-sms.allowed_ips' => ['10.0.0.8'],
]);
$this->app->instance('env', 'production');
$service = app(AdminSmsChallengeService::class);
$this->assertFalse($service->canSend('13800138000', '10.0.0.9'));
$this->assertTrue($service->canSend('13800138000', '10.0.0.8'));
config(['admin-sms.allowed_ips' => []]);
$this->assertTrue($service->canSend('13900139000', '10.0.0.9'));
$this->app->instance('env', 'testing');
}
}