Completed
Push — master ( 8927df...f70445 )
by Abdelrahman
02:05
created

TwoFactorSettingsController::backupTotp()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 14
nc 2
nop 1
dl 0
loc 24
rs 8.9713
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * NOTICE OF LICENSE
5
 *
6
 * Part of the Rinvex Fort Package.
7
 *
8
 * This source file is subject to The MIT License (MIT)
9
 * that is bundled with this package in the LICENSE file.
10
 *
11
 * Package: Rinvex Fort Package
12
 * License: The MIT License (MIT)
13
 * Link:    https://rinvex.com
14
 */
15
16
namespace Rinvex\Fort\Http\Controllers\Frontend;
17
18
use Carbon\Carbon;
19
use Illuminate\Support\MessageBag;
20
use Illuminate\Support\ViewErrorBag;
21
use Rinvex\Fort\Services\TwoFactorTotpProvider;
22
use Rinvex\Fort\Contracts\UserRepositoryContract;
23
use Rinvex\Fort\Http\Controllers\AuthenticatedController;
24
use Rinvex\Fort\Http\Requests\Frontend\TwoFactorTotpUpdateRequest;
25
use Rinvex\Fort\Http\Requests\Frontend\TwoFactorPhoneUpdateRequest;
26
27
class TwoFactorSettingsController extends AuthenticatedController
28
{
29
    /**
30
     * The user repository instance.
31
     *
32
     * @var \Rinvex\Fort\Contracts\UserRepositoryContract
33
     */
34
    protected $userRepository;
35
36
    /**
37
     * Create a new Two-Factor update controller instance.
38
     *
39
     * @param \Rinvex\Fort\Contracts\UserRepositoryContract $userRepository
40
     */
41
    public function __construct(UserRepositoryContract $userRepository)
42
    {
43
        parent::__construct();
44
45
        $this->userRepository = $userRepository;
46
    }
47
48
    /**
49
     * Show the Two-Factor TOTP enable form.
50
     *
51
     * @param \Rinvex\Fort\Http\Requests\Frontend\TwoFactorTotpUpdateRequest $request
52
     * @param \Rinvex\Fort\Services\TwoFactorTotpProvider                    $totpProvider
53
     *
54
     * @return \Illuminate\Http\Response
0 ignored issues
show
Documentation introduced by
Should the return type not be \Illuminate\View\View|\I...\Contracts\View\Factory?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
55
     */
56
    public function enableTotp(TwoFactorTotpUpdateRequest $request, TwoFactorTotpProvider $totpProvider)
57
    {
58
        $currentUser = $request->user($this->getGuard());
59
        $settings    = $currentUser->getTwoFactor();
60
61
        if (array_get($settings, 'totp.enabled') && ! session()->get('rinvex.fort.alert.success') && ! session()->get('errors')) {
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 130 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
62
            $messageBag = new MessageBag([trans('rinvex/fort::frontend/messages.verification.twofactor.totp.already')]);
63
            $errors     = (new ViewErrorBag())->put('default', $messageBag);
64
        }
65
66
        if (! $secret = array_get($settings, 'totp.secret')) {
67
            array_set($settings, 'totp.enabled', false);
68
            array_set($settings, 'totp.secret', $secret = $totpProvider->generateSecretKey());
69
70
            $this->userRepository->update($currentUser, [
71
                'two_factor' => $settings,
72
            ]);
73
        }
74
75
        $qrCode = $totpProvider->getQRCodeInline(config('rinvex.fort.twofactor.issuer'), $currentUser->email, $secret);
76
77
        return view('rinvex/fort::frontend/user.twofactor', compact('secret', 'qrCode', 'settings', 'errors'));
78
    }
79
80
    /**
81
     * Process the Two-Factor TOTP enable form.
82
     *
83
     * @param \Rinvex\Fort\Http\Requests\Frontend\TwoFactorTotpUpdateRequest $request
84
     * @param \Rinvex\Fort\Services\TwoFactorTotpProvider                    $totpProvider
85
     *
86
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
87
     */
88
    public function updateTotp(TwoFactorTotpUpdateRequest $request, TwoFactorTotpProvider $totpProvider)
89
    {
90
        $currentUser = $request->user($this->getGuard());
91
        $settings    = $currentUser->getTwoFactor();
92
        $secret      = array_get($settings, 'totp.secret');
93
        $backup      = array_get($settings, 'totp.backup');
94
        $backupAt    = array_get($settings, 'totp.backup_at');
95
96
        if ($totpProvider->verifyKey($secret, $request->get('token'))) {
97
            array_set($settings, 'totp.enabled', true);
98
            array_set($settings, 'totp.secret', $secret);
99
            array_set($settings, 'totp.backup', $backup ?: $this->generateTotpBackups());
100
            array_set($settings, 'totp.backup_at', $backupAt ?: (new Carbon())->toDateTimeString());
101
102
            // Update Two-Factor settings
103
            $this->userRepository->update($currentUser, [
104
                'two_factor' => $settings,
105
            ]);
106
107
            return intend([
108
                'back' => true,
109
                'with' => ['rinvex.fort.alert.success' => trans('rinvex/fort::frontend/messages.verification.twofactor.totp.enabled')],
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 135 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
110
            ]);
111
        }
112
113
        return intend([
114
            'back'       => true,
115
            'withErrors' => ['token' => trans('rinvex/fort::frontend/messages.verification.twofactor.totp.invalid_token')],
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 123 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
116
        ]);
117
    }
118
119
    /**
120
     * Process the Two-Factor TOTP disable.
121
     *
122
     * @param \Rinvex\Fort\Http\Requests\Frontend\TwoFactorTotpUpdateRequest $request
123
     *
124
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
125
     */
126
    public function disableTotp(TwoFactorTotpUpdateRequest $request)
127
    {
128
        $currentUser = $request->user($this->getGuard());
129
        $settings    = $currentUser->getTwoFactor();
130
131
        array_set($settings, 'totp', []);
132
133
        $this->userRepository->update($currentUser, [
134
            'two_factor' => $settings,
135
        ]);
136
137
        return intend([
138
            'route' => 'rinvex.fort.frontend.user.settings',
139
            'with'  => ['rinvex.fort.alert.success' => trans('rinvex/fort::frontend/messages.verification.twofactor.totp.disabled')],
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 133 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
140
        ]);
141
    }
142
143
    /**
144
     * Process the Two-Factor Phone enable.
145
     *
146
     * @param \Rinvex\Fort\Http\Requests\Frontend\TwoFactorPhoneUpdateRequest $request
147
     *
148
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
149
     */
150
    public function enablePhone(TwoFactorPhoneUpdateRequest $request)
151
    {
152
        $currentUser = $request->user($this->getGuard());
153
154
        if (! $currentUser->phone || ! $currentUser->phone_verified) {
155
            return intend([
156
                'route'      => 'rinvex.fort.frontend.user.settings',
157
                'withErrors' => ['phone' => trans('rinvex/fort::frontend/messages.account.phone_required')],
158
            ]);
159
        }
160
161
        $settings = $currentUser->getTwoFactor();
162
163
        array_set($settings, 'phone.enabled', true);
164
165
        $this->userRepository->update($currentUser, [
166
            'two_factor' => $settings,
167
        ]);
168
169
        return intend([
170
            'route' => 'rinvex.fort.frontend.user.settings',
171
            'with'  => ['rinvex.fort.alert.success' => trans('rinvex/fort::frontend/messages.verification.twofactor.phone.enabled')],
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 133 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
172
        ]);
173
    }
174
175
    /**
176
     * Process the Two-Factor Phone disable.
177
     *
178
     * @param \Rinvex\Fort\Http\Requests\Frontend\TwoFactorPhoneUpdateRequest $request
179
     *
180
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
181
     */
182
    public function disablePhone(TwoFactorPhoneUpdateRequest $request)
183
    {
184
        $currentUser = $request->user($this->getGuard());
185
        $settings    = $currentUser->getTwoFactor();
186
187
        array_set($settings, 'phone.enabled', false);
188
189
        $this->userRepository->update($currentUser, [
190
            'two_factor' => $settings,
191
        ]);
192
193
        return intend([
194
            'route' => 'rinvex.fort.frontend.user.settings',
195
            'with'  => ['rinvex.fort.alert.success' => trans('rinvex/fort::frontend/messages.verification.twofactor.phone.disabled')],
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 134 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
196
        ]);
197
    }
198
199
    /**
200
     * Process the Two-Factor OTP backup.
201
     *
202
     * @param \Rinvex\Fort\Http\Requests\Frontend\TwoFactorTotpUpdateRequest $request
203
     *
204
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
205
     */
206
    public function backupTotp(TwoFactorTotpUpdateRequest $request)
207
    {
208
        $currentUser = $request->user($this->getGuard());
209
        $settings    = $currentUser->getTwoFactor();
210
211
        if (! array_get($settings, 'totp.enabled')) {
212
            return intend([
213
                'route'      => 'rinvex.fort.frontend.user.settings',
214
                'withErrors' => ['rinvex.fort.verification.twofactor.totp.cant_backup' => trans('rinvex/fort::frontend/messages.verification.twofactor.totp.cant_backup')],
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 171 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
215
            ]);
216
        }
217
218
        array_set($settings, 'totp.backup', $this->generateTotpBackups());
219
        array_set($settings, 'totp.backup_at', (new Carbon())->toDateTimeString());
220
221
        $this->userRepository->update($currentUser, [
222
            'two_factor' => $settings,
223
        ]);
224
225
        return intend([
226
            'back' => true,
227
            'with' => ['rinvex.fort.alert.success' => trans('rinvex/fort::frontend/messages.verification.twofactor.totp.rebackup')],
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 132 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
228
        ]);
229
    }
230
231
    /**
232
     * Generate Two-Factor OTP backup codes.
233
     *
234
     * @return array
235
     */
236
    protected function generateTotpBackups()
237
    {
238
        $backup = [];
239
240
        for ($x = 0; $x <= 9; $x++) {
241
            $backup[] = str_pad(random_int(0, 9999999999), 10, 0, STR_PAD_BOTH);
242
        }
243
244
        return $backup;
245
    }
246
}
247