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 'webp-ffi'
|
||||||
gem 'rszr'
|
gem 'rszr'
|
||||||
gem 'zip_tricks'
|
gem 'zip_tricks'
|
||||||
|
gem 'twilio-ruby'
|
||||||
|
gem 'phonelib'
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
gem 'pry'
|
gem 'pry'
|
||||||
|
|
|
@ -142,6 +142,7 @@ GEM
|
||||||
io-extra (1.4.0)
|
io-extra (1.4.0)
|
||||||
ipaddress (0.8.3)
|
ipaddress (0.8.3)
|
||||||
json (2.6.2)
|
json (2.6.2)
|
||||||
|
jwt (2.7.1)
|
||||||
llhttp-ffi (0.4.0)
|
llhttp-ffi (0.4.0)
|
||||||
ffi-compiler (~> 1.0)
|
ffi-compiler (~> 1.0)
|
||||||
rake (~> 13.0)
|
rake (~> 13.0)
|
||||||
|
@ -192,6 +193,7 @@ GEM
|
||||||
ox (2.14.11)
|
ox (2.14.11)
|
||||||
paypal-recurring (1.1.0)
|
paypal-recurring (1.1.0)
|
||||||
pg (1.5.3)
|
pg (1.5.3)
|
||||||
|
phonelib (0.8.3)
|
||||||
progress (3.6.0)
|
progress (3.6.0)
|
||||||
pry (0.14.1)
|
pry (0.14.1)
|
||||||
coderay (~> 1.1)
|
coderay (~> 1.1)
|
||||||
|
@ -286,6 +288,10 @@ GEM
|
||||||
timeout (0.3.0)
|
timeout (0.3.0)
|
||||||
tins (1.31.1)
|
tins (1.31.1)
|
||||||
sync
|
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)
|
tzinfo (2.0.6)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
unf (0.1.4)
|
unf (0.1.4)
|
||||||
|
@ -356,6 +362,7 @@ DEPENDENCIES
|
||||||
nokogiri
|
nokogiri
|
||||||
paypal-recurring
|
paypal-recurring
|
||||||
pg
|
pg
|
||||||
|
phonelib
|
||||||
pry
|
pry
|
||||||
puma (< 7)
|
puma (< 7)
|
||||||
rack-cache
|
rack-cache
|
||||||
|
@ -385,6 +392,7 @@ DEPENDENCIES
|
||||||
thread
|
thread
|
||||||
tilt
|
tilt
|
||||||
timecop
|
timecop
|
||||||
|
twilio-ruby
|
||||||
webmock
|
webmock
|
||||||
webp-ffi
|
webp-ffi
|
||||||
will_paginate
|
will_paginate
|
||||||
|
|
2
app.rb
2
app.rb
|
@ -77,6 +77,8 @@ before do
|
||||||
# Skips the CSRF/validation check for stripe web hooks
|
# Skips the CSRF/validation check for stripe web hooks
|
||||||
elsif email_not_validated? && !(request.path =~ /^\/site\/.+\/confirm_email|^\/settings\/change_email|^\/signout|^\/welcome|^\/supporter/)
|
elsif email_not_validated? && !(request.path =~ /^\/site\/.+\/confirm_email|^\/settings\/change_email|^\/signout|^\/welcome|^\/supporter/)
|
||||||
redirect "/site/#{current_site.username}/confirm_email"
|
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
|
else
|
||||||
content_type :html, 'charset' => 'utf-8'
|
content_type :html, 'charset' => 'utf-8'
|
||||||
redirect '/' if request.post? && !csrf_safe?
|
redirect '/' if request.post? && !csrf_safe?
|
||||||
|
|
|
@ -98,6 +98,7 @@ post '/create' do
|
||||||
end
|
end
|
||||||
|
|
||||||
@site.email_confirmed = true if self.class.development?
|
@site.email_confirmed = true if self.class.development?
|
||||||
|
#@site.phone_confirmed = true if self.class.development?
|
||||||
@site.save
|
@site.save
|
||||||
|
|
||||||
unless education_whitelisted?
|
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
|
current_site.unblock! site
|
||||||
redirect request.referer
|
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
|
end
|
|
@ -177,3 +177,5 @@ $image_optim = ImageOptim.new pngout: false, svgo: false
|
||||||
Money.locale_backend = nil
|
Money.locale_backend = nil
|
||||||
Money.default_currency = Money::Currency.new("USD")
|
Money.default_currency = Money::Currency.new("USD")
|
||||||
Money.rounding_mode = BigDecimal::ROUND_HALF_UP
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def phone_verification_needed?
|
||||||
|
return true if phone_verification_required && !phone_verified
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def store_file(path, uploaded, opts={})
|
def store_file(path, uploaded, opts={})
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
You're almost ready!<br>
|
You're almost ready!<br>
|
||||||
<% end %>
|
<% 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>
|
</h3>
|
||||||
|
|
||||||
<div class="row">
|
<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