268 lines
12 KiB
Ruby
268 lines
12 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module API::V2
|
|
module Resource
|
|
class Phones < Grape::API
|
|
rescue_from(Twilio::REST::RestError) do |error|
|
|
Rails.logger.error "Twilio Client Error: #{error.message}"
|
|
error!({ errors: [twilio_dictionary_error(error.code)] }, 422)
|
|
end
|
|
|
|
helpers do
|
|
def validate_phone!(phone_number, landline = nil)
|
|
phone_number = Phone.international(phone_number)
|
|
|
|
error!({ errors: ['resource.phone.invalid_num'] }, 400) \
|
|
unless Phone.valid?(phone_number)
|
|
|
|
error!({ errors: ['resource.phone.number_exist'] }, 400) \
|
|
if Phone.verified.find_by_number(phone_number) && landline.blank?
|
|
|
|
# check phone is landline
|
|
error!({ errors: ['resource.phone.number_not_landline'] }, 400) \
|
|
if landline.present? && phone_number[2] == '9'
|
|
end
|
|
end
|
|
|
|
desc 'mobile related routes'
|
|
resource :mobiles do
|
|
desc 'Returns list of user\'s phones',
|
|
failure: [
|
|
{ code: 401, message: 'Invalid bearer token' },
|
|
],
|
|
success: Entities::Phone
|
|
get do
|
|
present current_user.phones, with: Entities::Phone
|
|
end
|
|
|
|
desc 'Add new mobile',
|
|
failure: [
|
|
{ code: 400, message: 'Required params are empty' },
|
|
{ code: 401, message: 'Invalid bearer token' },
|
|
{ code: 404, message: 'Record is not found' },
|
|
{ code: 422, message: 'Validation errors' }
|
|
],
|
|
success: { code: 200, message: 'New phone was added' }
|
|
params do
|
|
requires :phone_number,
|
|
type: String,
|
|
allow_blank: false,
|
|
desc: 'Phone number with country code(in iran +98)'
|
|
optional :channel,
|
|
type: String,
|
|
default: 'sms',
|
|
values: { value: -> { Phone::TWILIO_CHANNELS }, message: 'resource.phone.invalid_channel'},
|
|
desc: 'The verification method to use(this param is for legacy structure must be sms)'
|
|
end
|
|
post do
|
|
error!({ errors: ['kyc_follow_steps'] }, 403) if current_user.kyc_info.dig(:step) < 2
|
|
|
|
error!({ errors: ['resource.phone.code_doesnt_expired'] }, 422) if current_user.read_cache('register-mobile')
|
|
declared_params = declared(params)
|
|
validate_phone!(declared_params[:phone_number])
|
|
phone_number = Phone.international(declared_params[:phone_number])
|
|
# label = current_user.labels.find_by(key: 'access_phone', value: 'verified')
|
|
# error!({ errors: ['resource.phone.exists'] }, 422) if label.present?
|
|
if current_user.mobile('pending').present?
|
|
current_user.mobile('pending').update(number: phone_number)
|
|
else
|
|
current_user.phones.create(number: phone_number, category: 'mobile')
|
|
end
|
|
# code_error!(phone.errors.details, 422) if phone.errors.any?
|
|
error!({ errors: ['resource.phone.cant_send_message'] }, 422) unless KaveNegarSmsService.send_confirmation(current_user)
|
|
status 200
|
|
end
|
|
|
|
desc 'Resend activation code for mobile sms',
|
|
failure: [
|
|
{ code: 400, message: 'Required params are empty' },
|
|
{ code: 401, message: 'Invalid bearer token' },
|
|
{ code: 404, message: 'Record is not found' },
|
|
{ code: 422, message: 'Validation errors' }
|
|
],
|
|
success: { code: 200, message: 'Activation code was resend' }
|
|
params do
|
|
requires :phone_number,
|
|
type: String,
|
|
allow_blank: false,
|
|
desc: 'Phone number with country code( in iran +98 )'
|
|
optional :channel,
|
|
type: String,
|
|
default: 'sms',
|
|
values: { value: -> { Phone::TWILIO_CHANNELS }, message: 'resource.phone.invalid_channel'},
|
|
desc: 'The verification method to use(this param is for legacy structure must be sms)'
|
|
end
|
|
# TODO you can delete this api and use above
|
|
post '/send_code' do
|
|
error!({ errors: ['resource.phone.code_doesnt_expired'] }, 422) if current_user.read_cache('register-mobile')
|
|
declared_params = declared(params)
|
|
validate_phone!(declared_params[:phone_number])
|
|
|
|
phone_number = Phone.international(declared_params[:phone_number])
|
|
phone = current_user.phones.find_by_number(phone_number)
|
|
error!({ errors: ['resource.phone.doesnt_exist'] }, 404) unless phone
|
|
|
|
KaveNegarSmsService.send_confirmation(current_user)
|
|
status 200
|
|
end
|
|
|
|
desc 'Verify a mobile(enter code and verify number)',
|
|
failure: [
|
|
{ code: 400, message: 'Required params are empty' },
|
|
{ code: 401, message: 'Invalid bearer token' },
|
|
{ code: 404, message: 'Record is not found' }
|
|
],
|
|
success: API::V2::Entities::UserWithFullInfo
|
|
params do
|
|
requires :phone_number,
|
|
type: String,
|
|
allow_blank: false,
|
|
desc: 'phone number with country code(in iran with +98)'
|
|
requires :verification_code,
|
|
type: String,
|
|
allow_blank: false,
|
|
desc: 'Verification code from sms(this param is for legacy structure must be sms)'
|
|
end
|
|
post '/verify' do
|
|
declared_params = declared(params)
|
|
validate_phone!(declared_params[:phone_number])
|
|
error!({ errors: ['resource.phone.doesnt_exist'] }, 404) unless current_user.mobile('pending')
|
|
|
|
unless TOTPServiceAction.new('register-mobile').validate?(current_user.uid, declared(params)[:verification_code])
|
|
error!({ errors: ['resource.phone.verification_invalid'] }, 400)
|
|
end
|
|
current_user.delete_cache('register-mobile')
|
|
pending_mobile = current_user.mobile('pending')
|
|
last_verified_mobile = current_user.mobile('verified')
|
|
if last_verified_mobile&.step == 'owner_phone'
|
|
if pending_mobile.check_owner_ship
|
|
last_verified_mobile.update(state: 'replaced')
|
|
pending_mobile.update(validated_at: Time.current, state: 'verified', step: 'owner_phone')
|
|
else
|
|
pending_mobile.update(state: 'rejected')
|
|
end
|
|
elsif last_verified_mobile&.step == 'access_phone'
|
|
last_verified_mobile.update(state: 'replaced')
|
|
pending_mobile.update(validated_at: Time.current, step: 'access_phone', state: 'verified')
|
|
else
|
|
pending_mobile.update(validated_at: Time.current, step: 'access_phone', state: 'verified')
|
|
end
|
|
|
|
|
|
present current_user, with: API::V2::Entities::UserWithFullInfo
|
|
end
|
|
end
|
|
|
|
|
|
desc 'landline related routes'
|
|
resource :phones do
|
|
|
|
desc 'Add new phone',
|
|
failure: [
|
|
{ code: 400, message: 'Required params are empty' },
|
|
{ code: 401, message: 'Invalid bearer token' },
|
|
{ code: 404, message: 'Record is not found' },
|
|
{ code: 422, message: 'Validation errors' }
|
|
],
|
|
success: { code: 200, message: 'New phone was added' }
|
|
params do
|
|
requires :phone_number,
|
|
type: String,
|
|
allow_blank: false,
|
|
desc: 'Phone number with country code(in iran +98)'
|
|
optional :channel,
|
|
type: String,
|
|
default: 'call',
|
|
values: { value: -> { Phone::TWILIO_CHANNELS }, message: 'resource.phone.invalid_channel'},
|
|
desc: 'The verification method to use'
|
|
end
|
|
post do
|
|
error!({ errors: ['resource.phone.code_doesnt_expired'] }, 422) if current_user.read_cache('register-phone')
|
|
|
|
error!({ errors: ['kyc_follow_steps'] }, 403) if current_user.kyc_info.dig(:step) < 6
|
|
|
|
declared_params = declared(params)
|
|
validate_phone!(declared_params[:phone_number], true)
|
|
phone_number = Phone.international(declared_params[:phone_number])
|
|
phone = current_user.phones.find_by(category: :landline, step: 'telephone', state: 'pending')
|
|
label = current_user.labels.find_by(key: 'telephone', value: 'verified')
|
|
# TODO can edit for updating feature
|
|
error!({ errors: ['resource.phone.exists'] }, 422) if label.present?
|
|
|
|
if phone.present?
|
|
phone.update(number: phone_number)
|
|
else
|
|
current_user.phones.create(number: phone_number, category: :landline, step: 'telephone')
|
|
end
|
|
# code_error!(phone.errors.details, 422) if phone.errors.any?
|
|
KaveNegarSmsService.send_call_confirmation(current_user)
|
|
end
|
|
|
|
desc 'Resend activation code in call',
|
|
failure: [
|
|
{ code: 400, message: 'Required params are empty' },
|
|
{ code: 401, message: 'Invalid bearer token' },
|
|
{ code: 404, message: 'Record is not found' },
|
|
{ code: 422, message: 'Validation errors' }
|
|
],
|
|
success: { code: 200, message: 'Activation code was resend' }
|
|
params do
|
|
requires :phone_number,
|
|
type: String,
|
|
allow_blank: false,
|
|
desc: 'Phone number with country code'
|
|
optional :channel,
|
|
type: String,
|
|
default: 'call',
|
|
values: { value: -> { Phone::TWILIO_CHANNELS }, message: 'resource.phone.invalid_channel'},
|
|
desc: 'The verification method to use'
|
|
end
|
|
# TODO you can delete this api and use above
|
|
post '/send_code' do
|
|
error!({ errors: ['resource.phone.code_doesnt_expired'] }, 422) if current_user.read_cache('register-phone')
|
|
declared_params = declared(params)
|
|
validate_phone!(declared_params[:phone_number], true)
|
|
|
|
phone_number = Phone.international(declared_params[:phone_number])
|
|
phone = current_user.phones.find_by_number(phone_number)
|
|
error!({ errors: ['resource.phone.doesnt_exist'] }, 404) unless phone
|
|
|
|
KaveNegarSmsService.send_call_confirmation(current_user)
|
|
end
|
|
|
|
|
|
desc 'Verify a phone (enter code and verify number)',
|
|
failure: [
|
|
{ code: 400, message: 'Required params are empty' },
|
|
{ code: 401, message: 'Invalid bearer token' },
|
|
{ code: 404, message: 'Record is not found' }
|
|
],
|
|
success: API::V2::Entities::UserWithFullInfo
|
|
params do
|
|
requires :phone_number,
|
|
type: String,
|
|
allow_blank: false,
|
|
desc: 'Phone number with country code(in iran with +98)'
|
|
requires :verification_code,
|
|
type: String,
|
|
allow_blank: false,
|
|
desc: 'Verification code from call'
|
|
end
|
|
post '/verify' do
|
|
declared_params = declared(params)
|
|
validate_phone!(declared_params[:phone_number], true)
|
|
|
|
# phone_number = Phone.international(declared_params[:phone_number])
|
|
phone = current_user.phones.find_by(step: 'telephone', category: 'landline')
|
|
error!({ errors: ['resource.phone.doesnt_exist'] }, 404) unless phone
|
|
|
|
error!({ errors: ['resource.phone.verification_invalid'] }, 404) unless TOTPServiceAction.new('register-phone').validate?(current_user.uid, declared(params)[:verification_code])
|
|
current_user.delete_cache('register-phone')
|
|
phone.update(validated_at: Time.current, state: 'verified')
|
|
present current_user, with: API::V2::Entities::UserWithFullInfo
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|