mirror of
https://github.com/Vateron-Media/XC_VM.git
synced 2026-10-03 12:02:29 +02:00
ResellerAPI::processData() is the whitelist every reseller line, MAG and Enigma2 save goes through. Two fields in it could be turned on other people's subscriptions: - pair_id: a new line stored whatever id was sent. Pairing copies the paired line's expiry and bouquets onto this one on every renewal (MagService::syncLineDevices), so a reseller could buy the cheapest line paired to another reseller's paying customer and ride that subscription for free. MAG and Enigma2 saves already required the paired line to be the reseller's own; now every type does. - trial: accepted on an edit, where it reset the expiry for trial_credits (usually 0). The trial quota counts lines by created_at, which an edit does not change, so any existing line could be extended forever. The forms only send it when creating; the API now does the same. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V2uBUbGApb4A7Rbcoi7dxA
40 lines
1.5 KiB
PHP
40 lines
1.5 KiB
PHP
<?php
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
use XcVm\Domain\User\ResellerAPI;
|
|
|
|
/**
|
|
* ResellerAPI::processData() — the whitelist every reseller save goes through.
|
|
*
|
|
* Two fields a reseller could use against other people's subscriptions are
|
|
* decided here: `trial` (a trial is issued with a new subscription, never on an
|
|
* edit, where the per-period trial quota — counted by created_at — does not
|
|
* see it) and `pair_id` (pairing copies the paired line's subscription onto
|
|
* this one, so only a line the reseller manages may be named).
|
|
*/
|
|
final class ResellerAPIProcessDataTest extends TestCase {
|
|
|
|
protected function tearDown(): void {
|
|
unset($GLOBALS['rUserInfo'], $GLOBALS['rPermissions']);
|
|
}
|
|
|
|
public function testDropsKeysOutsideTheWhitelist(): void {
|
|
$rData = ResellerAPI::processData('line', ['username' => 'u', 'member_group_id' => 1, 'exp_date' => 1]);
|
|
$this->assertSame(['username' => 'u'], $rData);
|
|
}
|
|
|
|
public function testTrialOnlyWhenCreating(): void {
|
|
foreach (['line', 'mag', 'enigma'] as $rType) {
|
|
$this->assertSame('1', ResellerAPI::processData($rType, ['trial' => '1'])['trial'] ?? null, $rType . ' create');
|
|
$this->assertArrayNotHasKey('trial', ResellerAPI::processData($rType, ['edit' => '7', 'trial' => '1']), $rType . ' edit');
|
|
}
|
|
}
|
|
|
|
public function testPairIdNeedsALineTheResellerManages(): void {
|
|
// No reseller context loaded: Authorization::check() answers false.
|
|
foreach (['line', 'mag', 'enigma'] as $rType) {
|
|
$this->assertArrayNotHasKey('pair_id', ResellerAPI::processData($rType, ['pair_id' => '42']), $rType);
|
|
}
|
|
}
|
|
}
|