passwordless 0.12.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 +108 -191
- 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 +32 -70
- 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 -19
- metadata +12 -51
- data/app/views/passwordless/mailer/magic_link.text.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,30 +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(:redirect_to_response_options) { {} }
|
20
|
-
mattr_accessor(:success_redirect_path) { "/" }
|
21
|
-
mattr_accessor(:failure_redirect_path) { "/" }
|
22
|
-
mattr_accessor(:sign_out_redirect_path) { "/" }
|
23
|
-
|
24
|
-
mattr_accessor(:after_session_save) do
|
25
|
-
lambda { |session, _request| Mailer.magic_link(session).deliver_now }
|
13
|
+
def self.digest(token)
|
14
|
+
TokenDigest.new(token).digest
|
26
15
|
end
|
27
|
-
|
28
|
-
CookieDeprecation = ActiveSupport::Deprecation.new("0.9", "passwordless")
|
29
|
-
SessionValidDeprecation = ActiveSupport::Deprecation.new("0.9", "passwordless")
|
30
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: 2023-
|
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
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
37
|
requirements:
|
73
38
|
- - ">="
|
74
39
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
40
|
+
version: 3.1.11
|
83
41
|
description:
|
84
42
|
email:
|
85
43
|
- mikkel@brnbw.com
|
@@ -95,20 +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/
|
56
|
+
- app/views/passwordless/mailer/sign_in.text.erb
|
99
57
|
- app/views/passwordless/sessions/new.html.erb
|
58
|
+
- app/views/passwordless/sessions/show.html.erb
|
100
59
|
- config/locales/en.yml
|
101
60
|
- config/routes.rb
|
102
61
|
- db/migrate/20171104221735_create_passwordless_sessions.rb
|
103
62
|
- lib/generators/passwordless/views_generator.rb
|
104
63
|
- lib/passwordless.rb
|
64
|
+
- lib/passwordless/config.rb
|
105
65
|
- lib/passwordless/controller_helpers.rb
|
106
66
|
- lib/passwordless/engine.rb
|
107
67
|
- lib/passwordless/errors.rb
|
108
68
|
- lib/passwordless/model_helpers.rb
|
109
69
|
- lib/passwordless/router_helpers.rb
|
70
|
+
- lib/passwordless/short_token_generator.rb
|
110
71
|
- lib/passwordless/test_helpers.rb
|
111
|
-
- lib/passwordless/
|
72
|
+
- lib/passwordless/token_digest.rb
|
112
73
|
- lib/passwordless/version.rb
|
113
74
|
homepage: https://github.com/mikker/passwordless
|
114
75
|
licenses:
|
@@ -125,11 +86,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
125
86
|
version: '0'
|
126
87
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
88
|
requirements:
|
128
|
-
- - "
|
89
|
+
- - ">"
|
129
90
|
- !ruby/object:Gem::Version
|
130
|
-
version:
|
91
|
+
version: 1.3.1
|
131
92
|
requirements: []
|
132
|
-
rubygems_version: 3.4.
|
93
|
+
rubygems_version: 3.4.19
|
133
94
|
signing_key:
|
134
95
|
specification_version: 4
|
135
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,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
|