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

Fix :as option in passwordless_for #174

Merged
merged 6 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## Unreleased

### Fixed

- Route generation with :as option (#174)
- Test helper route generation (#174)

## 1.0.1

### Fixed
Expand Down
11 changes: 10 additions & 1 deletion app/mailers/passwordless/mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,16 @@ class Mailer < Passwordless.config.parent_mailer.constantize
# is still in memory (optional)
def sign_in(session, token = nil)
@token = token || session.token
@magic_link = send(:"confirm_#{session.authenticatable_type.tableize}_sign_in_url", session, token)
@magic_link = url_for(
{
controller: "passwordless/sessions",
action: "confirm",
id: session.id,
token: token,
authenticatable: "user",
resource: "users"
}
)
email_field = session.authenticatable.class.passwordless_email_field

mail(
Expand Down
6 changes: 4 additions & 2 deletions lib/passwordless/router_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ module RouterHelpers
# (Default: 'passwordless/sessions')
def passwordless_for(resource, at: :na, as: :na, controller: "passwordless/sessions")
at == :na && at = "/#{resource.to_s}"
as == :na && as = "#{resource.to_s}_"
as == :na && as = resource.to_s

as = as.to_s + "_" unless !as || as.to_s.end_with?("_")

plural = resource.to_s
singular = plural.singularize

defaults = {
authenticatable: singular,
resource: resource,
resource: resource
}

scope(defaults: defaults) do
Expand Down
55 changes: 43 additions & 12 deletions lib/passwordless/test_helpers.rb
Original file line number Diff line number Diff line change
@@ -1,34 +1,65 @@
module Passwordless
module TestHelpers
module TestCase
def passwordless_sign_out
delete(Passwordless::Engine.routes.url_helpers.sign_out_path)
def passwordless_sign_out(cls = nil)
cls ||= "User".constantize
dest = url_for(
{
controller: "passwordless/sessions",
action: "destroy",
authenticatable: cls.model_name.singular,
resource: cls.model_name.to_s.tableize
}
)
delete(dest)
follow_redirect!
end

def passwordless_sign_in(resource)
cls = resource.class
session = Passwordless::Session.create!(authenticatable: resource)
magic_link = Passwordless::Engine.routes.url_helpers.send(
:"confirm_#{session.authenticatable_type.tableize}_sign_in_url",
session,
session.token
magic_link = url_for(
{
controller: "passwordless/sessions",
action: "confirm",
id: session.id,
token: session.token,
authenticatable: cls.model_name.singular,
resource: cls.model_name.to_s.tableize
}
)
get(magic_link)
follow_redirect!
end
end

module SystemTestCase
def passwordless_sign_out
visit(Passwordless::Engine.routes.url_helpers.sign_out_path)
def passwordless_sign_out(cls = nil)
cls ||= "User".constantize
visit(
url_for(
{
controller: "passwordless/sessions",
action: "destroy",
authenticatable: cls.model_name.singular,
resource: cls.model_name.to_s.tableize
}
)
)
end

def passwordless_sign_in(resource)
cls = resource.class
session = Passwordless::Session.create!(authenticatable: resource)
magic_link = Passwordless::Engine.routes.url_helpers.send(
:"confirm_#{session.authenticatable_type.tableize}_sign_in_url",
session,
session.token
magic_link = url_for(
{
controller: "passwordless/sessions",
action: "confirm",
id: session.id,
token: session.token,
authenticatable: cls.model_name.singular,
resource: cls.model_name.to_s.tableize
}
)
visit(magic_link)
end
Expand Down
3 changes: 2 additions & 1 deletion test/dummy/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

Rails.application.routes.draw do
passwordless_for(:users)
passwordless_for(:admins, controller: 'admin/sessions')
passwordless_for(:admins, controller: "admin/sessions")
passwordless_for(:devs, as: :auth, at: "/")

resources(:users)
resources(:registrations, only: %i[new create])
Expand Down
20 changes: 20 additions & 0 deletions test/passwordless/router_helpers_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class RouterHelpersTest < ActionDispatch::IntegrationTest
{method: :get, path: "/users/sign_out"},
defaults
)

assert_equal "/users/sign_in", url_helpers.users_sign_in_path
end

test("map sign in for admin") do
Expand Down Expand Up @@ -100,7 +102,25 @@ class RouterHelpersTest < ActionDispatch::IntegrationTest
{method: :get, path: "/admins/sign_out"},
defaults
)

assert_equal "/admins/sign_in", url_helpers.admins_sign_in_path
end

test(":as option") do
defaults = {authenticatable: "dev", resource: "devs"}
assert_recognizes(
{controller: "passwordless/sessions", action: "new"}.merge(defaults),
{method: :get, path: "/sign_in"},
defaults
)

assert_equal "/sign_in", url_helpers.auth_sign_in_path
end

private

def url_helpers
Rails.application.routes.url_helpers
end
end
end
82 changes: 82 additions & 0 deletions test/passwordless/test_helpers_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
require "test_helper"
require "passwordless/test_helpers"

module Passwordless
class MockTest
include Rails.application.routes.url_helpers

def initialize
@actions = []
end

attr_reader :actions
end

class MockUnitTest < MockTest
include Passwordless::TestHelpers::TestCase

def get(*args)
@actions << [:get, args]
end

def delete(*args)
@actions << [:delete, args]
end

def follow_redirect!
@actions << [:follow_redirect!]
end
end

class MockSystemTest < MockTest
include Passwordless::TestHelpers::SystemTestCase

def visit(*args)
@actions << [:visit, args]
end
end

class PasswordlessTestHelpersTest < ActiveSupport::TestCase
test("unit test") do
alice = users(:alice)
controller = MockUnitTest.new

controller.passwordless_sign_in(alice)

assert 1, Session.count
assert alice, Session.last!.authenticatable
assert_match(
%r{^http:https://.*/users/sign_in/[a-z0-9]+/[a-z0-9]+}i,
controller.actions.first.last.first
)

controller.passwordless_sign_out

assert_match(
%r{^http:https://.*/users/sign_out},
controller.actions[-2].last.first
)
end

test("system test") do
alice = users(:alice)
controller = MockSystemTest.new

controller.passwordless_sign_in(alice)

assert 1, Session.count
assert alice, Session.last!.authenticatable
assert_match(
%r{^http:https://.*/users/sign_in/[a-z0-9]+/[a-z0-9]+}i,
controller.actions.last.last.first
)

controller.passwordless_sign_out

assert_match(
%r{^http:https://.*/users/sign_out},
controller.actions.last.last.first
)
end
end
end