Skip to content

Commit 24cbe7d

Browse files
committed
adding isChannelEnabledInConfig
1 parent cc797c1 commit 24cbe7d

File tree

4 files changed

+103
-4
lines changed

4 files changed

+103
-4
lines changed

config/mfa.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
'code_ttl_seconds' => 300,
66

77
'email' => [
8-
'enabled' => env('MFA_EMAIL_ENABLED', true),
8+
'enabled' => (bool)env('MFA_EMAIL_ENABLED', true),
99
'from_address' => env('MFA_EMAIL_FROM_ADDRESS', env('MAIL_FROM_ADDRESS')),
1010
'from_name' => env('MFA_EMAIL_FROM_NAME', env('MAIL_FROM_NAME', 'Laravel')),
1111
'subject' => env('MFA_EMAIL_SUBJECT', 'Your verification code'),
1212
'channel' => env('MFA_EMAIL_CHANNEL', \CodingLibs\MFA\Channels\EmailChannel::class),
1313
],
1414

1515
'sms' => [
16-
'enabled' => env('MFA_SMS_ENABLED', true),
16+
'enabled' => (bool)env('MFA_SMS_ENABLED', true),
1717
'driver' => env('MFA_SMS_DRIVER', 'log'), // log|null
1818
'from' => env('MFA_SMS_FROM', ''),
1919
'channel' => env('MFA_SMS_CHANNEL', \CodingLibs\MFA\Channels\SmsChannel::class),
@@ -27,7 +27,7 @@
2727
],
2828

2929
'remember' => [
30-
'enabled' => env('MFA_REMEMBER_ENABLED', true),
30+
'enabled' => (bool)env('MFA_REMEMBER_ENABLED', true),
3131
'cookie' => env('MFA_REMEMBER_COOKIE', 'mfa_rd'),
3232
'lifetime_days' => (int)env('MFA_REMEMBER_LIFETIME_DAYS', 30),
3333
'path' => env('MFA_REMEMBER_PATH', '/'),
@@ -38,7 +38,7 @@
3838
],
3939

4040
'recovery' => [
41-
'enabled' => env('MFA_RECOVERY_ENABLED', true),
41+
'enabled' => (bool)env('MFA_RECOVERY_ENABLED', true),
4242
'codes_count' => (int)env('MFA_RECOVERY_CODES_COUNT', 10),
4343
'code_length' => (int)env('MFA_RECOVERY_CODE_LENGTH', 10),
4444
'regenerate_on_use' => env('MFA_RECOVERY_REGENERATE_ON_USE', false),

src/Facades/MFA.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
* @method static bool verifyRecoveryCode(\Illuminate\Contracts\Auth\Authenticatable $user, string $code)
3838
* @method static int getRemainingRecoveryCodesCount(\Illuminate\Contracts\Auth\Authenticatable $user)
3939
* @method static int clearRecoveryCodes(\Illuminate\Contracts\Auth\Authenticatable $user)
40+
* @method static array getEnabledChannels(\Illuminate\Contracts\Auth\Authenticatable $user)
4041
*
4142
* @mixin \CodingLibs\MFA\MFA
4243
* @see \CodingLibs\MFA\MFA

src/MFA.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,5 +561,46 @@ protected function hashRecoveryCode(string $code): string
561561
$algo = (string) Arr::get($this->config, 'recovery.hash_algo', 'sha256');
562562
return hash($algo, $code);
563563
}
564+
565+
/**
566+
* Get all channels that are enabled both by the client and by configuration.
567+
*
568+
* @param Authenticatable $user The user to check enabled methods for
569+
* @return array<string, MfaChannel> Array of channel name => channel instance
570+
*/
571+
public function getEnabledChannels(Authenticatable $user): array
572+
{
573+
$enabledChannels = [];
574+
575+
foreach ($this->registry->all() as $name => $channel) {
576+
// Check if channel is enabled in config
577+
$configEnabled = $this->isChannelEnabledInConfig($name);
578+
579+
// Check if method is enabled by client
580+
$clientEnabled = $this->isEnabled($user, $name);
581+
582+
if ($configEnabled && $clientEnabled) {
583+
$enabledChannels[$name] = $channel;
584+
}
585+
}
586+
587+
return $enabledChannels;
588+
}
589+
590+
/**
591+
* Check if a channel is enabled in the configuration.
592+
*
593+
* @param string $channelName The channel name to check
594+
* @return bool True if the channel is enabled in config
595+
*/
596+
protected function isChannelEnabledInConfig(string $channelName): bool
597+
{
598+
$channelName = strtolower($channelName);
599+
600+
// Check if the channel has an 'enabled' property in config
601+
$enabled = Arr::get($this->config, "{$channelName}.enabled", true);
602+
603+
return (bool) $enabled;
604+
}
564605
}
565606

tests/Feature/MFATest.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,61 @@ public function send(Authenticatable $user, string $code, array $options = []):
161161
expect($skipAgain)->toBeFalse();
162162
});
163163

164+
it('returns only channels enabled by both client and config', function () {
165+
$user = new MFATestFakeUser(2001, 'user@example.com');
166+
$mfa = app(MFA::class);
167+
168+
// Initially, no channels should be enabled by client
169+
$enabledChannels = $mfa->getEnabledChannels($user);
170+
expect($enabledChannels)->toBeEmpty();
171+
172+
// Enable email method for the user
173+
$mfa->enableMethod($user, 'email');
174+
175+
// Now email should be in enabled channels (if config allows it)
176+
$enabledChannels = $mfa->getEnabledChannels($user);
177+
expect($enabledChannels)->toHaveKey('email');
178+
expect($enabledChannels['email'])->toBeInstanceOf(MfaChannel::class);
179+
180+
// Enable SMS method for the user
181+
$mfa->enableMethod($user, 'sms');
182+
183+
// Now both email and sms should be in enabled channels (if config allows them)
184+
$enabledChannels = $mfa->getEnabledChannels($user);
185+
expect($enabledChannels)->toHaveKeys(['email', 'sms']);
186+
expect($enabledChannels['email'])->toBeInstanceOf(MfaChannel::class);
187+
expect($enabledChannels['sms'])->toBeInstanceOf(MfaChannel::class);
188+
189+
// Disable email method for the user
190+
$mfa->disableMethod($user, 'email');
191+
192+
// Now only sms should be in enabled channels
193+
$enabledChannels = $mfa->getEnabledChannels($user);
194+
expect($enabledChannels)->not->toHaveKey('email');
195+
expect($enabledChannels)->toHaveKey('sms');
196+
expect($enabledChannels['sms'])->toBeInstanceOf(MfaChannel::class);
197+
});
198+
199+
it('excludes channels disabled in config even if enabled by client', function () {
200+
$user = new MFATestFakeUser(2002, 'user@example.com');
201+
202+
// Create MFA instance with custom config where email is disabled
203+
$config = config('mfa');
204+
$config['email']['enabled'] = false;
205+
$mfa = new MFA($config);
206+
207+
// Enable email method for the user
208+
$mfa->enableMethod($user, 'email');
209+
210+
// Email should not be in enabled channels because it's disabled in config
211+
$enabledChannels = $mfa->getEnabledChannels($user);
212+
expect($enabledChannels)->not->toHaveKey('email');
213+
214+
// But SMS should still be there if enabled in config and by client
215+
$mfa->enableMethod($user, 'sms');
216+
$enabledChannels = $mfa->getEnabledChannels($user);
217+
expect($enabledChannels)->toHaveKey('sms');
218+
expect($enabledChannels)->not->toHaveKey('email');
219+
});
220+
164221

0 commit comments

Comments
 (0)