createUserSession(['list_own_subusers']); $subuser = api_fixtures()->createSubuser([ 'name' => 'Legacy Permission Driver', ]); $grantId = api_fixtures()->grantSubuser( $subuser['id'], $session['user']['customer_number'], ['VEHICLES_LIST'] ); $legacyPermissions = '0'; $statement = api_test_runtime()->db()->prepare( 'UPDATE `subuser_grants` SET `permissions` = ? WHERE `id` = ?' ); $statement->bind_param('si', $legacyPermissions, $grantId); $statement->execute(); $statement->close(); $response = api_client()->get('/subusers?page=1&limit=5&include_non_enabled=true', $session['headers']); $response ->assertStatus(200) ->assertEnvelope() ->assertSuccess(); $matchingSubusers = array_values(array_filter( is_array($response->data()) ? $response->data() : [], static fn (mixed $item): bool => is_array($item) && (int)($item['id'] ?? 0) === (int)$subuser['id'] )); expect($matchingSubusers)->toHaveCount(1); expect($matchingSubusers[0]['grant_permissions'] ?? null)->toBe([]); expect($matchingSubusers[0]['permissions'] ?? null)->toBe([]); }); it('uses the same password policy for subuser setup and password auth', function (): void { api_test_covers('POST /subusers/setup', 'failure'); api_test_covers('POST /subusers/auth/password', 'failure'); $subuser = api_fixtures()->createSubuser(); $setupResponse = api_client()->post('/subusers/setup', [ 'token' => 'policy-test-token', 'name' => 'Policy Driver', 'password' => 'invalidpassword', ]); $authResponse = api_client()->post('/subusers/auth/password', [ 'subuser_id' => $subuser['id'], 'password' => 'invalidpassword', ]); $setupResponse ->assertStatus(400) ->assertEnvelope() ->assertSuccess(false) ->assertMessage(SUBUSER_PASSWORD_POLICY_MESSAGE); $authResponse ->assertStatus(400) ->assertEnvelope() ->assertSuccess(false) ->assertMessage(SUBUSER_PASSWORD_POLICY_MESSAGE); }); it('lists chauffeur grants across customers for superusers', function (): void { $session = api_fixtures()->createUserSession(['list_subusers']); $firstCustomer = api_fixtures()->createUser([ 'display_name' => 'Fleet Customer Alpha', 'economic_customer_name' => 'Fleet Customer Alpha', ]); $secondCustomer = api_fixtures()->createUser([ 'display_name' => 'Fleet Customer Beta', 'economic_customer_name' => 'Fleet Customer Beta', ]); $firstSubuser = api_fixtures()->createSubuser(['name' => 'Alpha Driver']); $secondSubuser = api_fixtures()->createSubuser(['name' => 'Beta Driver']); $firstGrantId = api_fixtures()->grantSubuser( (int)$firstSubuser['id'], (int)$firstCustomer['customer_number'], ['VEHICLES_LIST', 'SUBUSERS_LIST'] ); $secondGrantId = api_fixtures()->grantSubuser( (int)$secondSubuser['id'], (int)$secondCustomer['customer_number'], ['BOOKINGS_LIST'] ); $response = api_client()->get('/superuser/subusers?page=1&limit=20&search=Driver', $session['headers']); $response ->assertStatus(200) ->assertEnvelope() ->assertSuccess(); $rows = array_values(array_filter( is_array($response->data()) ? $response->data() : [], static fn (mixed $item): bool => is_array($item) && in_array((int)($item['grant_id'] ?? 0), [$firstGrantId, $secondGrantId], true) )); expect($rows)->toHaveCount(2); $byGrantId = []; foreach ($rows as $row) { $byGrantId[(int)$row['grant_id']] = $row; } expect($byGrantId[$firstGrantId]['customer_number'])->toBe((int)$firstCustomer['customer_number']); expect($byGrantId[$firstGrantId]['customer_name'])->toBe('Fleet Customer Alpha'); expect($byGrantId[$firstGrantId]['grant_permissions'])->toBe(['VEHICLES_LIST', 'SUBUSERS_LIST']); expect($byGrantId[$secondGrantId]['customer_number'])->toBe((int)$secondCustomer['customer_number']); expect($byGrantId[$secondGrantId]['customer_name'])->toBe('Fleet Customer Beta'); expect($byGrantId[$secondGrantId]['grant_permissions'])->toBe(['BOOKINGS_LIST']); }); it('lets superusers invite chauffeurs for a selected customer', function (): void { $session = api_fixtures()->createUserSession(['add_subusers']); $customer = api_fixtures()->createUser([ 'display_name' => 'Invite Target Customer', 'economic_customer_name' => 'Invite Target Customer', ]); $phone = 71000000 + ((int)$customer['customer_number'] % 1000000); $createdSubuserId = null; $createdGrantId = null; $setupToken = null; try { $response = api_client()->post('/superuser/subusers/invite', [ 'customer_number' => (int)$customer['customer_number'], 'name' => 'Invited Driver', 'phone_country_code' => 45, 'phone' => $phone, 'permissions' => ['VEHICLES_LIST'], 'note' => 'Created by superuser test', ], $session['headers']); $response ->assertStatus(200) ->assertEnvelope() ->assertSuccess(); $payload = $response->data(); $createdSubuserId = isset($payload['subuser']['id']) ? (int)$payload['subuser']['id'] : null; $createdGrantId = isset($payload['grant']['id']) ? (int)$payload['grant']['id'] : null; $setupToken = isset($payload['invite']['setup_token']) ? (string)$payload['invite']['setup_token'] : null; expect($payload['subuser']['customer_number'] ?? null)->toBe((int)$customer['customer_number']); expect($payload['subuser']['name'] ?? null)->toBe('Invited Driver'); expect($payload['subuser']['grant_permissions'] ?? null)->toBe(['VEHICLES_LIST']); expect($payload['grant']['note'] ?? null)->toBe('Created by superuser test'); expect($payload['invite']['setup_link'] ?? null)->toBeString(); } finally { if ($setupToken !== null && $setupToken !== '') { (new \objects\subusers_o())->invalidateSetupToken($setupToken); } if ($createdGrantId !== null) { api_test_runtime()->db()->query('DELETE FROM `subuser_grants` WHERE `id` = ' . $createdGrantId); } if ($createdSubuserId !== null) { api_test_runtime()->db()->query('DELETE FROM `tokens` WHERE `user_id` = ' . $createdSubuserId . " AND `type` = 'AUTH_TOKEN_SUBUSER'"); api_test_runtime()->db()->query('DELETE FROM `subusers` WHERE `id` = ' . $createdSubuserId); } } });