magic-link 0.1.0 → 1.2.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: 6d9cdcff5bac8ba5789ac41f1b297408a4fba83f063d3afbb3bd585549996be9
4
- data.tar.gz: 6e7cf401d907dcdb65421a2fac94084b1749b3bd84e5d0e0ac334e82738ef96d
3
+ metadata.gz: 4702207f1e6738652b3afb874370dedda68060c8d9c8ae9eb083eba8acec3912
4
+ data.tar.gz: 7c4e9bf8c79ef5fd2bb426b8c6f5bcbbc8e5f31db27345f81719d7819388928f
5
5
  SHA512:
6
- metadata.gz: 58db75b1fed54635bdc015e83a7f170c5c3193b054d94a35270a58f269045925c5a26004edc7ce5f9218057a72bec54d4d3095bf66aab19fce6b9ff1801a55df
7
- data.tar.gz: b06b4740c460825a17e969ff4cc0d9272463c028dd6b855f49d2dff8767a6e62277601065416cc6a3d55d1b9512172d99b3d1cb6517198a1a6d987c49a028b38
6
+ metadata.gz: 1a7f9f1c88d957ff6e8b1975c6734af4fa42aff3d8b2700c0086353f3045364aa1c7d219db4b2cdb84a97e9d981966126277b28b65341e5ba9e9e8478ea53158
7
+ data.tar.gz: 689167a5bc00421dc3929edb49b447c8957467b0adb448e1c86ab736e628b9a5bb5de53b0422ae055d654da7df8aeb1c0b7af29885ace08a5032d673abd4217e
data/README.md CHANGED
@@ -19,7 +19,7 @@ mount the engine
19
19
  mount Magic::Link::Engine, at: '/'
20
20
  ```
21
21
 
22
- Now users can visit `/magic_links/new` to enter their email and have a sign in
22
+ Now users can visit `/magic_links/new` (which you can link to with `magic_link.new_magic_link_path`) to enter their email and have a sign in
23
23
  link sent to them via email. Tokens are cleared after use and expire after the
24
24
  configured number of hours
25
25
 
@@ -1,6 +1,7 @@
1
1
  module Magic
2
2
  module Link
3
3
  class MagicLinksController < ::ApplicationController
4
+ skip_before_action :authenticate_user!, :raise => false
4
5
  before_action :check_user, only: :new
5
6
 
6
7
  def new
@@ -13,6 +14,26 @@ module Magic
13
14
  redirect_to main_app.root_path, notice: "Check your email for a sign in link!"
14
15
  end
15
16
 
17
+ def authenticate
18
+ email = params[:email].presence
19
+ token = params[:sign_in_token].presence
20
+ user = email && token && Magic::Link.user_class.find_by(email: email)
21
+
22
+ # TODO: Handle a different user trying to sign in
23
+ if token && send("#{Magic::Link.user_class.name.underscore}_signed_in?")
24
+ flash[:alert] = "You are already signed in"
25
+ redirect_to main_app.send(Magic::Link.after_sign_in_path)
26
+ elsif user && token_matches?(user) && token_not_expired?(user)
27
+ flash[:notice] = "You have signed in successfully"
28
+ user.update_columns(sign_in_token: nil, sign_in_token_sent_at: nil)
29
+ sign_in user
30
+ redirect_to main_app.send(Magic::Link.after_sign_in_path)
31
+ elsif email && token
32
+ flash[:alert] = "Your sign in token is invalid"
33
+ redirect_to magic_link.new_magic_link_path
34
+ end
35
+ end
36
+
16
37
  private
17
38
 
18
39
  def check_user
@@ -21,6 +42,17 @@ module Magic
21
42
  end
22
43
  end
23
44
 
45
+ def token_matches?(user)
46
+ Devise.secure_compare(
47
+ user.sign_in_token,
48
+ Devise.token_generator.digest(Magic::Link.user_class, :sign_in_token, params[:sign_in_token])
49
+ )
50
+ end
51
+
52
+ def token_not_expired?(user)
53
+ user.sign_in_token_sent_at >= Magic::Link.token_expiration_hours.hours.ago
54
+ end
55
+
24
56
  def permitted_params
25
57
  params.fetch(:magic_link, {}).permit(:email)
26
58
  end
@@ -1,5 +1,5 @@
1
1
  <p>Hey there! Here is your sign in link (you can only use it once):</p>
2
2
 
3
- <p><%= link_to "Sign In", main_app.root_url(email: @email, sign_in_token: @token) %></p>
3
+ <p><%= link_to "Sign In", magic_link.authenticate_url(email: @email, sign_in_token: @token) %></p>
4
4
 
5
5
  <p>Thanks!</p>
@@ -1,5 +1,5 @@
1
1
  Hey there! Here is your sign in link (you can only use it once):
2
2
 
3
- <%= main_app.root_url(email: @email, sign_in_token: @token) %>
3
+ <%= magic_link.authenticate_url(email: @email, sign_in_token: @token) %>
4
4
 
5
5
  Thanks!
@@ -1,7 +1,11 @@
1
1
  <div class="row">
2
2
  <div class="col-md-6 offset-md-3">
3
- <%= simple_form_for @magic_link do |f| %>
4
- <%= f.input :email, label: "Enter your email", autofocus: true %>
3
+ <%= form_for @magic_link do |f| %>
4
+ <div class="field">
5
+ <%= f.label :email %><br />
6
+ <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
7
+ </div>
8
+
5
9
  <%= f.submit "Email me a sign in link", class: "btn btn-primary btn-block" %>
6
10
  <% end %>
7
11
  <br>
@@ -1,3 +1,4 @@
1
1
  Magic::Link::Engine.routes.draw do
2
2
  resources :magic_links, only: [:new, :create]
3
+ get "/magic_links/authenticate", to: "magic_links#authenticate", as: :authenticate
3
4
  end
@@ -1,5 +1,4 @@
1
1
  require "magic/link/engine"
2
- require "magic/link/controller_extensions"
3
2
  require "magic/link/railtie"
4
3
 
5
4
  module Magic
@@ -13,6 +12,9 @@ module Magic
13
12
  mattr_accessor :token_expiration_hours
14
13
  @@token_expiration_hours = 6
15
14
 
15
+ mattr_accessor :after_sign_in_path
16
+ @@after_sign_in_path = "root_path"
17
+
16
18
  class << self
17
19
  def configure
18
20
  yield self
@@ -2,9 +2,7 @@ module Magic
2
2
  module Link
3
3
  class Railtie < ::Rails::Railtie
4
4
  config.to_prepare do
5
- ::ApplicationController.send(:include, Magic::Link::ControllerExtensions)
6
5
  ::ApplicationController.send(:helper, Magic::Link::ApplicationHelper)
7
- ::ApplicationController.send(:before_action, :authenticate_user_from_token!)
8
6
  end
9
7
  end
10
8
  end
@@ -1,5 +1,5 @@
1
1
  module Magic
2
2
  module Link
3
- VERSION = '0.1.0'
3
+ VERSION = '1.2.0'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: magic-link
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Van Der Beek
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-20 00:00:00.000000000 Z
11
+ date: 2020-07-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '5.2'
19
+ version: 5.2.2.1
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
- version: '5.2'
26
+ version: 5.2.2.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: devise
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '4'
33
+ version: 4.7.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '4'
40
+ version: 4.7.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: sqlite3
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -77,7 +77,6 @@ files:
77
77
  - app/views/magic/link/magic_links/new.html.erb
78
78
  - config/routes.rb
79
79
  - lib/magic/link.rb
80
- - lib/magic/link/controller_extensions.rb
81
80
  - lib/magic/link/engine.rb
82
81
  - lib/magic/link/railtie.rb
83
82
  - lib/magic/link/version.rb
@@ -86,7 +85,7 @@ homepage: https://github.com/dvanderbeek/magic-link
86
85
  licenses:
87
86
  - MIT
88
87
  metadata: {}
89
- post_install_message:
88
+ post_install_message:
90
89
  rdoc_options: []
91
90
  require_paths:
92
91
  - lib
@@ -102,7 +101,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
101
  version: '0'
103
102
  requirements: []
104
103
  rubygems_version: 3.0.6
105
- signing_key:
104
+ signing_key:
106
105
  specification_version: 4
107
106
  summary: Devise magic sign in links
108
107
  test_files: []
@@ -1,39 +0,0 @@
1
- module Magic
2
- module Link
3
- module ControllerExtensions
4
- def self.included(base)
5
- base.send(:include, InstanceMethods)
6
- end
7
-
8
- module InstanceMethods
9
- def authenticate_user_from_token!
10
- email = params[:email].presence
11
- token = params[:sign_in_token].presence
12
- user = email && token && Magic::Link.user_class.find_by(email: email)
13
-
14
- if token && send("#{Magic::Link.user_class.name.underscore}_signed_in?")
15
- flash.now[:alert] = "You are already signed in"
16
- elsif user && token_matches?(user) && token_not_expired?(user)
17
- flash[:notice] = "You have signed in successfully"
18
- user.update_columns(sign_in_token: nil, sign_in_token_sent_at: nil)
19
- sign_in user
20
- elsif email && token
21
- flash[:alert] = "Your sign in token is invalid"
22
- redirect_to main_app.root_path
23
- end
24
- end
25
-
26
- def token_matches?(user)
27
- Devise.secure_compare(
28
- user.sign_in_token,
29
- Devise.token_generator.digest(Magic::Link.user_class, :sign_in_token, params[:sign_in_token])
30
- )
31
- end
32
-
33
- def token_not_expired?(user)
34
- user.sign_in_token_sent_at >= Magic::Link.token_expiration_hours.hours.ago
35
- end
36
- end
37
- end
38
- end
39
- end