egroupware/api/tests/Storage/CustomfieldsTest.php
nathangray d6c6e14abf * Api: Prevent invalid customfield names
(cherry picked from commit ae86eb7812)
2021-06-11 13:18:03 -06:00

321 lines
8.0 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Tests for customfields
*
* @package api
* @subpackage tests
* @link http://www.egroupware.org
* @author Nathan Gray
* @copyright 2018 Nathan Gray
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
*/
namespace EGroupware\Api\Storage;
use EGroupware\Api\LoggedInTest as LoggedInTest;
class CustomfieldsTest extends LoggedInTest
{
const APP = 'test';
protected $customfields = null;
protected $simple_field = array(
'app' => self::APP,
'name' => 'test_field',
'label' => 'Custom field',
'type' => 'text',
'type2' => array(),
'help' => 'Custom field created for automated testing by CustomfieldsTest',
'values' => null,
'len' => null,
'rows' => null,
'order' => null,
'needed' => null,
'private' => array()
);
public function tearDown(): void
{
// Clean
$fields = Customfields::get(self::APP);
foreach($this->customfields as $field_name)
{
unset($fields[$field_name]);
}
Customfields::save(self::APP, $fields);
parent::tearDown();
}
protected function assertPreConditions() : void
{
parent::assertPreConditions();
$tables = $GLOBALS['egw']->db->table_names(true);
$this->assertContains('egw_test', $tables, 'Could not find DB table "egw_test", make sure test app is installed');
}
/**
* Check to make sure we can create a custom field
*/
public function testCreateField()
{
// Create
$field = $this->simple_field;
$this->customfields[] = $field['name'];
Customfields::update($field);
// Check
$fields = Customfields::get(self::APP);
$this->assertArrayHasKey($field['name'], $fields);
$saved_field = $fields[$field['name']];
foreach(array('app','label','type','type2','help','values','len','rows','needed','private') as $key)
{
$this->assertEquals($field[$key], $saved_field[$key], "Load of $key did not match save");
}
// Clean
unset($fields[$field['name']]);
Customfields::save(self::APP, $fields);
}
/**
* Test the access control on private custom fields
*/
public function testPrivateCannotBeReadWithoutPermission()
{
$field = $this->create_private_field();
// Get another user
$other_account = $this->get_another_user();
// Try to read - should not be there
$fields = Customfields::get(self::APP,$other_account);
$this->assertArrayNotHasKey($field['name'], $fields);
// Switch the users
$field['private'] = array($other_account);
Customfields::update($field);
// Try to read - should not be there
$fields = Customfields::get(self::APP,false);
$this->assertArrayNotHasKey($field['name'], $fields);
// Clean up
unset($fields[$field['name']]);
Customfields::save(self::APP, $fields);
}
/**
* Test that giving access allows access
*/
public function testGivingAccess()
{
$field = $this->create_private_field();
$fields = Customfields::get(self::APP);
// Get another user
$other_account = $this->get_another_user();
// Give access & check
$field['private'][] = $other_account;
Customfields::update($field);
$fields = Customfields::get(self::APP,$other_account);
$this->assertArrayHasKey($field['name'], $fields);
// Clean up
unset($fields[$field['name']]);
Customfields::save(self::APP, $fields);
}
/**
* Test that removing access disallows access
*/
public function testRemovingAccess()
{
$field = $this->create_private_field();
$fields = Customfields::get(self::APP);
// Get another user
$other_account = $this->get_another_user();
// Give access
$field['private'][] = $other_account;
Customfields::update($field);
$fields = Customfields::get(self::APP,$other_account);
$this->assertArrayHasKey($field['name'], $fields);
// Remove access, check its gone
$field['private'] = array($GLOBALS['egw_info']['user']['account_id']);
Customfields::update($field);
$fields = Customfields::get(self::APP,$other_account);
$this->assertArrayNotHasKey($field['name'], $fields);
// Clean up
unset($fields[$field['name']]);
Customfields::save(self::APP, $fields);
}
/**
* Test getting all fields ignores any access restrictions
*/
public function testGetAllFields()
{
$field = $this->create_private_field();
// Get another user
$other_account = $this->get_another_user();
// Change access so current user can't read it
$field['private'] = array($other_account);
Customfields::update($field);
$fields = Customfields::get(self::APP,true);
$this->assertEquals(1, count($fields));
$this->assertArrayHasKey($field['name'], $fields);
// Clean up
unset($fields[$field['name']]);
Customfields::save(self::APP, $fields);
}
/**
* Test getting options from a file
*
* @dataProvider fileOptionProvider
*/
public function testGetOptionsFromGoodFile($expected, $file)
{
// Load
$options = Customfields::get_options_from_file('api/tests/fixtures/Storage/' . $file);
// Check
$this->assertIsArray($options);
$this->assertEquals($expected, $options);
}
/**
* Provide some options (duplicated in the files) to check loading
*
* @return array
*/
public function fileOptionProvider()
{
// Expected options, file
return array(
array(array(
'' => 'Select',
'Α'=> 'α Alpha',
'Β'=> 'β Beta',
'Γ'=> 'γ Gamma',
'Δ'=> 'δ Delta',
'Ε'=> 'ε Epsilon',
'Ζ'=> 'ζ Zeta',
'Η'=> 'η Eta',
'Θ'=> 'θ Theta',
'Ι'=> 'ι Iota',
'Κ'=> 'κ Kappa',
'Λ'=> 'λ Lambda',
'Μ'=> 'μ Mu',
'Ν'=> 'ν Nu',
'Ξ'=> 'ξ Xi',
'Ο'=> 'ο Omicron',
'Π'=> 'π Pi',
'Ρ'=> 'ρ Rho',
'Σ'=> 'σ Sigma',
'Τ'=> 'τ Tau',
'Υ'=> 'υ Upsilon',
'Φ'=> 'φ Phi',
'Χ'=> 'χ Chi',
'Ψ'=> 'ψ Psi',
'Ω'=> 'ω Omega'
), 'greek_options.php'),
array(array(
'View Subs' => "egw_open('','infolog','list',{action:'sp',action_id:widget.getRoot().getArrayMgr('content').getEntry('info_id')},'infolog','infolog');"
), 'infolog_subs_option.php')
);
}
/**
* A file that is not found or cannot be read should return an array
* with an error message, and not error. It's impossible to deal with an
* actual invalid file though, they just cause Fatal Errors.
*/
public function testGetOptionsFromMissingFile()
{
$options = Customfields::get_options_from_file('totally invalid');
$this->assertIsArray($options);
$this->assertCount(1, $options);
}
/**
* Certain characters (&, ", etc.) will break our XML templates.
* Make sure they get stripped out.
*/
public function testInvalidName()
{
// Create
$field = $this->simple_field;
$this->customfields[] = $invalid_name = $field['name'] = '<Invalid> & "TEST"';
$this->customfields[] = $valid_name = 'Invalid TEST';
Customfields::update($field);
// Check
$fields = Customfields::get(self::APP);
$this->assertArrayNotHasKey($invalid_name, $fields, "Invalid customfield name was allowed");
$this->assertArrayHasKey($valid_name, $fields, "Invalid customfield name was not corrected");
$saved_field = $fields[$valid_name];
$this->assertEquals($valid_name, $saved_field['name'], "Invalid customfield name was allowed");
// Clean
unset($fields[$invalid_name], $fields[$saved_field['name']]);
Customfields::save(self::APP, $fields);
}
protected function create_private_field()
{
// Create field
$field = array_merge(
$this->simple_field,
array(
'private' => array($GLOBALS['egw_info']['user']['account_id'])
)
);
$this->customfields[] = $field['name'];
Customfields::update($field);
return $field;
}
/**
* Get another user that we can use to test
*/
protected function get_another_user()
{
$accounts = $GLOBALS['egw']->accounts->search(array(
'type' => 'accounts'
));
unset($accounts[$GLOBALS['egw_info']['user']['account_id']]);
if(count($accounts) == 0)
{
$this->markTestSkipped('Need more than one user to check private');
}
$other_account = key($accounts);
if(!$other_account)
{
$this->markTestSkipped('Need more than one user to check private');
}
return $other_account;
}
}