passwordless 1.6.0 → 1.7.0
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 +48 -2
- data/lib/passwordless/constraint.rb +40 -0
- data/lib/passwordless/controller_helpers.rb +1 -1
- data/lib/passwordless/engine.rb +0 -4
- data/lib/passwordless/version.rb +1 -1
- data/lib/passwordless.rb +1 -0
- metadata +4 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 7e765c341b12f05bb0156802dae574f7a0db31288181d4f71779a6ca49e48cd6
         | 
| 4 | 
            +
              data.tar.gz: 746f09e1aefaea54d0f926c9bff27548ba1f8a4fdeeea0cfbd87ddc4b22ad65f
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 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 =  | 
| 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  | 
| 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)
         | 
    
        data/lib/passwordless/engine.rb
    CHANGED
    
    | @@ -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
         | 
    
        data/lib/passwordless/version.rb
    CHANGED
    
    
    
        data/lib/passwordless.rb
    CHANGED
    
    
    
        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. | 
| 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- | 
| 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. | 
| 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.
         |