*/ private array $settings; /** @param array $settings */ public function __construct(array $settings = []) { $this->settings = $settings; } public function fetchOne($sql, $params = []) { return ['c' => $this->usedToday]; } public function getSetting($key, $default = null) { return $this->settings[$key] ?? $default; } } /** * Die Grenzen der Kiosk-Seite sind das, was sie vor Missbrauch schützt – * der Link ist öffentlich, also muss diese Logik stimmen. */ class KioskTest extends TestCase { /** @param array $overrides */ private function kiosk(array $overrides = []): array { return array_merge([ 'id' => 1, 'daily_limit' => 100, 'cooldown_seconds' => 20, 'last_used_at' => null, ], $overrides); } public function testTokenHasFixedShape(): void { $token = \Kiosk::newToken(); $this->assertMatchesRegularExpression('/^[0-9a-f]{32}$/', $token); $this->assertNotSame($token, \Kiosk::newToken(), 'Tokens dürfen sich nicht wiederholen'); } public function testSanitizeTokenRejectsAnythingElse(): void { $valid = \Kiosk::newToken(); $this->assertSame($valid, \Kiosk::sanitizeToken($valid)); $this->assertSame($valid, \Kiosk::sanitizeToken(strtoupper($valid))); $this->assertSame('', \Kiosk::sanitizeToken('kurz')); $this->assertSame('', \Kiosk::sanitizeToken("' OR 1=1 --")); $this->assertSame('', \Kiosk::sanitizeToken(null)); $this->assertSame('', \Kiosk::sanitizeToken($valid . 'ff')); } public function testCooldownBlocksSecondCode(): void { $db = new FakeKioskDb(); $kiosk = $this->kiosk(['last_used_at' => date('Y-m-d H:i:s', time() - 5)]); $result = \Kiosk::checkLimits($db, $kiosk); $this->assertFalse($result['allowed']); $this->assertSame('cooldown', $result['reason']); $this->assertGreaterThan(0, $result['wait']); $this->assertLessThanOrEqual(20, $result['wait']); } public function testCooldownExpires(): void { $db = new FakeKioskDb(); $kiosk = $this->kiosk(['last_used_at' => date('Y-m-d H:i:s', time() - 60)]); $this->assertTrue(\Kiosk::checkLimits($db, $kiosk)['allowed']); } public function testDailyLimitBlocks(): void { $db = new FakeKioskDb(); $db->usedToday = 100; $result = \Kiosk::checkLimits($db, $this->kiosk()); $this->assertFalse($result['allowed']); $this->assertSame('daily_limit', $result['reason']); } public function testZeroMeansUnlimited(): void { $db = new FakeKioskDb(); $db->usedToday = 5000; $kiosk = $this->kiosk(['daily_limit' => 0, 'cooldown_seconds' => 0]); $this->assertTrue(\Kiosk::checkLimits($db, $kiosk)['allowed']); } public function testVoucherSettingsPreferTemplate(): void { $db = new FakeKioskDb(['default_max_uses' => '1', 'default_expire_minutes' => '480']); $kiosk = $this->kiosk([ 'tpl_max_uses' => 5, 'tpl_expire_minutes' => 240, 'qos_rate_max_down' => 20000, 'qos_rate_max_up' => 5000, 'qos_usage_quota' => 1024, ]); $settings = \Kiosk::voucherSettings($db, $kiosk); $this->assertSame(5, $settings['max_uses']); $this->assertSame(240, $settings['expire_minutes']); $this->assertSame(20000, $settings['qos']['down']); $this->assertSame(1024, $settings['qos']['quota_mb']); } public function testVoucherSettingsFallBackToDefaults(): void { $db = new FakeKioskDb(['default_max_uses' => '3', 'default_expire_minutes' => '120']); $settings = \Kiosk::voucherSettings($db, $this->kiosk()); $this->assertSame(3, $settings['max_uses']); $this->assertSame(120, $settings['expire_minutes']); $this->assertSame(0, $settings['qos']['down']); } public function testPublicUrl(): void { $token = \Kiosk::newToken(); $this->assertSame( 'https://wlan.example.com/kiosk.php?k=' . $token, \Kiosk::publicUrl($token, 'https://wlan.example.com/') ); } }