@ -8,6 +8,7 @@
namespace Test\Core\Middleware ;
use OC\AppFramework\Http\Attributes\TwoFactorSetUpDoneRequired ;
use OC\AppFramework\Http\Request ;
use OC\Authentication\Exceptions\TwoFactorAuthRequiredException ;
use OC\Authentication\Exceptions\UserAlreadyLoggedInException ;
@ -17,7 +18,9 @@ use OC\Core\Controller\TwoFactorChallengeController;
use OC\Core\Middleware\TwoFactorMiddleware ;
use OC\User\Session ;
use OCP\AppFramework\Controller ;
use OCP\AppFramework\Http\Attribute\NoTwoFactorRequired ;
use OCP\AppFramework\Http\RedirectResponse ;
use OCP\AppFramework\Http\Response ;
use OCP\AppFramework\Utility\IControllerMethodReflector ;
use OCP\Authentication\TwoFactorAuth\ALoginSetupController ;
use OCP\Authentication\TwoFactorAuth\IProvider ;
@ -28,33 +31,52 @@ use OCP\ISession;
use OCP\IURLGenerator ;
use OCP\IUser ;
use OCP\IUserSession ;
use PHPUnit\Framework\Attributes\DataProvider ;
use PHPUnit\Framework\MockObject\MockObject ;
use Psr\Log\LoggerInterface ;
use Test\TestCase ;
class TwoFactorMiddlewareTest extends TestCase {
/** @var Manager|MockObject */
private $twoFactorManager ;
/** @var IUserSession|MockObject */
private $userSession ;
/** @var ISession|MockObject */
private $session ;
class HasTwoFactorAnnotationController extends Controller {
#[NoTwoFactorRequired]
public function index () : Response {
return new Response ();
}
}
/** @var IURLGenerator|MockObject */
private $urlGenerator ;
class LoginSetupController extends ALoginSetupController {
public function index () : Response {
return new Response ();
}
}
/** @var IControllerMethodReflector|MockObject */
private $reflector ;
class NoTwoFactorAnnotationController extends Controller {
public function index () : Response {
return new Response ();
}
}
/** @var IRequest|MockObject */
private $request ;
class NoTwoFactorChallengeAnnotationController extends TwoFactorChallengeController {
public function index () : Response {
return new Response ();
}
}
/** @var TwoFactorMiddleware */
private $middleware ;
class HasTwoFactorSetUpDoneAnnotationController extends TwoFactorChallengeController {
#[TwoFactorSetUpDoneRequired]
public function index () : Response {
return new Response ();
}
}
/** @var Controller */
private $controller ;
class TwoFactorMiddlewareTest extends TestCase {
private Manager & MockObject $twoFactorManager ;
private IUserSession & MockObject $userSession ;
private ISession & MockObject $session ;
private IURLGenerator & MockObject $urlGenerator ;
private IControllerMethodReflector & MockObject $reflector ;
private IRequest $request ;
private TwoFactorMiddleware $middleware ;
private LoggerInterface & MockObject $logger ;
protected function setUp () : void {
parent :: setUp ();
@ -68,6 +90,7 @@ class TwoFactorMiddlewareTest extends TestCase {
$this -> session = $this -> createMock ( ISession :: class );
$this -> urlGenerator = $this -> createMock ( IURLGenerator :: class );
$this -> reflector = $this -> createMock ( IControllerMethodReflector :: class );
$this -> logger = $this -> createMock ( LoggerInterface :: class );
$this -> request = new Request (
[
'server' => [
@ -78,8 +101,7 @@ class TwoFactorMiddlewareTest extends TestCase {
$this -> createMock ( IConfig :: class )
);
$this -> middleware = new TwoFactorMiddleware ( $this -> twoFactorManager , $this -> userSession , $this -> session , $this -> urlGenerator , $this -> reflector , $this -> request );
$this -> controller = $this -> createMock ( Controller :: class );
$this -> middleware = new TwoFactorMiddleware ( $this -> twoFactorManager , $this -> userSession , $this -> session , $this -> urlGenerator , $this -> reflector , $this -> request , $this -> logger );
}
public function testBeforeControllerNotLoggedIn () : void {
@ -90,12 +112,14 @@ class TwoFactorMiddlewareTest extends TestCase {
$this -> userSession -> expects ( $this -> never ())
-> method ( 'getUser' );
$this -> middleware -> beforeController ( $this -> controller , 'index' );
$controller = $this -> getMockBuilder ( NoTwoFactorAnnotationController :: class )
-> disableOriginalConstructor ()
-> getMock ();
$this -> middleware -> beforeController ( $controller , 'index' );
}
public function testBeforeSetupController () : void {
$user = $this -> createMock ( IUser :: class );
$controller = $this -> createMock ( ALoginSetupController :: class );
$this -> userSession -> expects ( $this -> any ())
-> method ( 'getUser' )
-> willReturn ( $user );
@ -105,7 +129,7 @@ class TwoFactorMiddlewareTest extends TestCase {
$this -> userSession -> expects ( $this -> never ())
-> method ( 'isLoggedIn' );
$this -> middleware -> beforeController ( $controller , 'create ');
$this -> middleware -> beforeController ( new LoginSetupController ( 'foo' , $this -> request ), 'index ');
}
public function testBeforeControllerNoTwoFactorCheckNeeded () : void {
@ -122,7 +146,10 @@ class TwoFactorMiddlewareTest extends TestCase {
-> with ( $user )
-> willReturn ( false );
$this -> middleware -> beforeController ( $this -> controller , 'index' );
$controller = $this -> getMockBuilder ( NoTwoFactorAnnotationController :: class )
-> disableOriginalConstructor ()
-> getMock ();
$this -> middleware -> beforeController ( $controller , 'index' );
}
@ -146,7 +173,10 @@ class TwoFactorMiddlewareTest extends TestCase {
-> with ( $user )
-> willReturn ( true );
$this -> middleware -> beforeController ( $this -> controller , 'index' );
$controller = $this -> getMockBuilder ( NoTwoFactorAnnotationController :: class )
-> disableOriginalConstructor ()
-> getMock ();
$this -> middleware -> beforeController ( $controller , 'index' );
}
@ -155,9 +185,6 @@ class TwoFactorMiddlewareTest extends TestCase {
$user = $this -> createMock ( IUser :: class );
$this -> reflector
-> method ( 'hasAnnotation' )
-> willReturn ( false );
$this -> userSession -> expects ( $this -> once ())
-> method ( 'isLoggedIn' )
-> willReturn ( true );
@ -173,7 +200,7 @@ class TwoFactorMiddlewareTest extends TestCase {
-> with ( $user )
-> willReturn ( false );
$twoFactorChallengeController = $this -> getMockBuilder ( TwoFactorChallengeController :: class )
$twoFactorChallengeController = $this -> getMockBuilder ( No TwoFactorChallengeAnnotation Controller:: class )
-> disableOriginalConstructor ()
-> getMock ();
$this -> middleware -> beforeController ( $twoFactorChallengeController , 'index' );
@ -188,7 +215,8 @@ class TwoFactorMiddlewareTest extends TestCase {
-> willReturn ( 'test/url' );
$expected = new RedirectResponse ( 'test/url' );
$this -> assertEquals ( $expected , $this -> middleware -> afterException ( $this -> controller , 'index' , $ex ));
$controller = new HasTwoFactorAnnotationController ( 'foo' , $this -> request );
$this -> assertEquals ( $expected , $this -> middleware -> afterException ( $controller , 'index' , $ex ));
}
public function testAfterException () : void {
@ -200,17 +228,13 @@ class TwoFactorMiddlewareTest extends TestCase {
-> willReturn ( 'redirect/url' );
$expected = new RedirectResponse ( 'redirect/url' );
$this -> assertEquals ( $expected , $this -> middleware -> afterException ( $this -> controller , 'index' , $ex ));
$controller = new HasTwoFactorAnnotationController ( 'foo' , $this -> request );
$this -> assertEquals ( $expected , $this -> middleware -> afterException ( $controller , 'index' , $ex ));
}
public function testRequires2FASetupDoneAnnotated () : void {
$user = $this -> createMock ( IUser :: class );
$this -> reflector
-> method ( 'hasAnnotation' )
-> willReturnCallback ( function ( string $annotation ) {
return $annotation === 'TwoFactorSetUpDoneRequired' ;
});
$this -> userSession -> expects ( $this -> once ())
-> method ( 'isLoggedIn' )
-> willReturn ( true );
@ -228,10 +252,10 @@ class TwoFactorMiddlewareTest extends TestCase {
$this -> expectException ( UserAlreadyLoggedInException :: class );
$twoFa ctorChallengeC ontroller = $this -> getMockBuilder ( TwoFactorChallenge Controller:: class )
$controller = $this -> getMockBuilder ( HasTwoFactorSetUpDoneAnnotation Controller:: class )
-> disableOriginalConstructor ()
-> getMock ();
$this -> middleware -> beforeController ( $twoFa ctorChallengeC ontroller , 'index' );
$this -> middleware -> beforeController ( $controller , 'index' );
}
public static function dataRequires2FASetupDone () : array {
@ -243,7 +267,7 @@ class TwoFactorMiddlewareTest extends TestCase {
];
}
#[\PHPUnit\Framework\Attributes\ DataProvider('dataRequires2FASetupDone')]
#[DataProvider('dataRequires2FASetupDone')]
public function testRequires2FASetupDone ( bool $hasProvider , bool $missingProviders , bool $expectEception ) : void {
if ( $hasProvider ) {
$provider = $this -> createMock ( IProvider :: class );
@ -257,9 +281,6 @@ class TwoFactorMiddlewareTest extends TestCase {
$user = $this -> createMock ( IUser :: class );
$this -> reflector
-> method ( 'hasAnnotation' )
-> willReturn ( false );
$this -> userSession
-> method ( 'getUser' )
-> willReturn ( $user );
@ -278,9 +299,9 @@ class TwoFactorMiddlewareTest extends TestCase {
$this -> assertTrue ( true );
}
$twoFa ctorChallengeC ontroller = $this -> getMockBuilder ( TwoFactorChallengeController :: class )
$controller = $this -> getMockBuilder ( No TwoFactorChallengeAnnotation Controller:: class )
-> disableOriginalConstructor ()
-> getMock ();
$this -> middleware -> beforeController ( $twoFa ctorChallengeC ontroller , 'index' );
$this -> middleware -> beforeController ( $controller , 'index' );
}
}