Select Git revision
LoginFlowTest.php
-
Sonia Zorba authoredSonia Zorba authored
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;
}
}