Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modify flow to add Paste in Token as default #159

Merged
merged 14 commits into from
Sep 7, 2023
Prev Previous commit
Next Next commit
Update readme
  • Loading branch information
mikker committed Sep 7, 2023
commit 565f0f876b02a3ed27de8e5fd1968516ede9a398
257 changes: 84 additions & 173 deletions README.md

Large diffs are not rendered by default.

15 changes: 13 additions & 2 deletions app/controllers/passwordless/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ def new
# Creates a new Session record then sends the magic link
# redirects to sign in page with generic flash message.
def create
@resource = find_authenticatable
unless @resource = find_authenticatable
raise(
ActiveRecord::RecordNotFound,
"Couldn't find #{authenticatable_type} with email #{passwordless_session_params[email_field]}"
)
end

@session = build_passwordless_session(@resource)

if @session.save
Expand All @@ -32,11 +38,16 @@ def create

redirect_to(
url_for(id: @session.id, action: "show"),
flash: {notice: I18n.t("passwordless.sessions.create.email_sent_if_record_found")}
flash: {notice: I18n.t("passwordless.sessions.create.email_sent")}
)
else
flash[:error] = I18n.t("passwordless.sessions.create.error")
render(:new, status: :unprocessable_entity)
end

rescue ActiveRecord::RecordNotFound
flash[:error] = I18n.t("passwordless.sessions.create.not_found")
render(:new, status: :not_found)
end

# get "/:resource/sign_in/:id"
Expand Down
4 changes: 3 additions & 1 deletion config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ en:
placeholder: "[email protected]"
submit: "Sign in"
create:
email_sent_if_record_found: "If we found you in the system, we've sent you an email."
email_sent: "We've sent you an email with a secret token"
not_found: "We couldn't find a user with that email address"
error: "An error occured"
errors:
invalid_token: "Token is invalid"
session_expired: "Your session has expired, please sign in again."
Expand Down
8 changes: 5 additions & 3 deletions lib/passwordless/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ def self.included(cls)
class Configuration
include Options

option :parent_mailer, default: "ActionMailer::Base"
option :default_from_address, default: "[email protected]"
option :token_generator, default: ShortTokenGenerator.new
option :parent_mailer, default: "ActionMailer::Base"
option :restrict_token_reuse, default: true
option :redirect_back_after_sign_in, default: true
option :token_generator, default: ShortTokenGenerator.new

option :expires_at, default: lambda { 1.year.from_now }
option :timeout_at, default: lambda { 10.minutes.from_now }

option :redirect_back_after_sign_in, default: true
option :redirect_to_response_options, default: {}
option :success_redirect_path, default: "/"
option :failure_redirect_path, default: "/"
Expand Down
14 changes: 12 additions & 2 deletions lib/passwordless/test_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ def passwordless_sign_out

def passwordless_sign_in(resource)
session = Passwordless::Session.create!(authenticatable: resource)
get(Passwordless::Engine.routes.url_helpers.token_sign_in_path(session.token))
magic_link = Passwordless::Engine.routes.url_helpers.send(
:"confirm_#{session.authenticatable_type.tableize}_sign_in_url",
session,
session.token
)
get(magic_link)
follow_redirect!
end
end
Expand All @@ -20,7 +25,12 @@ def passwordless_sign_out

def passwordless_sign_in(resource)
session = Passwordless::Session.create!(authenticatable: resource)
visit(Passwordless::Engine.routes.url_helpers.token_sign_in_path(session.token))
magic_link = Passwordless::Engine.routes.url_helpers.send(
:"confirm_#{session.authenticatable_type.tableize}_sign_in_url",
session,
session.token
)
visit(magic_link)
end
end
end
Expand Down
18 changes: 17 additions & 1 deletion test/controllers/passwordless/sessions_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,30 @@ class << User
end
end

test("POST /:passwordless_for/sign_in -> ERROR") do
test("POST /:passwordless_for/sign_in -> ERROR / not found") do
post("/users/sign_in", params: {passwordless: {email: "A@a"}})

assert_equal 404, status
assert_equal "/users/sign_in", path
assert_equal 0, ActionMailer::Base.deliveries.size

assert_template "passwordless/sessions/new"
assert_match "We couldn't find a user with that email address", flash[:error]
end

test("POST /:passwordless_for/sign_in -> ERROR / other error") do
create_user(email: "a@a")

with_config(expires_at: lambda { nil }) do
post("/users/sign_in", params: {passwordless: {email: "a@a"}})
end

assert_equal 422, status
assert_equal "/users/sign_in", path
assert_equal 0, ActionMailer::Base.deliveries.size

assert_template "passwordless/sessions/new"
assert_match "An error occured", flash[:error]
end

test("GET /:passwordless_for/sign_in/:id") do
Expand Down
6 changes: 4 additions & 2 deletions test/integration/authentication_flow_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class AuthenticationFlowTest < ActionDispatch::SystemTestCase
click_button "Sign in"
end

assert_content "If we found you in the system"
assert_content "We've sent you an email"

email = ActionMailer::Base.deliveries.last
assert_equal alice.email, email.to.first
Expand All @@ -33,6 +33,7 @@ class AuthenticationFlowTest < ActionDispatch::SystemTestCase
fill_in "passwordless[token]", with: token
click_button "Confirm"

assert_equal "/secret", current_path
assert_content "shhhh! secrets!"
end

Expand All @@ -47,14 +48,15 @@ class AuthenticationFlowTest < ActionDispatch::SystemTestCase
click_button "Sign in"
end

assert_content "If we found you in the system"
assert_content "We've sent you an email"

email = ActionMailer::Base.deliveries.last
assert_equal alice.email, email.to.first
magic_link = email.body.to_s.scan(%r{https://.*/sign_in/\d+/\w+}).at(0)

visit magic_link

assert_equal "/", current_path
assert_content "Current user: #{alice.email}"
end
end