dangerzone 0.0.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 (29) hide show
  1. data/README.md +21 -11
  2. data/lib/dangerzone/dangerzone_generator.rb +73 -59
  3. data/lib/dangerzone/templates/controllers/application_controller.rb +5 -6
  4. data/lib/dangerzone/templates/controllers/create_accounts_controller.rb +11 -15
  5. data/lib/dangerzone/templates/controllers/reset_passwords_controller.rb +12 -16
  6. data/lib/dangerzone/templates/controllers/sessions_controller.rb +19 -16
  7. data/lib/dangerzone/templates/migration.rb +2 -4
  8. data/lib/dangerzone/templates/models/user.rb +38 -12
  9. data/lib/dangerzone/templates/routes.rb +1 -1
  10. data/lib/dangerzone/templates/spec/controllers/create_accounts_controller_spec.rb +179 -0
  11. data/lib/dangerzone/templates/spec/controllers/reset_passwords_controller_spec.rb +131 -0
  12. data/lib/dangerzone/templates/spec/controllers/sessions_controller_spec.rb +135 -0
  13. data/lib/dangerzone/templates/spec/factories/users_factory.rb +15 -0
  14. data/lib/dangerzone/templates/spec/models/user_spec.rb +172 -0
  15. data/lib/dangerzone/templates/spec/spec_helper.rb +36 -0
  16. data/lib/dangerzone/templates/views/create_accounts/check_your_email.html.erb +1 -1
  17. data/lib/dangerzone/templates/views/create_accounts/new.html.erb +1 -1
  18. data/lib/dangerzone/templates/views/layouts/_dangerzone_nav.html.erb +10 -0
  19. data/lib/dangerzone/templates/views/layouts/application.html.erb +18 -0
  20. data/lib/dangerzone/templates/views/reset_passwords/new.html.erb +1 -1
  21. data/lib/dangerzone/templates/views/reset_passwords/reset_password_form.html.erb +2 -1
  22. data/lib/dangerzone/templates/views/sessions/new.html.erb +2 -2
  23. metadata +41 -22
  24. data/dangerzone.gemspec +0 -18
  25. data/lib/.DS_Store +0 -0
  26. data/lib/dangerzone/.DS_Store +0 -0
  27. data/lib/dangerzone/templates/.DS_Store +0 -0
  28. data/lib/dangerzone/templates/views/.DS_Store +0 -0
  29. data/lib/dangerzone/templates/views/nav.html.erb +0 -10
@@ -3,15 +3,13 @@ class CreateUsersTableViaDangerzone < ActiveRecord::Migration
3
3
  def up
4
4
  create_table :users do |t|
5
5
  t.string :email
6
- t.string :password
7
- t.string :password_confirmation
8
6
  t.string :password_digest
9
7
  t.string :sign_in_ip
10
8
  t.string :remember_token
11
9
  t.string :reset_password_token
12
10
  t.datetime :reset_password_sent_at
13
- t.boolean :confirmed, :default => false
14
- t.integer :sign_in_count, :default => 1
11
+ t.boolean :confirmed, default: false
12
+ t.integer :sign_in_count, default: 1
15
13
 
16
14
  t.timestamps
17
15
  end
@@ -1,25 +1,51 @@
1
1
  class User < ActiveRecord::Base
2
-
3
2
  has_secure_password
4
3
 
5
- attr_accessible :email, :password, :password_confirmation
4
+ attr_accessible(
5
+ :email,
6
+ :password,
7
+ :password_confirmation,
8
+ :reset_password_token,
9
+ :reset_password_sent_at,
10
+ :sign_in_ip,
11
+ :sign_in_count,
12
+ :confirmed,
13
+ :remember_token )
6
14
 
7
15
  validates_presence_of :email
8
16
  validates_uniqueness_of :email
9
- validates_format_of :email, :with => /.+@.+\..+/i
17
+ validates :password, :password_confirmation, presence: true, if: :new_record?
18
+ validates_format_of :email, with: /.+@.+\..+/i
19
+
20
+ before_save { self.email = self.email.try(:downcase) }
10
21
 
11
22
  def update_reset_password_credentials
12
- self.reset_password_sent_at = Time.now
13
- self.reset_password_token = SecureRandom.urlsafe_base64
14
- self.save
23
+ self.update_attributes(
24
+ reset_password_sent_at: Time.now,
25
+ reset_password_token: SecureRandom.urlsafe_base64 )
26
+ end
27
+
28
+ def sign_in!(ip, password_param)
29
+ return false unless self.confirmed && self.authenticate(password_param)
30
+ self.update_attributes(
31
+ sign_in_ip: ip,
32
+ sign_in_count: (self.sign_in_count + 1),
33
+ remember_token: SecureRandom.urlsafe_base64 )
15
34
  end
16
35
 
17
- def confirm(request_remote_ip)
18
- self.confirmed = true
19
- self.reset_password_sent_at = nil
20
- self.reset_password_token = nil
21
- self.sign_in_ip = request_remote_ip
22
- self.save
36
+ def confirm!(ip)
37
+ self.update_attributes(
38
+ sign_in_ip: ip,
39
+ confirmed: true,
40
+ reset_password_sent_at: nil,
41
+ reset_password_token: nil )
23
42
  end
24
43
 
44
+ def in_time?
45
+ (Time.now - self.reset_password_sent_at) < 24.hours if self.reset_password_sent_at
46
+ end
47
+
48
+ def token_matches?(token)
49
+ self.reset_password_token == token
50
+ end
25
51
  end
@@ -13,6 +13,6 @@
13
13
  put '/resend_confirmation_email' => 'create_accounts#resend_confirmation_email', as: 'resend_confirmation_email'
14
14
 
15
15
  get '/forgot_password' => 'reset_passwords#new', as: 'forgot_password'
16
- put '/reset_password' => 'reset_passwords#send_reset_password', as: 'send_reset_password'
16
+ put '/reset_password' => 'reset_passwords#requested_reset_password', as: 'requested_reset_password'
17
17
  get '/reset_password/:id/:reset_password_token' => 'reset_passwords#reset_password_form', as: 'reset_password_form'
18
18
  put '/update_password' => 'reset_passwords#update_password', as: 'update_password'
@@ -0,0 +1,179 @@
1
+ require 'spec_helper'
2
+
3
+ describe CreateAccountsController do
4
+ before { ActionMailer::Base.deliveries = [] }
5
+
6
+ describe '#create' do
7
+
8
+ it "saves an unconfirmed user" do
9
+ params = { user: FactoryGirl.attributes_for(:user, :confirmed) }
10
+ post :create, params
11
+ expect(assigns(:user).confirmed).to be_false
12
+ end
13
+
14
+ describe 'when successful' do
15
+ let(:valid_params) { { user: FactoryGirl.attributes_for(:user) } }
16
+ before { post :create, valid_params }
17
+
18
+ it "assigns a user with the values in valid_params" do
19
+ expect(assigns(:user).email).to eq(valid_params[:user][:email])
20
+ end
21
+
22
+ it "sends them a confirmation email" do
23
+ expect(ActionMailer::Base.deliveries).to_not be_empty
24
+ end
25
+
26
+ it "saves the user" do
27
+ expect(assigns(:user)).to be_persisted
28
+ end
29
+
30
+ it "redirects them to check_your_email" do
31
+ expect(response).to redirect_to :check_your_email
32
+ end
33
+ end
34
+
35
+ describe 'when unsuccessful' do
36
+ let(:invalid_params) { {:user => { email: 'x' }}}
37
+ before(:each) { post :create, invalid_params }
38
+
39
+ it "redirects them to the sign up page" do
40
+ expect(response).to redirect_to :sign_up
41
+ end
42
+
43
+ it "does not persist @user" do
44
+ expect(assigns(:user)).to be_new_record
45
+ end
46
+
47
+ it "does not send them an email" do
48
+ expect(ActionMailer::Base.deliveries).to be_empty
49
+ end
50
+ end
51
+ end
52
+
53
+ describe '#new' do
54
+ it "renders the new template" do
55
+ get :new
56
+ expect(response).to render_template :new
57
+ end
58
+ end
59
+
60
+ describe '#resend_confirmation_email' do
61
+ let(:user){ FactoryGirl.create(:user) }
62
+
63
+ describe "when user is not confirmed and has valid email" do
64
+
65
+ it "redirects to the check_your_email page" do
66
+ put :resend_confirmation_email, email: user.email
67
+ expect(response).to redirect_to :check_your_email
68
+ end
69
+
70
+ it "sends a confirmation email" do
71
+ put :resend_confirmation_email, email: user.email
72
+ expect(ActionMailer::Base.deliveries).to_not be_empty
73
+ end
74
+
75
+ it "updates the user's reset password credentials" do
76
+ old_token = user.reset_password_token
77
+ old_time = user.reset_password_sent_at
78
+ put :resend_confirmation_email, email: user.email
79
+ user.reload
80
+ expect(user.reset_password_token).to_not eq(old_token)
81
+ expect(user.reset_password_sent_at).to_not eq(old_time)
82
+ end
83
+ end
84
+
85
+ describe "when user is already confirmed" do
86
+ let(:confirmed_user) { FactoryGirl.create(:user, :confirmed) }
87
+
88
+ it "redirects to the check_your_email page" do
89
+ put :resend_confirmation_email, email: confirmed_user.email
90
+ expect(response).to redirect_to :check_your_email
91
+ end
92
+
93
+ it "does not send an email" do
94
+ put :resend_confirmation_email, email: confirmed_user.email
95
+ expect(ActionMailer::Base.deliveries).to be_empty
96
+ end
97
+
98
+ it "does not update their reset password credentials" do
99
+ user.should_not_receive :update_reset_password_credentials
100
+ put :resend_confirmation_email, email: confirmed_user.email
101
+ end
102
+ end
103
+
104
+ describe "when email in params does not belong to any user" do
105
+
106
+ it "redirects to the check_your_email page when there is no email in params" do
107
+ put :resend_confirmation_email
108
+ expect(response).to redirect_to :check_your_email
109
+ end
110
+
111
+ it "does not send an email" do
112
+ put :resend_confirmation_email, email: 'not_there@example.com'
113
+ expect(ActionMailer::Base.deliveries).to be_empty
114
+ end
115
+
116
+ it "does not update their reset password credentials" do
117
+ user.should_not_receive :update_reset_password_credentials
118
+ put :resend_confirmation_email, email: 'not_there@example.com'
119
+ end
120
+ end
121
+ end
122
+
123
+ describe "#confirm" do
124
+ let(:user){ FactoryGirl.create(:user) }
125
+ before { user.update_reset_password_credentials }
126
+
127
+ context "user has proper reset password credentials" do
128
+ before { get :confirm, id: user.id, reset_password_token: user.reset_password_token }
129
+
130
+ it "redirects to the root_url" do
131
+ expect(response).to redirect_to root_url
132
+ end
133
+
134
+ it "confirms the user" do
135
+ expect(User.first.confirmed).to be_true
136
+ end
137
+
138
+ it "puts the user's id in the session hash" do
139
+ expect(session[:user_id]).to eq(user.id)
140
+ end
141
+ end
142
+
143
+ context "user does not have right token" do
144
+ before { get :confirm, id: user.id, reset_password_token: 'wrong'}
145
+
146
+ it "redirects them to the sign up page" do
147
+ expect(response).to redirect_to :sign_up
148
+ end
149
+
150
+ it "does not confirm the user" do
151
+ expect(User.first.confirmed).to be_false
152
+ end
153
+
154
+ it "does not set the session hash to the user's id" do
155
+ expect(session[:user_id]).to be_nil
156
+ end
157
+ end
158
+
159
+ context "user is trying to confirm after more than an hour" do
160
+ before do
161
+ user.reset_password_sent_at = Time.now - 2.days
162
+ user.save
163
+ get :confirm, id: user.id, reset_password_token: user.reset_password_token
164
+ end
165
+
166
+ it "redirects them to the sign up page" do
167
+ expect(response).to redirect_to :sign_up
168
+ end
169
+
170
+ it "does not confirm the user" do
171
+ expect(User.first.confirmed).to be_false
172
+ end
173
+
174
+ it "does not set the session hash to the user's id" do
175
+ expect(session[:user_id]).to be_nil
176
+ end
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,131 @@
1
+ require 'spec_helper'
2
+
3
+ describe ResetPasswordsController do
4
+
5
+ describe '#requested_reset_password' do
6
+ before { ActionMailer::Base.deliveries = []}
7
+ let(:user) { FactoryGirl.create(:user) }
8
+
9
+ it "renders to forgot_password page (:new)" do
10
+ put :requested_reset_password, email: user.email
11
+ expect(response).to redirect_to :forgot_password
12
+ end
13
+
14
+ context 'when update_reset_password_credentials is successful' do
15
+
16
+ it "sends an email" do
17
+ put :requested_reset_password, email: user.email
18
+ expect(ActionMailer::Base.deliveries).to_not be_empty
19
+ end
20
+
21
+ it "updates the user's reset password credentials" do
22
+ old_token = user.reset_password_token
23
+ old_time = user.reset_password_sent_at
24
+ put :requested_reset_password, email: user.email
25
+ expect(User.first.reset_password_token).to_not eq(old_token)
26
+ expect(User.first.reset_password_sent_at).to_not eq(old_time)
27
+ end
28
+ end
29
+
30
+ context 'when update_reset_password_credentials fails' do
31
+ it "doesn't send an email" do
32
+ put :requested_reset_password, email: "not an email"
33
+ expect(ActionMailer::Base.deliveries).to be_empty
34
+ end
35
+ end
36
+ end
37
+
38
+ describe '#reset_password_form' do
39
+ let(:user){ FactoryGirl.create(:user) }
40
+ before { user.update_reset_password_credentials }
41
+
42
+ context "user has proper reset password credentials" do
43
+ it "renders reset password form" do
44
+ get :reset_password_form, id: user.id, reset_password_token: user.reset_password_token
45
+ expect(response).to render_template :reset_password_form
46
+ end
47
+ end
48
+
49
+ context "user does not have right token" do
50
+ before { get :reset_password_form, id: user.id, reset_password_token: 'wrong'}
51
+
52
+ it "renders the forgot password page" do
53
+ expect(response).to redirect_to :forgot_password
54
+ end
55
+
56
+ it "does not set the session hash to the user's id" do
57
+ expect(session[:reset_password_user_id]).to be_nil
58
+ end
59
+ end
60
+
61
+ context "user is trying to reset password after more than an hour" do
62
+ before do
63
+ user.reset_password_sent_at = Time.now - 2.days
64
+ user.save
65
+ get :reset_password_form, id: user.id, reset_password_token: user.reset_password_token
66
+ end
67
+
68
+ it "renders the forgot password page" do
69
+ expect(response).to redirect_to :forgot_password
70
+ end
71
+
72
+ it "does not set the session hash to the user's id" do
73
+ expect(session[:reset_password_user_id]).to be_nil
74
+ end
75
+ end
76
+ end
77
+
78
+ describe '#update_password' do
79
+ let(:user){ FactoryGirl.create(:user) }
80
+ before do
81
+ user.update_reset_password_credentials
82
+ session[:reset_password_user_id] = user.id
83
+ end
84
+
85
+ context 'the user is in time' do
86
+
87
+ context 'and their password and confirmation match' do
88
+ before { put :update_password, password: 'new_password', password_confirmation: 'new_password', id: user.id }
89
+
90
+ it "sets session[:user_id] to their user id" do
91
+ expect(session[:user_id]).to eq(user.id)
92
+ end
93
+
94
+ it "redirects them to the root_url" do
95
+ expect(response).to redirect_to :root
96
+ end
97
+ end
98
+
99
+ context "but their password and confirmation don't match" do
100
+ it "redirects them to the reset password form" do
101
+ put :update_password, password: 'new_password', password_confirmation: "doesn't match", id: user.id
102
+ expect(response).to redirect_to reset_password_form_path(user.id, user.reset_password_token)
103
+ end
104
+ end
105
+
106
+ end
107
+
108
+ context "user is too late" do
109
+ it "redirects to #requested_reset_password" do
110
+ user.reset_password_sent_at = Time.now - 2.days
111
+ user.save
112
+ put :update_password, password: 'new_password', password_confirmation: 'new_password', id: user.id
113
+ expect(response).to redirect_to :forgot_password
114
+ end
115
+ end
116
+
117
+ context "incorrect id comes in" do
118
+ it "redirects to #forgot_password" do
119
+ put :update_password, password: 'new_password', password_confirmation: 'new_password', id: 1234124
120
+ expect(response).to redirect_to :forgot_password
121
+ end
122
+ end
123
+ end
124
+
125
+ describe '#new' do
126
+ it "renders the new template" do
127
+ get :new
128
+ expect(response).to render_template :new
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,135 @@
1
+ require 'spec_helper'
2
+
3
+ describe SessionsController do
4
+
5
+ describe '#new' do
6
+ let(:confirmed_user) { FactoryGirl.create(:user) }
7
+
8
+ it 'renders the :new page' do
9
+ get :new
10
+ expect(response).to render_template :new
11
+ end
12
+
13
+ it 'redirects to root if user is already signed in' do
14
+ session[:user_id] = 5
15
+ get :new
16
+ expect(response).to redirect_to :root
17
+ end
18
+ end
19
+
20
+ describe '#destroy' do
21
+
22
+ it 'clears the permanent cookies' do
23
+ cookies.permanent[:remember_token] = 'remember token'
24
+ delete :destroy
25
+ expect(cookies[:remember_token]).to be_nil
26
+ end
27
+
28
+ it 'clears the session hash' do
29
+ session[:user_id] = 5
30
+ delete :destroy
31
+ expect(session[:user_id]).to be_nil
32
+ end
33
+
34
+ it 'redirects to the sign in page' do
35
+ delete :destroy
36
+ expect(response).to redirect_to :sign_in
37
+ end
38
+ end
39
+
40
+ describe '#create' do
41
+ let(:user){ FactoryGirl.create(:user, :confirmed) }
42
+ let(:params){ {email: user.email, password: 'password1234'} }
43
+
44
+ before { controller.reset_session }
45
+
46
+ it 'clears cookies before signing in so 2 people cannot be signed in at once (w/out remember me)' do
47
+ session[:user_id] = 'x'
48
+ cookies.permanent[:remember_token] = 'some token'
49
+ post :create, params
50
+ expect(session[:user_id]).to eq(user.id)
51
+ expect(cookies[:remember_token]).to be_nil
52
+ end
53
+
54
+ it 'clears cookies before signing in so 2 people cannot be signed in at once (with remember me)' do
55
+ session[:user_id] = 'x'
56
+ cookies.permanent[:remember_token] = 'some token'
57
+ params[:remember_me] = '1'
58
+ post :create, params
59
+ expect(session[:user_id]).to be_nil
60
+ expect(cookies[:remember_token]).to eq(assigns(:user).remember_token)
61
+ end
62
+
63
+ context 'when a non user email tries to login' do
64
+ it 'redirects to the sign in page' do
65
+ post :create
66
+ expect(response).to redirect_to :sign_in
67
+ end
68
+ end
69
+
70
+ context 'incorrect password' do
71
+ it 'redirects to the sign in page' do
72
+ params[:password] = 'wrong'
73
+ post :create, params
74
+ expect(response).to redirect_to :sign_in
75
+ end
76
+ end
77
+
78
+ context 'user is not confirmed' do
79
+ it 'redirects to the sign in page' do
80
+ params[:email] = FactoryGirl.create(:user).email
81
+ post :create, params
82
+ expect(response).to redirect_to :sign_in
83
+ end
84
+ end
85
+
86
+ context 'password is correct and user is confirmed' do
87
+
88
+ it 'updates the their sign in ip' do
89
+ user.sign_in_ip = 'old ip'
90
+ user.save
91
+ post :create, params
92
+ expect(assigns(:user)).to_not eq('old ip')
93
+ end
94
+
95
+ it 'increments the their sign in count' do
96
+ old_sign_in_count = user.sign_in_count
97
+ post :create, params
98
+ expect(assigns(:user).sign_in_count).to eq(old_sign_in_count + 1)
99
+ end
100
+
101
+ it 'redirects to the root url' do
102
+ post :create, params
103
+ expect(response).to redirect_to :root
104
+ end
105
+
106
+ it 'saves the user' do
107
+ old_updated_at = user.updated_at
108
+ post :create, params
109
+ expect(assigns(:user)).to_not eq(old_updated_at)
110
+ end
111
+
112
+ context 'user has selected remember me' do
113
+ before { params[:remember_me] = '1' }
114
+
115
+ it 'gives the user a new remember token' do
116
+ old_token = user.remember_token
117
+ post :create, params
118
+ expect(assigns(:user)).to_not eq(old_token)
119
+ end
120
+
121
+ it 'puts the their id in the permanent cookies' do
122
+ post :create, params
123
+ expect(cookies[:remember_token]).to_not be_nil
124
+ end
125
+ end
126
+
127
+ context 'user has not selected remember me' do
128
+ it 'puts the their id in the session hash' do
129
+ post :create, params
130
+ expect(session[:user_id]).to eq(user.id)
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end