passwordless 0.4.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 482e11575373d9175f46bb4ad1d70bbad5297de2b9e732a84db9051a5ea493b9
4
- data.tar.gz: 578348c9d8ea9dcac2eba8576ee0f110f698c519247882c39abe1e7c420a41a6
3
+ metadata.gz: d79c41fb0ddc3797af28166832ab336c3c3c2347c9336be03e04441554347772
4
+ data.tar.gz: 0f24f481eff8e766e7546e21c53fa196fa61421037a6543c58c7bca81e78899e
5
5
  SHA512:
6
- metadata.gz: e82a891d207b39e8b6dd3641f9091a7f16c082947ebb787b25bcd126135cade72f6a098405dc424c73e16431a6ded7f97f55ef2298a870bdcf01698f97083347
7
- data.tar.gz: 01d409c746efa765165947fd7bf83dd15371ac55559fa881535242fcab12b333bb9d7bce1a50c3d6eb2ef0fac3bd8e3d52dbf9a9d3719ca22bf6ff4dc0cb14a7
6
+ metadata.gz: c3a7038ffd29a1cb8218905fb974fd3d59b45b11190e3df9e125e8fc5c200638d7f7cf1c954d3a17b256594c4429a144fcd5259a210fa3fed5b13a05551af6c4
7
+ data.tar.gz: 3a1506b2dfba720a3ca82df7ce992fb74d450691dd31e8b250d961a7c882680fda2fb36674a6d474fa7114dc922839448547ade16b6c1c57348c08b1c9c8de25
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  <br />
5
5
  </p>
6
6
 
7
- <img src='https://travis-ci.org/mikker/passwordless.svg?branch=master' alt='Build status' /> <img src='https://img.shields.io/gem/v/passwordless.svg' alt='Gem version' />
7
+ [![Travis](https://travis-ci.org/mikker/passwordless.svg?branch=master)](https://travis-ci.org/mikker/passwordless) [![Rubygems](https://img.shields.io/gem/v/passwordless.svg)](https://rubygems.org/gems/passwordless) [![codecov](https://codecov.io/gh/mikker/passwordless/branch/master/graph/badge.svg)](https://codecov.io/gh/mikker/passwordless)
8
8
 
9
9
  Add authentication to your Rails app without all the icky-ness of passwords.
10
10
 
@@ -19,6 +19,7 @@ Add authentication to your Rails app without all the icky-ness of passwords.
19
19
  * [Registering new users](#registering-new-users)
20
20
  * [Generating tokens](#generating-tokens)
21
21
  * [Redirecting back after sign-in](#redirecting-back-after-sign-in)
22
+ * [URLs and links](#urls-and-links)
22
23
  * [License](#license)
23
24
 
24
25
  ## Installation
@@ -48,7 +49,9 @@ Then specify which field on your `User` record is the email field with:
48
49
 
49
50
  ```ruby
50
51
  class User < ApplicationRecord
51
- passwordless_with :email
52
+ validates :email, presence: true, uniqueness: { case_sensitive: false }
53
+
54
+ passwordless_with :email # <-- here!
52
55
  end
53
56
  ```
54
57
 
@@ -87,11 +90,11 @@ class ApplicationController < ActionController::Base
87
90
  end
88
91
  ```
89
92
 
90
- Et voilá:
93
+ Et voilà:
91
94
 
92
95
  ```ruby
93
96
  class VerySecretThingsController < ApplicationController
94
- before_filter :require_user!
97
+ before_action :require_user!
95
98
 
96
99
  def index
97
100
  @things = current_user.very_secret_things
@@ -162,7 +165,7 @@ class ApplicationController < ActionController::Base
162
165
 
163
166
  def require_user!
164
167
  return if current_user
165
- save_passwordless_redirect_location! # <-- here we go!
168
+ save_passwordless_redirect_location!(User) # <-- here we go!
166
169
  redirect_to root_path, flash: {error: 'You are not worthy!'}
167
170
  end
168
171
  end
@@ -170,6 +173,20 @@ end
170
173
 
171
174
  This can be turned off with `Passwordless.redirect_back_after_sign_in = false` but if you just don't save the previous destination, you'll be fine.
172
175
 
176
+ ### URLs and links
177
+
178
+ By default, Passwordless uses the resource name given to `passwordless_for` to generate its routes and helpers.
179
+
180
+ ```ruby
181
+ passwordless_for :users
182
+ # <%= users.sign_in_path %> # => /users/sign_in
183
+
184
+ passwordless_for :users, at: '/', as: :auth
185
+ # <%= auth.sign_in_path %> # => /sign_in
186
+ ```
187
+
188
+ Also be sure to [specify ActionMailer's `default_url_options.host`](http://guides.rubyonrails.org/action_mailer_basics.html#generating-urls-in-action-mailer-views).
189
+
173
190
  # License
174
191
 
175
192
  MIT
data/Rakefile CHANGED
@@ -1,22 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
4
  require 'bundler/setup'
3
5
  rescue LoadError
4
6
  puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
7
  end
6
8
 
7
- require 'rdoc/task'
8
-
9
- RDoc::Task.new(:rdoc) do |rdoc|
10
- rdoc.rdoc_dir = 'rdoc'
11
- rdoc.title = 'Passwordless'
12
- rdoc.options << '--line-numbers'
13
- rdoc.rdoc_files.include('README.md')
14
- rdoc.rdoc_files.include('lib/**/*.rb')
15
- end
9
+ require 'yard'
10
+ YARD::Rake::YardocTask.new
11
+ task docs: :yard
16
12
 
17
- APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
13
+ APP_RAKEFILE = File.expand_path('../test/dummy/Rakefile', __FILE__)
18
14
  load 'rails/tasks/engine.rake'
19
-
20
15
  load 'rails/tasks/statistics.rake'
21
16
 
22
17
  require 'bundler/gem_tasks'
@@ -1,5 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passwordless
4
+ # Base for Passwordless controllers
2
5
  class ApplicationController < ::ApplicationController
6
+ # Always returns true. Use to check if <Some>Controller inherits
7
+ # from ApplicationController.
8
+ # @return [boolean]
3
9
  def passwordless_controller?
4
10
  true
5
11
  end
@@ -1,28 +1,31 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bcrypt'
2
4
 
3
5
  module Passwordless
6
+ # Controller for managing Passwordless sessions
4
7
  class SessionsController < ApplicationController
8
+ # Raise this exception when a session is expired.
9
+ class ExpiredSessionError < StandardError; end
10
+
5
11
  include ControllerHelpers
6
12
 
7
13
  helper_method :authenticatable_resource
8
14
 
15
+ # get '/sign_in'
16
+ # Assigns an email_field and new Session to be used by new view.
17
+ # renders sessions/new.html.erb.
9
18
  def new
10
- @email_field = authenticatable_class.passwordless_email_field
11
-
19
+ @email_field = email_field
12
20
  @session = Session.new
13
21
  end
14
22
 
23
+ # post '/sign_in'
24
+ # Creates a new Session record then sends the magic link
25
+ # renders sessions/create.html.erb.
26
+ # @see Mailer#magic_link Mailer#magic_link
15
27
  def create
16
- email_field = authenticatable_class.passwordless_email_field
17
- authenticatable = authenticatable_class.where(
18
- "lower(#{email_field}) = ?", params[:passwordless][email_field]
19
- ).first
20
-
21
- session = Session.new.tap do |us|
22
- us.remote_addr = request.remote_addr
23
- us.user_agent = request.env['HTTP_USER_AGENT']
24
- us.authenticatable = authenticatable
25
- end
28
+ session = build_passwordless_session(find_authenticatable)
26
29
 
27
30
  if session.save
28
31
  Mailer.magic_link(session).deliver_now
@@ -31,27 +34,40 @@ module Passwordless
31
34
  render
32
35
  end
33
36
 
37
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
38
+
39
+ # get '/sign_in/:token'
40
+ # Looks up session record by provided token. Signs in user if a match
41
+ # is found. Redirects to either the user's original destination
42
+ # or _root_path_
43
+ # @see ControllerHelpers#sign_in
44
+ # @see ControllerHelpers#save_passwordless_redirect_location!
34
45
  def show
35
46
  # Make it "slow" on purpose to make brute-force attacks more of a hassle
36
47
  BCrypt::Password.create(params[:token])
37
48
 
38
- session = Session.valid.find_by!(
39
- authenticatable_type: authenticatable_classname,
40
- token: params[:token]
41
- )
49
+ session = find_session
50
+ raise ExpiredSessionError if session.expired?
42
51
 
43
52
  sign_in session.authenticatable
44
53
 
45
- enabled = Passwordless.redirect_back_after_sign_in
46
- destination = dest = reset_passwordless_redirect_location!
54
+ redirect_enabled = Passwordless.redirect_back_after_sign_in
55
+ destination = reset_passwordless_redirect_location!(User)
47
56
 
48
- if enabled && destination
49
- redirect_to dest
57
+ if redirect_enabled && destination
58
+ redirect_to destination
50
59
  else
51
60
  redirect_to main_app.root_path
52
61
  end
62
+ rescue ExpiredSessionError
63
+ flash[:error] = I18n.t('.passwordless.sessions.create.session_expired')
64
+ redirect_to main_app.root_path
53
65
  end
66
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
54
67
 
68
+ # match '/sign_out', via: %i[get delete].
69
+ # Signs user out. Redirects to root_path
70
+ # @see ControllerHelpers#sign_out
55
71
  def destroy
56
72
  sign_out authenticatable_class
57
73
  redirect_to main_app.root_path
@@ -74,5 +90,22 @@ module Passwordless
74
90
  def authenticatable_resource
75
91
  authenticatable.pluralize
76
92
  end
93
+
94
+ def email_field
95
+ authenticatable_class.passwordless_email_field
96
+ end
97
+
98
+ def find_authenticatable
99
+ authenticatable_class.where(
100
+ "lower(#{email_field}) = ?", params[:passwordless][email_field]
101
+ ).first
102
+ end
103
+
104
+ def find_session
105
+ Session.valid.find_by!(
106
+ authenticatable_type: authenticatable_classname,
107
+ token: params[:token]
108
+ )
109
+ end
77
110
  end
78
111
  end
@@ -1,7 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passwordless
4
+ # The mailer responsible for sending Passwordless' mails.
2
5
  class Mailer < ActionMailer::Base
3
6
  default from: Passwordless.default_from_address
4
7
 
8
+ # Sends a magic link (secret token) email.
9
+ # @param session [Session] A Passwordless Session
5
10
  def magic_link(session)
6
11
  @session = session
7
12
 
@@ -11,7 +16,10 @@ module Passwordless
11
16
  send(authenticatable_resource_name).token_sign_in_url(session.token)
12
17
 
13
18
  email_field = @session.authenticatable.class.passwordless_email_field
14
- mail to: @session.authenticatable.send(email_field), subject: "Your magic link ✨"
19
+ mail(
20
+ to: @session.authenticatable.send(email_field),
21
+ subject: I18n.t('passwordless.mailer.subject')
22
+ )
15
23
  end
16
24
  end
17
25
  end
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passwordless
4
+ # Base record for Passordless' models
2
5
  class ApplicationRecord < ActiveRecord::Base
3
6
  self.abstract_class = true
4
7
  end
@@ -1,6 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passwordless
4
+ # The session responsible for holding the connection between the record
5
+ # trying to log in and the unique tokens.
2
6
  class Session < ApplicationRecord
3
- belongs_to :authenticatable, polymorphic: true
7
+ belongs_to :authenticatable,
8
+ polymorphic: true, inverse_of: :passwordless_sessions
4
9
 
5
10
  validates \
6
11
  :timeout_at,
@@ -13,9 +18,13 @@ module Passwordless
13
18
  before_validation :set_defaults
14
19
 
15
20
  scope :valid, lambda {
16
- where('timeout_at > ? AND expires_at > ?', Time.current, Time.current)
21
+ where('timeout_at > ?', Time.current)
17
22
  }
18
23
 
24
+ def expired?
25
+ expires_at <= Time.current
26
+ end
27
+
19
28
  private
20
29
 
21
30
  def set_defaults
@@ -1,2 +1 @@
1
- Here's your link:
2
- <%= @magic_link %>
1
+ <%= I18n.t('passwordless.mailer.magic_link', link: @magic_link) %>
@@ -1 +1 @@
1
- <p>If we found you in the system, we've sent you an email.</p>
1
+ <p><%= I18n.t('passwordless.sessions.success.email_sent_if_record_found') %></p>
@@ -1,5 +1,5 @@
1
1
  <%= form_for @session, url: send(authenticatable_resource).sign_in_path do |f| %>
2
2
  <% email_field_name = :"passwordless[#{@email_field}]" %>
3
3
  <%= text_field_tag email_field_name, params.fetch(email_field_name, nil) %>
4
- <%= f.submit 'Send magic link' %>
4
+ <%= f.submit I18n.t('passwordless.sessions.new.submit') %>
5
5
  <% end %>
@@ -0,0 +1,12 @@
1
+ ---
2
+ en:
3
+ passwordless:
4
+ sessions:
5
+ create:
6
+ session_expired: 'Your session has expired, please sign in again.'
7
+ email_sent_if_record_found: "If we found you in the system, we've sent you an email."
8
+ new:
9
+ submit: 'Send magic link'
10
+ mailer:
11
+ subject: "Your magic link ✨'"
12
+ magic_link: "Here's your link: %{link}"
data/config/routes.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Passwordless::Engine.routes.draw do
2
4
  get '/sign_in', to: 'sessions#new', as: :sign_in
3
5
  post '/sign_in', to: 'sessions#create'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CreatePasswordlessSessions < ActiveRecord::Migration[5.1]
2
4
  def change
3
5
  create_table :passwordless_sessions do |t|
@@ -1,5 +1,29 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passwordless
4
+ # Helpers to work with Passwordless sessions from controllers
2
5
  module ControllerHelpers
6
+ # Build a new Passwordless::Session from an _authenticatable_ record.
7
+ # Set's `user_agent` and `remote_addr` from Rails' `request`.
8
+ # @param authenticatable [ActiveRecord::Base] Instance of an
9
+ # authenticatable Rails model
10
+ # @return [Session] the new Session object
11
+ # @see ModelHelpers#passwordless_with
12
+ def build_passwordless_session(authenticatable)
13
+ Session.new.tap do |us|
14
+ us.remote_addr = request.remote_addr
15
+ us.user_agent = request.env['HTTP_USER_AGENT']
16
+ us.authenticatable = authenticatable
17
+ end
18
+ end
19
+
20
+ # Authenticate a record using cookies. Looks for a cookie corresponding to
21
+ # the _authenticatable_class_. If found try to find it in the database.
22
+ # @param authenticatable_class [ActiveRecord::Base] any Model connected to
23
+ # passwordless. (e.g - _User_ or _Admin_).
24
+ # @return [ActiveRecord::Base|nil] an instance of Model found by id stored
25
+ # in cookies.encrypted or nil if nothing is found.
26
+ # @see ModelHelpers#passwordless_with
3
27
  def authenticate_by_cookie(authenticatable_class)
4
28
  key = cookie_name(authenticatable_class)
5
29
  authenticatable_id = cookies.encrypted[key]
@@ -8,28 +32,49 @@ module Passwordless
8
32
  authenticatable_class.find_by(id: authenticatable_id)
9
33
  end
10
34
 
35
+ # Signs in user by assigning their id to a permanent cookie.
36
+ # @param authenticatable [ActiveRecord::Base] Instance of Model to sign in
37
+ # (e.g - @user when @user = User.find(id: some_id)).
38
+ # @return [ActiveRecord::Base] the record that is passed in.
11
39
  def sign_in(authenticatable)
12
40
  key = cookie_name(authenticatable.class)
13
41
  cookies.encrypted.permanent[key] = { value: authenticatable.id }
14
42
  authenticatable
15
43
  end
16
44
 
45
+ # Signs out user by deleting their encrypted cookie.
46
+ # @param (see #authenticate_by_cookie)
47
+ # @return [boolean] Always true
17
48
  def sign_out(authenticatable_class)
18
49
  key = cookie_name(authenticatable_class)
19
50
  cookies.encrypted.permanent[key] = { value: nil }
20
51
  cookies.delete(key)
52
+ true
21
53
  end
22
54
 
23
- def save_passwordless_redirect_location!
24
- session[:destination_when_rejected] = request.original_url
55
+ # Saves request.original_url as the redirect location for a
56
+ # passwordless Model.
57
+ # @param (see #authenticate_by_cookie)
58
+ # @return [String] the redirect url that was just saved.
59
+ def save_passwordless_redirect_location!(authenticatable_class)
60
+ session[session_key(authenticatable_class)] = request.original_url
25
61
  end
26
62
 
27
- def reset_passwordless_redirect_location!
28
- session.delete :destination_when_rejected
63
+ # Resets the redirect_location to root_path by deleting the redirect_url
64
+ # from session.
65
+ # @param (see #authenticate_by_cookie)
66
+ # @return [String, nil] the redirect url that was just deleted,
67
+ # or nil if no url found for given Model.
68
+ def reset_passwordless_redirect_location!(authenticatable_class)
69
+ session.delete session_key(authenticatable_class)
29
70
  end
30
71
 
31
72
  private
32
73
 
74
+ def session_key(authenticatable_class)
75
+ :"passwordless_prev_location--#{authenticatable_class}"
76
+ end
77
+
33
78
  def cookie_name(authenticatable_class)
34
79
  :"#{authenticatable_class.to_s.underscore}_id"
35
80
  end
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passwordless
4
+ # Engine that runs the passwordless gem.
2
5
  class Engine < ::Rails::Engine
3
6
  isolate_namespace Passwordless
4
7
 
@@ -9,5 +12,10 @@ module Passwordless
9
12
  ActiveRecord::Base.extend ModelHelpers
10
13
  require 'passwordless/controller_helpers'
11
14
  end
15
+
16
+ config.before_initialize do |app|
17
+ app.config.i18n.load_path +=
18
+ Dir[Engine.root.join('config', 'locales', '*.yml')]
19
+ end
12
20
  end
13
21
  end
@@ -1,6 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passwordless
4
+ # Some helpers for models that can sign in passswordlessly.
2
5
  module ModelHelpers
6
+ # Creates relationship - has_many :passwordless_sessions
7
+ # Defines a method `Class.passwordless_email_field` returning its email
8
+ # field name (e.g. `:email`)
9
+ # @param field [string] email submitted by user.
3
10
  def passwordless_with(field)
11
+ has_many :passwordless_sessions, class_name: 'Passwordless::Session'
4
12
  define_singleton_method(:passwordless_email_field) { field }
5
13
  end
6
14
  end
@@ -1,5 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passwordless
4
+ # Helpers for generating passwordless routes.
2
5
  module RouterHelpers
6
+ # Generates passwordless routes for a given Model
7
+ # Example usage:
8
+ # passwordless_for :users
9
+ # # or with options ...
10
+ # passwordless_for :users, at: 'session_stuff', as: :user_session_things
11
+ # @param resource [Symbol] the pluralized symbol of a Model (e.g - :users).
12
+ # @param at [String] Optional - provide custom path for the passwordless
13
+ # engine to get mounted at (using the above example your URLs end
14
+ # up like: /session_stuff/sign_in). (Default: resource.to_s)
15
+ # @param as [Symbol] Optional - provide custom scope for url
16
+ # helpers (using the above example in a view:
17
+ # <%= link_to 'Sign in', user_session_things.sign_in_path %>).
18
+ # (Default: resource.to_s)
3
19
  def passwordless_for(resource, at: nil, as: nil)
4
20
  mount(
5
21
  Passwordless::Engine,
@@ -1,5 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passwordless
4
+ # Generates random numbers for Session records
2
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
3
11
  def call(_session)
4
12
  SecureRandom.urlsafe_base64(32)
5
13
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passwordless
2
- VERSION = '0.4.0'
4
+ VERSION = '0.5.0' # :nodoc:
3
5
  end
data/lib/passwordless.rb CHANGED
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'passwordless/engine'
2
4
  require 'passwordless/url_safe_base_64_generator'
3
5
 
6
+ # The main Passwordless module
4
7
  module Passwordless
5
8
  mattr_accessor(:default_from_address) { 'CHANGE_ME@example.com' }
6
- mattr_accessor(:token_generator) do
7
- UrlSafeBase64Generator.new
8
- end
9
+ mattr_accessor(:token_generator) { UrlSafeBase64Generator.new }
9
10
  mattr_accessor(:redirect_back_after_sign_in) { true }
10
11
  end
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: passwordless
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.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: 2017-11-27 00:00:00.000000000 Z
11
+ date: 2018-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 5.1.4
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 5.1.4
27
27
  - !ruby/object:Gem::Dependency
@@ -52,7 +52,35 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- description: Description of Passwordless.
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: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description:
56
84
  email:
57
85
  - mikkel@brnbw.com
58
86
  executables: []
@@ -70,6 +98,7 @@ files:
70
98
  - app/views/passwordless/mailer/magic_link.text.erb
71
99
  - app/views/passwordless/sessions/create.html.erb
72
100
  - app/views/passwordless/sessions/new.html.erb
101
+ - config/locales/en.yml
73
102
  - config/routes.rb
74
103
  - db/migrate/20171104221735_create_passwordless_sessions.rb
75
104
  - lib/passwordless.rb
@@ -79,7 +108,6 @@ files:
79
108
  - lib/passwordless/router_helpers.rb
80
109
  - lib/passwordless/url_safe_base_64_generator.rb
81
110
  - lib/passwordless/version.rb
82
- - lib/tasks/passwordless_tasks.rake
83
111
  homepage: https://github.com/mikker/passwordless
84
112
  licenses:
85
113
  - MIT
@@ -100,8 +128,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
128
  version: '0'
101
129
  requirements: []
102
130
  rubyforge_project:
103
- rubygems_version: 2.7.2
131
+ rubygems_version: 2.7.3
104
132
  signing_key:
105
133
  specification_version: 4
106
- summary: Summary of Passwordless.
134
+ summary: Add authentication to your app without all the ickyness of passwords.
107
135
  test_files: []
@@ -1,4 +0,0 @@
1
- # desc "Explaining what the task does"
2
- # task :passwordless do
3
- # # Task goes here
4
- # end