passwordless 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 44758dfedcb5f0b737a6892abdb754751f14d4da6d0c4e7e3ae9fa41d1b544ee
4
- data.tar.gz: 01e6534d9d3f8e11ff1f13e908c62a096fc32129a1f34df5a75defa97b7a0b31
3
+ metadata.gz: 7e765c341b12f05bb0156802dae574f7a0db31288181d4f71779a6ca49e48cd6
4
+ data.tar.gz: 746f09e1aefaea54d0f926c9bff27548ba1f8a4fdeeea0cfbd87ddc4b22ad65f
5
5
  SHA512:
6
- metadata.gz: 29e04ae936111350bf9673b2fd38f88e47006b72bcdd4aac5a38595623ab93558ab03e0a62677197d21f56e5370f38cc9fa5b5cc44bd8d8bdecf43e5ee66932d
7
- data.tar.gz: 0701f4569d5e37ca19d42eb1afe00bd4b99fb68a1e2951ff9ec419221d32fb559e012cbc80115013b94cb316b5b98c70f32e862ce448cc2985464a39f73d9e4a
6
+ metadata.gz: 8792ad81a4efbd5a071bb8a119d3e1ad057f2112e2bebbb888bbfdc9a84b95a77e4e2cb68ffb957fecb98f75cf05efb6c17cbd5c97b67a41f1372257eeb1cae9
7
+ data.tar.gz: 763dbbba33a8568976b5a5df2c28f0d157dcf9fc92504bf9ca016e85f8239c59b1e6ae48f4fa4e2e5ab2391aba9239ce956f7706c5437e168c27756a80fc9f33
data/README.md CHANGED
@@ -8,7 +8,24 @@
8
8
 
9
9
  Add authentication to your Rails app without all the icky-ness of passwords. _Magic link_ authentication, if you will. We call it _passwordless_.
10
10
 
11
- ---
11
+ - [Installation](#installation)
12
+ - [Upgrading](#upgrading)
13
+ - [Usage](#usage)
14
+ - [Getting the current user, restricting access, the usual](#getting-the-current-user-restricting-access-the-usual)
15
+ - [Providing your own templates](#providing-your-own-templates)
16
+ - [Registering new users](#registering-new-users)
17
+ - [URLs and links](#urls-and-links)
18
+ - [Route constraints](#route-constraints)
19
+ - [Configuration](#configuration)
20
+ - [Delivery method](#delivery-method)
21
+ - [Token generation](#token-generation)
22
+ - [Timeout and Expiry](#timeout-and-expiry)
23
+ - [Redirection after sign-in](#redirection-after-sign-in)
24
+ - [Looking up the user](#looking-up-the-user)
25
+ - [Test helpers](#test-helpers)
26
+ - [Security considerations](#security-considerations)
27
+ - [Alternatives](#alternatives)
28
+ - [License](#license)
12
29
 
13
30
  ## Installation
14
31
 
@@ -149,6 +166,35 @@ config.action_mailer.default_url_options = {host: "www.example.com"}
149
166
  routes.default_url_options[:host] ||= "www.example.com"
150
167
  ```
151
168
 
169
+ ### Route constraints
170
+
171
+ With [constraints](https://guides.rubyonrails.org/routing.html#request-based-constraints) you can restrict access to certain routes.
172
+ Passwordless provides `Passwordless::Constraint` and it's negative counterpart `Passwordless::NotConstraint` for this purpose.
173
+
174
+ To limit a route to only authenticated `User`s:
175
+
176
+ ```ruby
177
+ constraints Passwordless::Constraint.new(User) do
178
+ # ...
179
+ end
180
+ ```
181
+
182
+ The constraint takes a second `if:` argument, that expects a block and is passed the `authenticatable` record, (ie. `User`):
183
+
184
+ ```ruby
185
+ constraints Passwordless::Constraint.new(User, if: -> (user) { user.email.include?("john") }) do
186
+ # ...
187
+ end
188
+ ```
189
+
190
+ The negated version has the same API but with the opposite result, ie. ensuring authenticated user **don't** have access:
191
+
192
+ ```ruby
193
+ constraints Passwordless::NotConstraint.new(User) do
194
+ get("/no-users-allowed", to: "secrets#index")
195
+ end
196
+ ```
197
+
152
198
  ## Configuration
153
199
 
154
200
  To customize Passwordless, create a file `config/initializers/passwordless.rb`.
@@ -160,7 +206,7 @@ Passwordless.configure do |config|
160
206
  config.default_from_address = "CHANGE_ME@example.com"
161
207
  config.parent_controller = "ApplicationController"
162
208
  config.parent_mailer = "ActionMailer::Base"
163
- config.restrict_token_reuse = false # Can a token/link be used multiple times?
209
+ config.restrict_token_reuse = true # Can a token/link be used multiple times?
164
210
  config.token_generator = Passwordless::ShortTokenGenerator.new # Used to generate magic link tokens.
165
211
 
166
212
  config.expires_at = lambda { 1.year.from_now } # How long until a signed in session expires.
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "passwordless/controller_helpers"
4
+
5
+ module Passwordless
6
+ # A class the constraint routes to authenticated records
7
+ class Constraint
8
+ include ControllerHelpers
9
+
10
+ attr_reader :authenticatable_type, :predicate, :session
11
+
12
+ # @param [Class] authenticatable_type Authenticatable class
13
+ # @option options [Proc] :if A lambda that takes an authenticatable and returns a boolean
14
+ def initialize(authenticatable_type, **options)
15
+ @authenticatable_type = authenticatable_type
16
+ # `if' is a keyword but so we do this instead of keyword arguments
17
+ @predicate = options.fetch(:if) { -> (_) { true } }
18
+ end
19
+
20
+ def matches?(request)
21
+ # used in authenticate_by_session
22
+ @session = request.session
23
+ authenticatable = authenticate_by_session(authenticatable_type)
24
+ !!(authenticatable && predicate.call(authenticatable))
25
+ end
26
+ end
27
+
28
+ # A class the constraint routes to NOT authenticated records
29
+ class ConstraintNot < Constraint
30
+ # @param [Class] authenticatable_type Authenticatable class
31
+ # @option options [Proc] :if A lambda that takes an authenticatable and returns a boolean
32
+ def initialize(authenticatable_type, **options)
33
+ super
34
+ end
35
+
36
+ def matches?(request)
37
+ !super
38
+ end
39
+ end
40
+ end
@@ -54,7 +54,7 @@ module Passwordless
54
54
  end
55
55
 
56
56
  # Signs in session
57
- # @param authenticatable [Passwordless::Session] Instance of {Passwordless::Session}
57
+ # @param passwordless_session [Passwordless::Session] Instance of {Passwordless::Session}
58
58
  # to sign in
59
59
  # @return [ActiveRecord::Base] the record that is passed in.
60
60
  def sign_in(passwordless_session)
@@ -11,9 +11,5 @@ module Passwordless
11
11
  ActionDispatch::Routing::Mapper.include RouterHelpers
12
12
  ActiveRecord::Base.extend ModelHelpers
13
13
  end
14
-
15
- config.before_initialize do |app|
16
- app.config.i18n.load_path += Dir[Engine.root.join("config", "locales", "*.yml")]
17
- end
18
14
  end
19
15
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Passwordless
4
4
  # :nodoc:
5
- VERSION = "1.6.0"
5
+ VERSION = "1.7.0"
6
6
  end
data/lib/passwordless.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require "active_support"
4
4
  require "passwordless/config"
5
5
  require "passwordless/context"
6
+ require "passwordless/constraint"
6
7
  require "passwordless/errors"
7
8
  require "passwordless/engine"
8
9
  require "passwordless/token_digest"
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: 1.6.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikkel Malmberg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-25 00:00:00.000000000 Z
11
+ date: 2024-05-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -62,6 +62,7 @@ files:
62
62
  - lib/generators/passwordless/views_generator.rb
63
63
  - lib/passwordless.rb
64
64
  - lib/passwordless/config.rb
65
+ - lib/passwordless/constraint.rb
65
66
  - lib/passwordless/context.rb
66
67
  - lib/passwordless/controller_helpers.rb
67
68
  - lib/passwordless/engine.rb
@@ -91,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
91
92
  - !ruby/object:Gem::Version
92
93
  version: '0'
93
94
  requirements: []
94
- rubygems_version: 3.5.9
95
+ rubygems_version: 3.5.10
95
96
  signing_key:
96
97
  specification_version: 4
97
98
  summary: Add authentication to your app without all the ickyness of passwords.