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 +4 -4
- data/README.md +1 -1
- data/app/controllers/magic/link/magic_links_controller.rb +32 -0
- data/app/views/magic/link/magic_link_mailer/send_magic_link.html.erb +1 -1
- data/app/views/magic/link/magic_link_mailer/send_magic_link.text.erb +1 -1
- data/app/views/magic/link/magic_links/new.html.erb +6 -2
- data/config/routes.rb +1 -0
- data/lib/magic/link.rb +3 -1
- data/lib/magic/link/railtie.rb +0 -2
- data/lib/magic/link/version.rb +1 -1
- metadata +9 -10
- data/lib/magic/link/controller_extensions.rb +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4702207f1e6738652b3afb874370dedda68060c8d9c8ae9eb083eba8acec3912
|
4
|
+
data.tar.gz: 7c4e9bf8c79ef5fd2bb426b8c6f5bcbbc8e5f31db27345f81719d7819388928f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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",
|
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,7 +1,11 @@
|
|
1
1
|
<div class="row">
|
2
2
|
<div class="col-md-6 offset-md-3">
|
3
|
-
<%=
|
4
|
-
|
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>
|
data/config/routes.rb
CHANGED
data/lib/magic/link.rb
CHANGED
@@ -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
|
data/lib/magic/link/railtie.rb
CHANGED
@@ -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
|
data/lib/magic/link/version.rb
CHANGED
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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
|