Skip to content

Commit

Permalink
fixed some code styles
Browse files Browse the repository at this point in the history
  • Loading branch information
samuraee committed Jan 16, 2025
1 parent 078338c commit d90dc8f
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 66 deletions.
21 changes: 11 additions & 10 deletions config/otp.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

/**
* ██████╗ ██╗ ██╗██████╗ ███╗ ███╗ ██████╗ ███╗ ██╗███████╗████████╗███████╗██████╗ ███████╗
* ██╔══██╗██║ ██║██╔══██╗ ████╗ ████║██╔═══██╗████╗ ██║██╔════╝╚══██╔══╝██╔════╝██╔══██╗██╔════╝
Expand All @@ -10,7 +11,7 @@
*/
return [

/*
/*
* The format option allows you to decide
* which generator implementation to be used when
* generating new passwords.
Expand All @@ -30,25 +31,25 @@

'customize' => '123456789ABCDEFG@#$%',

/*
/*
* The length of the password.
*/

'length' => env('OTP_LENGTH', 6),
'length' => env('OTP_LENGTH', 6),

/*
* The separator of the password.
*/

'separator' => '-',

/*
/*
* Requiring correct input of uppercase and lowercase letters.
*/

'sensitive' => env('OTP_SENSITIVE', false),
'sensitive' => env('OTP_SENSITIVE', false),

/*
/*
* The expiry time of the password in minutes.
*/

Expand All @@ -60,7 +61,7 @@

'attempts' => env('OTP_ATTEMPT_TIMES', 5),

/*
/*
* The repeated password.
* The previous password is valid when new password generated
* until either one password used or itself expired.
Expand All @@ -75,7 +76,7 @@

'disposable' => true,

/*
/*
* The prefix of the cache key to be used to store.
*/

Expand All @@ -86,6 +87,6 @@
*/

'demo' => env('OTP_DEMO', false),
'demo_passwords' => ['1234','123456','12345678']
'demo_passwords' => ['1234', '123456', '12345678'],

];
];
8 changes: 4 additions & 4 deletions resources/lang/en/messages.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php

return [
'invalid' => 'The :attribute is not a valid code.',
'expired' => 'The :attribute is expired.',
'max_attempt' => 'The :attribute reached the maximum allowed attempts.',
];
'invalid' => 'The :attribute is not a valid code.',
'expired' => 'The :attribute is expired.',
'max_attempt' => 'The :attribute reached the maximum allowed attempts.',
];
124 changes: 83 additions & 41 deletions src/Otp.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,117 +4,150 @@

use Exception;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Facade;
use Illuminate\Support\Str;
use Illuminate\Foundation\Application;

class Otp
{
private string $format = 'numeric';

private string $customize;

private int $length = 6;

private string $separator = '-';

private bool $sensitive = false;

private int $expires = 15;

private int $attempts = 5;

private bool $repeated = true;

private bool $disposable = true;

private string $prefix = 'OTPPX_';

private $data;

private bool $skip = false;

private bool $demo = false;

private array $demo_passwords = ['1234', '123456', '12345678'];

public function __construct()
{
foreach (['format', 'customize', 'length', 'separator', 'sensitive', 'expires', 'attempts', 'repeated', 'disposable', 'prefix', 'data', 'demo', 'demo_passwords'] as $value) {
if (!empty(config('otp.' . $value))) $this->{$value} = config('otp.' . $value);
if (! empty(config('otp.'.$value))) {
$this->{$value} = config('otp.'.$value);
}
}
}

public function __call(string $method, $params)
{
if (!str_starts_with($method, 'set')) {
if (! str_starts_with($method, 'set')) {
return;
}

$property = Str::camel(substr($method, 3));
if (!property_exists($this, $property)) {
if (! property_exists($this, $property)) {
return;
}

$this->{$property} = $params[0] ?? null;
if ($property == 'customize') {
$this->format = 'customize';
}

return $this;
}

/**
* @throws Exception
*/
public function generate(string $identifier = null, array $options = []): string
public function generate(?string $identifier = null, array $options = []): string
{
if (!empty($options)) foreach (['format', 'customize', 'length', 'separator', 'sensitive', 'expires', 'repeated', 'prefix', 'data'] as $value) {
if (isset($options[$value])) $this->{$value} = $options[$value];
if (! empty($options)) {
foreach (['format', 'customize', 'length', 'separator', 'sensitive', 'expires', 'repeated', 'prefix', 'data'] as $value) {
if (isset($options[$value])) {
$this->{$value} = $options[$value];
}
}
}

if ($identifier === null) $identifier = session()->getId();
if ($identifier === null) {
$identifier = session()->getId();
}
$array = $this->repeated ? $this->readData($identifier, []) : [];
$password = $this->generateNewPassword();
if (!$this->sensitive) $password = strtoupper($password);
if (! $this->sensitive) {
$password = strtoupper($password);
}
$array[md5($password)] = [
'expires' => time() + $this->expires * 60,
'data' => $this->data
'data' => $this->data,
];
$this->writeData($identifier, $array);

return $password;
}

public function validate(string $identifier = null, string $password = null, array $options = []): object
public function validate(?string $identifier = null, ?string $password = null, array $options = []): object
{
if (!empty($options)) foreach (['attempts', 'sensitive', 'disposable', 'skip'] as $value) {
if (isset($options[$value])) $this->{$value} = $options[$value];
if (! empty($options)) {
foreach (['attempts', 'sensitive', 'disposable', 'skip'] as $value) {
if (isset($options[$value])) {
$this->{$value} = $options[$value];
}
}
}

if ($password === null) {
if ($identifier === null) {
throw new Exception("Validate parameter can not be null");
throw new Exception('Validate parameter can not be null');
}
$password = $identifier;
$identifier = null;
}

if ($this->demo && in_array($password, $this->demo_passwords)) {
return (object)[
return (object) [
'status' => true,
'demo' => true
'demo' => true,
];
}

if ($identifier === null) $identifier = session()->getId();
$attempt = $this->readData('_attempt_' . $identifier, 0);
if ($identifier === null) {
$identifier = session()->getId();
}
$attempt = $this->readData('_attempt_'.$identifier, 0);
if ($attempt >= $this->attempts) {
return (object)[
return (object) [
'status' => false,
'error' => 'max_attempt',
];
}

$codes = $this->readData($identifier, []);
if (!$this->sensitive) $password = strtoupper($password);
if (! $this->sensitive) {
$password = strtoupper($password);
}

if (! isset($codes[md5($password)])) {
$this->writeData('_attempt_'.$identifier, $attempt + 1);

if (!isset($codes[md5($password)])) {
$this->writeData('_attempt_' . $identifier, $attempt + 1);
return (object)[
return (object) [
'status' => false,
'error' => 'invalid',
];
}

if (time() > $codes[md5($password)]['expires']) {
$this->writeData('_attempt_' . $identifier, $attempt + 1);
return (object)[
$this->writeData('_attempt_'.$identifier, $attempt + 1);

return (object) [
'status' => false,
'error' => 'expired',
];
Expand All @@ -124,37 +157,46 @@ public function validate(string $identifier = null, string $password = null, arr
'status' => true,
];

if (!empty($codes[md5($password)]['data'])) {
if (! empty($codes[md5($password)]['data'])) {
$response['data'] = $codes[md5($password)]['data'];
}

if (!$this->skip) $this->forget($identifier, !$this->disposable ? $password : null);
if (! $this->skip) {
$this->forget($identifier, ! $this->disposable ? $password : null);
}
$this->resetAttempt($identifier);

return (object)$response;
return (object) $response;
}

public function forget(string $identifier = null, string $password = null): bool
public function forget(?string $identifier = null, ?string $password = null): bool
{
if ($identifier === null) $identifier = session()->getId();
if ($identifier === null) {
$identifier = session()->getId();
}
if ($password !== null) {
$codes = $this->readData($identifier, []);
if (!isset($codes[md5($password)])) {
if (! isset($codes[md5($password)])) {
return false;
}
unset($codes[md5($password)]);
$this->writeData($identifier, $codes);

return true;
}

$this->deleteData($identifier);

return true;
}

public function resetAttempt(string $identifier = null): bool
public function resetAttempt(?string $identifier = null): bool
{
if ($identifier === null) $identifier = session()->getId();
$this->deleteData('_attempt_' . $identifier);
if ($identifier === null) {
$identifier = session()->getId();
}
$this->deleteData('_attempt_'.$identifier);

return true;
}

Expand All @@ -168,7 +210,7 @@ private function generateNewPassword(): string
'string' => $this->sensitive ? '23456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ' : '23456789ABCDEFGHJKLMNPQRSTUVWXYZ',
'numeric' => '0123456789',
'numeric-no-zero' => '123456789',
'customize' => $this->customize
'customize' => $this->customize,
];

$lengths = is_array($this->length) ? $this->length : [$this->length];
Expand All @@ -180,22 +222,22 @@ private function generateNewPassword(): string

return implode($this->separator, $password);
} catch (Exception) {
throw new Exception("Fail to generate password, please check the format is correct.");
throw new Exception('Fail to generate password, please check the format is correct.');
}
}

private function writeData(string $key, mixed $value): void
{
Cache::put($this->prefix . $key, $value, $this->expires * 60 * 3);
Cache::put($this->prefix.$key, $value, $this->expires * 60 * 3);
}

private function readData(string $key, mixed $default = null): mixed
{
return Cache::get($this->prefix . $key, $default);
return Cache::get($this->prefix.$key, $default);
}

private function deleteData(string $key): void
{
Cache::forget($this->prefix . $key);
Cache::forget($this->prefix.$key);
}
}
}
4 changes: 1 addition & 3 deletions src/OtpFacade.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ class OtpFacade extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor(): string
{
return 'otp';
}
}
}
8 changes: 4 additions & 4 deletions src/OtpServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

namespace PhpMonsters\Otp;

use Illuminate\Support\ServiceProvider;
use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider;

class OtpServiceProvider extends ServiceProvider
{
Expand All @@ -25,10 +25,10 @@ public function register()
public function boot()
{
$this->loadTranslationsFrom(__DIR__.'/../lang', 'otp');

$this->publishes([
__DIR__.'/../resources/lang' => $this->app->langPath('vendor/otp'),
__DIR__.'/../config/otp.php' => config_path('otp.php')
__DIR__.'/../config/otp.php' => config_path('otp.php'),
]);
}
}
}
Loading

0 comments on commit d90dc8f

Please sign in to comment.