Completed
Push — master ( 02cf3a...234179 )
by Guy
12s
created

testExceptionsOnStartMethodAreLogged()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 0
dl 0
loc 10
rs 10
c 0
b 0
f 0
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\LoginHandler;
20
use SilverStripe\TOTP\Method;
21
22
class LoginHandlerTest 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 LoginHandler
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->store = new SessionStore($this->request);
53
        $this->handler = LoginHandler::create();
54
55
        // Mock environment variable for encryption key
56
        Environment::setEnv('SS_MFA_SECRET_KEY', 'foobar123');
57
58
        // Mock the encryption adapter to return the plaintext input
59
        $encryptionAdapter = $this->createMock(EncryptionAdapterInterface::class);
60
        $encryptionAdapter->expects($this->any())->method('decrypt')->willReturnArgument(0);
61
        Injector::inst()->registerService($encryptionAdapter, EncryptionAdapterInterface::class);
62
63
        // Create a registered method and attach it to the member
64
        $registeredMethod = new RegisteredMethod();
65
        $registeredMethod->MethodClassName = Method::class;
66
        $registeredMethod->Data = json_encode(['secret' => 'ABCD1234']);
67
        $registeredMethod->write();
68
69
        $memberID = $this->logInWithPermission();
70
        $this->member = Member::get()->byID($memberID);
71
        $this->member->RegisteredMFAMethods()->add($registeredMethod);
72
    }
73
74
    public function testStartWithNoSecret()
75
    {
76
        $method = $this->member->RegisteredMFAMethods()->first();
77
        $method->Data = json_encode([]);
78
        $method->write();
79
80
        $result = $this->handler->start($this->store, $method);
81
        $this->assertFalse($result['enabled']);
82
    }
83
84
    public function testStartWithNoEncryptionKey()
85
    {
86
        Environment::setEnv('SS_MFA_SECRET_KEY', '');
87
        $result = $this->handler->start($this->store, $this->member->RegisteredMFAMethods()->first());
88
        $this->assertFalse($result['enabled']);
89
    }
90
91
    public function testStartSuccess()
92
    {
93
        $result = $this->handler->start($this->store, $this->member->RegisteredMFAMethods()->first());
94
        $this->assertTrue($result['enabled']);
95
        $this->assertGreaterThan(1, $result['codeLength']);
96
        $this->assertSame('ABCD1234', $this->store->getState()['secret']);
97
    }
98
99
    public function testVerify()
100
    {
101
        $this->request->setBody(json_encode(['code' => '135246']));
102
        /** @var LoginHandler&PHPUnit_Framework_MockObject_MockObject $handler */
103
        $handler = $this->getMockBuilder(LoginHandler::class)
104
            ->setMethods(['getTotp'])
105
            ->getMock();
106
107
        $handler->expects($this->once())->method('getTotp')->willReturn(
108
            $totp = $this->createMock(TOTPInterface::class)
109
        );
110
        $totp->expects($this->once())->method('verify')->with('135246')->willReturn(true);
111
112
        $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

112
        /** @scrutinizer ignore-call */ 
113
        $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...
113
        $this->assertTrue($result, 'Mocked TOTP verification with the right argument should return true');
114
    }
115
116
    public function testExceptionsOnStartMethodAreLogged()
117
    {
118
        Environment::setEnv('SS_MFA_SECRET_KEY', null);
119
120
        /** @var LoggerInterface|PHPUnit_Framework_MockObject_MockObject $logger */
121
        $logger = $this->createMock(LoggerInterface::class);
122
        $logger->expects($this->once())->method('debug');
123
124
        $this->handler->setLogger($logger);
125
        $this->handler->start($this->store, $this->member->RegisteredMFAMethods()->first());
126
    }
127
}
128