Skip to content

Feature 1792 - users can choose to recieve password resets via SMS#3757

Merged
compwron merged 25 commits into
rubyforgood:mainfrom
xihai01:f/1792
Jul 19, 2022
Merged

Feature 1792 - users can choose to recieve password resets via SMS#3757
compwron merged 25 commits into
rubyforgood:mainfrom
xihai01:f/1792

Conversation

@xihai01
Copy link
Copy Markdown
Collaborator

@xihai01 xihai01 commented Jul 16, 2022

What github issue is this PR for, if any?

Resolves #1792

What changed, and why?

CASA users can now send password resets via SMS in addition to email.
Users can have the flexible options of getting a reset link via:

  • Just email
  • Just phone number
  • Both email and phone number

To achieve this:

  • A phone number field is added in the front end
  • A passwords controller with a create action is implemented to override Devise's passwords controller. This is needed to add in the functionality of sending via SMS.

How is this tested? (please write tests!) 💖💪

  • A view spec is created to test front end aspect (i.e additional text and phone number field is present on page)
  • A system spec is created to test user flow (forgot password -> enter email and/or phone number -> click send -> redirect with a notice) and rendering of any form validation errors
  • A request spec is created to test our custom route that it calls short io and twilio services
    and redirects if no form errors occur

Screenshots please :)

demo

SMS received via my phone (short link was visible thanks to @7riumph 's branded domain)

SMS

Feelings gif (optional)

excitment
I really enjoyed this issue - it allowed me to dive deeper into the internals of Devise

@xihai01 xihai01 added zzz_archived: 📱 SMS work relating to SMS notifications #1017 codethechange code.the.change developers labels Jul 16, 2022
@xihai01 xihai01 self-assigned this Jul 16, 2022
Comment thread spec/system/devise/passwords/new_spec.rb Outdated
@xihai01
Copy link
Copy Markdown
Collaborator Author

xihai01 commented Jul 16, 2022

@compwron @harsohailB @7riumph rspec is failing because the db is missing a "user reminder times" table and the lib/tasks tests depend on it. Looking at the schema, it seems to me someone refactored the "users reminder times" to "user case contact types reminders". Any clue to what's going on here?
Screenshot from 2022-07-16 11-18-39
Screenshot from 2022-07-16 11-25-42

@xihai01
Copy link
Copy Markdown
Collaborator Author

xihai01 commented Jul 16, 2022

I'll work on fixing the code climate issues. Please don't merge yet or until everything is green. :)

@harsohailB
Copy link
Copy Markdown
Collaborator

it seems to me someone refactored the "users reminder times" to "user case contact types reminders"

@xihai01 It should be the opposite. I refactored "user case contact types reminders" table to "users reminder times" to make it re-usable for all reminder times. #3735

Copy link
Copy Markdown
Collaborator

@harsohailB harsohailB left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nice job! Glad you enjoyed this because I was having a really hard time wrapping my head around Devise. Just a few comments about code separation and reusability in the passwords controller.

end

validation = valid_phone_number(phone_number)
if validation[0]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do something like this instead so its more readable than indexing:

phone_number_is_valid, error_message = valid_phone_number(phone_number)

if phone_number_is_valid
    error_message = "Phone number not found" if User.find_by(phone_number: phone_number)
end

if error_message
    resource.errors.add(:phone_number, error_message)
end

end

# otherwise, send reset email and sms
@resource = email.blank? ? User.find_by(phone_number: phone_number) : User.find_by(email: email)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like you are already querying User.find_by(phone_number: phone_number) and User.find_by(email: email) above in the file to add error if the queries doesn't find anything. Maybe put these in a variable so you only call them once and reuse them if the query does find something?

Comment thread app/controllers/users/passwords_controller.rb Outdated
phone_number = params[resource_name][:phone_number]
reset_token = nil

if email.blank? && phone_number.blank?
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should have 2 clear paths for email and sms based on what is filled out. Right now, its hard to follow the logic as we have a lot if statements that keep checking email.blank? and phone_number.blank?. Maybe:

if !email.blank? && valid_email
   # run this code which  only has to do with the email
end

if !phone_number.blank? && valid_phone_number
   # run this code which  only has to do with the sms
end

@xihai01
Copy link
Copy Markdown
Collaborator Author

xihai01 commented Jul 16, 2022

TO DO STILL:

  • create action is apparently still too complex for a human to understand -> need refactoring extra credit to @harsohailB for the help
  • migrate request spec to a controller spec to pass that spec checker 💩
  • fix error with failing lib/tasks tests; once fixed should resolve factory bot lint check too - 2 🐦 1 🪨

@compwron
Copy link
Copy Markdown
Collaborator

This is exciting!
CI is failing on lint and spec

@xihai01
Copy link
Copy Markdown
Collaborator Author

xihai01 commented Jul 19, 2022

This is exciting! CI is failing on lint and spec

fixed! I drop the db and recreated it. It seemed the schema I had was outdated with some missing tables.

@@ -0,0 +1,71 @@
class Users::PasswordsController < Devise::PasswordsController
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eek

tag.meta(property: "og:#{type}", **options)
end

def resource_name
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for devise ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, for devise. The devise view calls some internal methods like resource and resource_name. So we need to map these to use them in our controllers and specs

@compwron compwron merged commit a681cb6 into rubyforgood:main Jul 19, 2022
Copy link
Copy Markdown
Collaborator

@7riumph 7riumph left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥🔥🔥

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codethechange code.the.change developers erb Touches ERB templates ruby Touches Ruby code 🧪 Tests Tests zzz_archived: 📱 SMS work relating to SMS notifications #1017

Projects

None yet

Development

Successfully merging this pull request may close these issues.

users can choose to receive password reset via SMS

4 participants