Skip to content
Snippets Groups Projects
Select Git revision
  • 7da13cba8ec470ef4699ba143bb0073cd16d839f
  • master default
  • rocky-linux-9
  • development
  • v1.0.4
  • v1.0.3
  • v1.0.2
7 results

LoginFlowTest.php

Blame
  • LoginFlowTest.php 12.55 KiB
    <?php
    
    use PHPUnit\Framework\TestCase;
    
    if (session_status() === PHP_SESSION_NONE) {
        session_start();
    }
    
    /**
     * This test has a setup similar to the LoginHandlerTest one, however SessionData and
     * UserHandler are not mocked, so interaction between session and login handler can be
     * tested and complete login and join flows can be simulated step by step.
     */
    final class LoginFlowTest extends TestCase {
    
        private $locatorStub;
        private $userDaoStub;
        private $oAuth2RequestHandler;
        private $auditLogger;
        private $gmsClientStub;
        private $sessionData;
        private $userHandler;
        private $loginHandler;
    
        public function setUp(): void {
            $this->locatorStub = $this->createMock(\RAP\Locator::class);
            $this->locatorStub->method('getBasePath')->willReturn('http://rap-ia2');
    
            $this->userDaoStub = $this->createMock(\RAP\UserDAO::class);
            $this->locatorStub->method('getUserDAO')->willReturn($this->userDaoStub);
    
            $this->oAuth2RequestHandler = $this->createMock(\RAP\OAuth2RequestHandler::class);
            $this->locatorStub->method('getOAuth2RequestHandler')->willReturn($this->oAuth2RequestHandler);
    
            $this->auditLogger = $this->createMock(\Monolog\Logger::class);
            $this->locatorStub->method('getAuditLogger')->willReturn($this->auditLogger);
    
            $this->gmsClientStub = $this->createMock(\RAP\GmsClient::class);
            $this->locatorStub->method('getGmsClient')->willReturn($this->gmsClientStub);
    
            $this->sessionData = new \RAP\SessionData();
            $this->locatorStub->method('getSession')->willReturn($this->sessionData);
    
            $this->userHandler = new \RAP\UserHandler($this->locatorStub);
            $this->locatorStub->method('getUserHandler')->willReturn($this->userHandler);
    
            $this->loginHandler = new \RAP\LoginHandler($this->locatorStub);
        }
    
        public function testNewIdentityLogin(): void {
    
            $this->sessionData->setAction('account');
    
            $identity = $this->getFakeIdentity1();
    
            // verify DAO is called for checking user existence
            $this->userDaoStub->expects($this->once())
                    ->method('findUserByIdentity')->with($identity->type, $identity->typedId);
    
            $redirect1 = $this->loginHandler->onIdentityDataReceived($identity);
    
            // verify ids are not set
            $this->assertNull($this->sessionData->getUser()->id);
            $this->assertNull($this->sessionData->getUser()->identities[0]->id);
    
            $this->assertEquals("http://rap-ia2/tou-check", $redirect1);
    
            $this->userDaoStub->method('createUser')->willReturn('2');
            $this->userDaoStub->method('insertIdentity')->willReturn('3');
    
            $redirect2 = $this->loginHandler->register();
    
            $this->assertEquals('2', $this->sessionData->getUser()->id);
            $this->assertEquals('3', $this->sessionData->getUser()->identities[0]->id);
    
            $this->assertEquals("http://rap-ia2/account", $redirect2);
        }
    
        public function testExistingUserLogin(): void {
    
            $this->sessionData->setAction('account');
    
            $user = $this->getFakeUser1();
            $this->assertEquals('test@example.com', $user->identities[0]->email);
    
            $this->userDaoStub->method('findUserByIdentity')->willReturn($user);
    
            $this->userDaoStub->expects($this->once())
                    ->method('updateIdentity')->with($this->anything());
    
            $redirect = $this->loginHandler->onIdentityDataReceived($this->getFakeIdentity1NewEmail());
    
            // verify email update
            $this->assertEquals('test2@example.com', $user->identities[0]->email);
    
            $this->assertEquals('http://rap-ia2/account', $redirect);
        }
    
        public function testNewIdentityAutojoin(): void {
    
            $this->oAuth2RequestHandler->method('getRedirectResponseUrl')->willReturn('http://redirect-url');
            $this->sessionData->setOAuth2RequestData(new \RAP\OAuth2RequestData());
    
            $this->userDaoStub->method('findJoinableUsersByEmail')->willReturn(['1', '2']);
    
            $this->userDaoStub->method('findUserById')->will($this->returnValueMap([
                        ['1', $this->getFakeUser1()],
                        ['2', $this->getFakeUser2()]
            ]));
    
            // Login: two joinable users detected
            $redirect1 = $this->loginHandler->onIdentityDataReceived($this->getFakeIdentity3());
    
            $this->assertTrue($this->sessionData->isAutojoin());
            $this->assertEquals('http://rap-ia2/confirm-join', $redirect1);
            $this->assertNotNull($this->sessionData->getUserToJoin());
            $this->assertNull($this->sessionData->getUser()->id);
    
            $this->userDaoStub->method('findJoinableUsersByUserId')->will($this->onConsecutiveCalls(['2'], []));
    
            // First confirm join
            $redirect2 = $this->loginHandler->confirmJoin();
    
            $this->assertEquals('1', $this->sessionData->getUser()->id);
            $this->assertEquals('http://rap-ia2/confirm-join', $redirect2);
    
            $this->gmsClientStub->method('joinGroups')->willReturn('2');
    
            $this->gmsClientStub->expects($this->once())
                    ->method('joinGroups')->with($this->anything());
    
            // Second confirm join, then redirect to caller application
            $redirect3 = $this->loginHandler->confirmJoin();
    
            $this->assertEquals('2', $this->sessionData->getUser()->id);
            $this->assertEquals('http://redirect-url', $redirect3);
        }
    
        public function testJoinAlreadyJoinedUser(): void { // go to account page without joining
            $user = $this->getFakeUser1();
    
            $this->sessionData->setAction('join');
            $this->sessionData->setUser($user);
    
            $this->userDaoStub->method('findUserByIdentity')->willReturn($user);
    
            $redirect = $this->loginHandler->onIdentityDataReceived($this->getFakeIdentity1());
    
            $this->assertEquals('http://rap-ia2/account', $redirect);
        }
    
        public function testRejectJoinExistingUser(): void {
    
            $this->sessionData->setAction('account');
    
            $this->userDaoStub->method('findUserByIdentity')->willReturn($this->getFakeUser1());
            $this->userDaoStub->method('findUserById')->willReturn($this->getFakeUser2());
            $this->userDaoStub->method('findJoinableUsersByUserId')->will($this->onConsecutiveCalls(['2'], []));
    
            $redirect1 = $this->loginHandler->onIdentityDataReceived($this->getFakeIdentity1());
    
            $this->assertTrue($this->sessionData->isAutojoin());
            $this->assertEquals('http://rap-ia2/confirm-join', $redirect1);
    
            $this->userDaoStub->expects($this->once())->method('insertRejectedJoin');
    
            // User rejects join, redirect to account page
            $redirect2 = $this->loginHandler->rejectJoin();
    
            $this->assertEquals('http://rap-ia2/account', $redirect2);
        }
    
        public function testRejectJoinNewUser(): void {
    
            $this->sessionData->setAction('account');
    
            $this->userDaoStub->method('findJoinableUsersByEmail')->willReturn(['1', '2']);
            $this->userDaoStub->method('findUserById')->will(
                    $this->returnValueMap(array(
                        array('1', $this->getFakeUser1()),
                        array('2', $this->getFakeUser2()))));
    
            // Login: two joinable users detected
            $redirect1 = $this->loginHandler->onIdentityDataReceived($this->getFakeIdentity3());
    
            $this->assertTrue($this->sessionData->isAutojoin());
            $this->assertEquals('http://rap-ia2/confirm-join', $redirect1);
    
            // User rejects first join, new confirm join is displayed
            $redirect2 = $this->loginHandler->rejectJoin();
    
            $this->assertEquals(1, count($this->sessionData->getRejectedJoins()));
            $this->assertEquals('http://rap-ia2/confirm-join', $redirect2);
    
            // User rejects second join, redirect to TOU check
            $redirect3 = $this->loginHandler->rejectJoin();
    
            $this->assertEquals(2, count($this->sessionData->getRejectedJoins()));
            $this->assertEquals('http://rap-ia2/tou-check', $redirect3);
    
            $this->userDaoStub->method('createUser')->willReturn('5');
            $this->userDaoStub->expects($this->exactly(2))->method('insertRejectedJoin');
    
            // User accepts TOU
            $redirect4 = $this->loginHandler->register();
            $this->assertEquals('http://rap-ia2/account', $redirect4);
        }
    
        public function testExplicitJoin(): void {
    
            // First login result
            $this->sessionData->setUser($this->getFakeUser2());
    
            $this->sessionData->setAction('join');
    
            $this->userDaoStub->method('findUserById')->willReturn($this->getFakeUser1());
    
            // Second login
            $redirect1 = $this->loginHandler->onIdentityDataReceived($this->getFakeIdentity1());
    
            $this->assertFalse($this->sessionData->isAutojoin());
            $this->assertEquals('http://rap-ia2/confirm-join', $redirect1);
    
            // User confirms the join
            $redirect2 = $this->loginHandler->confirmJoin();
            $this->assertEquals('http://rap-ia2/account', $redirect2);
        }
    
        public function testExplicitJoinAndAutojoin(): void {
            // First login result
            $this->sessionData->setUser($this->getFakeUser2());
    
            $this->sessionData->setAction('join');
    
            $this->userDaoStub->method('findUserById')->willReturn($this->getFakeUser1());
            $this->userDaoStub->method('findJoinableUsersByUserId')->will($this->onConsecutiveCalls(['2'], []));
    
            // Second login
            $redirect1 = $this->loginHandler->onIdentityDataReceived($this->getFakeIdentity1());
    
            $this->assertFalse($this->sessionData->isAutojoin());
            $this->assertEquals('http://rap-ia2/confirm-join', $redirect1);
    
            // User confirms the join, another join is detected
            $redirect2 = $this->loginHandler->confirmJoin();
    
            $this->assertTrue($this->sessionData->isAutojoin());
            $this->assertEquals('http://rap-ia2/confirm-join', $redirect2);
    
            // User confirm the second join too
            $redirect3 = $this->loginHandler->confirmJoin();
            $this->assertEquals('http://rap-ia2/account', $redirect3);
        }
    
        public function testExplicitJoinAndRejectedAutojoin(): void {
    
            // First login result
            $this->sessionData->setUser($this->getFakeUser2());
    
            $this->sessionData->setAction('join');
    
            $this->userDaoStub->method('findUserById')->willReturn($this->getFakeUser1());
            $this->userDaoStub->method('findJoinableUsersByUserId')->will($this->onConsecutiveCalls(['2'], []));
    
            // Second login
            $redirect1 = $this->loginHandler->onIdentityDataReceived($this->getFakeIdentity1());
    
            $this->assertFalse($this->sessionData->isAutojoin());
            $this->assertEquals('http://rap-ia2/confirm-join', $redirect1);
    
            // User confirms the join, another join is detected
            $redirect2 = $this->loginHandler->confirmJoin();
    
            $this->assertTrue($this->sessionData->isAutojoin());
            $this->assertEquals('http://rap-ia2/confirm-join', $redirect2);
    
            $this->userDaoStub->expects($this->once())->method('insertRejectedJoin');
    
            // User reject the second join
            $redirect3 = $this->loginHandler->rejectJoin();
            $this->assertEquals('http://rap-ia2/account', $redirect3);
        }
    
        private function getFakeUser1(): \RAP\User {
    
            $user = new \RAP\User();
            $user->id = '1';
            $identity = new \RAP\Identity('eduGAIN');
            $identity->email = 'test@example.com';
            $identity->id = '4';
            $identity->typedId = '123';
            $user->addIdentity($identity);
            return $user;
        }
    
        private function getFakeUser2(): \RAP\User {
    
            $user = new \RAP\User();
            $user->id = '2';
            $identity = new \RAP\Identity('eduGAIN');
            $identity->email = 'test@example.com';
            $identity->id = '6';
            $identity->typedId = '999';
            $user->addIdentity($identity);
            return $user;
        }
    
        private function getFakeIdentity1(): \RAP\Identity {
    
            $identity = new \RAP\Identity(\RAP\Identity::EDU_GAIN);
            $identity->typedId = '123';
            $identity->email = 'test@example.com';
            return $identity;
        }
    
        private function getFakeIdentity1NewEmail(): \RAP\Identity {
    
            $identity = new \RAP\Identity(\RAP\Identity::EDU_GAIN);
            $identity->typedId = '123';
            $identity->email = 'test2@example.com';
            return $identity;
        }
    
        private function getFakeIdentity2(): \RAP\Identity {
    
            $identity = new \RAP\Identity(\RAP\Identity::EDU_GAIN);
            $identity->typedId = '456';
            $identity->email = 'test3@example.com';
            return $identity;
        }
    
        private function getFakeIdentity3(): \RAP\Identity {
    
            $identity = new \RAP\Identity(\RAP\Identity::GOOGLE);
            $identity->typedId = '789';
            $identity->email = 'test@example.com';
            return $identity;
        }
    
    }