passwordless 0.11.0 → 1.0.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +112 -189
- data/Rakefile +7 -7
- data/app/controllers/passwordless/sessions_controller.rb +121 -39
- data/app/mailers/passwordless/mailer.rb +13 -11
- data/app/models/passwordless/session.rb +25 -12
- data/app/views/passwordless/mailer/sign_in.text.erb +1 -0
- data/app/views/passwordless/sessions/new.html.erb +8 -4
- data/app/views/passwordless/sessions/show.html.erb +5 -0
- data/config/locales/en.yml +18 -6
- data/config/routes.rb +0 -4
- data/db/migrate/20171104221735_create_passwordless_sessions.rb +1 -3
- data/lib/generators/passwordless/views_generator.rb +5 -5
- data/lib/passwordless/config.rb +71 -0
- data/lib/passwordless/controller_helpers.rb +31 -69
- data/lib/passwordless/engine.rb +2 -6
- data/lib/passwordless/errors.rb +4 -0
- data/lib/passwordless/router_helpers.rb +24 -10
- data/lib/passwordless/short_token_generator.rb +9 -0
- data/lib/passwordless/test_helpers.rb +19 -9
- data/lib/passwordless/token_digest.rb +18 -0
- data/lib/passwordless/version.rb +1 -1
- data/lib/passwordless.rb +5 -18
- metadata +12 -52
- data/app/views/passwordless/mailer/magic_link.text.erb +0 -1
- data/app/views/passwordless/sessions/create.html.erb +0 -1
- data/lib/passwordless/url_safe_base_64_generator.rb +0 -15
data/lib/passwordless/engine.rb
CHANGED
@@ -3,17 +3,13 @@
|
|
3
3
|
module Passwordless
|
4
4
|
# Engine that runs the passwordless gem.
|
5
5
|
class Engine < ::Rails::Engine
|
6
|
-
isolate_namespace Passwordless
|
7
|
-
|
8
6
|
config.to_prepare do
|
9
7
|
require "passwordless/router_helpers"
|
10
|
-
|
11
|
-
ActionDispatch::Routing::Mapper.include RouterHelpers
|
12
8
|
require "passwordless/model_helpers"
|
13
|
-
|
14
|
-
ActiveRecord::Base.extend ModelHelpers
|
15
9
|
require "passwordless/controller_helpers"
|
16
10
|
|
11
|
+
ActionDispatch::Routing::Mapper.include RouterHelpers
|
12
|
+
ActiveRecord::Base.extend ModelHelpers
|
17
13
|
end
|
18
14
|
|
19
15
|
config.before_initialize do |app|
|
data/lib/passwordless/errors.rb
CHANGED
@@ -8,6 +8,8 @@ module Passwordless
|
|
8
8
|
# passwordless_for :users
|
9
9
|
# # or with options ...
|
10
10
|
# passwordless_for :users, at: 'session_stuff', as: :user_session_things
|
11
|
+
# # or with a custom controller ...
|
12
|
+
# passwordless_for :users, controller: 'my_custom_controller'
|
11
13
|
# @param resource [Symbol] the pluralized symbol of a Model (e.g - :users).
|
12
14
|
# @param at [String] Optional - provide custom path for the passwordless
|
13
15
|
# engine to get mounted at (using the above example your URLs end
|
@@ -16,17 +18,29 @@ module Passwordless
|
|
16
18
|
# helpers (using the above example in a view:
|
17
19
|
# <%= link_to 'Sign in', user_session_things.sign_in_path %>).
|
18
20
|
# (Default: resource.to_s)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
as: mount_as,
|
26
|
-
defaults: {authenticatable: resource.to_s.singularize}
|
27
|
-
)
|
21
|
+
# @param controller [String] Optional - provide a custom controller for
|
22
|
+
# sessions to use (using the above example the controller called would be MyCustomController
|
23
|
+
# (Default: 'passwordless/sessions')
|
24
|
+
def passwordless_for(resource, at: :na, as: :na, controller: "passwordless/sessions")
|
25
|
+
at == :na && at = "/#{resource.to_s}"
|
26
|
+
as == :na && as = "#{resource.to_s}_"
|
28
27
|
|
29
|
-
|
28
|
+
plural = resource.to_s
|
29
|
+
singular = plural.singularize
|
30
|
+
|
31
|
+
defaults = {
|
32
|
+
authenticatable: singular,
|
33
|
+
resource: resource,
|
34
|
+
}
|
35
|
+
|
36
|
+
scope(defaults: defaults) do
|
37
|
+
get("#{at}/sign_in", to: "#{controller}#new", as: :"#{as}sign_in")
|
38
|
+
post("#{at}/sign_in", to: "#{controller}#create")
|
39
|
+
get("#{at}/sign_in/:id", to: "#{controller}#show", as: :"verify_#{as}sign_in")
|
40
|
+
get("#{at}/sign_in/:id/:token", to: "#{controller}#confirm", as: :"confirm_#{as}sign_in")
|
41
|
+
patch("#{at}/sign_in/:id", to: "#{controller}#update")
|
42
|
+
match("#{at}/sign_out", to: "#{controller}#destroy", via: %i[get delete], as: :"#{as}sign_out")
|
43
|
+
end
|
30
44
|
end
|
31
45
|
end
|
32
46
|
end
|
@@ -2,25 +2,35 @@ module Passwordless
|
|
2
2
|
module TestHelpers
|
3
3
|
module TestCase
|
4
4
|
def passwordless_sign_out
|
5
|
-
delete
|
5
|
+
delete(Passwordless::Engine.routes.url_helpers.sign_out_path)
|
6
6
|
follow_redirect!
|
7
7
|
end
|
8
8
|
|
9
9
|
def passwordless_sign_in(resource)
|
10
|
-
session = Passwordless::Session.create!(authenticatable: resource
|
11
|
-
|
10
|
+
session = Passwordless::Session.create!(authenticatable: resource)
|
11
|
+
magic_link = Passwordless::Engine.routes.url_helpers.send(
|
12
|
+
:"confirm_#{session.authenticatable_type.tableize}_sign_in_url",
|
13
|
+
session,
|
14
|
+
session.token
|
15
|
+
)
|
16
|
+
get(magic_link)
|
12
17
|
follow_redirect!
|
13
18
|
end
|
14
19
|
end
|
15
20
|
|
16
21
|
module SystemTestCase
|
17
22
|
def passwordless_sign_out
|
18
|
-
visit
|
23
|
+
visit(Passwordless::Engine.routes.url_helpers.sign_out_path)
|
19
24
|
end
|
20
25
|
|
21
26
|
def passwordless_sign_in(resource)
|
22
|
-
session = Passwordless::Session.create!(authenticatable: resource
|
23
|
-
|
27
|
+
session = Passwordless::Session.create!(authenticatable: resource)
|
28
|
+
magic_link = Passwordless::Engine.routes.url_helpers.send(
|
29
|
+
:"confirm_#{session.authenticatable_type.tableize}_sign_in_url",
|
30
|
+
session,
|
31
|
+
session.token
|
32
|
+
)
|
33
|
+
visit(magic_link)
|
24
34
|
end
|
25
35
|
end
|
26
36
|
end
|
@@ -36,8 +46,8 @@ end
|
|
36
46
|
|
37
47
|
if defined?(RSpec)
|
38
48
|
RSpec.configure do |config|
|
39
|
-
config.include
|
40
|
-
config.include
|
41
|
-
config.include
|
49
|
+
config.include(::Passwordless::TestHelpers::TestCase, type: :request)
|
50
|
+
config.include(::Passwordless::TestHelpers::TestCase, type: :controller)
|
51
|
+
config.include(::Passwordless::TestHelpers::SystemTestCase, type: :system)
|
42
52
|
end
|
43
53
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Passwordless
|
2
|
+
class TokenDigest
|
3
|
+
ALGORITHM = "SHA256"
|
4
|
+
|
5
|
+
def initialize(str)
|
6
|
+
@str = str
|
7
|
+
end
|
8
|
+
|
9
|
+
def digest
|
10
|
+
key = self.class.key()
|
11
|
+
OpenSSL::HMAC.hexdigest(ALGORITHM, key, @str)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.key
|
15
|
+
@key ||= ActiveSupport::KeyGenerator.new(Rails.application.secret_key_base).generate_key("passwordless")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/passwordless/version.rb
CHANGED
data/lib/passwordless.rb
CHANGED
@@ -1,29 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support"
|
4
|
+
require "passwordless/config"
|
4
5
|
require "passwordless/errors"
|
5
6
|
require "passwordless/engine"
|
6
|
-
require "passwordless/
|
7
|
+
require "passwordless/token_digest"
|
7
8
|
|
8
9
|
# The main Passwordless module
|
9
10
|
module Passwordless
|
10
|
-
|
11
|
-
mattr_accessor(:default_from_address) { "CHANGE_ME@example.com" }
|
12
|
-
mattr_accessor(:token_generator) { UrlSafeBase64Generator.new }
|
13
|
-
mattr_accessor(:restrict_token_reuse) { false }
|
14
|
-
mattr_accessor(:redirect_back_after_sign_in) { true }
|
15
|
-
mattr_accessor(:mounted_as) { :configured_when_mounting_passwordless }
|
11
|
+
extend Configurable
|
16
12
|
|
17
|
-
|
18
|
-
|
19
|
-
mattr_accessor(:success_redirect_path) { "/" }
|
20
|
-
mattr_accessor(:failure_redirect_path) { "/" }
|
21
|
-
mattr_accessor(:sign_out_redirect_path) { "/" }
|
22
|
-
|
23
|
-
mattr_accessor(:after_session_save) do
|
24
|
-
lambda { |session, _request| Mailer.magic_link(session).deliver_now }
|
13
|
+
def self.digest(token)
|
14
|
+
TokenDigest.new(token).digest
|
25
15
|
end
|
26
|
-
|
27
|
-
CookieDeprecation = ActiveSupport::Deprecation.new("0.9", "passwordless")
|
28
|
-
SessionValidDeprecation = ActiveSupport::Deprecation.new("0.9", "passwordless")
|
29
16
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: passwordless
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mikkel Malmberg
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-09-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -28,58 +28,16 @@ dependencies:
|
|
28
28
|
name: bcrypt
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: 3.1.11
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: 3.1.11
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: sqlite3
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: 1.4.1
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: 1.4.1
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: yard
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: standard
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
36
|
version_requirements: !ruby/object:Gem::Requirement
|
79
37
|
requirements:
|
80
38
|
- - ">="
|
81
39
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
40
|
+
version: 3.1.11
|
83
41
|
description:
|
84
42
|
email:
|
85
43
|
- mikkel@brnbw.com
|
@@ -95,21 +53,23 @@ files:
|
|
95
53
|
- app/mailers/passwordless/mailer.rb
|
96
54
|
- app/models/passwordless/application_record.rb
|
97
55
|
- app/models/passwordless/session.rb
|
98
|
-
- app/views/passwordless/mailer/
|
99
|
-
- app/views/passwordless/sessions/create.html.erb
|
56
|
+
- app/views/passwordless/mailer/sign_in.text.erb
|
100
57
|
- app/views/passwordless/sessions/new.html.erb
|
58
|
+
- app/views/passwordless/sessions/show.html.erb
|
101
59
|
- config/locales/en.yml
|
102
60
|
- config/routes.rb
|
103
61
|
- db/migrate/20171104221735_create_passwordless_sessions.rb
|
104
62
|
- lib/generators/passwordless/views_generator.rb
|
105
63
|
- lib/passwordless.rb
|
64
|
+
- lib/passwordless/config.rb
|
106
65
|
- lib/passwordless/controller_helpers.rb
|
107
66
|
- lib/passwordless/engine.rb
|
108
67
|
- lib/passwordless/errors.rb
|
109
68
|
- lib/passwordless/model_helpers.rb
|
110
69
|
- lib/passwordless/router_helpers.rb
|
70
|
+
- lib/passwordless/short_token_generator.rb
|
111
71
|
- lib/passwordless/test_helpers.rb
|
112
|
-
- lib/passwordless/
|
72
|
+
- lib/passwordless/token_digest.rb
|
113
73
|
- lib/passwordless/version.rb
|
114
74
|
homepage: https://github.com/mikker/passwordless
|
115
75
|
licenses:
|
@@ -126,11 +86,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
126
86
|
version: '0'
|
127
87
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
88
|
requirements:
|
129
|
-
- - "
|
89
|
+
- - ">"
|
130
90
|
- !ruby/object:Gem::Version
|
131
|
-
version:
|
91
|
+
version: 1.3.1
|
132
92
|
requirements: []
|
133
|
-
rubygems_version: 3.
|
93
|
+
rubygems_version: 3.4.19
|
134
94
|
signing_key:
|
135
95
|
specification_version: 4
|
136
96
|
summary: Add authentication to your app without all the ickyness of passwords.
|
@@ -1 +0,0 @@
|
|
1
|
-
<%= I18n.t('passwordless.mailer.magic_link', link: @magic_link) %>
|
@@ -1 +0,0 @@
|
|
1
|
-
<p><%= I18n.t('passwordless.sessions.create.email_sent_if_record_found') %></p>
|
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Passwordless
|
4
|
-
# Generates random numbers for Session records
|
5
|
-
class UrlSafeBase64Generator
|
6
|
-
# Passwordless' default random string strategy. Generates a url safe
|
7
|
-
# base64 random string.
|
8
|
-
# @param _session [Session] Optional - Passwordless passes the sesion Record
|
9
|
-
# to generators so you can (optionally) use it for generating your tokens.
|
10
|
-
# @return [String] 32 byte base64 string
|
11
|
-
def call(_session)
|
12
|
-
SecureRandom.urlsafe_base64(32)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|