authkit 0.4.0 → 0.5.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 +0 -3
- data/Rakefile +3 -2
- data/lib/authkit/version.rb +1 -1
- data/lib/generators/authkit/install_generator.rb +181 -35
- data/lib/generators/authkit/templates/app/controllers/application_controller.rb +6 -0
- data/lib/generators/authkit/templates/app/controllers/auths_controller.rb +144 -0
- data/lib/generators/authkit/templates/app/controllers/email_confirmation_controller.rb +1 -1
- data/lib/generators/authkit/templates/app/controllers/password_reset_controller.rb +7 -1
- data/lib/generators/authkit/templates/app/controllers/sessions_controller.rb +11 -2
- data/lib/generators/authkit/templates/app/controllers/signup_controller.rb +4 -2
- data/lib/generators/authkit/templates/app/controllers/upload_controller.rb +78 -0
- data/lib/generators/authkit/templates/app/controllers/users_controller.rb +2 -2
- data/lib/generators/authkit/templates/app/forms/signup.rb +57 -7
- data/lib/generators/authkit/templates/app/helpers/auths_helper.rb +26 -0
- data/lib/generators/authkit/templates/app/helpers/upload_helper.rb +118 -0
- data/lib/generators/authkit/templates/app/models/auth.rb +81 -0
- data/lib/generators/authkit/templates/app/models/avatar.rb +45 -0
- data/lib/generators/authkit/templates/app/models/user.rb +53 -26
- data/lib/generators/authkit/templates/app/views/auths/connect.html.erb +34 -0
- data/lib/generators/authkit/templates/app/views/password_change/show.html.erb +9 -9
- data/lib/generators/authkit/templates/app/views/password_reset/show.html.erb +6 -6
- data/lib/generators/authkit/templates/app/views/sessions/new.html.erb +25 -7
- data/lib/generators/authkit/templates/app/views/signup/new.html.erb +44 -32
- data/lib/generators/authkit/templates/app/views/users/complete.html.erb +39 -0
- data/lib/generators/authkit/templates/app/views/users/edit.html.erb +31 -31
- data/lib/generators/authkit/templates/app/workers/avatar_import_worker.rb +12 -0
- data/lib/generators/authkit/templates/config/initializers/filter_parameter_logging.rb +2 -2
- data/lib/generators/authkit/templates/config/initializers/omniauth.rb +59 -0
- data/lib/generators/authkit/templates/config/initializers/paperclip.rb +68 -0
- data/lib/generators/authkit/templates/db/migrate/add_authkit_fields_to_users.rb +8 -6
- data/lib/generators/authkit/templates/db/migrate/create_auths.rb +24 -0
- data/lib/generators/authkit/templates/db/migrate/create_avatars.rb +27 -0
- data/lib/generators/authkit/templates/lib/full_name_splitter.rb +111 -0
- data/lib/generators/authkit/templates/lib/username_format_validator.rb +11 -0
- data/lib/generators/authkit/templates/spec/controllers/application_controller_spec.rb +31 -38
- data/lib/generators/authkit/templates/spec/controllers/auths_controller_spec.rb +72 -0
- data/lib/generators/authkit/templates/spec/controllers/email_confirmation_controller_spec.rb +25 -27
- data/lib/generators/authkit/templates/spec/controllers/password_change_controller_spec.rb +30 -30
- data/lib/generators/authkit/templates/spec/controllers/password_reset_controller_spec.rb +20 -20
- data/lib/generators/authkit/templates/spec/controllers/sessions_controller_spec.rb +33 -33
- data/lib/generators/authkit/templates/spec/controllers/signup_controller_spec.rb +19 -19
- data/lib/generators/authkit/templates/spec/controllers/users_controller_spec.rb +21 -21
- data/lib/generators/authkit/templates/spec/factories/user.rb +3 -3
- data/lib/generators/authkit/templates/spec/forms/signup_spec.rb +32 -31
- data/lib/generators/authkit/templates/spec/models/auth_spec.rb +18 -0
- data/lib/generators/authkit/templates/spec/models/user_spec.rb +72 -78
- data/spec/rails_helper.rb +50 -0
- data/spec/spec_helper.rb +70 -13
- metadata +35 -17
- data/lib/generators/authkit/templates/spec/spec_helper.rb +0 -4
@@ -0,0 +1,59 @@
|
|
1
|
+
OmniAuth.config.logger = Rails.logger
|
2
|
+
|
3
|
+
Rails.application.config.middleware.use OmniAuth::Builder do
|
4
|
+
<% if provider?(:facebook) %>
|
5
|
+
# https://github.com/mkdynamic/omniauth-facebook
|
6
|
+
provider :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET'], {
|
7
|
+
setup: lambda{ |env|
|
8
|
+
default_scope = 'email'
|
9
|
+
env['omniauth.strategy'].options[:scope] = env['rack.session']['facebook_oauth_scope'] || default_scope
|
10
|
+
},
|
11
|
+
display: 'popup',
|
12
|
+
image_size: 'square', # 50x50
|
13
|
+
reauthenticate: true
|
14
|
+
}
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<% if provider?(:google) %>
|
18
|
+
# https://github.com/zquestz/omniauth-google-oauth2
|
19
|
+
provider :google_oauth2, ENV['GOOGLE_API_CLIENT_ID'], ENV['GOOGLE_API_CLIENT_SECRET'], {
|
20
|
+
setup: lambda{ |env|
|
21
|
+
default_scope = 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile'
|
22
|
+
env['omniauth.strategy'].options[:scope] = env['rack.session']['google_oauth_scope'] || default_scope
|
23
|
+
},
|
24
|
+
access_type: 'offline',
|
25
|
+
prompt: 'consent', # To get an offline access token you must specify 'consent'
|
26
|
+
image_aspect_ratio: 'square',
|
27
|
+
scope: 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile',
|
28
|
+
redirect_uri:"#{ENV['DOMAIN']}/auth/google_oauth2/callback"
|
29
|
+
}
|
30
|
+
<% end %>
|
31
|
+
|
32
|
+
<% if provider?(:soundcloud) %>
|
33
|
+
# https://github.com/soundcloud/omniauth-soundcloud
|
34
|
+
provider "soundcloud", ENV['SOUNDCLOUD_CLIENT_ID'], ENV['SOUNDCLOUD_SECRET']
|
35
|
+
<% end %>
|
36
|
+
|
37
|
+
<% if provider?(:tumblr) %>
|
38
|
+
# https://github.com/jamiew/omniauth-tumblr
|
39
|
+
provider :tumblr, ENV['TUMBLR_KEY'], ENV['TUMBLR_SECRET']
|
40
|
+
<% end %>
|
41
|
+
|
42
|
+
<% if provider?(:twitter) %>
|
43
|
+
# https://github.com/arunagw/omniauth-twitter
|
44
|
+
provider :twitter, ENV['TWITTER_CONSUMER_KEY'], ENV['TWITTER_CONSUMER_SECRET'], {
|
45
|
+
image_size: 'bigger', # 73x73
|
46
|
+
authorize_params: {
|
47
|
+
force_login: true
|
48
|
+
}
|
49
|
+
}
|
50
|
+
<% end %>
|
51
|
+
|
52
|
+
<% if provider?(:shopify) %>
|
53
|
+
# https://github.com/Shopify/omniauth-shopify-oauth2
|
54
|
+
provider :shopify, ENV['SHOPIFY_API_KEY'], ENV['SHOPIFY_SHARED_SECRET'],
|
55
|
+
:scope => 'read_products,read_orders,write_content,read_customers,write_themes,write_script_tags',
|
56
|
+
:setup => lambda { |env| params = Rack::Utils.parse_query(env['QUERY_STRING'])
|
57
|
+
env['omniauth.strategy'].options[:client_options][:site] = "https://#{params['shop']}" }
|
58
|
+
<% end %>
|
59
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# By default attachments are stored on S3. The path of the file is unique
|
2
|
+
# (based on the hash which is calculated at the time of upload). We expect
|
3
|
+
# that hash to be predictable so we set the :default_url (which usually
|
4
|
+
# points to a missing.png) to a calculated interpolation called
|
5
|
+
# :s3_default_url. When uploading directly we expect the signed params
|
6
|
+
# to include the ${filename} key for Amazon uploads. This prevents
|
7
|
+
# a variety of JavaScript filename vulnerabilities (though doesn't
|
8
|
+
# entirely prevent bad filenames). Given that, we actually prefer to
|
9
|
+
# use the uploaded filename in the resulting path (without escaping).
|
10
|
+
Paperclip::Attachment.default_options.merge!(
|
11
|
+
storage: :s3,
|
12
|
+
default_url: ':s3_default_url',
|
13
|
+
url: ':s3_domain_url',
|
14
|
+
path: '/system/:class/:style/:hash/:filename',
|
15
|
+
hash_data: ':class/:attachment/:id/:style/:uploaded_at',
|
16
|
+
hash_secret: ENV['aws_hash_secret'],
|
17
|
+
s3_permissions: :private,
|
18
|
+
s3_protocol: 'https',
|
19
|
+
s3_credentials: {
|
20
|
+
bucket: ENV['aws_bucket'],
|
21
|
+
access_key_id: ENV['aws_access_key_id'],
|
22
|
+
secret_access_key: ENV['aws_secret_access_key']
|
23
|
+
},
|
24
|
+
restricted_characters: nil,
|
25
|
+
escape_url: false
|
26
|
+
)
|
27
|
+
|
28
|
+
# By default, the :hash interpolation includes the :updated_at interpolation.
|
29
|
+
# This way, every time the model changes the hash is also changed and the
|
30
|
+
# content is expired. This can break if the same file is uploaded at the
|
31
|
+
# same second with different contents, but in such a case there are a number
|
32
|
+
# of other coordinated pieces (transactions, background jobs, etc) that
|
33
|
+
# might break and it could be expected.
|
34
|
+
#
|
35
|
+
# When importing, however, the updated_at key changes when the attachment_import_url is
|
36
|
+
# actually imported into the attachment, which changes the hash. This makes
|
37
|
+
# it impossible to predict what the ultimate URL will be because you cannot
|
38
|
+
# know what the future updated_at will be. Instead, if you record the time
|
39
|
+
# that the attachment_import_url was set and use that to calculate the hash the
|
40
|
+
# hash won't change when the contents of attachment_import_url are actually imported.
|
41
|
+
Paperclip.interpolates :uploaded_at do |attachment, style_name|
|
42
|
+
return attachment.instance.attachment_uploaded_at.to_i.to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
# When importing, the attachment_import_url is set, but not the attachment information.
|
46
|
+
# In order to poll for the completed processed styles (like thumb) we need
|
47
|
+
# to know what the ultimate url will be. This interpolation is used as the
|
48
|
+
# default_url and, if the attachment_import_url is set can assume the eventual path.
|
49
|
+
Paperclip.interpolates :s3_default_url do |attachment, style_name|
|
50
|
+
return nil if attachment.instance.blank? || attachment.instance.attachment_import_url.blank?
|
51
|
+
uri = URI.parse(attachment.instance.attachment_import_url) rescue nil
|
52
|
+
return nil unless uri
|
53
|
+
# Currently, Paperclip doesn't pass the style to the default, it always uses 'original'
|
54
|
+
style_name = "thumb"
|
55
|
+
classname = plural_cache.underscore_and_pluralize(attachment.instance.class.to_s)
|
56
|
+
original_filename = File.basename(URI.decode(uri.path))
|
57
|
+
basename = original_filename.gsub(/#{Regexp.escape(File.extname(original_filename))}$/, "")
|
58
|
+
extension = ((style = attachment.styles[style_name.to_s.to_sym]) && style[:format]) || File.extname(original_filename).gsub(/^\.+/, "")
|
59
|
+
filename = [basename, extension].reject(&:blank?).join(".")
|
60
|
+
hash = attachment.hash_key(style_name)
|
61
|
+
path = "system/#{classname}/#{style_name}/#{hash}/#{filename}"
|
62
|
+
if attachment.s3_permissions(style_name) == "public-read"
|
63
|
+
UploadHelper.aws_bucket_url + "/" + path
|
64
|
+
else
|
65
|
+
# We still get an authenticated url for the path, it is just based on the destination rather than the current
|
66
|
+
UploadHelper.aws_url_for(path)
|
67
|
+
end
|
68
|
+
end
|
@@ -6,8 +6,8 @@ class AddAuthkitFieldsToUsers < ActiveRecord::Migration
|
|
6
6
|
def self.up
|
7
7
|
add_column :users, :email, :string, :default => "", :null => false
|
8
8
|
add_column :users, :password_digest, :string, :default => "", :null => false
|
9
|
-
add_column :users, :username, :string, :limit => 64
|
10
|
-
|
9
|
+
<% if username? %>add_column :users, :username, :string, :limit => 64
|
10
|
+
<% end %>
|
11
11
|
add_column :users, :time_zone, :string, :default => "Eastern Time (US & Canada)"
|
12
12
|
add_column :users, :first_name, :string
|
13
13
|
add_column :users, :last_name, :string
|
@@ -50,10 +50,12 @@ class AddAuthkitFieldsToUsers < ActiveRecord::Migration
|
|
50
50
|
add_column :users, :unlock_token, :string
|
51
51
|
add_column :users, :unlock_token_created_at, :datetime
|
52
52
|
|
53
|
+
add_column :users, :suspended_at, :datetime
|
54
|
+
|
53
55
|
# Make sure the validations are enforced
|
54
56
|
add_index :users, :email, :unique => true
|
55
|
-
add_index :users, :username, :unique => true
|
56
|
-
add_index :users, :reset_password_token, :unique => true
|
57
|
+
<% if username? %>add_index :users, :username, :unique => true
|
58
|
+
<% end %>add_index :users, :reset_password_token, :unique => true
|
57
59
|
add_index :users, :remember_token, :unique => true
|
58
60
|
add_index :users, :confirmation_token, :unique => true
|
59
61
|
add_index :users, :unlock_token, :unique => true
|
@@ -63,8 +65,8 @@ class AddAuthkitFieldsToUsers < ActiveRecord::Migration
|
|
63
65
|
def self.down
|
64
66
|
drop_column :users, :email
|
65
67
|
drop_column :users, :password_digest
|
66
|
-
drop_column :users, :username
|
67
|
-
|
68
|
+
<% if username? %>drop_column :users, :username
|
69
|
+
<% end %>
|
68
70
|
drop_column :users, :time_zone
|
69
71
|
drop_column :users, :first_name
|
70
72
|
drop_column :users, :last_name
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Generated by Authkit.
|
2
|
+
#
|
3
|
+
# Create an auths table for managing OAuth authentication.
|
4
|
+
class CreateAuths < ActiveRecord::Migration
|
5
|
+
def self.up
|
6
|
+
create_table :auths do |t|
|
7
|
+
t.integer :user_id
|
8
|
+
t.string :provider
|
9
|
+
t.string :uid
|
10
|
+
t.string :email
|
11
|
+
t.boolean :verified_email
|
12
|
+
t.string :token
|
13
|
+
t.datetime :token_expires_at
|
14
|
+
t.string :refresh_token
|
15
|
+
t.string :secret_token
|
16
|
+
t.text :env
|
17
|
+
t.timestamps
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.down
|
22
|
+
drop_table :auths
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Generated by Authkit.
|
2
|
+
#
|
3
|
+
# Create an avatars table for managing user profile images
|
4
|
+
#
|
5
|
+
class CreateAvatars < ActiveRecord::Migration
|
6
|
+
def self.up
|
7
|
+
create_table :avatars do |t|
|
8
|
+
t.integer :user_id
|
9
|
+
t.integer :top, default: 0
|
10
|
+
t.integer :left, default: 0
|
11
|
+
t.integer :width, default: 0
|
12
|
+
t.integer :height, default: 0
|
13
|
+
t.text :remote_url
|
14
|
+
t.string :attachment_file_name
|
15
|
+
t.string :attachment_content_type
|
16
|
+
t.integer :attachment_file_size
|
17
|
+
t.datetime :attachment_updated_at
|
18
|
+
t.boolean :attachment_importing, default: false
|
19
|
+
t.datetime :attachment_uploaded_at
|
20
|
+
t.timestamps
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.down
|
25
|
+
drop_table :avatars
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
class FullNameSplitter
|
2
|
+
|
3
|
+
PREFIXES = %w(de da la du del dei vda. dello della degli delle van von der den heer ten ter vande vanden vander voor ver aan mc mac ben ibn bint al).freeze
|
4
|
+
HONORIFICS = %w(mr mrs miss ms dr capt ofc rev prof sir cr hon).freeze
|
5
|
+
|
6
|
+
def initialize(full_name, honorific=false)
|
7
|
+
full_name ||= ''
|
8
|
+
@full_name = full_name.to_s.strip.gsub(/\s+/, ' ')
|
9
|
+
@honorific = [] if honorific
|
10
|
+
@first_name = []
|
11
|
+
@last_name = []
|
12
|
+
split!
|
13
|
+
end
|
14
|
+
|
15
|
+
def split!
|
16
|
+
# Reset these
|
17
|
+
@first_name = []
|
18
|
+
@last_name = []
|
19
|
+
@honorific = [] if honorific?
|
20
|
+
|
21
|
+
# deals with comma, eg. Smith, John => John Smith
|
22
|
+
tokens = @full_name.split(',')
|
23
|
+
if tokens.size == 2
|
24
|
+
@full_name = (tokens[1] + ' ' + tokens[0]).lstrip
|
25
|
+
end
|
26
|
+
|
27
|
+
@units = @full_name.split(/\s+/)
|
28
|
+
while @unit = @units.shift do
|
29
|
+
if honorific?
|
30
|
+
@honorific << @unit
|
31
|
+
elsif prefix? or with_apostrophe? or (first_name? and last_unit? and not initial?) or (has_honorific? and last_unit? and not first_name?)
|
32
|
+
@last_name << @unit and break
|
33
|
+
else
|
34
|
+
@first_name << @unit
|
35
|
+
end
|
36
|
+
end
|
37
|
+
@last_name += @units
|
38
|
+
|
39
|
+
adjust_exceptions!
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def split_with_honorific(name)
|
44
|
+
split(name, true)
|
45
|
+
end
|
46
|
+
|
47
|
+
def split(name, honorific=false)
|
48
|
+
end
|
49
|
+
|
50
|
+
def honorific
|
51
|
+
@honorific.nil? || @honorific.empty? ? nil : @honorific[0].gsub(/[^\w]/, '')
|
52
|
+
end
|
53
|
+
|
54
|
+
def first_name
|
55
|
+
@first_name.empty? ? nil : @first_name.join(' ')
|
56
|
+
end
|
57
|
+
|
58
|
+
def last_name
|
59
|
+
@last_name.empty? ? nil : @last_name.join(' ')
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def honorific?
|
65
|
+
!@honorific.nil? && HONORIFICS.include?(@unit.downcase.gsub(/[^\w]/, '')) && @honorific.empty? && @first_name.empty? && @last_name.empty?
|
66
|
+
end
|
67
|
+
|
68
|
+
def has_honorific?
|
69
|
+
not @honorific.nil? and not @honorific.empty?
|
70
|
+
end
|
71
|
+
|
72
|
+
def prefix?
|
73
|
+
PREFIXES.include?(@unit.downcase)
|
74
|
+
end
|
75
|
+
|
76
|
+
# M or W.
|
77
|
+
def initial?
|
78
|
+
@unit =~ /^\w\.?$/
|
79
|
+
end
|
80
|
+
|
81
|
+
# O'Connor, d'Artagnan match
|
82
|
+
# Noda' doesn't match
|
83
|
+
def with_apostrophe?
|
84
|
+
@unit =~ /\w{1}'\w+/
|
85
|
+
end
|
86
|
+
|
87
|
+
def last_unit?
|
88
|
+
@units.empty?
|
89
|
+
end
|
90
|
+
|
91
|
+
def first_name?
|
92
|
+
not @first_name.empty?
|
93
|
+
end
|
94
|
+
|
95
|
+
def adjust_exceptions!
|
96
|
+
return if @first_name.size <= 1
|
97
|
+
|
98
|
+
# Adjusting exceptions like
|
99
|
+
# "Ludwig Mies van der Rohe" => ["Ludwig", "Mies van der Rohe" ]
|
100
|
+
# "Juan Martín de la Cruz Gómez" => ["Juan Martín", "de la Cruz Gómez" ]
|
101
|
+
# "Javier Reyes de la Barrera" => ["Javier", "Reyes de la Barrera" ]
|
102
|
+
# Rosa María Pérez Martínez Vda. de la Cruz
|
103
|
+
# => ["Rosa María", "Pérez Martínez Vda. de la Cruz"]
|
104
|
+
if last_name =~ /^(van der|(vda\. )?de la \w+$)/i
|
105
|
+
loop do
|
106
|
+
@last_name.unshift @first_name.pop
|
107
|
+
break if @first_name.size <= 2
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class UsernameFormatValidator < ActiveModel::EachValidator
|
2
|
+
def validate_each(object, attribute, value)
|
3
|
+
unless UsernameFormatValidator::is_valid_username(value)
|
4
|
+
object.errors[attribute] << (options[:message] || "is not a valid username")
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.is_valid_username(value)
|
9
|
+
value =~ /\A[0-9A-Za-z\-\_]+\z/
|
10
|
+
end
|
11
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'rails_helper'
|
2
2
|
|
3
3
|
describe ApplicationController do
|
4
4
|
let(:user) { create(:user) }
|
@@ -28,31 +28,27 @@ describe ApplicationController do
|
|
28
28
|
describe "current_user" do
|
29
29
|
it "returns nil if there is no current user" do
|
30
30
|
get :new
|
31
|
-
controller.send(:current_user).
|
31
|
+
expect(controller.send(:current_user)).to be_nil
|
32
32
|
end
|
33
33
|
|
34
34
|
it "does not perform multiple finds" do
|
35
|
-
where = double
|
36
|
-
|
37
|
-
User.should_receive(:where).and_return(where)
|
35
|
+
where = double(first: nil)
|
36
|
+
expect(User).to receive(:where).and_return(where)
|
38
37
|
get :new, {}, unknown_session
|
39
|
-
controller.send(:current_user).
|
38
|
+
expect(controller.send(:current_user)).to be_nil
|
40
39
|
end
|
41
40
|
|
42
41
|
it "finds the current user in the session" do
|
43
42
|
get :new, {}, logged_in_session
|
44
|
-
controller.send(:current_user).
|
43
|
+
expect(controller.send(:current_user)).to eq(user)
|
45
44
|
end
|
46
45
|
|
47
46
|
it "finds the current user from the remember cookie" do
|
48
47
|
user.save
|
49
48
|
user.set_remember_token
|
50
|
-
|
51
|
-
request.env["action_dispatch.secret_token"] = "SECRET"
|
52
|
-
verifier = ActiveSupport::MessageVerifier.new(request.env["action_dispatch.secret_token".freeze])
|
53
|
-
request.cookies[:remember] = verifier.generate(user.remember_token)
|
49
|
+
cookies.signed[:remember] = user.remember_token
|
54
50
|
get :index
|
55
|
-
controller.send(:current_user).
|
51
|
+
expect(controller.send(:current_user)).to eq(user)
|
56
52
|
end
|
57
53
|
|
58
54
|
it "doesn't find the current user from the remember cookie if it is expired" do
|
@@ -61,23 +57,20 @@ describe ApplicationController do
|
|
61
57
|
user.remember_token_created_at = 1.year.ago
|
62
58
|
user.save
|
63
59
|
|
64
|
-
|
65
|
-
request.env["action_dispatch.secret_token"] = "SECRET"
|
66
|
-
verifier = ActiveSupport::MessageVerifier.new(request.env["action_dispatch.secret_token".freeze])
|
67
|
-
request.cookies[:remember] = verifier.generate(user.remember_token)
|
60
|
+
cookies.signed[:remember] = user.remember_token
|
68
61
|
get :index
|
69
|
-
controller.send(:current_user).
|
62
|
+
expect(controller.send(:current_user)).to be_nil
|
70
63
|
end
|
71
64
|
|
72
65
|
it "sets the time zone" do
|
73
|
-
User.
|
66
|
+
expect_any_instance_of(User).to receive(:time_zone).and_return("Pacific Time (US & Canada)")
|
74
67
|
get :index, {}, logged_in_session
|
75
|
-
Time.zone.name.
|
68
|
+
expect(Time.zone.name).to eq("Pacific Time (US & Canada)")
|
76
69
|
end
|
77
70
|
|
78
71
|
it "has a logged in helper method" do
|
79
72
|
get :new, {}, logged_in_session
|
80
|
-
controller.
|
73
|
+
expect(controller.send(:logged_in?)).to eq(true)
|
81
74
|
end
|
82
75
|
end
|
83
76
|
|
@@ -85,42 +78,42 @@ describe ApplicationController do
|
|
85
78
|
it "does not allow tracking if there is a do not track header" do
|
86
79
|
request.headers["DNT"] = "1"
|
87
80
|
get :new
|
88
|
-
controller.send(:allow_tracking?).
|
81
|
+
expect(controller.send(:allow_tracking?)).to eq(false)
|
89
82
|
end
|
90
83
|
|
91
84
|
it "allows tracking if there is no do not track header" do
|
92
85
|
get :new
|
93
|
-
controller.send(:allow_tracking?).
|
86
|
+
expect(controller.send(:allow_tracking?)).to eq(true)
|
94
87
|
end
|
95
88
|
end
|
96
89
|
|
97
90
|
describe "when requiring a user" do
|
98
91
|
it "allows access if there is a user" do
|
99
92
|
get :index, {}, logged_in_session
|
100
|
-
response.
|
93
|
+
expect(response).to be_success
|
101
94
|
end
|
102
95
|
|
103
96
|
it "stores the return path" do
|
104
97
|
get :index, {}
|
105
|
-
session[:return_url].
|
98
|
+
expect(session[:return_url]).to eq("/anonymous")
|
106
99
|
end
|
107
100
|
|
108
101
|
describe "when responding to html" do
|
109
102
|
it "sets the flash message" do
|
110
103
|
get :index, {}
|
111
|
-
flash.
|
104
|
+
expect(flash).to_not be_empty
|
112
105
|
end
|
113
106
|
|
114
107
|
it "redirecs the user to login" do
|
115
108
|
get :index, {}
|
116
|
-
response.
|
109
|
+
expect(response).to be_redirect
|
117
110
|
end
|
118
111
|
end
|
119
112
|
|
120
113
|
describe "when responding to json" do
|
121
114
|
it "returns a forbidden status" do
|
122
115
|
get :index, {format: :json}
|
123
|
-
response.code.
|
116
|
+
expect(response.code).to eq("403")
|
124
117
|
end
|
125
118
|
end
|
126
119
|
end
|
@@ -128,27 +121,27 @@ describe ApplicationController do
|
|
128
121
|
describe "login" do
|
129
122
|
it "tracks the login" do
|
130
123
|
get :new
|
131
|
-
user.
|
124
|
+
expect(user).to receive(:track_sign_in)
|
132
125
|
controller.send(:login, user)
|
133
126
|
end
|
134
127
|
|
135
128
|
it "remembers the user using a token and cookie" do
|
136
129
|
get :new
|
137
|
-
controller.
|
138
|
-
user.
|
130
|
+
expect(controller).to receive(:set_remember_cookie)
|
131
|
+
expect(user).to receive(:set_remember_token)
|
139
132
|
controller.send(:login, user, true)
|
140
133
|
end
|
141
134
|
|
142
135
|
it "does not remember the user using a token and cookie when not requested" do
|
143
136
|
get :new
|
144
|
-
controller.
|
145
|
-
user.
|
137
|
+
expect(controller).to_not receive(:set_remember_cookie)
|
138
|
+
expect(user).to_not receive(:set_remember_token)
|
146
139
|
controller.send(:login, user, false)
|
147
140
|
end
|
148
141
|
|
149
142
|
it "resets the session" do
|
150
143
|
get :new
|
151
|
-
controller.
|
144
|
+
expect(controller).to receive(:reset_session)
|
152
145
|
controller.send(:login, user)
|
153
146
|
end
|
154
147
|
end
|
@@ -156,19 +149,19 @@ describe ApplicationController do
|
|
156
149
|
describe "logout" do
|
157
150
|
it "resets the session" do
|
158
151
|
get :index, {}, logged_in_session
|
159
|
-
controller.
|
152
|
+
expect(controller).to receive(:reset_session)
|
160
153
|
controller.send(:logout)
|
161
154
|
end
|
162
155
|
|
163
156
|
it "logs the user out" do
|
164
157
|
get :index, {}, logged_in_session
|
165
158
|
controller.send(:logout)
|
166
|
-
controller.send(:current_user).
|
159
|
+
expect(controller.send(:current_user)).to be_nil
|
167
160
|
end
|
168
161
|
|
169
162
|
it "clears the remember token" do
|
170
163
|
get :index, {}, logged_in_session
|
171
|
-
User.
|
164
|
+
expect_any_instance_of(User).to receive(:clear_remember_token).and_return(:true)
|
172
165
|
controller.send(:logout)
|
173
166
|
end
|
174
167
|
end
|
@@ -177,12 +170,12 @@ describe ApplicationController do
|
|
177
170
|
request.env["action_dispatch.secret_token"] = "SECRET"
|
178
171
|
get :new
|
179
172
|
controller.send(:login, user)
|
180
|
-
cookies.permanent.signed[:remember].
|
173
|
+
expect(cookies.permanent.signed[:remember]).to eq(user.remember_token)
|
181
174
|
end
|
182
175
|
|
183
176
|
it "redirects to a stored session location if present" do
|
184
177
|
get :new, {}, {return_url: "/return"}
|
185
|
-
controller.
|
178
|
+
expect(controller).to receive(:redirect_to).with("/return").and_return(true)
|
186
179
|
controller.send(:redirect_back_or_default)
|
187
180
|
end
|
188
181
|
end
|