authkit 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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -3
  3. data/Rakefile +3 -2
  4. data/lib/authkit/version.rb +1 -1
  5. data/lib/generators/authkit/install_generator.rb +181 -35
  6. data/lib/generators/authkit/templates/app/controllers/application_controller.rb +6 -0
  7. data/lib/generators/authkit/templates/app/controllers/auths_controller.rb +144 -0
  8. data/lib/generators/authkit/templates/app/controllers/email_confirmation_controller.rb +1 -1
  9. data/lib/generators/authkit/templates/app/controllers/password_reset_controller.rb +7 -1
  10. data/lib/generators/authkit/templates/app/controllers/sessions_controller.rb +11 -2
  11. data/lib/generators/authkit/templates/app/controllers/signup_controller.rb +4 -2
  12. data/lib/generators/authkit/templates/app/controllers/upload_controller.rb +78 -0
  13. data/lib/generators/authkit/templates/app/controllers/users_controller.rb +2 -2
  14. data/lib/generators/authkit/templates/app/forms/signup.rb +57 -7
  15. data/lib/generators/authkit/templates/app/helpers/auths_helper.rb +26 -0
  16. data/lib/generators/authkit/templates/app/helpers/upload_helper.rb +118 -0
  17. data/lib/generators/authkit/templates/app/models/auth.rb +81 -0
  18. data/lib/generators/authkit/templates/app/models/avatar.rb +45 -0
  19. data/lib/generators/authkit/templates/app/models/user.rb +53 -26
  20. data/lib/generators/authkit/templates/app/views/auths/connect.html.erb +34 -0
  21. data/lib/generators/authkit/templates/app/views/password_change/show.html.erb +9 -9
  22. data/lib/generators/authkit/templates/app/views/password_reset/show.html.erb +6 -6
  23. data/lib/generators/authkit/templates/app/views/sessions/new.html.erb +25 -7
  24. data/lib/generators/authkit/templates/app/views/signup/new.html.erb +44 -32
  25. data/lib/generators/authkit/templates/app/views/users/complete.html.erb +39 -0
  26. data/lib/generators/authkit/templates/app/views/users/edit.html.erb +31 -31
  27. data/lib/generators/authkit/templates/app/workers/avatar_import_worker.rb +12 -0
  28. data/lib/generators/authkit/templates/config/initializers/filter_parameter_logging.rb +2 -2
  29. data/lib/generators/authkit/templates/config/initializers/omniauth.rb +59 -0
  30. data/lib/generators/authkit/templates/config/initializers/paperclip.rb +68 -0
  31. data/lib/generators/authkit/templates/db/migrate/add_authkit_fields_to_users.rb +8 -6
  32. data/lib/generators/authkit/templates/db/migrate/create_auths.rb +24 -0
  33. data/lib/generators/authkit/templates/db/migrate/create_avatars.rb +27 -0
  34. data/lib/generators/authkit/templates/lib/full_name_splitter.rb +111 -0
  35. data/lib/generators/authkit/templates/lib/username_format_validator.rb +11 -0
  36. data/lib/generators/authkit/templates/spec/controllers/application_controller_spec.rb +31 -38
  37. data/lib/generators/authkit/templates/spec/controllers/auths_controller_spec.rb +72 -0
  38. data/lib/generators/authkit/templates/spec/controllers/email_confirmation_controller_spec.rb +25 -27
  39. data/lib/generators/authkit/templates/spec/controllers/password_change_controller_spec.rb +30 -30
  40. data/lib/generators/authkit/templates/spec/controllers/password_reset_controller_spec.rb +20 -20
  41. data/lib/generators/authkit/templates/spec/controllers/sessions_controller_spec.rb +33 -33
  42. data/lib/generators/authkit/templates/spec/controllers/signup_controller_spec.rb +19 -19
  43. data/lib/generators/authkit/templates/spec/controllers/users_controller_spec.rb +21 -21
  44. data/lib/generators/authkit/templates/spec/factories/user.rb +3 -3
  45. data/lib/generators/authkit/templates/spec/forms/signup_spec.rb +32 -31
  46. data/lib/generators/authkit/templates/spec/models/auth_spec.rb +18 -0
  47. data/lib/generators/authkit/templates/spec/models/user_spec.rb +72 -78
  48. data/spec/rails_helper.rb +50 -0
  49. data/spec/spec_helper.rb +70 -13
  50. metadata +35 -17
  51. data/lib/generators/authkit/templates/spec/spec_helper.rb +0 -4
@@ -0,0 +1,45 @@
1
+ class Avatar < ActiveRecord::Base
2
+ # Avatar images are publicly available (you can share the URL and it won't
3
+ # expire, but you probably can't guess it). Also, the images should be
4
+ # cached on the client side as the path name includes a hash.
5
+ has_attached_file :attachment,
6
+ styles: {thumb: "200x200#"},
7
+ s3_permissions: 'public-read',
8
+ s3_headers: {"Cache-Control" => "max-age=#{1.year.to_i}", "Expires" => 1.year.from_now.httpdate}
9
+
10
+ before_validation :prepare_import
11
+ validates :attachment, attachment_presence: true, unless: :attachment_importing?
12
+ after_save :async_import
13
+
14
+ def as_json(options = {})
15
+ super({
16
+ methods: [:url]
17
+ }.merge(options))
18
+ end
19
+
20
+ def url
21
+ self.attachment.url(:thumb)
22
+ end
23
+
24
+ def import!
25
+ return false unless self.attachment_importing?
26
+ self.attachment_importing = false
27
+ if self.remote_url.present?
28
+ uri = URI.parse(self.remote_url)
29
+ self.attachment = uri
30
+ self.attachment_file_name = File.basename(URI.decode(uri.path))
31
+ end
32
+ self.save
33
+ end
34
+
35
+ protected
36
+
37
+ def prepare_import
38
+ return unless self.remote_url.present? && self.remote_url_changed?
39
+ self.attachment_importing = true
40
+ end
41
+
42
+ def async_import
43
+ AvatarImportWorker.perform_async(self.id) if self.attachment_importing?
44
+ end
45
+ end
@@ -1,37 +1,49 @@
1
1
  require 'email_format_validator'
2
-
2
+ require 'full_name_splitter'
3
+ <% if username? %>require 'username_format_validator'
4
+ <% end %>
3
5
  class User < ActiveRecord::Base
4
- has_secure_password
5
- has_one_time_password
6
+ <% if oauth? %>
7
+ has_many :auths
8
+ <% end %>
6
9
 
7
- # Uncomment if you are not using strong params (note, that email is only permitted on
8
- # signup and confirmation_email is only permitted on update):
9
- #
10
- # attr_accessible :username,
11
- # :email,
12
- # :confirmation_email,
13
- # :password,
14
- # :password_confirmation,
15
- # :time_zone,
16
- # :first_name,
17
- # :last_name,
18
- # :bio,
19
- # :website,
20
- # :phone_number
10
+ has_secure_password validations: false
11
+ has_one_time_password
21
12
 
22
13
  before_validation :downcase_email
23
14
  before_validation :set_confirmation_email
24
15
 
25
- # Whenever the password is set, validate (not only on create)
26
- validates :password, presence: true, confirmation: true, length: {minimum: 6}, if: :password_set?
27
- validates :username, presence: true, uniqueness: {case_sensitive: false}
28
- validates :email, email_format: true, presence: true, uniqueness: true
29
- validates :confirmation_email, email_format: true, presence: true
30
-
16
+ validates :password, confirmation: true, length: { minimum: 6 }, if: :has_password?
17
+ validates :email, email_format: true, uniqueness: { allow_nil: true }
18
+ validates :confirmation_email, email_format: true
19
+ <% if username? %>validates :username, username_format: true, uniqueness: { case_sensitive: false, allow_nil: true }
20
+ <% end %>
21
+ validates :password, presence: true, unless: :has_auth_or_skip_password_validation?
22
+ validates :email, presence: true, unless: :has_auth?
23
+ validates :confirmation_email, presence: true, unless: :has_auth?
24
+ <% if username? %>validates :username, presence: true, unless: :has_auth?
25
+ <% end %>
31
26
  # Confirm emails check for existing emails for uniqueness as a convenience
32
27
  validate :confirmation_email_uniqueness, if: :confirmation_email_set?
33
28
 
34
- def display_name
29
+ def suspended?
30
+ self.suspended_at.present?
31
+ end
32
+
33
+ def incomplete?
34
+ <% if username? %>username.blank? || <% end %>email.blank? || password_digest.blank?
35
+ end
36
+
37
+ def full_name=(value)
38
+ return if value.blank?
39
+
40
+ splitter = FullNameSplitter.new(value)
41
+ self.first_name = splitter.first_name
42
+ self.last_name = splitter.last_name
43
+ self.full_name
44
+ end
45
+
46
+ def full_name
35
47
  [first_name, last_name].compact.join(" ")
36
48
  end
37
49
 
@@ -141,7 +153,23 @@ class User < ActiveRecord::Base
141
153
 
142
154
  protected
143
155
 
144
- def password_set?
156
+ def has_auth?
157
+ <% if oauth? %>
158
+ self.auths.first.present?
159
+ <% else %>
160
+ false
161
+ <% end %>
162
+ end
163
+
164
+ def has_auth_or_skip_password_validation?
165
+ has_auth? || skip_password_validation?
166
+ end
167
+
168
+ def skip_password_validation?
169
+ self.password.blank? && self.password_digest.present?
170
+ end
171
+
172
+ def has_password?
145
173
  self.password.present?
146
174
  end
147
175
 
@@ -167,5 +195,4 @@ class User < ActiveRecord::Base
167
195
  def confirmation_email_uniqueness
168
196
  errors.add(:confirmation_email, :taken, value: email) if User.where('email = ?', confirmation_email).count > 0
169
197
  end
170
-
171
198
  end
@@ -0,0 +1,34 @@
1
+ <div class="providers">
2
+ <%% providers.each do |provider| %>
3
+ <a href="/auth/<%%= provider %>?connect=1" class="oauth <%%= provider %>"><i class="fa <%%= provider_font_awesome_icon(provider) %>"></i> <%%= provider_formatted_name(provider) %> Account</a>
4
+ <%% end %>
5
+ </div>
6
+
7
+ <table class="connected">
8
+ <%% current_user.auths.order('provider, id').each do |auth| %>
9
+ <tr class="auth <%%= auth.provider %>">
10
+ <td width="30">
11
+ <%% unless auth.image_url.blank? %>
12
+ <img src="<%%= auth.image_url %>" class="avatar">
13
+ <%% end %>
14
+ </td>
15
+ <td>
16
+ <span class="name"><%%= auth.name %></span>
17
+ <%%= link_to 'Disconnect', disconnect_url(auth) %>
18
+ </td>
19
+ <td align="center">
20
+ <span class="icon"><i class="fa <%%= provider_font_awesome_icon(auth.provider) %>"></i></span>
21
+ </td>
22
+ </li>
23
+ <%% end %>
24
+ <%% if current_user.auths.count == 0 %>
25
+ <tr>
26
+ <td colspan="3">You have not connected any social accounts</td>
27
+ </tr>
28
+ <%% end %>
29
+ </table>
30
+
31
+ <div class="agreement">
32
+ By connecting your account you are also agreeing to our<br />
33
+ <a href="<%%= terms_path %>" target="_blank">Terms &amp; Conditions</a> and <a href="<%%= privacy_path %>" target="_blank">Privacy Policy</a>
34
+ </div>
@@ -1,17 +1,17 @@
1
1
  <h1>Please enter a new password</h1>
2
2
 
3
- <%= form_tag(password_change_path, method: "post") do %>
4
- <%= hidden_field_tag :token, params[:token] %>
5
- <%= hidden_field_tag :email, params[:email] %>
3
+ <%%= form_tag(password_change_path, method: "post") do %>
4
+ <%%= hidden_field_tag :token, params[:token] %>
5
+ <%%= hidden_field_tag :email, params[:email] %>
6
6
 
7
7
  <div class="field">
8
- <%= label_tag "password" %>
9
- <%= password_field_tag "password" %>
8
+ <%%= label_tag "password" %>
9
+ <%%= password_field_tag "password" %>
10
10
  </div>
11
11
  <div class="field">
12
- <%= label_tag "password_confirmation" %>
13
- <%= password_field_tag "password_confirmation" %>
12
+ <%%= label_tag "password_confirmation" %>
13
+ <%%= password_field_tag "password_confirmation" %>
14
14
  </div>
15
15
 
16
- <%= submit_tag "Change" %>
17
- <% end %>
16
+ <%%= submit_tag "Change" %>
17
+ <%% end %>
@@ -1,12 +1,12 @@
1
1
  <h1>Reset your password</h1>
2
2
 
3
- <%= form_tag(password_reset_path, method: "post") do %>
4
- <%= hidden_field_tag :token, params[:token] %>
3
+ <%%= form_tag(password_reset_path, method: "post") do %>
4
+ <%%= hidden_field_tag :token, params[:token] %>
5
5
 
6
6
  <div class="field">
7
- <%= label_tag "email", "Email or username" %>
8
- <%= text_field_tag "email" %>
7
+ <%%= label_tag "email", "Email<% if username? %> or username<% end %>" %>
8
+ <%%= text_field_tag "email" %>
9
9
  </div>
10
10
 
11
- <%= submit_tag "Reset" %>
12
- <% end %>
11
+ <%%= submit_tag "Reset" %>
12
+ <%% end %>
@@ -1,17 +1,35 @@
1
1
  <h1>Sign In</h1>
2
2
 
3
- <%= form_tag(login_path, method: "post") do %>
3
+ <%%= form_tag(login_path, method: "post") do %>
4
4
  <div class="field">
5
- <%= label_tag "email", "Email or username" %>
6
- <%= text_field_tag "email" %>
5
+ <%%= label_tag "email", "Email<% if username? %> or username<% end %>" %>
6
+ <%%= text_field_tag "email" %>
7
7
  </div>
8
8
  <div class="field">
9
- <%= label_tag "password" %>
10
- <%= password_field_tag "password" %>
9
+ <%%= label_tag "password" %>
10
+ <%%= password_field_tag "password" %>
11
11
  </div>
12
12
  <div class="field">
13
- <%= check_box_tag :remember_me, "1", true %>
13
+ <%%= check_box_tag :remember_me, "1", true %>
14
14
  <label for="remember_me">Keep me signed in on this computer</label>
15
15
  </div>
16
- <%= submit_tag "Login" %>
16
+ <div class="login">
17
+ <%%= submit_tag "Login" %>
18
+ </div>
19
+
20
+ <div class="forgot">
21
+ <a href="/password/reset" class="forgot">Forgot your password?</a>
22
+ </div>
23
+ <%% end %>
24
+
25
+ <% if oauth? %>
26
+ <div class="or">
27
+ or sign in using a connected account
28
+ </div>
29
+
30
+ <div class="providers">
31
+ <%% providers.each do |provider| %>
32
+ <a href="/auth/<%%= provider %>?login=1" class="oauth <%%= provider %>"><i class="fa <%%= provider_font_awesome_icon(provider) %>"></i> <%%= provider_formatted_name(provider) %> Account</a>
33
+ <%% end %>
34
+ </div>
17
35
  <% end %>
@@ -1,62 +1,74 @@
1
1
  <h1>Sign Up</h1>
2
2
 
3
- <% if @signup.errors.any? %>
3
+ <% if oauth? %>
4
+ <div class="providers">
5
+ <%% providers.each do |provider| %>
6
+ <a href="/auth/<%%= provider %>?signup=1" class="oauth <%%= provider %>"><i class="fa <%%= provider_font_awesome_icon(provider) %>"></i> <%%= provider_formatted_name(provider) %> Account</a>
7
+ <%% end %>
8
+ </div>
9
+
10
+ <div class="or">
11
+ or sign up using your email
12
+ </div>
13
+ <% end %>
14
+
15
+ <%% if @signup.errors.any? %>
4
16
  <div id="error_explanation">
5
17
  <div class="alert alert-error">
6
- The form contains <%= pluralize(@signup.errors.count, "error") %>.
18
+ The form contains <%%= pluralize(@signup.errors.count, "error") %>.
7
19
  </div>
8
20
  <ul>
9
- <% @signup.errors.full_messages.each do |msg| %>
10
- <li>* <%= msg %></li>
11
- <% end %>
21
+ <%% @signup.errors.full_messages.each do |msg| %>
22
+ <li>* <%%= msg %></li>
23
+ <%% end %>
12
24
  </ul>
13
25
  </div>
14
- <% end %>
26
+ <%% end %>
15
27
 
16
- <%= form_for @signup, url: signup_path do |f| %>
28
+ <%%= form_for @signup, url: signup_path do |f| %>
17
29
  <div class="field">
18
- <%= f.label "first_name" %>
19
- <%= f.text_field "first_name" %>
30
+ <%%= f.label "first_name" %>
31
+ <%%= f.text_field "first_name" %>
20
32
  </div>
21
33
  <div class="field">
22
- <%= f.label "last_name" %>
23
- <%= f.text_field "last_name" %>
34
+ <%%= f.label "last_name" %>
35
+ <%%= f.text_field "last_name" %>
24
36
  </div>
25
37
  <div class="field">
26
- <%= f.label "bio" %>
27
- <%= f.text_area "bio" %>
38
+ <%%= f.label "bio" %>
39
+ <%%= f.text_area "bio" %>
28
40
  </div>
29
41
  <div class="field">
30
- <%= f.label "website" %>
31
- <%= f.text_field "website" %>
42
+ <%%= f.label "website" %>
43
+ <%%= f.text_field "website" %>
32
44
  </div>
33
45
  <div class="field">
34
- <%= f.label "phone_number" %>
35
- <%= f.text_field "phone_number" %>
46
+ <%%= f.label "phone_number" %>
47
+ <%%= f.text_field "phone_number" %>
36
48
  </div>
37
49
  <div class="field">
38
- <%= f.label "time_zone" %>
39
- <%= f.time_zone_select('time_zone', ActiveSupport::TimeZone.us_zones, :default => "Pacific Time (US & Canada)") %>
50
+ <%%= f.label "time_zone" %>
51
+ <%%= f.time_zone_select('time_zone', ActiveSupport::TimeZone.us_zones, :default => "Pacific Time (US & Canada)") %>
40
52
  </div>
41
53
  <div class="field">
42
- <%= f.label "email" %>
43
- <%= f.text_field "email" %>
54
+ <%%= f.label "email" %>
55
+ <%%= f.text_field "email" %>
44
56
  </div>
45
- <div class="field">
46
- <%= f.label "username" %>
47
- <%= f.text_field "username" %>
57
+ <% if username? %><div class="field">
58
+ <%%= f.label "username" %>
59
+ <%%= f.text_field "username" %>
48
60
  </div>
49
- <div class="field">
50
- <%= f.label "password" %>
51
- <%= f.password_field "password" %>
61
+ <% end %><div class="field">
62
+ <%%= f.label "password" %>
63
+ <%%= f.password_field "password" %>
52
64
  </div>
53
65
  <div class="field">
54
- <%= f.label "password_confirmation" %>
55
- <%= f.password_field "password_confirmation" %>
66
+ <%%= f.label "password_confirmation" %>
67
+ <%%= f.password_field "password_confirmation" %>
56
68
  </div>
57
69
  <div class="field">
58
- <%= check_box_tag :remember_me, "1", true %>
70
+ <%%= check_box_tag :remember_me, "1", true %>
59
71
  <label for="remember_me">Keep me signed in on this computer</label>
60
72
  </div>
61
- <%= f.submit "Sign up" %>
62
- <% end %>
73
+ <%%= f.submit "Sign up" %>
74
+ <%% end %>
@@ -0,0 +1,39 @@
1
+ <h1>One more step to complete your account</h1>
2
+
3
+ <%% if @user.errors.any? %>
4
+ <div id="error_explanation">
5
+ <div class="alert alert-error">
6
+ The form contains <%%= pluralize(@user.errors.count, "error") %>.
7
+ </div>
8
+ <ul>
9
+ <%% @user.errors.full_messages.each do |msg| %>
10
+ <li>* <%%= msg %></li>
11
+ <%% end %>
12
+ </ul>
13
+ </div>
14
+ <%% end %>
15
+
16
+ <%%= form_for @user do |f| %>
17
+ <div class="field">
18
+ <%%= f.label "first_name" %>
19
+ <%%= f.text_field "first_name" %>
20
+ </div>
21
+ <div class="field">
22
+ <%%= f.label "last_name" %>
23
+ <%%= f.text_field "last_name" %>
24
+ </div>
25
+ <div class="field">
26
+ <%%= f.label "email" %>
27
+ <%%= f.text_field "confirmation_email" %>
28
+ </div>
29
+ <div class="field">
30
+ <%%= f.label "password" %>
31
+ <%%= f.password_field "password" %>
32
+ </div>
33
+ <div class="field">
34
+ <%%= f.label "password_confirmation" %>
35
+ <%%= f.password_field "password_confirmation" %>
36
+ </div>
37
+ <%%= f.submit "Finish" %>
38
+ <%% end %>
39
+
@@ -1,58 +1,58 @@
1
1
  <h1>Account</h1>
2
2
 
3
- <% if @user.errors.any? %>
3
+ <%% if @user.errors.any? %>
4
4
  <div id="error_explanation">
5
5
  <div class="alert alert-error">
6
- The form contains <%= pluralize(@user.errors.count, "error") %>.
6
+ The form contains <%%= pluralize(@user.errors.count, "error") %>.
7
7
  </div>
8
8
  <ul>
9
- <% @user.errors.full_messages.each do |msg| %>
10
- <li>* <%= msg %></li>
11
- <% end %>
9
+ <%% @user.errors.full_messages.each do |msg| %>
10
+ <li>* <%%= msg %></li>
11
+ <%% end %>
12
12
  </ul>
13
13
  </div>
14
- <% end %>
14
+ <%% end %>
15
15
 
16
- <%= form_for @user do |f| %>
16
+ <%%= form_for @user do |f| %>
17
17
  <div class="field">
18
- <%= f.label "first_name" %>
19
- <%= f.text_field "first_name" %>
18
+ <%%= f.label "first_name" %>
19
+ <%%= f.text_field "first_name" %>
20
20
  </div>
21
21
  <div class="field">
22
- <%= f.label "last_name" %>
23
- <%= f.text_field "last_name" %>
22
+ <%%= f.label "last_name" %>
23
+ <%%= f.text_field "last_name" %>
24
24
  </div>
25
25
  <div class="field">
26
- <%= f.label "bio" %>
27
- <%= f.text_area "bio" %>
26
+ <%%= f.label "bio" %>
27
+ <%%= f.text_area "bio" %>
28
28
  </div>
29
29
  <div class="field">
30
- <%= f.label "website" %>
31
- <%= f.text_field "website" %>
30
+ <%%= f.label "website" %>
31
+ <%%= f.text_field "website" %>
32
32
  </div>
33
33
  <div class="field">
34
- <%= f.label "phone_number" %>
35
- <%= f.text_field "phone_number" %>
34
+ <%%= f.label "phone_number" %>
35
+ <%%= f.text_field "phone_number" %>
36
36
  </div>
37
37
  <div class="field">
38
- <%= f.label "time_zone" %>
39
- <%= f.time_zone_select('time_zone', ActiveSupport::TimeZone.us_zones, :default => "Pacific Time (US & Canada)") %>
38
+ <%%= f.label "time_zone" %>
39
+ <%%= f.time_zone_select('time_zone', ActiveSupport::TimeZone.us_zones, :default => "Pacific Time (US & Canada)") %>
40
40
  </div>
41
41
  <div class="field">
42
- <%= f.label "email" %>
43
- <%= f.text_field "confirmation_email" %>
42
+ <%%= f.label "email" %>
43
+ <%%= f.text_field "confirmation_email" %>
44
44
  </div>
45
- <div class="field">
46
- <%= f.label "username" %>
47
- <%= f.text_field "username" %>
45
+ <% if username? %><div class="field">
46
+ <%%= f.label "username" %>
47
+ <%%= f.text_field "username" %>
48
48
  </div>
49
- <div class="field">
50
- <%= f.label "password" %>
51
- <%= f.password_field "password" %>
49
+ <% end %><div class="field">
50
+ <%%= f.label "password" %>
51
+ <%%= f.password_field "password" %>
52
52
  </div>
53
53
  <div class="field">
54
- <%= f.label "password_confirmation" %>
55
- <%= f.password_field "password_confirmation" %>
54
+ <%%= f.label "password_confirmation" %>
55
+ <%%= f.password_field "password_confirmation" %>
56
56
  </div>
57
- <%= f.submit "Save" %>
58
- <% end %>
57
+ <%%= f.submit "Save" %>
58
+ <%% end %>