Completed
Push — master ( a3802c...bae652 )
by Robbie
24s queued 11s
created

VerifyHandlerTest::testVerifyValidatesCodes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
1
<?php
2
3
namespace SilverStripe\MFA\Tests\BackupCode;
4
5
use PHPUnit_Framework_MockObject_MockObject;
6
use SilverStripe\Control\Email\Email;
7
use SilverStripe\Control\HTTPRequest;
8
use SilverStripe\Dev\SapphireTest;
9
use SilverStripe\MFA\BackupCode\VerifyHandler;
10
use SilverStripe\MFA\Extension\MemberExtension;
11
use SilverStripe\MFA\Model\RegisteredMethod;
12
use SilverStripe\MFA\Service\Notification;
13
use SilverStripe\MFA\Store\StoreInterface;
14
use SilverStripe\ORM\DataObject;
15
use SilverStripe\Security\Member;
16
17
class VerifyHandlerTest extends SapphireTest
18
{
19
    protected static $fixture_file = 'VerifyHandlerTest.yml';
20
21
    /**
22
     * @dataProvider getVerifyTests
23
     */
24
    public function testVerifyValidatesCodes($expectedResult, $input, $message)
25
    {
26
        $handler = (new VerifyHandler())->setNotificationService($this->createMock(Notification::class));
27
28
        // Test a code with invalid characters
29
        list ($request, $store, $method) = $this->scaffoldVerifyParams($input);
30
        $this->assertSame($expectedResult, $handler->verify($request, $store, $method)->isSuccessful(), $message);
31
    }
32
33
    public function testVerifySendsNotification()
34
    {
35
        $handler = (new VerifyHandler())->setNotificationService((Notification::create()));
36
        list ($request, $store, $method) = $this->scaffoldVerifyParams('123456');
37
        $this->assertTrue($handler->verify($request, $store, $method)->isSuccessful());
38
        $this->assertEmailSent($store->getMember()->Email, null, '/recovery code was used/');
39
    }
40
41
    public function testVerifyInvalidatesCodesThatHaveBeenUsed()
42
    {
43
        $handler = (new VerifyHandler())->setNotificationService($this->createMock(Notification::class));
44
45
        // Test a code with invalid characters
46
        list ($request, $store, $method) = $this->scaffoldVerifyParams('123456');
47
        $this->assertTrue($handler->verify($request, $store, $method)->isSuccessful());
48
49
        $method = DataObject::get_by_id(RegisteredMethod::class, $method->ID);
50
        $codes = json_decode($method->Data, true);
51
52
        $this->assertCount(3, $codes, 'Only 3 codes remain against the method');
53
54
        list ($request, $store, $method) = $this->scaffoldVerifyParams('123456');
55
        $this->assertFalse(
56
            $handler->verify($request, $store, $method)->isSuccessful(),
57
            'Attempting to validate the previously used code now returns false'
58
        );
59
    }
60
61
    public function getVerifyTests()
62
    {
63
        return [
64
            [false, 'asw123', 'Invalid characters are handled'],
65
            [false, '', 'Empty codes are handled'],
66
            [false, null, 'Null input is handled'],
67
            [false, str_pad('', 10000, 'code'), 'Long codes are handled'],
68
            [true, '123456', 'Valid codes are valid'],
69
        ];
70
    }
71
72
    protected function scaffoldVerifyParams($userInput)
73
    {
74
        /** @var Member|MemberExtension $member */
75
        $member = $this->objFromFixture(Member::class, 'guy');
76
77
        /** @var HTTPRequest|PHPUnit_Framework_MockObject_MockObject $request */
78
        $request = $this->createMock(HTTPRequest::class);
79
        $request->expects($this->once())->method('getBody')->willReturn("{\"code\":\"{$userInput}\"}");
80
81
        /** @var StoreInterface|PHPUnit_Framework_MockObject_MockObject $store */
82
        $store = $this->createMock(StoreInterface::class);
83
        $store->expects($this->any())->method('getMember')->willReturn($member);
84
85
        /** @var RegisteredMethod $registeredMethod */
86
        $registeredMethod = $member->RegisteredMFAMethods()->first();
87
88
        return [$request, $store, $registeredMethod];
89
    }
90
}
91