mirror of
https://github.com/neocities/neocities.git
synced 2025-04-24 17:22:35 +02:00
first pass at phone validation
This commit is contained in:
parent
0c8696009f
commit
143704215f
10 changed files with 167 additions and 1 deletions
2
Gemfile
2
Gemfile
|
@ -58,6 +58,8 @@ gem 'rss'
|
|||
gem 'webp-ffi'
|
||||
gem 'rszr'
|
||||
gem 'zip_tricks'
|
||||
gem 'twilio-ruby'
|
||||
gem 'phonelib'
|
||||
|
||||
group :development, :test do
|
||||
gem 'pry'
|
||||
|
|
|
@ -142,6 +142,7 @@ GEM
|
|||
io-extra (1.4.0)
|
||||
ipaddress (0.8.3)
|
||||
json (2.6.2)
|
||||
jwt (2.7.1)
|
||||
llhttp-ffi (0.4.0)
|
||||
ffi-compiler (~> 1.0)
|
||||
rake (~> 13.0)
|
||||
|
@ -192,6 +193,7 @@ GEM
|
|||
ox (2.14.11)
|
||||
paypal-recurring (1.1.0)
|
||||
pg (1.5.3)
|
||||
phonelib (0.8.3)
|
||||
progress (3.6.0)
|
||||
pry (0.14.1)
|
||||
coderay (~> 1.1)
|
||||
|
@ -286,6 +288,10 @@ GEM
|
|||
timeout (0.3.0)
|
||||
tins (1.31.1)
|
||||
sync
|
||||
twilio-ruby (6.3.1)
|
||||
faraday (>= 0.9, < 3.0)
|
||||
jwt (>= 1.5, < 3.0)
|
||||
nokogiri (>= 1.6, < 2.0)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
unf (0.1.4)
|
||||
|
@ -356,6 +362,7 @@ DEPENDENCIES
|
|||
nokogiri
|
||||
paypal-recurring
|
||||
pg
|
||||
phonelib
|
||||
pry
|
||||
puma (< 7)
|
||||
rack-cache
|
||||
|
@ -385,6 +392,7 @@ DEPENDENCIES
|
|||
thread
|
||||
tilt
|
||||
timecop
|
||||
twilio-ruby
|
||||
webmock
|
||||
webp-ffi
|
||||
will_paginate
|
||||
|
|
2
app.rb
2
app.rb
|
@ -77,6 +77,8 @@ before do
|
|||
# Skips the CSRF/validation check for stripe web hooks
|
||||
elsif email_not_validated? && !(request.path =~ /^\/site\/.+\/confirm_email|^\/settings\/change_email|^\/signout|^\/welcome|^\/supporter/)
|
||||
redirect "/site/#{current_site.username}/confirm_email"
|
||||
elsif current_site && current_site.phone_verification_needed? && !(request.path =~ /^\/site\/.+\/confirm_phone/)
|
||||
redirect "/site/#{current_site.username}/confirm_phone"
|
||||
else
|
||||
content_type :html, 'charset' => 'utf-8'
|
||||
redirect '/' if request.post? && !csrf_safe?
|
||||
|
|
|
@ -98,6 +98,7 @@ post '/create' do
|
|||
end
|
||||
|
||||
@site.email_confirmed = true if self.class.development?
|
||||
#@site.phone_confirmed = true if self.class.development?
|
||||
@site.save
|
||||
|
||||
unless education_whitelisted?
|
||||
|
|
58
app/site.rb
58
app/site.rb
|
@ -295,4 +295,62 @@ get '/site/:username/unblock' do |username|
|
|||
|
||||
current_site.unblock! site
|
||||
redirect request.referer
|
||||
end
|
||||
|
||||
get '/site/:username/confirm_phone' do
|
||||
require_login
|
||||
redirect '/' unless current_site.phone_verification_needed?
|
||||
@title = 'Verify your Phone Number'
|
||||
erb :'site/confirm_phone'
|
||||
end
|
||||
|
||||
post '/site/:username/confirm_phone' do
|
||||
require_login
|
||||
redirect '/' unless current_site.phone_verification_needed?
|
||||
|
||||
if params[:phone_intl]
|
||||
phone = Phonelib.parse params[:phone_intl]
|
||||
|
||||
if !phone.valid?
|
||||
flash[:error] = "Invalid phone number, please try again."
|
||||
redirect "/site/#{current_site.username}/confirm_phone"
|
||||
end
|
||||
|
||||
if phone.types.include?(:premium_rate) || phone.types.include?(:shared_cost)
|
||||
flash[:error] = 'Neocities does not support this type of number, please use another number.'
|
||||
redirect "/site/#{current_site.username}/confirm_phone"
|
||||
end
|
||||
|
||||
current_site.phone_verification_sent_at = Time.now
|
||||
current_site.save_changes validate: false
|
||||
|
||||
verification = $twilio.verify
|
||||
.v2
|
||||
.services($config['twilio_service_sid'])
|
||||
.verifications
|
||||
.create(to: phone.e164, channel: 'sms')
|
||||
|
||||
current_site.phone_verification_sid = verification.sid
|
||||
current_site.save_changes validate: false
|
||||
|
||||
flash[:success] = 'Validation message sent! Check your phone and enter the code below.'
|
||||
else
|
||||
# Check code
|
||||
vc = $twilio.verify
|
||||
.v2
|
||||
.services($config['twilio_service_sid'])
|
||||
.verification_checks
|
||||
.create(verification_sid: current_site.phone_verification_sid, code: params[:code])
|
||||
|
||||
# puts vc.status (pending if failed, approved if it passed)
|
||||
if vc.status == 'approved'
|
||||
current_site.phone_verified = true
|
||||
current_site.save_changes validate: false
|
||||
else
|
||||
flash[:error] = 'Code was not correct, please re-enter.'
|
||||
end
|
||||
end
|
||||
|
||||
# Will redirect to / automagically if phone was verified
|
||||
redirect "/site/#{current_site.username}/confirm_phone"
|
||||
end
|
|
@ -177,3 +177,5 @@ $image_optim = ImageOptim.new pngout: false, svgo: false
|
|||
Money.locale_backend = nil
|
||||
Money.default_currency = Money::Currency.new("USD")
|
||||
Money.rounding_mode = BigDecimal::ROUND_HALF_UP
|
||||
|
||||
$twilio = Twilio::REST::Client.new $config['twilio_account_sid'], $config['twilio_auth_token']
|
||||
|
|
15
migrations/119_verify_phone.rb
Normal file
15
migrations/119_verify_phone.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
Sequel.migration do
|
||||
up {
|
||||
DB.add_column :sites, :phone_verification_required, :boolean, default: false
|
||||
DB.add_column :sites, :phone_verified, :boolean, default: false
|
||||
DB.add_column :sites, :phone_verification_sid, :text
|
||||
DB.add_column :sites, :phone_verification_sent_at, :time
|
||||
}
|
||||
|
||||
down {
|
||||
DB.drop_column :sites, :phone_verification_required
|
||||
DB.drop_column :sites, :phone_verified
|
||||
DB.drop_column :sites, :phone_verification_sid
|
||||
DB.drop_column :sites, :phone_verification_sent_at
|
||||
}
|
||||
end
|
|
@ -1789,6 +1789,11 @@ class Site < Sequel::Model
|
|||
end
|
||||
end
|
||||
|
||||
def phone_verification_needed?
|
||||
return true if phone_verification_required && !phone_verified
|
||||
false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def store_file(path, uploaded, opts={})
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
You're almost ready!<br>
|
||||
<% end %>
|
||||
|
||||
We sent an email to <strong><%= current_site.email %></strong> to make sure it's correct.<br>Please check your email, enter the confirmation code here, and you're all set.
|
||||
We sent an email to <strong><%= current_site.email %></strong> to make sure it's correct.<br>Please check your email, and enter the confirmation code here.
|
||||
</h3>
|
||||
|
||||
<div class="row">
|
||||
|
|
73
views/site/confirm_phone.erb
Normal file
73
views/site/confirm_phone.erb
Normal file
|
@ -0,0 +1,73 @@
|
|||
<section class="section plans welcome">
|
||||
<h2>Verify your phone number</h2>
|
||||
<div class="txt-Center"><img src="/img/catbus.png" width="90px"></div>
|
||||
<h3 class="subtitle">
|
||||
You're almost ready!<br>
|
||||
To prevent spam and keep the searchability of your site high, we have one last step:
|
||||
<br>please verify your mobile phone number.
|
||||
</h3>
|
||||
|
||||
<div class="row">
|
||||
<div class="col col-100 txt-Center" style="margin-top: 10px;">
|
||||
<% if flash[:success] %>
|
||||
<div class="alert alert-block alert-success" style="margin-top: 20px">
|
||||
<%== flash[:success] %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if flash[:error] %>
|
||||
<div class="alert alert-block alert-error" style="margin-top: 20px">
|
||||
<%== flash[:error] %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<form method="POST" action="/site/<%= current_site.username %>/confirm_phone" class="content">
|
||||
<%== csrf_token_input_html %>
|
||||
|
||||
<% if current_site.phone_verification_sid %>
|
||||
<fieldset>
|
||||
<label for="token">Enter the code:<br></label>
|
||||
<input name="code" type="text" class="input-Area" autofill="off" autocapitalize="off" autocorrect="off" value="<%= flash[:code] %>" style="width: 290px">
|
||||
</fieldset>
|
||||
<input class="btn-Action" type="submit" value="Verify Code">
|
||||
<% else %>
|
||||
|
||||
<fieldset>
|
||||
<label for="token">Enter your phone number<br><small>(including country code)</small></label>
|
||||
<input id="phone" name="phone" type="text" class="input-Area" autofill="off" autocapitalize="off" autocorrect="off" autocomplete="off" style="width: 290px">
|
||||
<input id="phone_intl" name="phone_intl" type="hidden">
|
||||
</fieldset>
|
||||
<input id="submitButton" class="btn-Action" type="submit" value="Send Verification Code" style="display: none">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/intl-tel-input@18.2.1/build/css/intlTelInput.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/intl-tel-input@18.2.1/build/js/intlTelInput.min.js"></script>
|
||||
<script>
|
||||
const input = document.querySelector("#phone");
|
||||
const iti = window.intlTelInput(input, {
|
||||
nationalMode: true,
|
||||
utilsScript: "https://cdn.jsdelivr.net/npm/intl-tel-input@18.2.1/build/js/utils.js",
|
||||
});
|
||||
|
||||
const handleChange = () => {
|
||||
let text;
|
||||
if(iti.isValidNumber()) {
|
||||
document.getElementById('submitButton').style = "display: inline-block"
|
||||
document.getElementById('phone_intl').value = iti.getNumber()
|
||||
} else {
|
||||
document.getElementById('submitButton').style = "display: none"
|
||||
}
|
||||
};
|
||||
|
||||
// listen to "keyup", but also "change" to update when the user selects a country
|
||||
input.addEventListener('change', handleChange);
|
||||
input.addEventListener('keyup', handleChange);
|
||||
</script>
|
||||
|
||||
<% end %>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
Loading…
Add table
Reference in a new issue