This commit is contained in:
2025-10-22 20:08:22 +05:00
commit 736e3bef18
2573 changed files with 120385 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
<?php
return [
'apple_testing_phone' => '61126667',
'apple_testing_code' => 77777,
'min_code' => 10000,
'max_code' => 99999,
'message' => 'Tassyklaýyş belgi: :code',
'validation_message' => 'Tassyklaýyş belgi nädogry.',
'no_username_or_code_message' => 'Telefon belgisi ýa-da tassyklaýyş belgisi ýok.',
];

View File

@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('otp_verifications', function (Blueprint $table) {
$table->id();
$table->string('username');
$table->string('code');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('otp_verifications');
}
};

View File

@@ -0,0 +1,26 @@
<?php
namespace App\Modules\OtpVerification\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
/**
* @property int $id
* @property string $username
* @property string $code
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
*/
class OtpVerification extends Model
{
/**
* The table associated with the model.
*/
protected $table = 'otp_verifications';
/**
* The attributes that are mass assignable.
*/
protected $fillable = ['username', 'code'];
}

View File

@@ -0,0 +1,72 @@
<?php
namespace App\Modules\OtpVerification;
use App\Modules\Core\ModulePackage;
use App\Modules\Core\ModulePackageType;
use App\Modules\Makeable;
use App\Modules\ModuleContract;
class OtpVerificationModule implements ModuleContract
{
use Makeable;
/**
* Module is enabled
*/
protected bool $enabled = true;
/**
* Check if is module enabled
*/
public function isEnabled(): bool
{
return $this->enabled;
}
/**
* Disable module
*/
public function disable(): void
{
$this->enabled = false;
}
/**
* Enable module
*/
public function enable(): void
{
$this->enabled = true;
}
/**
* Check if module has a filament resource
*/
public function hasFilamentResource(): bool
{
return false;
}
/**
* Get module composer requirements
*/
public function getComposerRequirements(): array
{
return [];
}
/**
* Get module composer suggestions
*/
public function getComposerSuggestions(): array
{
return [
new ModulePackage(
type: ModulePackageType::MODULE,
name: 'Sms',
message: 'For sending sms verification codes.',
),
];
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace App\Modules\OtpVerification\Repositories;
use App\Modules\OtpVerification\Models\OtpVerification;
use App\Modules\Sms\Repositories\SmsRepository;
class OtpVerificationRepository
{
/**
* Send a sms verification
*/
public static function sendSMSVerification(string|int $phone_number): ?OtpVerification
{
abort_unless(module('Sms')->isEnabled(), 500, 'Sms module is not enabled');
/* for apple testing */
$phone_code = ($phone_number == config('module.otp-verification.apple_testing_phone'))
? config()->integer('module.otp-verification.apple_testing_code')
: rand(config()->integer('module.otp-verification.min_code'), config()->integer('module.otp-verification.max_code'));
$verification = OtpVerification::where(['username' => $phone_number])->first();
$verification
? $verification->update(['code' => $phone_code])
: OtpVerification::create(['username' => $phone_number, 'code' => $phone_code]);
SmsRepository::sendSMS($phone_number, str_replace(':code', (string) $phone_code, config()->string('module.otp-verification.message')));
return $verification;
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace App\Modules\OtpVerification\Rules;
use App\Modules\OtpVerification\Models\OtpVerification;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class OtpVerificationRule implements ValidationRule
{
public function __construct(
protected null|int|string $username
) {}
/**
* Run the validation rule.
*
* @param \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString $fail
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (! $this->username || ! $value) {
$fail(config()->string('module.otp-verification.no_username_or_code_message'));
return;
}
OtpVerification::query()
->where('username', $this->username)
->where('code', $value)
->firstOr(fn () => $fail(config()->string('module.otp-verification.validation_message')));
}
}

View File

@@ -0,0 +1,12 @@
<?php
use App\Modules\OtpVerification\Models\OtpVerification;
use App\Modules\OtpVerification\Repositories\OtpVerificationRepository;
/**
* Send a sms verification
*/
function sendSMSVerification(string|int $phone_number): ?OtpVerification
{
return OtpVerificationRepository::sendSMSVerification($phone_number);
}