Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for additional otp parameters #25

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions src/Events/OtpPrepared.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,21 @@
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Salehhashemi\OtpManager\Contracts\OtpTypeInterface;

class OtpPrepared
{
use Dispatchable, InteractsWithSockets, SerializesModels;

public string $mobile;

public string $code;

/**
* Create a new event instance.
*
* @return void
* @param array<string, string> $params
*/
public function __construct(string $mobile, string $code)
{
$this->mobile = $mobile;
$this->code = $code;
}
public function __construct(
public readonly string $mobile,
public readonly string $code,
public readonly ?OtpTypeInterface $type,
public readonly array $params,
) {}
}
4 changes: 2 additions & 2 deletions src/Facade/OtpManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
use Salehhashemi\OtpManager\Dto\SentOtpDto;

/**
* @method static SentOtpDto send(string $mobile, OtpTypeInterface $type = null)
* @method static SentOtpDto sendAndRetryCheck(string $mobile, OtpTypeInterface $type = null)
* @method static SentOtpDto send(string $mobile, OtpTypeInterface $type = null, array $params = [])
* @method static SentOtpDto sendAndRetryCheck(string $mobile, OtpTypeInterface $type = null, array $params = [])
* @method static bool verify(string $mobile, int $otp, string $trackingCode, OtpTypeInterface $type = null)
* @method static OtpDto|null getVerifyCode(string $mobile, OtpTypeInterface $type = null)
* @method static bool deleteVerifyCode(string $mobile, OtpTypeInterface $type = null)
Expand Down
17 changes: 12 additions & 5 deletions src/OtpManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ public function __construct()
*
* @param string $mobile The mobile number to which the OTP should be sent.
* @param \Salehhashemi\OtpManager\Contracts\OtpTypeInterface|null $type The type or category of OTP being sent (e.g., 'login', 'reset_password').
* @param array<string, string> $params Additional parameters that can be passed to the OTP event.
* @return \Salehhashemi\OtpManager\Dto\SentOtpDto An object containing details of the sent OTP.
*
* @throws \Exception If the OTP generation fails or any other exception occurs.
*/
public function send(string $mobile, ?OtpTypeInterface $type = null): SentOtpDto
public function send(string $mobile, ?OtpTypeInterface $type = null, array $params = []): SentOtpDto
{
$this->validateMobile($mobile);

Expand All @@ -54,7 +55,12 @@ public function send(string $mobile, ?OtpTypeInterface $type = null): SentOtpDto

$otp = new SentOtpDto($this->getNewCode($mobile), $this->waitingTime, $this->trackingCode);

event(new OtpPrepared(mobile: $mobile, code: (string) $otp->code));
event(new OtpPrepared(
mobile: $mobile,
code: (string) $otp->code,
type: $type,
params: $params,
));

return $otp;
}
Expand All @@ -67,24 +73,25 @@ public function send(string $mobile, ?OtpTypeInterface $type = null): SentOtpDto
*
* @param string $mobile The mobile number to which the OTP should be resent.
* @param \Salehhashemi\OtpManager\Contracts\OtpTypeInterface|null $type The type or category of OTP being sent (e.g., 'login', 'reset_password').
* @param array<string, string> $params Additional parameters that can be passed to the OTP event.
* @return \Salehhashemi\OtpManager\Dto\SentOtpDto An object containing details of the sent OTP.
*
* @throws \Exception If any other exception occurs.
*/
public function sendAndRetryCheck(string $mobile, ?OtpTypeInterface $type = null): SentOtpDto
public function sendAndRetryCheck(string $mobile, ?OtpTypeInterface $type = null, array $params = []): SentOtpDto
{
$this->validateMobile($mobile);

$this->type = $type;

$created = $this->getSentAt($mobile, $type);
if (! $created) {
return $this->send($mobile, $type);
return $this->send($mobile, $type, $params);
}

$retryAfter = $created->addSeconds($this->waitingTime);
if (Carbon::now()->greaterThan($retryAfter)) {
return $this->send($mobile, $type);
return $this->send($mobile, $type, $params);
}

$remainingTime = (int) Carbon::now()->diffInSeconds($retryAfter);
Expand Down
24 changes: 12 additions & 12 deletions tests/OtpManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function test_send_function_sends_otp()
{
Event::fake();

$otpManager = new OtpManager();
$otpManager = new OtpManager;
$sentOtp = $otpManager->send('1234567890', MyOtpEnum::SIGNUP);

$this->assertNotNull($sentOtp);
Expand All @@ -37,7 +37,7 @@ public function test_send_function_sends_otp()

public function test_verify_function_verifies_otp()
{
$otpManager = new OtpManager();
$otpManager = new OtpManager;
$sentOtp = $otpManager->send('1234567890', MyOtpEnum::SIGNUP);

$isVerified = $otpManager->verify('1234567890', $sentOtp->code, $sentOtp->trackingCode, MyOtpEnum::SIGNUP);
Expand All @@ -47,7 +47,7 @@ public function test_verify_function_verifies_otp()

public function test_verify_function_verifies_otp_without_type()
{
$otpManager = new OtpManager();
$otpManager = new OtpManager;
$sentOtp = $otpManager->send('1234567890');

$isVerified = $otpManager->verify('1234567890', $sentOtp->code, $sentOtp->trackingCode);
Expand All @@ -57,7 +57,7 @@ public function test_verify_function_verifies_otp_without_type()

public function test_delete_function_deletes_otp()
{
$otpManager = new OtpManager();
$otpManager = new OtpManager;
$otpManager->send('1234567890', MyOtpEnum::SIGNUP);

$otpManager->deleteVerifyCode('1234567890', MyOtpEnum::SIGNUP);
Expand All @@ -72,13 +72,13 @@ public function test_send_function_fails_for_empty_mobile()
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Mobile number cannot be empty.');

$otpManager = new OtpManager();
$otpManager = new OtpManager;
$otpManager->send('', MyOtpEnum::SIGNUP);
}

public function test_verify_function_fails_for_wrong_code()
{
$otpManager = new OtpManager();
$otpManager = new OtpManager;
$sentOtp = $otpManager->send('1234567890', MyOtpEnum::SIGNUP);

$isVerified = $otpManager->verify('1234567890', 1, $sentOtp->trackingCode, MyOtpEnum::SIGNUP);
Expand All @@ -88,7 +88,7 @@ public function test_verify_function_fails_for_wrong_code()

public function test_verify_function_fails_for_wrong_tracking_code()
{
$otpManager = new OtpManager();
$otpManager = new OtpManager;
$sentOtp = $otpManager->send('1234567890', MyOtpEnum::SIGNUP);

$isVerified = $otpManager->verify('1234567890', $sentOtp->code, 'wrongTrackingCode', MyOtpEnum::SIGNUP);
Expand All @@ -98,7 +98,7 @@ public function test_verify_function_fails_for_wrong_tracking_code()

public function test_getSentAt_returns_correct_time()
{
$otpManager = new OtpManager();
$otpManager = new OtpManager;
$otpManager->send('1234567890', MyOtpEnum::SIGNUP);

$sentAt = $otpManager->getSentAt('1234567890', MyOtpEnum::SIGNUP);
Expand All @@ -108,7 +108,7 @@ public function test_getSentAt_returns_correct_time()

public function test_isVerifyCodeHasBeenSent_returns_true()
{
$otpManager = new OtpManager();
$otpManager = new OtpManager;
$otpManager->send('1234567890', MyOtpEnum::SIGNUP);

$isSent = $otpManager->isVerifyCodeHasBeenSent('1234567890', MyOtpEnum::SIGNUP);
Expand All @@ -118,7 +118,7 @@ public function test_isVerifyCodeHasBeenSent_returns_true()

public function test_sendAndRetryCheck_throws_validation_exception_for_quick_retry()
{
$otpManager = new OtpManager();
$otpManager = new OtpManager;
$otpManager->send('1234567890', MyOtpEnum::SIGNUP);

$this->expectException(ValidationException::class);
Expand All @@ -128,7 +128,7 @@ public function test_sendAndRetryCheck_throws_validation_exception_for_quick_ret

public function test_verify_function_fails_after_exceeding_max_attempts_and_advises_new_otp_request()
{
$otpManager = new OtpManager();
$otpManager = new OtpManager;

// Adjust the configuration for maximum verification attempts to 1 for the test.
config(['otp.max_verify_attempts' => 1]);
Expand Down Expand Up @@ -161,7 +161,7 @@ public function test_verify_function_fails_after_exceeding_max_attempts_and_advi

public function test_attempts_reset_after_successful_verification()
{
$otpManager = new OtpManager();
$otpManager = new OtpManager;
config(['otp.max_verify_attempts' => 2]);

// Send and verify OTP successfully
Expand Down
7 changes: 3 additions & 4 deletions tests/OtpRateLimiterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,13 @@ public function test_middleware_blocks_requests_above_limit()

$request = Request::create('/', 'GET', ['REMOTE_ADDR' => '127.0.0.1']);

$middleware = new OtpRateLimiter();
$middleware = new OtpRateLimiter;

$this->expectException(TooManyRequestsHttpException::class);

// Trigger middleware multiple times to exceed the limit
for ($i = 0; $i < 5; $i++) {
$response = $middleware->handle($request, function () {
});
$response = $middleware->handle($request, function () {});
}
}

Expand All @@ -41,7 +40,7 @@ public function test_middleware_does_not_block_requests_below_limit()

$request = Request::create('/', 'GET', ['REMOTE_ADDR' => '127.0.0.1']);

$middleware = new OtpRateLimiter();
$middleware = new OtpRateLimiter;

for ($i = 0; $i < 2; $i++) {
$response = $middleware->handle($request, function () {
Expand Down
Loading