@ -31,10 +31,14 @@ namespace OCA\Settings\Tests\Controller;
use OC\Accounts\AccountManager ;
use OC\Encryption\Exceptions\ModuleDoesNotExistsException ;
use OC\ForbiddenException ;
use OC\Group\Manager ;
use OC\KnownUser\KnownUserService ;
use OCA\Settings\Controller\UsersController ;
use OCP\Accounts\IAccount ;
use OCP\Accounts\IAccountManager ;
use OCP\Accounts\IAccountProperty ;
use OCP\Accounts\PropertyDoesNotExistException ;
use OCP\App\IAppManager ;
use OCP\AppFramework\Http ;
use OCP\BackgroundJob\IJobList ;
@ -53,6 +57,7 @@ use OCP\IUserSession;
use OCP\L10N\IFactory ;
use OCP\Mail\IMailer ;
use OCP\Security\ISecureRandom ;
use PHPUnit\Framework\MockObject\MockObject ;
/**
* @ group DB
@ -180,49 +185,77 @@ class UsersControllerTest extends \Test\TestCase {
}
}
protected function getDefaultAccountManagerUserData () {
return [
IAccountManager :: PROPERTY_DISPLAYNAME =>
[
'value' => 'Default display name' ,
'scope' => IAccountManager :: SCOPE_FEDERATED ,
'verified' => IAccountManager :: VERIFIED ,
],
IAccountManager :: PROPERTY_ADDRESS =>
[
'value' => 'Default address' ,
'scope' => IAccountManager :: SCOPE_LOCAL ,
'verified' => IAccountManager :: VERIFIED ,
],
IAccountManager :: PROPERTY_WEBSITE =>
[
'value' => 'Default website' ,
'scope' => IAccountManager :: SCOPE_LOCAL ,
'verified' => IAccountManager :: VERIFIED ,
],
IAccountManager :: PROPERTY_EMAIL =>
[
'value' => 'Default email' ,
'scope' => IAccountManager :: SCOPE_FEDERATED ,
'verified' => IAccountManager :: VERIFIED ,
],
IAccountManager :: PROPERTY_AVATAR =>
[
'scope' => IAccountManager :: SCOPE_FEDERATED
],
IAccountManager :: PROPERTY_PHONE =>
[
'value' => 'Default phone' ,
'scope' => IAccountManager :: SCOPE_LOCAL ,
'verified' => IAccountManager :: VERIFIED ,
],
IAccountManager :: PROPERTY_TWITTER =>
[
'value' => 'Default twitter' ,
'scope' => IAccountManager :: SCOPE_LOCAL ,
'verified' => IAccountManager :: VERIFIED ,
],
protected function buildPropertyMock ( string $name , string $value , string $scope , string $verified = IAccountManager :: VERIFIED ) : MockObject {
$property = $this -> createMock ( IAccountProperty :: class );
$property -> expects ( $this -> any ())
-> method ( 'getName' )
-> willReturn ( $name );
$property -> expects ( $this -> any ())
-> method ( 'getValue' )
-> willReturn ( $value );
$property -> expects ( $this -> any ())
-> method ( 'getScope' )
-> willReturn ( $scope );
$property -> expects ( $this -> any ())
-> method ( 'getVerified' )
-> willReturn ( $verified );
return $property ;
}
protected function getDefaultAccountMock ( bool $useDefaultValues = true ) : MockObject {
$propertyMocks = [
IAccountManager :: PROPERTY_DISPLAYNAME => $this -> buildPropertyMock (
IAccountManager :: PROPERTY_DISPLAYNAME ,
'Default display name' ,
IAccountManager :: SCOPE_FEDERATED ,
),
IAccountManager :: PROPERTY_ADDRESS => $this -> buildPropertyMock (
IAccountManager :: PROPERTY_ADDRESS ,
'Default address' ,
IAccountManager :: SCOPE_LOCAL ,
),
IAccountManager :: PROPERTY_WEBSITE => $this -> buildPropertyMock (
IAccountManager :: PROPERTY_WEBSITE ,
'Default website' ,
IAccountManager :: SCOPE_LOCAL ,
),
IAccountManager :: PROPERTY_EMAIL => $this -> buildPropertyMock (
IAccountManager :: PROPERTY_EMAIL ,
'Default email' ,
IAccountManager :: SCOPE_FEDERATED ,
),
IAccountManager :: PROPERTY_AVATAR => $this -> buildPropertyMock (
IAccountManager :: PROPERTY_AVATAR ,
'' ,
IAccountManager :: SCOPE_FEDERATED ,
),
IAccountManager :: PROPERTY_PHONE => $this -> buildPropertyMock (
IAccountManager :: PROPERTY_PHONE ,
'Default phone' ,
IAccountManager :: SCOPE_LOCAL ,
),
IAccountManager :: PROPERTY_TWITTER => $this -> buildPropertyMock (
IAccountManager :: PROPERTY_TWITTER ,
'Default twitter' ,
IAccountManager :: SCOPE_LOCAL ,
),
];
$account = $this -> createMock ( IAccount :: class );
$account -> expects ( $this -> any ())
-> method ( 'getProperty' )
-> willReturnCallback ( function ( string $propertyName ) use ( $propertyMocks ) {
if ( isset ( $propertyMocks [ $propertyName ])) {
return $propertyMocks [ $propertyName ];
}
throw new PropertyDoesNotExistException ( $propertyName );
});
$account -> expects ( $this -> any ())
-> method ( 'getProperties' )
-> willReturn ( $propertyMocks );
return $account ;
}
/**
@ -248,13 +281,12 @@ class UsersControllerTest extends \Test\TestCase {
if ( $saveData ) {
$this -> accountManager -> expects ( $this -> once ())
-> method ( 'getUser ' )
-> method ( 'getAccount ' )
-> with ( $user )
-> willReturn ( $this -> getDefaultAccountManagerUserData ());
-> willReturn ( $this -> getDefaultAccountMock ());
$controller -> expects ( $this -> once ())
-> method ( 'saveUserSettings' )
-> willReturnArgument ( 1 );
-> method ( 'saveUserSettings' );
} else {
$controller -> expects ( $this -> never ()) -> method ( 'saveUserSettings' );
}
@ -289,20 +321,67 @@ class UsersControllerTest extends \Test\TestCase {
public function testSetUserSettingsWhenUserDisplayNameChangeNotAllowed () {
$controller = $this -> getController ( false , [ 'saveUserSettings' ]);
$avatarScope = IAccountManager :: SCOPE_PUBLISHED ;
$displayName = 'Display name' ;
$displayNameScope = IAccountManager :: SCOPE_PUBLISHED ;
$phone = '47658468' ;
$phoneScope = IAccountManager :: SCOPE_PUBLISHED ;
$email = 'john@example.com' ;
$emailScope = IAccountManager :: SCOPE_PUBLISHED ;
$website = 'nextcloud.com' ;
$websiteScope = IAccountManager :: SCOPE_PUBLISHED ;
$address = 'street and city' ;
$addressScope = IAccountManager :: SCOPE_PUBLISHED ;
$twitter = '@nextclouders' ;
$twitterScope = IAccountManager :: SCOPE_PUBLISHED ;
$user = $this -> createMock ( IUser :: class );
$user -> method ( 'getUID' ) -> willReturn ( 'johndoe' );
$this -> userSession -> method ( 'getUser' ) -> willReturn ( $user );
$defaultProperties = $this -> getDefaultAccountManagerUserData ();
/** @var MockObject|IAccount $userAccount */
$userAccount = $this -> getDefaultAccountMock ();
$this -> accountManager -> expects ( $this -> once ())
-> method ( 'getUser' )
-> method ( 'getAccount ' )
-> with ( $user )
-> willReturn ( $defaultProperties );
-> willReturn ( $userAccount );
/** @var MockObject|IAccountProperty $avatarProperty */
$avatarProperty = $userAccount -> getProperty ( IAccountManager :: PROPERTY_AVATAR );
$avatarProperty -> expects ( $this -> atLeastOnce ())
-> method ( 'setScope' )
-> with ( $avatarScope )
-> willReturnSelf ();
/** @var MockObject|IAccountProperty $avatarProperty */
$avatarProperty = $userAccount -> getProperty ( IAccountManager :: PROPERTY_ADDRESS );
$avatarProperty -> expects ( $this -> atLeastOnce ())
-> method ( 'setScope' )
-> with ( $addressScope )
-> willReturnSelf ();
$avatarProperty -> expects ( $this -> atLeastOnce ())
-> method ( 'setValue' )
-> with ( $address )
-> willReturnSelf ();
/** @var MockObject|IAccountProperty $emailProperty */
$emailProperty = $userAccount -> getProperty ( IAccountManager :: PROPERTY_EMAIL );
$emailProperty -> expects ( $this -> never ())
-> method ( 'setValue' );
$emailProperty -> expects ( $this -> never ())
-> method ( 'setScope' );
/** @var MockObject|IAccountProperty $emailProperty */
$emailProperty = $userAccount -> getProperty ( IAccountManager :: PROPERTY_DISPLAYNAME );
$emailProperty -> expects ( $this -> never ())
-> method ( 'setValue' );
$emailProperty -> expects ( $this -> never ())
-> method ( 'setScope' );
$this -> config -> expects ( $this -> once ())
-> method ( 'getSystemValue' )
-> method ( 'getSystemValueBool ' )
-> with ( 'allow_user_to_change_display_name' )
-> willReturn ( false );
@ -311,41 +390,13 @@ class UsersControllerTest extends \Test\TestCase {
-> with ( 'federatedfilesharing' )
-> willReturn ( true );
$avatarScope = IAccountManager :: SCOPE_PUBLISHED ;
$displayName = 'Display name' ;
$displayNameScope = IAccountManager :: SCOPE_PUBLISHED ;
$phone = '47658468' ;
$phoneScope = IAccountManager :: SCOPE_PUBLISHED ;
$email = 'john@example.com' ;
$emailScope = IAccountManager :: SCOPE_PUBLISHED ;
$website = 'nextcloud.com' ;
$websiteScope = IAccountManager :: SCOPE_PUBLISHED ;
$address = 'street and city' ;
$addressScope = IAccountManager :: SCOPE_PUBLISHED ;
$twitter = '@nextclouders' ;
$twitterScope = IAccountManager :: SCOPE_PUBLISHED ;
// Display name and email are not changed.
$expectedProperties = $defaultProperties ;
$expectedProperties [ IAccountManager :: PROPERTY_AVATAR ][ 'scope' ] = $avatarScope ;
$expectedProperties [ IAccountManager :: PROPERTY_PHONE ][ 'value' ] = $phone ;
$expectedProperties [ IAccountManager :: PROPERTY_PHONE ][ 'scope' ] = $phoneScope ;
$expectedProperties [ IAccountManager :: PROPERTY_WEBSITE ][ 'value' ] = $website ;
$expectedProperties [ IAccountManager :: PROPERTY_WEBSITE ][ 'scope' ] = $websiteScope ;
$expectedProperties [ IAccountManager :: PROPERTY_ADDRESS ][ 'value' ] = $address ;
$expectedProperties [ IAccountManager :: PROPERTY_ADDRESS ][ 'scope' ] = $addressScope ;
$expectedProperties [ IAccountManager :: PROPERTY_TWITTER ][ 'value' ] = $twitter ;
$expectedProperties [ IAccountManager :: PROPERTY_TWITTER ][ 'scope' ] = $twitterScope ;
$this -> mailer -> expects ( $this -> once ()) -> method ( 'validateMailAddress' )
-> willReturn ( true );
$controller -> expects ( $this -> once ())
-> method ( 'saveUserSettings' )
-> with ( $user , $expectedProperties )
-> willReturnArgument ( 1 );
-> method ( 'saveUserSettings' );
$result = $ controller -> setUserSettings (
$controller -> setUserSettings (
$avatarScope ,
$displayName ,
$displayNameScope ,
@ -369,12 +420,13 @@ class UsersControllerTest extends \Test\TestCase {
$this -> userSession -> method ( 'getUser' ) -> willReturn ( $user );
$defaultProperties = $this -> getDefaultAccountManagerUserData ();
$defaultProperties = []; //$this->getDefaultAccountMock();
$userAccount = $this -> getDefaultAccountMock ();
$this -> accountManager -> expects ( $this -> once ())
-> method ( 'getUser ' )
-> method ( 'getAccount ' )
-> with ( $user )
-> willReturn ( $defaultProperties );
-> willReturn ( $userAccount );
$this -> appManager -> expects ( $this -> any ())
-> method ( 'isEnabledForUser' )
@ -417,10 +469,9 @@ class UsersControllerTest extends \Test\TestCase {
$controller -> expects ( $this -> once ())
-> method ( 'saveUserSettings' )
-> with ( $user , $expectedProperties )
-> willReturnArgument ( 1 );
-> with ( $userAccount );
$result = $ controller -> setUserSettings (
$controller -> setUserSettings (
$avatarScope ,
$displayName ,
$displayNameScope ,
@ -450,12 +501,13 @@ class UsersControllerTest extends \Test\TestCase {
$this -> userSession -> method ( 'getUser' ) -> willReturn ( $user );
$defaultProperties = $this -> getDefaultAccountManagerUserData ();
/** @var IAccount|MockObject $userAccount */
$userAccount = $this -> getDefaultAccountMock ();
$this -> accountManager -> expects ( $this -> once ())
-> method ( 'getUser ' )
-> method ( 'getAccount ' )
-> with ( $user )
-> willReturn ( $defaultProperties );
-> willReturn ( $userAccount );
$avatarScope = ( $property === 'avatarScope' ) ? $propertyValue : null ;
$displayName = ( $property === 'displayName' ) ? $propertyValue : null ;
@ -471,46 +523,43 @@ class UsersControllerTest extends \Test\TestCase {
$twitter = ( $property === 'twitter' ) ? $propertyValue : null ;
$twitterScope = ( $property === 'twitterScope' ) ? $propertyValue : null ;
$expectedProperties = $defaultProperties ;
if ( $property === 'avatarScope' ) {
$expectedProperties [ IAccountManager :: PROPERTY_AVATAR ][ 'scope' ] = $propertyValue ;
}
if ( $property === 'displayName' ) {
$expectedProperties [ IAccountManager :: PROPERTY_DISPLAYNAME ][ 'value' ] = $propertyValue ;
}
if ( $property === 'displayNameScope' ) {
$expectedProperties [ IAccountManager :: PROPERTY_DISPLAYNAME ][ 'scope' ] = $propertyValue ;
}
if ( $property === 'phone' ) {
$expectedProperties [ IAccountManager :: PROPERTY_PHONE ][ 'value' ] = $propertyValue ;
}
if ( $property === 'phoneScope' ) {
$expectedProperties [ IAccountManager :: PROPERTY_PHONE ][ 'scope' ] = $propertyValue ;
}
if ( $property === 'email' ) {
$expectedProperties [ IAccountManager :: PROPERTY_EMAIL ][ 'value' ] = $propertyValue ;
}
if ( $property === 'emailScope' ) {
$expectedProperties [ IAccountManager :: PROPERTY_EMAIL ][ 'scope' ] = $propertyValue ;
}
if ( $property === 'website' ) {
$expectedProperties [ IAccountManager :: PROPERTY_WEBSITE ][ 'value' ] = $propertyValue ;
}
if ( $property === 'websiteScope' ) {
$expectedProperties [ IAccountManager :: PROPERTY_WEBSITE ][ 'scope' ] = $propertyValue ;
}
if ( $property === 'address' ) {
$expectedProperties [ IAccountManager :: PROPERTY_ADDRESS ][ 'value' ] = $propertyValue ;
}
if ( $property === 'addressScope' ) {
$expectedProperties [ IAccountManager :: PROPERTY_ADDRESS ][ 'scope' ] = $propertyValue ;
}
if ( $property === 'twitter' ) {
$expectedProperties [ IAccountManager :: PROPERTY_TWITTER ][ 'value' ] = $propertyValue ;
}
if ( $property === 'twitterScope' ) {
$expectedProperties [ IAccountManager :: PROPERTY_TWITTER ][ 'scope' ] = $propertyValue ;
/** @var IAccountProperty[]|MockObject[] $expectedProperties */
$expectedProperties = $userAccount -> getProperties ();
$isScope = strrpos ( $property , 'Scope' ) === strlen ( $property ) - strlen ( 5 );
switch ( $property ) {
case 'avatarScope' :
$propertyId = IAccountManager :: PROPERTY_AVATAR ;
break ;
case 'displayName' :
case 'displayNameScope' :
$propertyId = IAccountManager :: PROPERTY_DISPLAYNAME ;
break ;
case 'phone' :
case 'phoneScope' :
$propertyId = IAccountManager :: PROPERTY_PHONE ;
break ;
case 'email' :
case 'emailScope' :
$propertyId = IAccountManager :: PROPERTY_EMAIL ;
break ;
case 'website' :
case 'websiteScope' :
$propertyId = IAccountManager :: PROPERTY_WEBSITE ;
break ;
case 'address' :
case 'addressScope' :
$propertyId = IAccountManager :: PROPERTY_ADDRESS ;
break ;
case 'twitter' :
case 'twitterScope' :
$propertyId = IAccountManager :: PROPERTY_TWITTER ;
break ;
default :
$propertyId = '404' ;
}
$expectedProperties [ $propertyId ] -> expects ( $this -> any ())
-> method ( $isScope ? 'getScope' : 'getValue' )
-> willReturn ( $propertyValue );
if ( ! empty ( $email )) {
$this -> mailer -> expects ( $this -> once ()) -> method ( 'validateMailAddress' )
@ -519,10 +568,9 @@ class UsersControllerTest extends \Test\TestCase {
$controller -> expects ( $this -> once ())
-> method ( 'saveUserSettings' )
-> with ( $user , $expectedProperties )
-> willReturnArgument ( 1 );
-> with ( $userAccount );
$result = $ controller -> setUserSettings (
$controller -> setUserSettings (
$avatarScope ,
$displayName ,
$displayNameScope ,
@ -593,10 +641,33 @@ class UsersControllerTest extends \Test\TestCase {
-> willReturn ( true );
}
$this -> accountManager -> expects ( $this -> once ()) -> method ( 'updateUser' )
-> with ( $user , $data );
$properties = [];
foreach ( $data as $propertyName => $propertyData ) {
$properties [ $propertyName ] = $this -> createMock ( IAccountProperty :: class );
$properties [ $propertyName ] -> expects ( $this -> any ())
-> method ( 'getValue' )
-> willReturn ( $propertyData [ 'value' ]);
}
$account = $this -> createMock ( IAccount :: class );
$account -> expects ( $this -> any ())
-> method ( 'getUser' )
-> willReturn ( $user );
$account -> expects ( $this -> any ())
-> method ( 'getProperty' )
-> willReturnCallback ( function ( string $propertyName ) use ( $properties ) {
return $properties [ $propertyName ];
});
$this -> accountManager -> expects ( $this -> any ())
-> method ( 'getAccount' )
-> willReturn ( $account );
$this -> accountManager -> expects ( $this -> once ())
-> method ( 'updateAccount' )
-> with ( $account );
$this -> invokePrivate ( $controller , 'saveUserSettings' , [ $user , $data ]);
$this -> invokePrivate ( $controller , 'saveUserSettings' , [ $account ]);
}
public function dataTestSaveUserSettings () {
@ -655,21 +726,15 @@ class UsersControllerTest extends \Test\TestCase {
/**
* @ dataProvider dataTestSaveUserSettingsException
*
* @ param array $data
* @ param string $oldEmailAddress
* @ param string $oldDisplayName
* @ param bool $setDisplayNameResult
* @ param bool $canChangeEmail
*
*/
public function testSaveUserSettingsException ( $data ,
$oldEmailAddress ,
$oldDisplayName ,
$setDisplayNameResult ,
$canChangeEmail
public function testSaveUserSettingsException (
array $data ,
string $oldEmailAddress ,
string $oldDisplayName ,
bool $setDisplayNameResult ,
bool $canChangeEmail
) {
$this -> expectException ( \OC\ ForbiddenException:: class );
$this -> expectException ( ForbiddenException :: class );
$controller = $this -> getController ();
$user = $this -> createMock ( IUser :: class );
@ -677,6 +742,22 @@ class UsersControllerTest extends \Test\TestCase {
$user -> method ( 'getDisplayName' ) -> willReturn ( $oldDisplayName );
$user -> method ( 'getEMailAddress' ) -> willReturn ( $oldEmailAddress );
/** @var MockObject|IAccount $userAccount */
$userAccount = $this -> createMock ( IAccount :: class );
$userAccount -> expects ( $this -> any ())
-> method ( 'getUser' )
-> willReturn ( $user );
$propertyMocks = [];
foreach ( $data as $propertyName => $propertyData ) {
/** @var MockObject|IAccountProperty $property */
$propertyMocks [ $propertyName ] = $this -> buildPropertyMock ( $propertyName , $propertyData [ 'value' ], '' );
}
$userAccount -> expects ( $this -> any ())
-> method ( 'getProperty' )
-> willReturnCallback ( function ( string $propertyName ) use ( $propertyMocks ) {
return $propertyMocks [ $propertyName ];
});
if ( $data [ IAccountManager :: PROPERTY_EMAIL ][ 'value' ] !== $oldEmailAddress ) {
$user -> method ( 'canChangeDisplayName' )
-> willReturn ( $canChangeEmail );
@ -688,7 +769,7 @@ class UsersControllerTest extends \Test\TestCase {
-> willReturn ( $setDisplayNameResult );
}
$this -> invokePrivate ( $controller , 'saveUserSettings' , [ $user , $data ]);
$this -> invokePrivate ( $controller , 'saveUserSettings' , [ $userAccount ]);
}
@ -748,15 +829,34 @@ class UsersControllerTest extends \Test\TestCase {
$controller = $this -> getController ( false , [ 'signMessage' , 'getCurrentTime' ]);
$user = $this -> createMock ( IUser :: class );
$property = $this -> buildPropertyMock ( $type , $dataBefore [ $type ][ 'value' ], '' , IAccountManager :: NOT_VERIFIED );
$property -> expects ( $this -> atLeastOnce ())
-> method ( 'setVerified' )
-> with ( IAccountManager :: VERIFICATION_IN_PROGRESS )
-> willReturnSelf ();
$property -> expects ( $this -> atLeastOnce ())
-> method ( 'setVerificationData' )
-> with ( $signature )
-> willReturnSelf ();
$userAccount = $this -> createMock ( IAccount :: class );
$userAccount -> expects ( $this -> any ())
-> method ( 'getUser' )
-> willReturn ( $user );
$userAccount -> expects ( $this -> any ())
-> method ( 'getProperty' )
-> willReturn ( $property );
$this -> userSession -> expects ( $this -> once ()) -> method ( 'getUser' ) -> willReturn ( $user );
$this -> accountManager -> expects ( $this -> once ()) -> method ( 'getUser' ) -> with ( $user ) -> willReturn ( $dataBefore );
$this -> accountManager -> expects ( $this -> once ()) -> method ( 'getAccount ' ) -> with ( $user ) -> willReturn ( $userAccount );
$user -> expects ( $this -> any ()) -> method ( 'getCloudId' ) -> willReturn ( 'user@nextcloud.com' );
$user -> expects ( $this -> any ()) -> method ( 'getUID' ) -> willReturn ( 'uid' );
$controller -> expects ( $this -> once ()) -> method ( 'signMessage' ) -> with ( $user , $message ) -> willReturn ( $signature );
$controller -> expects ( $this -> any ()) -> method ( 'getCurrentTime' ) -> willReturn ( 1234567 );
if ( $onlyVerificationCode === false ) {
$this -> accountManager -> expects ( $this -> once ()) -> method ( 'updateUser' ) -> with ( $user , $expectedData ) -> willReturnArgument ( 1 );
$this -> accountManager -> expects ( $this -> once ()) -> method ( 'updateAccount ' ) -> with ( $userAccount ) -> willReturnArgument ( 1 );
$this -> jobList -> expects ( $this -> once ()) -> method ( 'add' )
-> with ( 'OCA\Settings\BackgroundJobs\VerifyUserData' ,
[