-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfunction.php
More file actions
209 lines (189 loc) · 6.03 KB
/
Copy pathfunction.php
File metadata and controls
209 lines (189 loc) · 6.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
<?php
if (!function_exists('mfa_is_user_enrolled')) {
/**
* Check if user has enabled MFA
*
* @param mixed $user
* @param string $guard
* @return bool
*/
function mfa_is_user_enrolled($user, $guard)
{
if (!$user) {
return false;
}
// Use the effective config (file defaults ⊕ DB overrides), same as every
// other consumer, instead of reading config() directly.
$guardConfig = mfa_get_guard_config($guard);
if (!$guardConfig) {
return false;
}
$mfaRecord = \App\GP247\Plugins\MFA\Models\TwoFactorAuth::where('user_type', $guardConfig['model'])
->where('user_id', $user->id)
->where('enabled', 1)
->first();
return $mfaRecord !== null;
}
}
if (!function_exists('mfa_is_verified')) {
/**
* Check if current session has verified MFA
*
* @return bool
*/
function mfa_is_verified()
{
$sessionKey = config('Plugins/MFA.session_key', 'mfa_verified');
return session($sessionKey, false) === true;
}
}
if (!function_exists('mfa_set_verified')) {
/**
* Mark current session as MFA verified
*
* @return void
*/
function mfa_set_verified()
{
$sessionKey = config('Plugins/MFA.session_key', 'mfa_verified');
session([$sessionKey => true]);
}
}
if (!function_exists('mfa_clear_verified')) {
/**
* Clear MFA verification from session
*
* @return void
*/
function mfa_clear_verified()
{
$sessionKey = config('Plugins/MFA.session_key', 'mfa_verified');
session()->forget($sessionKey);
}
}
if (!function_exists('mfa_setting_fields')) {
/**
* The per-guard settings a site owner may edit from the admin screen.
*
* WHY: only these user-facing fields are overlaid from the DB; dev-level
* fields (model, redirect_*) stay in config.php as package defaults.
*
* @return array<int, string>
*/
function mfa_setting_fields()
{
return ['enabled', 'forced', 'qr_code_size', 'recovery_codes_count', 'window'];
}
}
if (!function_exists('mfa_setting_overrides')) {
/**
* User-set guard overrides stored in `admin_config` (code `MFA_config`).
*
* WHY: config.php is package-owned and gets overwritten on 1-click update
* (ADR plugin-manager_extension-update-flow #7). Storing the site owner's
* choices in admin_config — which the update flow preserves — is what keeps
* them from being reset. Returns [guard => [field => value]].
*
* WHY not statically cached: a Livewire save() and the subsequent re-render
* run in one PHP request; a static cache would show stale values right after
* saving. The lookup is a single indexed row — cheap enough to read live.
*
* @return array<string, array<string, mixed>>
*/
function mfa_setting_overrides()
{
$row = \GP247\Core\Models\AdminConfig::where('group', 'Plugins')
->where('key', 'MFA_config')
->first();
$decoded = $row ? json_decode((string) $row->value, true) : null;
return is_array($decoded) ? $decoded : [];
}
}
if (!function_exists('mfa_effective_guards')) {
/**
* Effective guard config = file defaults ⊕ DB overrides (per guard).
*
* @return array<string, array<string, mixed>>
*/
function mfa_effective_guards()
{
$defaults = (array) config('Plugins/MFA.guards', []);
$overrides = mfa_setting_overrides();
foreach ($defaults as $guard => $conf) {
if (isset($overrides[$guard]) && is_array($overrides[$guard])) {
// Only the whitelisted user-facing fields are overlaid.
foreach (mfa_setting_fields() as $field) {
if (array_key_exists($field, $overrides[$guard])) {
$defaults[$guard][$field] = $overrides[$guard][$field];
}
}
}
}
return $defaults;
}
}
if (!function_exists('mfa_get_guard_config')) {
/**
* Get effective MFA configuration for a specific guard (file ⊕ DB override).
*
* @param string $guard
* @return array|null
*/
function mfa_get_guard_config($guard)
{
$guards = mfa_effective_guards();
return $guards[$guard] ?? null;
}
}
if (!function_exists('mfa_save_guard_settings')) {
/**
* Persist per-guard user settings to `admin_config` (code `MFA_config`),
* keeping only the whitelisted fields for guards that exist in config.php.
*
* @param array<string, array<string, mixed>> $settings guard => [field => value]
* @return void
*/
function mfa_save_guard_settings(array $settings)
{
$defaults = (array) config('Plugins/MFA.guards', []);
$clean = [];
foreach ($settings as $guard => $values) {
if (!isset($defaults[$guard]) || !is_array($values)) {
continue;
}
$row = [];
foreach (mfa_setting_fields() as $field) {
if (array_key_exists($field, $values)) {
$row[$field] = $values[$field];
}
}
if ($row !== []) {
$clean[$guard] = $row;
}
}
\GP247\Core\Models\AdminConfig::updateOrCreate(
['group' => 'Plugins', 'key' => 'MFA_config'],
[
'code' => 'MFA_config',
'store_id' => GP247_STORE_ID_GLOBAL,
'value' => json_encode($clean),
]
);
}
}
if (!function_exists('mfa_generate_recovery_codes')) {
/**
* Generate recovery codes
*
* @param int $count
* @return array
*/
function mfa_generate_recovery_codes($count = 8)
{
$codes = [];
for ($i = 0; $i < $count; $i++) {
$codes[] = strtoupper(substr(str_replace(['+', '/', '='], '', base64_encode(random_bytes(6))), 0, 8));
}
return $codes;
}
}