saucy 0.2.18 → 0.2.20
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.
@@ -22,17 +22,17 @@ class InvitationsController < ApplicationController
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def show
|
25
|
-
|
26
|
-
render
|
25
|
+
with_invitation { render }
|
27
26
|
end
|
28
27
|
|
29
28
|
def update
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
29
|
+
with_invitation do
|
30
|
+
if @invitation.accept(params[:invitation])
|
31
|
+
sign_in @invitation.user
|
32
|
+
redirect_to root_url
|
33
|
+
else
|
34
|
+
render :action => 'show'
|
35
|
+
end
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
@@ -41,4 +41,15 @@ class InvitationsController < ApplicationController
|
|
41
41
|
def assign_projects
|
42
42
|
@projects = current_account.projects_by_name
|
43
43
|
end
|
44
|
+
|
45
|
+
def with_invitation
|
46
|
+
@invitation = Invitation.find_by_code!(params[:id])
|
47
|
+
if @invitation.used?
|
48
|
+
flash[:error] = t("invitations.show.used",
|
49
|
+
:default => "That invitation has already been used.")
|
50
|
+
redirect_to root_url
|
51
|
+
else
|
52
|
+
yield
|
53
|
+
end
|
54
|
+
end
|
44
55
|
end
|
data/app/models/invitation.rb
CHANGED
@@ -4,13 +4,14 @@ class Invitation < ActiveRecord::Base
|
|
4
4
|
validates_presence_of :email
|
5
5
|
has_and_belongs_to_many :projects
|
6
6
|
|
7
|
+
before_create :generate_code
|
7
8
|
after_create :deliver_invitation
|
8
9
|
|
9
10
|
attr_accessor :new_user_name, :new_user_password,
|
10
11
|
:new_user_password_confirmation, :existing_user_password
|
11
12
|
attr_writer :new_user_email, :existing_user_email
|
12
13
|
attr_reader :user
|
13
|
-
attr_protected :account_id
|
14
|
+
attr_protected :account_id, :used
|
14
15
|
|
15
16
|
validate :validate_accepting_user, :on => :update
|
16
17
|
|
@@ -20,12 +21,16 @@ class Invitation < ActiveRecord::Base
|
|
20
21
|
|
21
22
|
def accept(attributes)
|
22
23
|
self.attributes = attributes
|
24
|
+
self.used = true
|
23
25
|
@user = existing_user || new_user
|
24
26
|
if valid?
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
27
|
+
transaction do
|
28
|
+
save!
|
29
|
+
@user.save!
|
30
|
+
@user.memberships.create!(:account => account,
|
31
|
+
:admin => admin,
|
32
|
+
:projects => projects)
|
33
|
+
end
|
29
34
|
end
|
30
35
|
end
|
31
36
|
|
@@ -37,6 +42,10 @@ class Invitation < ActiveRecord::Base
|
|
37
42
|
@existing_user_email ||= email
|
38
43
|
end
|
39
44
|
|
45
|
+
def to_param
|
46
|
+
code
|
47
|
+
end
|
48
|
+
|
40
49
|
private
|
41
50
|
|
42
51
|
def deliver_invitation
|
@@ -84,4 +93,8 @@ class Invitation < ActiveRecord::Base
|
|
84
93
|
errors.add(:existing_user_password, "is incorrect")
|
85
94
|
end
|
86
95
|
end
|
96
|
+
|
97
|
+
def generate_code
|
98
|
+
self.code = SecureRandom.hex(8)
|
99
|
+
end
|
87
100
|
end
|
@@ -101,11 +101,11 @@ describe InvitationsController, "invalid create", :as => :account_admin do
|
|
101
101
|
end
|
102
102
|
|
103
103
|
describe InvitationsController, "show" do
|
104
|
-
let(:invitation) { Factory.stub(:invitation) }
|
104
|
+
let(:invitation) { Factory.stub(:invitation, :code => 'abc') }
|
105
105
|
let(:account) { invitation.account }
|
106
106
|
|
107
107
|
before do
|
108
|
-
Invitation.stubs(:
|
108
|
+
Invitation.stubs(:find_by_code! => invitation)
|
109
109
|
get :show, :id => invitation.to_param, :account_id => account.to_param
|
110
110
|
end
|
111
111
|
|
@@ -115,19 +115,37 @@ describe InvitationsController, "show" do
|
|
115
115
|
end
|
116
116
|
|
117
117
|
it "assigns the invitation" do
|
118
|
-
Invitation.should have_received(:
|
118
|
+
Invitation.should have_received(:find_by_code!).with(invitation.to_param)
|
119
119
|
should assign_to(:invitation).with(invitation)
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
123
|
+
describe InvitationsController, "show for a used invitation" do
|
124
|
+
let(:invitation) { Factory.stub(:invitation, :code => 'abc', :used => true) }
|
125
|
+
let(:account) { invitation.account }
|
126
|
+
|
127
|
+
before do
|
128
|
+
Invitation.stubs(:find_by_code! => invitation)
|
129
|
+
get :show, :id => invitation.to_param, :account_id => account.to_param
|
130
|
+
end
|
131
|
+
|
132
|
+
it "redirects to the root url" do
|
133
|
+
should redirect_to("/")
|
134
|
+
end
|
135
|
+
|
136
|
+
it "sets a flash message" do
|
137
|
+
should set_the_flash.to(/used/i)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
123
141
|
describe InvitationsController, "valid update" do
|
124
|
-
let(:invitation) { Factory.stub(:invitation) }
|
142
|
+
let(:invitation) { Factory.stub(:invitation, :code => 'abc') }
|
125
143
|
let(:account) { invitation.account }
|
126
144
|
let(:attributes) { 'attributes' }
|
127
145
|
let(:user) { Factory.stub(:user) }
|
128
146
|
|
129
147
|
before do
|
130
|
-
Invitation.stubs(:
|
148
|
+
Invitation.stubs(:find_by_code! => invitation)
|
131
149
|
invitation.stubs(:accept => true)
|
132
150
|
invitation.stubs(:user => user)
|
133
151
|
put :update, :id => invitation.to_param,
|
@@ -140,7 +158,7 @@ describe InvitationsController, "valid update" do
|
|
140
158
|
end
|
141
159
|
|
142
160
|
it "accepts the invitation" do
|
143
|
-
Invitation.should have_received(:
|
161
|
+
Invitation.should have_received(:find_by_code!).with(invitation.to_param)
|
144
162
|
invitation.should have_received(:accept).with(attributes)
|
145
163
|
end
|
146
164
|
|
@@ -150,11 +168,11 @@ describe InvitationsController, "valid update" do
|
|
150
168
|
end
|
151
169
|
|
152
170
|
describe InvitationsController, "invalid update" do
|
153
|
-
let(:invitation) { Factory.stub(:invitation) }
|
171
|
+
let(:invitation) { Factory.stub(:invitation, :code => 'abc') }
|
154
172
|
let(:account) { invitation.account }
|
155
173
|
|
156
174
|
before do
|
157
|
-
Invitation.stubs(:
|
175
|
+
Invitation.stubs(:find_by_code! => invitation)
|
158
176
|
invitation.stubs(:accept => false)
|
159
177
|
put :update, :id => invitation.to_param,
|
160
178
|
:account_id => account.to_param,
|
@@ -174,3 +192,22 @@ describe InvitationsController, "invalid update" do
|
|
174
192
|
should assign_to(:invitation).with(invitation)
|
175
193
|
end
|
176
194
|
end
|
195
|
+
|
196
|
+
describe InvitationsController, "update for a used invitation" do
|
197
|
+
let(:invitation) { Factory.stub(:invitation, :code => 'abc', :used => true) }
|
198
|
+
let(:account) { invitation.account }
|
199
|
+
|
200
|
+
before do
|
201
|
+
Invitation.stubs(:find_by_code! => invitation)
|
202
|
+
put :update, :id => invitation.to_param, :account_id => account.to_param
|
203
|
+
end
|
204
|
+
|
205
|
+
it "redirects to the root url" do
|
206
|
+
should redirect_to("/")
|
207
|
+
end
|
208
|
+
|
209
|
+
it "sets a flash message" do
|
210
|
+
should set_the_flash.to(/used/i)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
@@ -7,6 +7,7 @@ describe Invitation do
|
|
7
7
|
it { should have_and_belong_to_many(:projects) }
|
8
8
|
|
9
9
|
it { should_not allow_mass_assignment_of(:account_id) }
|
10
|
+
it { should_not allow_mass_assignment_of(:used) }
|
10
11
|
|
11
12
|
%w(new_user_name new_user_email new_user_password
|
12
13
|
new_user_password_confirmation existing_user_password).each do |attribute|
|
@@ -19,9 +20,15 @@ end
|
|
19
20
|
|
20
21
|
describe Invitation, "saved" do
|
21
22
|
let(:mail) { stub('invitation', :deliver => true) }
|
22
|
-
before { InvitationMailer.stubs(:invitation => mail) }
|
23
23
|
subject { Factory(:invitation) }
|
24
24
|
let(:email) { subject.email }
|
25
|
+
let(:code) { 'abchex123' }
|
26
|
+
|
27
|
+
before do
|
28
|
+
SecureRandom.stubs(:hex => code)
|
29
|
+
InvitationMailer.stubs(:invitation => mail)
|
30
|
+
subject
|
31
|
+
end
|
25
32
|
|
26
33
|
it "sends an invitation email" do
|
27
34
|
InvitationMailer.should have_received(:invitation).with(subject)
|
@@ -39,6 +46,15 @@ describe Invitation, "saved" do
|
|
39
46
|
it "defauls existing user email to invited email" do
|
40
47
|
subject.existing_user_email.should == subject.email
|
41
48
|
end
|
49
|
+
|
50
|
+
it "generates a code" do
|
51
|
+
SecureRandom.should have_received(:hex).with(8)
|
52
|
+
subject.code.should == code
|
53
|
+
end
|
54
|
+
|
55
|
+
it "uses the code in the url" do
|
56
|
+
subject.to_param.should == code
|
57
|
+
end
|
42
58
|
end
|
43
59
|
|
44
60
|
describe Invitation, "valid accept for a new user" do
|
@@ -75,6 +91,10 @@ describe Invitation, "valid accept for a new user" do
|
|
75
91
|
user.should be_member_of(project)
|
76
92
|
end
|
77
93
|
end
|
94
|
+
|
95
|
+
it "marks the invitation as used" do
|
96
|
+
subject.reload.should be_used
|
97
|
+
end
|
78
98
|
end
|
79
99
|
|
80
100
|
describe Invitation, "invalid accept for a new user" do
|
@@ -94,6 +114,10 @@ describe Invitation, "invalid accept for a new user" do
|
|
94
114
|
it "adds error messages" do
|
95
115
|
subject.errors[:new_user_password].should be_present
|
96
116
|
end
|
117
|
+
|
118
|
+
it "doesn't mark the invitation as used" do
|
119
|
+
subject.reload.should_not be_used
|
120
|
+
end
|
97
121
|
end
|
98
122
|
|
99
123
|
describe Invitation, "valid accept for an existing user" do
|
@@ -115,6 +139,10 @@ describe Invitation, "valid accept for an existing user" do
|
|
115
139
|
it "adds the user to the account" do
|
116
140
|
account.users.should include(user)
|
117
141
|
end
|
142
|
+
|
143
|
+
it "marks the invitation as used" do
|
144
|
+
subject.reload.should be_used
|
145
|
+
end
|
118
146
|
end
|
119
147
|
|
120
148
|
describe Invitation, "accepting with an invalid password" do
|
@@ -136,6 +164,108 @@ describe Invitation, "accepting with an invalid password" do
|
|
136
164
|
end
|
137
165
|
end
|
138
166
|
|
167
|
+
describe Invitation, "saved" do
|
168
|
+
let(:mail) { stub('invitation', :deliver => true) }
|
169
|
+
subject { Factory(:invitation) }
|
170
|
+
let(:email) { subject.email }
|
171
|
+
let(:code) { 'abchex123' }
|
172
|
+
|
173
|
+
before do
|
174
|
+
SecureRandom.stubs(:hex => code)
|
175
|
+
InvitationMailer.stubs(:invitation => mail)
|
176
|
+
subject
|
177
|
+
end
|
178
|
+
|
179
|
+
it "sends an invitation email" do
|
180
|
+
InvitationMailer.should have_received(:invitation).with(subject)
|
181
|
+
mail.should have_received(:deliver)
|
182
|
+
end
|
183
|
+
|
184
|
+
it "delegates account name" do
|
185
|
+
subject.account_name.should == subject.account.name
|
186
|
+
end
|
187
|
+
|
188
|
+
it "defauls new user email to invited email" do
|
189
|
+
subject.new_user_email.should == subject.email
|
190
|
+
end
|
191
|
+
|
192
|
+
it "defauls existing user email to invited email" do
|
193
|
+
subject.existing_user_email.should == subject.email
|
194
|
+
end
|
195
|
+
|
196
|
+
it "generates a code" do
|
197
|
+
SecureRandom.should have_received(:hex).with(8)
|
198
|
+
subject.code.should == code
|
199
|
+
end
|
200
|
+
|
201
|
+
it "uses the code in the url" do
|
202
|
+
subject.to_param.should == code
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
describe Invitation, "valid accept for a new user" do
|
207
|
+
let(:account) { Factory(:account) }
|
208
|
+
let(:projects) { [Factory(:project, :account => account)] }
|
209
|
+
let(:password) { 'secret' }
|
210
|
+
let(:name) { 'Rocket' }
|
211
|
+
subject { Factory(:invitation, :account => account, :projects => projects) }
|
212
|
+
|
213
|
+
let!(:result) do
|
214
|
+
subject.accept(:new_user_password => password,
|
215
|
+
:new_user_password_confirmation => password,
|
216
|
+
:new_user_name => name)
|
217
|
+
end
|
218
|
+
|
219
|
+
let(:user) { subject.user }
|
220
|
+
|
221
|
+
it "returns true" do
|
222
|
+
result.should be_true
|
223
|
+
end
|
224
|
+
|
225
|
+
it "creates a saved, confirmed user" do
|
226
|
+
user.should_not be_nil
|
227
|
+
user.should be_persisted
|
228
|
+
user.name.should == name
|
229
|
+
end
|
230
|
+
|
231
|
+
it "adds the user to the account" do
|
232
|
+
account.users.should include(user)
|
233
|
+
end
|
234
|
+
|
235
|
+
it "adds the user to each of the invitation's projects" do
|
236
|
+
projects.each do |project|
|
237
|
+
user.should be_member_of(project)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
it "marks the invitation as used" do
|
242
|
+
subject.reload.should be_used
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
describe Invitation, "invalid accept for a new user" do
|
247
|
+
subject { Factory(:invitation) }
|
248
|
+
let!(:result) { subject.accept({}) }
|
249
|
+
let(:user) { subject.user }
|
250
|
+
let(:account) { subject.account }
|
251
|
+
|
252
|
+
it "returns false" do
|
253
|
+
result.should be_false
|
254
|
+
end
|
255
|
+
|
256
|
+
it "doesn't create a user" do
|
257
|
+
user.should be_new_record
|
258
|
+
end
|
259
|
+
|
260
|
+
it "adds error messages" do
|
261
|
+
subject.errors[:new_user_password].should be_present
|
262
|
+
end
|
263
|
+
|
264
|
+
it "doesn't mark the invitation as used" do
|
265
|
+
subject.reload.should_not be_used
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
139
269
|
describe Invitation, "accepting with an unknown email" do
|
140
270
|
subject { Factory(:invitation, :email => 'unknown') }
|
141
271
|
let(:account) { subject.account }
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: saucy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 63
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 20
|
10
|
+
version: 0.2.20
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- thoughtbot, inc.
|
@@ -17,13 +17,14 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2011-02-
|
20
|
+
date: 2011-02-11 00:00:00 -05:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|
24
|
-
|
24
|
+
type: :runtime
|
25
25
|
prerelease: false
|
26
|
-
|
26
|
+
name: formtastic
|
27
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
27
28
|
none: false
|
28
29
|
requirements:
|
29
30
|
- - ">="
|
@@ -33,12 +34,12 @@ dependencies:
|
|
33
34
|
- 1
|
34
35
|
- 2
|
35
36
|
version: "1.2"
|
36
|
-
|
37
|
-
version_requirements: *id001
|
37
|
+
requirement: *id001
|
38
38
|
- !ruby/object:Gem::Dependency
|
39
|
-
|
39
|
+
type: :runtime
|
40
40
|
prerelease: false
|
41
|
-
|
41
|
+
name: railties
|
42
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
42
43
|
none: false
|
43
44
|
requirements:
|
44
45
|
- - ">="
|
@@ -49,12 +50,12 @@ dependencies:
|
|
49
50
|
- 0
|
50
51
|
- 3
|
51
52
|
version: 3.0.3
|
52
|
-
|
53
|
-
version_requirements: *id002
|
53
|
+
requirement: *id002
|
54
54
|
- !ruby/object:Gem::Dependency
|
55
|
-
|
55
|
+
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
|
57
|
+
name: braintree
|
58
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
58
59
|
none: false
|
59
60
|
requirements:
|
60
61
|
- - ">="
|
@@ -65,12 +66,12 @@ dependencies:
|
|
65
66
|
- 6
|
66
67
|
- 2
|
67
68
|
version: 2.6.2
|
68
|
-
|
69
|
-
version_requirements: *id003
|
69
|
+
requirement: *id003
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
|
-
|
71
|
+
type: :runtime
|
72
72
|
prerelease: false
|
73
|
-
|
73
|
+
name: sham_rack
|
74
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
74
75
|
none: false
|
75
76
|
requirements:
|
76
77
|
- - "="
|
@@ -81,12 +82,12 @@ dependencies:
|
|
81
82
|
- 3
|
82
83
|
- 3
|
83
84
|
version: 1.3.3
|
84
|
-
|
85
|
-
version_requirements: *id004
|
85
|
+
requirement: *id004
|
86
86
|
- !ruby/object:Gem::Dependency
|
87
|
-
|
87
|
+
type: :runtime
|
88
88
|
prerelease: false
|
89
|
-
|
89
|
+
name: sinatra
|
90
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
90
91
|
none: false
|
91
92
|
requirements:
|
92
93
|
- - "="
|
@@ -97,12 +98,12 @@ dependencies:
|
|
97
98
|
- 1
|
98
99
|
- 2
|
99
100
|
version: 1.1.2
|
100
|
-
|
101
|
-
version_requirements: *id005
|
101
|
+
requirement: *id005
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
|
-
|
103
|
+
type: :development
|
104
104
|
prerelease: false
|
105
|
-
|
105
|
+
name: aruba
|
106
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
106
107
|
none: false
|
107
108
|
requirements:
|
108
109
|
- - "="
|
@@ -113,8 +114,7 @@ dependencies:
|
|
113
114
|
- 2
|
114
115
|
- 6
|
115
116
|
version: 0.2.6
|
116
|
-
|
117
|
-
version_requirements: *id006
|
117
|
+
requirement: *id006
|
118
118
|
description: Clearance-based Rails engine for Software as a Service (Saas) that provides account and project management
|
119
119
|
email: support@thoughtbot.com
|
120
120
|
executables: []
|