completed SMS gateway project
This commit is contained in:
86
app/controllers/api/v1/otp_controller.rb
Normal file
86
app/controllers/api/v1/otp_controller.rb
Normal file
@@ -0,0 +1,86 @@
|
||||
module Api
|
||||
module V1
|
||||
class OtpController < ApplicationController
|
||||
include ApiAuthenticatable
|
||||
include RateLimitable
|
||||
|
||||
# POST /api/v1/otp/send
|
||||
def send_otp
|
||||
phone_number = params.require(:phone_number)
|
||||
purpose = params[:purpose] || "authentication"
|
||||
expiry_minutes = params[:expiry_minutes]&.to_i || 5
|
||||
|
||||
# Rate limit by phone number
|
||||
return unless rate_limit_by_phone!(phone_number, limit: 3, period: 1.hour)
|
||||
|
||||
# Validate phone number
|
||||
phone = Phonelib.parse(phone_number)
|
||||
unless phone.valid?
|
||||
render json: { error: "Invalid phone number format" }, status: :unprocessable_entity
|
||||
return
|
||||
end
|
||||
|
||||
# Send OTP
|
||||
result = OtpCode.send_otp(
|
||||
phone.e164,
|
||||
purpose: purpose,
|
||||
expiry_minutes: expiry_minutes,
|
||||
ip_address: request.remote_ip
|
||||
)
|
||||
|
||||
render json: {
|
||||
success: true,
|
||||
expires_at: result[:otp].expires_at,
|
||||
message_id: result[:sms].message_id
|
||||
}
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
# Rate limit error from OTP model
|
||||
if e.record.errors[:base].any?
|
||||
render json: {
|
||||
error: e.record.errors[:base].first
|
||||
}, status: :too_many_requests
|
||||
else
|
||||
render json: {
|
||||
error: e.message,
|
||||
details: e.record.errors.full_messages
|
||||
}, status: :unprocessable_entity
|
||||
end
|
||||
rescue ActionController::ParameterMissing => e
|
||||
render json: { error: e.message }, status: :bad_request
|
||||
end
|
||||
|
||||
# POST /api/v1/otp/verify
|
||||
def verify
|
||||
phone_number = params.require(:phone_number)
|
||||
code = params.require(:code)
|
||||
|
||||
# Validate phone number
|
||||
phone = Phonelib.parse(phone_number)
|
||||
unless phone.valid?
|
||||
render json: { error: "Invalid phone number format" }, status: :unprocessable_entity
|
||||
return
|
||||
end
|
||||
|
||||
# Verify OTP
|
||||
result = OtpCode.verify(phone.e164, code)
|
||||
|
||||
if result[:success]
|
||||
render json: {
|
||||
success: true,
|
||||
verified: true
|
||||
}
|
||||
else
|
||||
attempts_remaining = 3 - (result[:attempts_remaining] || 0)
|
||||
render json: {
|
||||
success: false,
|
||||
verified: false,
|
||||
error: result[:error],
|
||||
attempts_remaining: [attempts_remaining, 0].max
|
||||
}
|
||||
end
|
||||
rescue ActionController::ParameterMissing => e
|
||||
render json: { error: e.message }, status: :bad_request
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user