feat: add app and database modules
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Helpers\ApiResponse;
|
||||
use App\Mail\TwoFactorOtp;
|
||||
use App\Services\Auth\OtpService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
class OtpController extends Controller
|
||||
{
|
||||
public function __construct(protected OtpService $otpService) {}
|
||||
|
||||
#[OA\Post(
|
||||
path: '/v1/otp/send',
|
||||
operationId: 'otpSend',
|
||||
tags: ['OTP'],
|
||||
summary: 'Send a 6-digit OTP to the given email',
|
||||
requestBody: new OA\RequestBody(
|
||||
required: true,
|
||||
content: new OA\JsonContent(
|
||||
required: ['email'],
|
||||
properties: [new OA\Property(property: 'email', type: 'string', format: 'email')]
|
||||
)
|
||||
),
|
||||
responses: [
|
||||
new OA\Response(response: 200, description: 'OTP sent'),
|
||||
new OA\Response(response: 500, description: 'Mail delivery failed'),
|
||||
]
|
||||
)]
|
||||
public function send(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'email' => 'required|email',
|
||||
]);
|
||||
|
||||
$email = $request->email;
|
||||
$code = $this->otpService->generate($email);
|
||||
|
||||
try {
|
||||
Mail::to($email)->send(new TwoFactorOtp(
|
||||
otp: $code,
|
||||
ipAddress: $request->ip(),
|
||||
userAgent: $request->userAgent(),
|
||||
));
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('OTP send failed', ['email' => $email, 'error' => $e->getMessage()]);
|
||||
|
||||
return ApiResponse::serverError('Failed to send OTP. Please try again later.');
|
||||
}
|
||||
|
||||
return ApiResponse::success(null, 'OTP has been sent to your email');
|
||||
}
|
||||
|
||||
#[OA\Post(
|
||||
path: '/v1/otp/verify',
|
||||
operationId: 'otpVerify',
|
||||
tags: ['OTP'],
|
||||
summary: 'Verify an OTP code',
|
||||
requestBody: new OA\RequestBody(
|
||||
required: true,
|
||||
content: new OA\JsonContent(
|
||||
required: ['email', 'code'],
|
||||
properties: [
|
||||
new OA\Property(property: 'email', type: 'string', format: 'email'),
|
||||
new OA\Property(property: 'code', type: 'string', minLength: 6, maxLength: 6, example: '123456'),
|
||||
]
|
||||
)
|
||||
),
|
||||
responses: [
|
||||
new OA\Response(response: 200, description: 'OTP verified'),
|
||||
new OA\Response(response: 422, description: 'Invalid or expired OTP'),
|
||||
]
|
||||
)]
|
||||
public function verify(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'email' => 'required|email',
|
||||
'code' => 'required|string|size:6',
|
||||
]);
|
||||
|
||||
if (! $this->otpService->verify($request->input('email'), $request->input('code'))) {
|
||||
return ApiResponse::error('Invalid or expired OTP code', 422);
|
||||
}
|
||||
|
||||
return ApiResponse::success(null, 'OTP verified successfully');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user