VerifyHandlerTest   A
last analyzed

Complexity

Total Complexity 6

Size/Duplication

Total Lines 108
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 50
c 1
b 0
f 0
dl 0
loc 108
rs 10
wmc 6

6 Methods

Rating   Name   Duplication   Size   Complexity  
A testStartWithNoSecret() 0 8 1
A testStartSuccess() 0 6 1
A setUp() 0 27 1
A testStartWithNoEncryptionKey() 0 5 1
A testExceptionsOnStartMethodAreLogged() 0 10 1
A testVerify() 0 17 1
1
<?php
2
3
namespace SilverStripe\TOTP\Tests;
4
5
use OTPHP\TOTPInterface;
6
use PHPUnit_Framework_MockObject_MockObject;
7
use Psr\Log\LoggerInterface;
8
use SilverStripe\Control\HTTPRequest;
9
use SilverStripe\Control\Session;
10
use SilverStripe\Core\Environment;
11
use SilverStripe\Core\Injector\Injector;
12
use SilverStripe\Dev\SapphireTest;
13
use SilverStripe\MFA\Extension\MemberExtension;
14
use SilverStripe\MFA\Model\RegisteredMethod;
15
use SilverStripe\MFA\Service\EncryptionAdapterInterface;
16
use SilverStripe\MFA\Store\SessionStore;
17
use SilverStripe\MFA\Store\StoreInterface;
18
use SilverStripe\Security\Member;
19
use SilverStripe\TOTP\VerifyHandler;
20
use SilverStripe\TOTP\Method;
21
22
class VerifyHandlerTest extends SapphireTest
23
{
24
    protected $usesDatabase = true;
25
26
    /**
27
     * @var HTTPRequest
28
     */
29
    protected $request;
30
31
    /**
32
     * @var StoreInterface
33
     */
34
    protected $store;
35
36
    /**
37
     * @var VerifyHandler
38
     */
39
    protected $handler;
40
41
    /**
42
     * @var Member&MemberExtension
43
     */
44
    protected $member;
45
46
    protected function setUp()
47
    {
48
        parent::setUp();
49
50
        $this->request = new HTTPRequest('GET', '/');
51
        $this->request->setSession(new Session([]));
52
        $this->handler = VerifyHandler::create();
53
54
        // Mock environment variable for encryption key
55
        Environment::setEnv('SS_MFA_SECRET_KEY', 'foobar123');
56
57
        // Mock the encryption adapter to return the plaintext input
58
        $encryptionAdapter = $this->createMock(EncryptionAdapterInterface::class);
59
        $encryptionAdapter->expects($this->any())->method('decrypt')->willReturnArgument(0);
60
        Injector::inst()->registerService($encryptionAdapter, EncryptionAdapterInterface::class);
61
62
        // Create a registered method and attach it to the member
63
        $registeredMethod = new RegisteredMethod();
64
        $registeredMethod->MethodClassName = Method::class;
65
        $registeredMethod->Data = json_encode(['secret' => 'ABCD1234']);
66
        $registeredMethod->write();
67
68
        $memberID = $this->logInWithPermission();
69
        $this->member = Member::get()->byID($memberID);
70
        $this->member->RegisteredMFAMethods()->add($registeredMethod);
71
72
        $this->store = new SessionStore($this->member);
73
    }
74
75
    public function testStartWithNoSecret()
76
    {
77
        $method = $this->member->RegisteredMFAMethods()->first();
78
        $method->Data = json_encode([]);
79
        $method->write();
80
81
        $result = $this->handler->start($this->store, $method);
82
        $this->assertFalse($result['enabled']);
83
    }
84
85
    public function testStartWithNoEncryptionKey()
86
    {
87
        Environment::setEnv('SS_MFA_SECRET_KEY', '');
88
        $result = $this->handler->start($this->store, $this->member->RegisteredMFAMethods()->first());
89
        $this->assertFalse($result['enabled']);
90
    }
91
92
    public function testStartSuccess()
93
    {
94
        $result = $this->handler->start($this->store, $this->member->RegisteredMFAMethods()->first());
95
        $this->assertTrue($result['enabled']);
96
        $this->assertGreaterThan(1, $result['codeLength']);
97
        $this->assertSame('ABCD1234', $this->store->getState()['secret']);
98
    }
99
100
    public function testVerify()
101
    {
102
        $this->request->setBody(json_encode(['code' => '135246']));
103
        /** @var VerifyHandler&PHPUnit_Framework_MockObject_MockObject $handler */
104
        $handler = $this->getMockBuilder(VerifyHandler::class)
105
            ->setMethods(['getTotp'])
106
            ->getMock();
107
108
        $handler->expects($this->once())->method('getTotp')->willReturn(
109
            $totp = $this->createMock(TOTPInterface::class)
110
        );
111
        $totp->expects($this->once())->method('verify')->with('135246')->willReturn(true);
112
113
        $result = $handler->verify($this->request, $this->store, $this->member->RegisteredMFAMethods()->first());
0 ignored issues
show
Bug introduced by
The method verify() does not exist on PHPUnit_Framework_MockObject_MockObject. Did you maybe mean __phpunit_verify()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

113
        /** @scrutinizer ignore-call */ 
114
        $result = $handler->verify($this->request, $this->store, $this->member->RegisteredMFAMethods()->first());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
114
        $this->assertTrue(
115
            $result->isSuccessful(),
116
            'Mocked TOTP verification with the right argument should return successful result'
117
        );
118
    }
119
120
    public function testExceptionsOnStartMethodAreLogged()
121
    {
122
        Environment::setEnv('SS_MFA_SECRET_KEY', null);
123
124
        /** @var LoggerInterface|PHPUnit_Framework_MockObject_MockObject $logger */
125
        $logger = $this->createMock(LoggerInterface::class);
126
        $logger->expects($this->once())->method('debug');
127
128
        $this->handler->setLogger($logger);
129
        $this->handler->start($this->store, $this->member->RegisteredMFAMethods()->first());
130
    }
131
}
132