Passed
Push — master ( 7e81b0...7eb007 )
by Robbie
12:39 queued 11s
created

src/BackupCode/RegisterHandler.php (2 issues)

1
<?php declare(strict_types=1);
2
3
namespace SilverStripe\MFA\BackupCode;
4
5
use Exception;
6
use SilverStripe\Control\HTTPRequest;
7
use SilverStripe\Core\Config\Configurable;
8
use SilverStripe\Core\Extensible;
9
use SilverStripe\Core\Injector\Injector;
10
use SilverStripe\MFA\Method\Handler\RegisterHandlerInterface;
11
use SilverStripe\MFA\Method\MethodInterface;
12
use SilverStripe\MFA\Service\BackupCodeGeneratorInterface;
13
use SilverStripe\MFA\Service\RegisteredMethodManager;
14
use SilverStripe\MFA\State\BackupCode;
15
use SilverStripe\MFA\State\Result;
16
use SilverStripe\MFA\Store\StoreInterface;
17
18
class RegisterHandler implements RegisterHandlerInterface
19
{
20
    use Extensible;
21
    use Configurable;
22
23
    /**
24
     * Provide a user help link that will be available when registering backup codes
25
     * TODO Will this have a user help link as a default?
26
     *
27
     * @config
28
     * @var string
29
     */
30
    private static $user_help_link;
0 ignored issues
show
The private property $user_help_link is not used, and could be removed.
Loading history...
31
32
    /**
33
     * Stores any data required to handle a registration process with a method, and returns relevant state to be applied
34
     * to the front-end application managing the process.
35
     *
36
     * @param StoreInterface $store An object that hold session data (and the Member) that can be mutated
37
     * @return array Props to be passed to a front-end component
38
     * @throws Exception When there is no valid source of CSPRNG
39
     */
40
    public function start(StoreInterface $store): array
41
    {
42
        // Create or update the RegisteredMethod on the member. This breaks the normal flow as it's created on "start"
43
        // instead of after receiving a response from the user
44
45
        /** @var MethodInterface $method */
46
        $method = Injector::inst()->get(Method::class);
47
48
        /** @var BackupCodeGeneratorInterface $generator */
49
        $generator = Injector::inst()->get(BackupCodeGeneratorInterface::class);
50
        $codes = $generator->generate();
51
52
        RegisteredMethodManager::singleton()->registerForMember(
53
            $store->getMember(),
54
            $method,
55
            array_map(function (BackupCode $backupCode) {
56
                return json_encode($backupCode);
57
            }, $codes)
58
        );
59
60
        // Return un-hashed codes for the front-end UI
61
        return [
62
            'codes' => array_map(function (BackupCode $backupCode) {
63
                return $backupCode->getCode();
64
            }, $codes),
65
        ];
66
    }
67
68
    /**
69
     * Confirm that the provided details are valid, and create a new RegisteredMethod against the member.
70
     *
71
     * @param HTTPRequest $request
72
     * @param StoreInterface $store
73
     * @return array
74
     */
75
    public function register(HTTPRequest $request, StoreInterface $store): Result
76
    {
77
        // Backup codes are unique where no confirmation or user input is required. The method is registered on "start"
78
        return Result::create();
0 ignored issues
show
Bug Best Practice introduced by
The expression return SilverStripe\MFA\State\Result::create() returns the type SilverStripe\MFA\State\Result which is incompatible with the documented return type array.
Loading history...
79
    }
80
81
    /**
82
     * Provide a localised description of this MFA Method.
83
     *
84
     * eg. "Verification codes are created by an app on your phone"
85
     *
86
     * @return string
87
     */
88
    public function getDescription(): string
89
    {
90
        return _t(
91
            __CLASS__ . '.DESCRIPTION',
92
            'Recovery codes enable you to log into your account in the event your primary authentication is not '
93
            . 'available. Each code can only be used once. Store these codes somewhere safe, as they will not be '
94
            . 'viewable after this leaving this page.'
95
        );
96
    }
97
98
    /**
99
     * Provide a localised URL to a support article about the registration process for this MFA Method.
100
     *
101
     * @return string
102
     */
103
    public function getSupportLink(): string
104
    {
105
        return (string) $this->config()->get('user_help_link');
106
    }
107
108
    /**
109
     * Provide a localised string to describe the support link {@see getSupportLink} about this MFA Method.
110
     *
111
     * @return string
112
     */
113
    public function getSupportText(): string
114
    {
115
        return _t(__CLASS__ . '.SUPPORT_LINK_DESCRIPTION', 'Learn about recovery codes.');
116
    }
117
118
    /**
119
     * Get the key that a React UI component is registered under (with @silverstripe/react-injector on the front-end)
120
     *
121
     * @return string
122
     */
123
    public function getComponent(): string
124
    {
125
        return 'BackupCodeRegister';
126
    }
127
}
128