Skip to content

Commit

Permalink
Merge pull request #32 from laruby2/twilio-register
Browse files Browse the repository at this point in the history
Use Twilio text messages for user register (US only for now)
  • Loading branch information
kangkyu authored Aug 9, 2024
2 parents 2a1f845 + b8b07c3 commit 93d397d
Show file tree
Hide file tree
Showing 13 changed files with 197 additions and 10 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,4 @@ group :test do
end

gem "tailwindcss-rails", "= 2.0.23"
gem "twilio-ruby", "~> 7.2"
23 changes: 20 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ GEM
tzinfo (~> 2.0)
addressable (2.8.5)
public_suffix (>= 2.0.2, < 6.0)
base64 (0.2.0)
bcrypt (3.1.19)
bindex (0.8.1)
bootsnap (1.16.0)
Expand All @@ -91,6 +92,11 @@ GEM
irb (>= 1.5.0)
reline (>= 0.3.1)
erubi (1.12.0)
faraday (2.10.1)
faraday-net_http (>= 2.0, < 3.2)
logger
faraday-net_http (3.1.1)
net-http
globalid (1.1.0)
activesupport (>= 5.0)
i18n (1.14.1)
Expand All @@ -104,6 +110,9 @@ GEM
jbuilder (2.11.5)
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
jwt (2.8.2)
base64
logger (1.6.0)
loofah (2.21.3)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
Expand All @@ -118,6 +127,8 @@ GEM
mini_mime (1.1.5)
minitest (5.19.0)
msgpack (1.7.2)
net-http (0.4.1)
uri
net-imap (0.3.7)
date
net-protocol
Expand All @@ -128,9 +139,9 @@ GEM
net-smtp (0.3.3)
net-protocol
nio4r (2.5.9)
nokogiri (1.15.4-arm64-darwin)
nokogiri (1.16.7-arm64-darwin)
racc (~> 1.4)
nokogiri (1.15.4-x86_64-linux)
nokogiri (1.16.7-x86_64-linux)
racc (~> 1.4)
pg (1.5.4)
pry (0.14.2)
Expand All @@ -141,7 +152,7 @@ GEM
public_suffix (5.0.3)
puma (5.6.7)
nio4r (~> 2.0)
racc (1.7.1)
racc (1.8.1)
rack (2.2.8)
rack-test (2.1.0)
rack (>= 1.3)
Expand Down Expand Up @@ -206,8 +217,13 @@ GEM
actionpack (>= 6.0.0)
activejob (>= 6.0.0)
railties (>= 6.0.0)
twilio-ruby (7.2.3)
faraday (>= 0.9, < 3.0)
jwt (>= 1.5, < 3.0)
nokogiri (>= 1.6, < 2.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
uri (0.13.0)
web-console (4.2.0)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
Expand Down Expand Up @@ -247,6 +263,7 @@ DEPENDENCIES
stimulus-rails
tailwindcss-rails (= 2.0.23)
turbo-rails
twilio-ruby (~> 7.2)
tzinfo-data
web-console
webdrivers
Expand Down
94 changes: 94 additions & 0 deletions app/controllers/phone_numbers_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
class PhoneNumbersController < ApplicationController

# post request to twilio
def verify
telephone = params[:phone_number]

r = /\A\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})\z/
m = r.match(params[:phone_number])
if m.present? && m.length == 4
telephone = "+1#{m[1]}#{m[2]}#{m[3]}" # E.164 format
end

response = client.lookups.v1.phone_numbers(telephone).fetch
valid_num = response.phone_number # if invalid, throws an exception

verification = client
.verify
.v2
.services(service_sid)
.verifications
.create(
to: valid_num,
channel: 'sms'
)

# go to passcode form after posting twilio
if verification.status == 'pending'
session[:telephone] = telephone
redirect_to phone_numbers_passcode_url
else
flash.now[:alert] = "Verification did not process"
render :new, status: :unprocessable_entity
end
rescue => e
if e.code == 20404
flash.now[:alert] = "Not a valid phone number"
render :new, status: :unprocessable_entity
else
raise e
end
end

def passcode_enter
verification_check = client
.verify
.v2
.services(service_sid)
.verification_checks
.create(
to: session[:telephone],
code: params[:passcode]
)

# go back to user siginup page when successful
if verification_check.status == 'approved'

redirect_to register_url, notice: "Phone number is verified"
else
flash.now[:alert] = "Passcode is not being approved"
render :edit, status: :unprocessable_entity
end
rescue => e
if e.code == 20404
flash.now[:alert] = "Not a valid passcode"
render :edit, status: :unprocessable_entity
else
raise e
end
end

def edit
end

def new
end

private

def client
@client ||= Twilio::REST::Client.new(account_sid, auth_token)
end

def account_sid
ENV['TWILIO_ACCOUNT_SID']
end

def auth_token
ENV['TWILIO_AUTH_TOKEN']
end

def service_sid
ENV['TWILIO_SERVICE_SID']
end
end
1 change: 1 addition & 0 deletions app/controllers/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def create

def destroy
session[:user_id] = nil
session[:telephone] = nil
redirect_to new_session_url
end
end
12 changes: 11 additions & 1 deletion app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
class UsersController < ApplicationController
before_action :require_signin, only: [:index, :show]
before_action :require_admin, only: [:index]
before_action :require_telephone, only: [:new, :create]

def new
@user = User.new
@user.phone_number = session[:telephone]
end

def create
@user = User.new(user_params)
@user.phone_number = session[:telephone]

if @user.save
session[:user_id] = @user.id
session[:telephone] = nil
redirect_to session[:intended_url] || root_url
else
flash.now[:alert] = "Sign up not successful"
flash.now[:alert] = "Sign up not successful: #{@user.errors.full_messages.to_sentence}"
render :new, status: :unprocessable_entity
end
end
Expand All @@ -37,4 +41,10 @@ def show
def user_params
params.require(:user).permit(:username, :phone_number, :password)
end

def require_telephone
unless session[:telephone]
redirect_to signin_url
end
end
end
4 changes: 4 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ class User < ApplicationRecord
validates :username, presence: true,
uniqueness: { case_sensitive: false }

validates :phone_number, format: {
with: /\A\([0-9]{3}\)[-. ][0-9]{3}[-. ][0-9]{4}\z|\A\+[1-9]\d{1,14}\z/
}

enum user_role: [:admin, :member]

def assign_my_votes_to_contestants(contestants)
Expand Down
2 changes: 1 addition & 1 deletion app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<% if signed_in? %>
<%= link_to "Hello \"#{current_user.username}\"", user_path(current_user.another_id), class: class_name_by_tab(user_path(current_user.another_id)) %>
<% else %>
<%= link_to "Register", new_user_path, class: class_name_by_tab(new_user_path) %>
<%= link_to "Register", phone_numbers_verify_path, class: class_name_by_tab(new_user_path) %>
<%= link_to "Sign In", new_session_path, class: class_name_by_tab(new_session_path) %>
<% end %>
</div>
Expand Down
22 changes: 22 additions & 0 deletions app/views/phone_numbers/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<div class="mb-6 px-6 max-w-3xl mx-auto lg:ml-0 lg:mr-auto xl:mx-0 xl:px-12 xl:w-3/4">
<h2 class="text-3xl font-bold text-gray-800">Enter 6 digit passcode</h2>
<hr class="my-8 border-b-2 border-gray-200">
</div>

<%= form_with url: phone_numbers_passcode_path, class: "w-full max-w-sm" do |f| %>
<div class="md:flex md:items-center mb-6">
<div class="md:w-1/3">
<%= f.label :passcode, class: "block text-gray-500 font-bold md:text-right mb-1 md:mb-0 pr-4" %>
</div>
<div class="md:w-2/3">
<%= f.password_field :passcode, required: true, class: "bg-gray-200 appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-purple-500" %>
</div>
</div>
<div class="md:flex md:items-center">
<div class="md:w-1/3"></div>
<div class="md:w-2/3">
<%= f.submit "Submit", class: "shadow bg-purple-500 hover:bg-purple-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded" %>
<%= link_to "Cancel", root_path, class: "py-2 px-4 border border-gray-500 rounded text-gray-500 hover:bg-gray-100 hover:border-gray-700 hover:text-gray-700 font-bold" %>
</div>
</div>
<% end %>
28 changes: 28 additions & 0 deletions app/views/phone_numbers/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<div class="mb-6 px-6 max-w-3xl mx-auto lg:ml-0 lg:mr-auto xl:mx-0 xl:px-12 xl:w-3/4">
<h2 class="text-3xl font-bold text-gray-800">Verify phone number</h2>
<hr class="my-8 border-b-2 border-gray-200">

<p class="text-gray-400">
Do you have a username already? Then
<%= link_to "Sign In", signin_path, class: "text-green-500 underline" %>
</p>
</div>

<%= form_with model: @user, class: "w-full max-w-sm" do |f| %>

<div class="md:flex md:items-center mb-6">
<div class="md:w-1/3">
<%= f.label :phone_number, class: "block text-gray-500 font-bold md:text-right mb-1 md:mb-0 pr-4" %>
</div>
<div class="md:w-2/3">
<%= f.phone_field :phone_number, autofocus: true, required: true, class: "bg-gray-200 appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-purple-500" %>
</div>
</div>

<div class="md:flex md:items-center">
<div class="md:w-1/3"></div>
<div class="md:w-2/3">
<%= f.submit "Verify", formaction: phone_numbers_verify_path, class: "shadow bg-purple-500 hover:bg-purple-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded" %>
</div>
</div>
<% end %>
2 changes: 1 addition & 1 deletion app/views/sessions/new.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<div class="md:w-1/3"></div>
<div class="md:w-2/3">
<%= f.submit "Sign In", class: "shadow bg-purple-500 hover:bg-purple-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded" %>
<%= link_to "Register", register_path, class: "py-2 px-4 border border-gray-500 rounded text-gray-500 hover:bg-gray-100 hover:border-gray-700 hover:text-gray-700 font-bold" %>
<%= link_to "Register", phone_numbers_verify_path, class: "py-2 px-4 border border-gray-500 rounded text-gray-500 hover:bg-gray-100 hover:border-gray-700 hover:text-gray-700 font-bold" %>
</div>
</div>
<% end %>
9 changes: 7 additions & 2 deletions app/views/users/new.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="mb-6 px-6 max-w-3xl mx-auto lg:ml-0 lg:mr-auto xl:mx-0 xl:px-12 xl:w-3/4">
<h2 class="text-3xl font-bold text-gray-800">Register</h2>
<h2 class="text-3xl font-bold text-gray-800">Create a username</h2>
<hr class="my-8 border-b-2 border-gray-200">
</div>

Expand All @@ -17,7 +17,12 @@
<%= f.label :phone_number, class: "block text-gray-500 font-bold md:text-right mb-1 md:mb-0 pr-4" %>
</div>
<div class="md:w-2/3">
<%= f.phone_field :phone_number, class: "bg-gray-200 appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-purple-500" %>
<div class="mt-2 flex rounded-md shadow-sm">
<div class="relative flex flex-grow items-stretch focus-within:z-10">
<%= f.phone_field :phone_number, disabled: true, placeholder: "(555) 987-6543", class: "bg-gray-200 appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-purple-500" %>
</div>
<%= f.submit "Verify", disabled: true, formaction: phone_numbers_verify_path, class: "relative -ml-px inline-flex items-center gap-x-1.5 rounded-r-md px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50" %>
</div>
</div>
</div>
<div class="md:flex md:items-center mb-6">
Expand Down
5 changes: 5 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
resources :users, only: [:new, :show, :create, :index]
get "register" => "users#new"

get 'phone_numbers/verify' => "phone_numbers#new"
post 'phone_numbers/verify' => "phone_numbers#verify"
get 'phone_numbers/passcode' => "phone_numbers#edit"
post 'phone_numbers/passcode' => "phone_numbers#passcode_enter"

resource :session, only: [:new, :create, :destroy]
get "signin" => "sessions#new"

Expand Down
4 changes: 2 additions & 2 deletions db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
{ name: "Star Wars", location: "Galaxy" }
])
users = User.create([
{ username: "jimmy", phone_number: "abcd123", password: "1111" },
{ username: "gapbun", phone_number: "asdf456", password: "1111", user_role: "admin" }
{ username: "jimmy", phone_number: "+13231234567", password: "secret" },
{ username: "gapbun", phone_number: "+11234567890", password: "secret", user_role: "admin" }
])

0 comments on commit 93d397d

Please sign in to comment.