262 lines
7.1 KiB
PHP
262 lines
7.1 KiB
PHP
<?php
|
|
|
|
namespace BlueSpice\PermissionManager\Tests;
|
|
|
|
use BlueSpice\PermissionManager\GroupManager;
|
|
use BlueSpice\PermissionManager\Logging\GroupManagerSpecialLogLogger;
|
|
use Exception;
|
|
use MediaWiki\Config\Config;
|
|
use MediaWiki\HookContainer\HookContainer;
|
|
use MediaWiki\Permissions\Authority;
|
|
use MWStake\MediaWiki\Component\DynamicConfig\DynamicConfigManager;
|
|
use MWStake\MediaWiki\Component\DynamicConfig\GlobalsDynamicConfig;
|
|
use PHPUnit\Framework\MockObject\MockObject;
|
|
use PHPUnit\Framework\TestCase;
|
|
use Psr\Log\LoggerInterface;
|
|
use Wikimedia\Rdbms\IDatabase;
|
|
use Wikimedia\Rdbms\ILoadBalancer;
|
|
|
|
class GroupManagerTest extends TestCase {
|
|
|
|
/**
|
|
* @param string $group
|
|
* @param bool $expectSuccess
|
|
* @return void
|
|
* @throws Exception
|
|
* @dataProvider provideAddData
|
|
* @covers \BlueSpice\PermissionManager\GroupManager::addGroup
|
|
*/
|
|
public function testAddGroup( string $group, bool $expectSuccess ) {
|
|
$authority = $this->getAuthorityMock();
|
|
$configMock = $this->getConfigMock();
|
|
$dynamicConfigMock = $this->getDynamicConfigMock(
|
|
$expectSuccess ? $this->compileConfigData( $group, $configMock ) : null
|
|
);
|
|
$lbMock = $this->getLBMock();
|
|
if ( $expectSuccess ) {
|
|
$hcMock = $this->getHookContainerMock( 'BSPermissionManagerGroupAdded', [ $group, $authority ] );
|
|
} else {
|
|
$hcMock = $this->getHookContainerMock();
|
|
}
|
|
$loggerMock = $this->getLoggerMock( $expectSuccess );
|
|
$spLoggerMock = $this->getSpLoggerMock( $expectSuccess );
|
|
|
|
$manager = new GroupManager( $dynamicConfigMock, $lbMock, $configMock, $hcMock, $loggerMock, $spLoggerMock );
|
|
if ( !$expectSuccess ) {
|
|
$this->expectException( Exception::class );
|
|
}
|
|
$manager->addGroup( $group, $authority );
|
|
}
|
|
|
|
/**
|
|
* @param string $new
|
|
* @param bool $expectSuccess
|
|
* @return void
|
|
* @throws Exception
|
|
* @dataProvider provideEditData
|
|
* @covers \BlueSpice\PermissionManager\GroupManager::editGroup
|
|
*/
|
|
public function testEditGroup( string $new, bool $expectSuccess ) {
|
|
$old = 'Dummy';
|
|
$authority = $this->getAuthorityMock();
|
|
$configMock = $this->getConfigMock();
|
|
$dynamicConfigMock = $this->getDynamicConfigMock(
|
|
$expectSuccess ? [ $new => true ] : null
|
|
);
|
|
if ( $expectSuccess ) {
|
|
$lbMock = $this->getLBMock( 'update', [
|
|
'user_groups',
|
|
[ 'ug_group' => $new ],
|
|
[ 'ug_group' => $old ],
|
|
GroupManager::class . '::renameGroup'
|
|
] );
|
|
} else {
|
|
$lbMock = $this->getLBMock();
|
|
}
|
|
|
|
if ( $expectSuccess ) {
|
|
$hcMock = $this->getHookContainerMock( 'BSPermissionManagerGroupEdited', [ $old, $new, $authority ] );
|
|
} else {
|
|
$hcMock = $this->getHookContainerMock();
|
|
}
|
|
$loggerMock = $this->getLoggerMock( $expectSuccess );
|
|
$spLoggerMock = $this->getSpLoggerMock( $expectSuccess );
|
|
|
|
$manager = new GroupManager( $dynamicConfigMock, $lbMock, $configMock, $hcMock, $loggerMock, $spLoggerMock );
|
|
if ( !$expectSuccess ) {
|
|
$this->expectException( Exception::class );
|
|
}
|
|
$manager->editGroup( $old, $new, $authority );
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
* @throws Exception
|
|
* @covers \BlueSpice\PermissionManager\GroupManager::removeGroup
|
|
*/
|
|
public function testRemoveGroup() {
|
|
$authority = $this->getAuthorityMock();
|
|
$configMock = $this->getConfigMock();
|
|
$dynamicConfigMock = $this->getDynamicConfigMock( [] );
|
|
$lbMock = $this->getLBMock( 'delete', [
|
|
'user_groups',
|
|
[ 'ug_group' => 'Dummy' ],
|
|
GroupManager::class . '::unassignUsers'
|
|
] );
|
|
$hcMock = $this->getHookContainerMock( 'BSPermissionManagerGroupDeleted', [ 'Dummy', $authority ] );
|
|
$loggerMock = $this->getLoggerMock( true );
|
|
$spLoggerMock = $this->getSpLoggerMock( true );
|
|
|
|
$manager = new GroupManager( $dynamicConfigMock, $lbMock, $configMock, $hcMock, $loggerMock, $spLoggerMock );
|
|
$manager->removeGroup( 'Dummy', $authority );
|
|
}
|
|
|
|
/**
|
|
* @return array[]
|
|
*/
|
|
public function provideAddData(): array {
|
|
// "old name" is always "Dummy"
|
|
return [
|
|
[ 'foo', true ],
|
|
[ 'foo123', true ],
|
|
// same name
|
|
[ 'Dummy', false ]
|
|
];
|
|
}
|
|
|
|
public function provideEditData(): array {
|
|
return [
|
|
[ 'foo', true ],
|
|
[ 'Dummy"""', false ],
|
|
[ 'foo123', true ],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @return Config|MockObject
|
|
*/
|
|
private function getConfigMock() {
|
|
$mock = $this->createMock( Config::class );
|
|
$mock->method( 'get' )->willReturnCallback( static function ( $key ) {
|
|
if ( $key === 'AdditionalGroups' ) {
|
|
return [ 'Dummy' => true ];
|
|
}
|
|
if ( $key === 'GroupPermissions' ) {
|
|
return [ '*' => [], 'sysop' => [], 'Dummy' => [] ];
|
|
}
|
|
return null;
|
|
} );
|
|
return $mock;
|
|
}
|
|
|
|
/**
|
|
* @param array|null $data
|
|
* @return DynamicConfigManager|MockObject
|
|
*/
|
|
private function getDynamicConfigMock( ?array $data ) {
|
|
$configMock = $this->createMock( GlobalsDynamicConfig::class );
|
|
$mock = $this->createMock( DynamicConfigManager::class );
|
|
if ( is_array( $data ) ) {
|
|
$mock->expects( $this->once() )
|
|
->method( 'storeConfig' )
|
|
->with( $configMock, $data );
|
|
} else {
|
|
$mock->expects( $this->never() )
|
|
->method( 'storeConfig' );
|
|
}
|
|
$mock->method( 'getConfigObject' )->willReturnCallback( static function ( $key ) use ( $configMock ) {
|
|
if ( $key === 'bs-groupmanager-groups' ) {
|
|
return $configMock;
|
|
}
|
|
return null;
|
|
} );
|
|
return $mock;
|
|
}
|
|
|
|
/**
|
|
* @param string|null $method
|
|
* @param array $data
|
|
* @return ILoadBalancer|MockObject
|
|
*/
|
|
private function getLBMock( ?string $method = null, array $data = [] ) {
|
|
$dbMock = $this->createMock( IDatabase::class );
|
|
$mock = $this->createMock( ILoadBalancer::class );
|
|
if ( $method !== null ) {
|
|
$dbMock->expects( $this->once() )
|
|
->method( $method )
|
|
->with( ...$data )
|
|
->willReturn( true );
|
|
}
|
|
$mock->method( 'getConnection' )->willReturn( $dbMock );
|
|
return $mock;
|
|
}
|
|
|
|
/**
|
|
* @param string $group
|
|
* @param Config $config
|
|
* @return array[]
|
|
*/
|
|
private function compileConfigData( string $group, Config $config ): array {
|
|
$groups = $config->get( 'AdditionalGroups' ) ?? [];
|
|
$groups[$group] = true;
|
|
return $groups;
|
|
}
|
|
|
|
private function getHookContainerMock( string $hook = '', array $args = [] ) {
|
|
$mock = $this->createMock( HookContainer::class );
|
|
if ( $hook ) {
|
|
$mock->expects( $this->once() )
|
|
->method( 'run' )
|
|
->with( $hook, $args );
|
|
} else {
|
|
$mock->expects( $this->never() )
|
|
->method( 'run' );
|
|
}
|
|
return $mock;
|
|
}
|
|
|
|
/**
|
|
* @return Authority|MockObject
|
|
*/
|
|
private function getAuthorityMock() {
|
|
$mock = $this->createMock( Authority::class );
|
|
$mock->expects( $this->once() )
|
|
->method( 'isAllowed' )
|
|
->willReturn( true );
|
|
return $mock;
|
|
}
|
|
|
|
/**
|
|
* @param bool $expectSuccess
|
|
* @return LoggerInterface|MockObject
|
|
*/
|
|
private function getLoggerMock( bool $expectSuccess ) {
|
|
$mock = $this->createMock( LoggerInterface::class );
|
|
if ( $expectSuccess ) {
|
|
$mock->expects( $this->once() )
|
|
->method( 'info' );
|
|
} else {
|
|
$mock->expects( $this->never() )
|
|
->method( 'log' );
|
|
}
|
|
return $mock;
|
|
}
|
|
|
|
/**
|
|
* @param bool $expectSuccess
|
|
* @return GroupManagerSpecialLogLogger|MockObject
|
|
*/
|
|
private function getSpLoggerMock( bool $expectSuccess ) {
|
|
$mock = $this->createMock( GroupManagerSpecialLogLogger::class );
|
|
if ( $expectSuccess ) {
|
|
$mock->expects( $this->once() )
|
|
->method( 'log' );
|
|
} else {
|
|
$mock->expects( $this->never() )
|
|
->method( 'log' );
|
|
}
|
|
return $mock;
|
|
}
|
|
|
|
}
|