nelumba-mongodb 0.0.1
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.
- data/.gitignore +17 -0
- data/.travis.yml +10 -0
- data/Gemfile +25 -0
- data/LICENSE +127 -0
- data/README.md +29 -0
- data/Rakefile +60 -0
- data/lib/nelumba-mongodb.rb +35 -0
- data/lib/nelumba-mongodb/activity.rb +316 -0
- data/lib/nelumba-mongodb/article.rb +30 -0
- data/lib/nelumba-mongodb/authorization.rb +213 -0
- data/lib/nelumba-mongodb/avatar.rb +130 -0
- data/lib/nelumba-mongodb/comment.rb +7 -0
- data/lib/nelumba-mongodb/embedded_object.rb +43 -0
- data/lib/nelumba-mongodb/feed.rb +268 -0
- data/lib/nelumba-mongodb/identity.rb +191 -0
- data/lib/nelumba-mongodb/image.rb +121 -0
- data/lib/nelumba-mongodb/note.rb +5 -0
- data/lib/nelumba-mongodb/object.rb +43 -0
- data/lib/nelumba-mongodb/person.rb +533 -0
- data/lib/nelumba-mongodb/version.rb +3 -0
- data/nelumba-mongodb.gemspec +26 -0
- data/spec/activity_spec.rb +337 -0
- data/spec/article_spec.rb +71 -0
- data/spec/authorization_spec.rb +514 -0
- data/spec/avatar_spec.rb +418 -0
- data/spec/feed_spec.rb +485 -0
- data/spec/helper.rb +72 -0
- data/spec/identity_spec.rb +245 -0
- data/spec/note_spec.rb +71 -0
- data/spec/person_spec.rb +922 -0
- metadata +164 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'nelumba-mongodb/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "nelumba-mongodb"
|
8
|
+
gem.version = Nelumba::MONGODB_VERSION
|
9
|
+
gem.authors = ["wilkie"]
|
10
|
+
gem.email = ["wilkie@xomb.com"]
|
11
|
+
gem.description = %q{A persistence layer for nelumba.}
|
12
|
+
gem.summary = %q{A persistence layer for nelumba.}
|
13
|
+
gem.homepage = "https://github.com/hotsh/nelumba-mongodb"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
#gem.add_dependency "nelumba"
|
21
|
+
gem.add_dependency "redcarpet" # Markdown renderer
|
22
|
+
gem.add_dependency "bson_ext" # Database
|
23
|
+
gem.add_dependency "mongo_mapper" # Database
|
24
|
+
gem.add_dependency "bcrypt-ruby" # Basic Authentication
|
25
|
+
gem.add_dependency "rmagick" # Used for avatar resizing
|
26
|
+
end
|
@@ -0,0 +1,337 @@
|
|
1
|
+
require_relative 'helper'
|
2
|
+
|
3
|
+
describe Nelumba::Activity do
|
4
|
+
describe "Schema" do
|
5
|
+
it "should have a feed_id" do
|
6
|
+
Nelumba::Activity.keys.keys.must_include "feed_id"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should have a uid" do
|
10
|
+
Nelumba::Activity.keys.keys.must_include "uid"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should have a url" do
|
14
|
+
Nelumba::Activity.keys.keys.must_include "url"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should have a type" do
|
18
|
+
Nelumba::Activity.keys.keys.must_include "type"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should have an actor_id" do
|
22
|
+
Nelumba::Activity.keys.keys.must_include "actor_id"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should have an actor_type" do
|
26
|
+
Nelumba::Activity.keys.keys.must_include "actor_type"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should have a target_id" do
|
30
|
+
Nelumba::Activity.keys.keys.must_include "target_id"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should have a target_type" do
|
34
|
+
Nelumba::Activity.keys.keys.must_include "target_type"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should have an external_object_id" do
|
38
|
+
Nelumba::Activity.keys.keys.must_include "external_object_id"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should have an external_object_type" do
|
42
|
+
Nelumba::Activity.keys.keys.must_include "external_object_type"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should have a title" do
|
46
|
+
Nelumba::Activity.keys.keys.must_include "title"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should have a content" do
|
50
|
+
Nelumba::Activity.keys.keys.must_include "content"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should have a source" do
|
54
|
+
Nelumba::Activity.keys.keys.must_include "source"
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should have an in_reply_to_ids" do
|
58
|
+
Nelumba::Activity.keys.keys.must_include "in_reply_to_ids"
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should have an replies_ids" do
|
62
|
+
Nelumba::Activity.keys.keys.must_include "replies_ids"
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should have an shares_ids" do
|
66
|
+
Nelumba::Activity.keys.keys.must_include "shares_ids"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should have an mentions_ids" do
|
70
|
+
Nelumba::Activity.keys.keys.must_include "mentions_ids"
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should have an likes_ids" do
|
74
|
+
Nelumba::Activity.keys.keys.must_include "likes_ids"
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should have a published" do
|
78
|
+
Nelumba::Activity.keys.keys.must_include "published"
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should have a updated" do
|
82
|
+
Nelumba::Activity.keys.keys.must_include "updated"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "create!" do
|
87
|
+
it "should assign default uid" do
|
88
|
+
activity = Nelumba::Activity.new
|
89
|
+
activity.run_callbacks :create
|
90
|
+
|
91
|
+
activity.uid.must_equal "/activities/#{activity.id}"
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should assign default url" do
|
95
|
+
activity = Nelumba::Activity.new
|
96
|
+
activity.run_callbacks :create
|
97
|
+
|
98
|
+
activity.url.must_equal "/activities/#{activity.id}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "#actor=" do
|
103
|
+
it "should assign actor_id to the id of a given Nelumba::Person" do
|
104
|
+
activity = Nelumba::Activity.new
|
105
|
+
actor = Nelumba::Person.new
|
106
|
+
|
107
|
+
activity.actor = actor
|
108
|
+
|
109
|
+
activity.actor_id.must_equal actor.id
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should assign actor_id to the id of a given Nelumba::Activity" do
|
113
|
+
activity = Nelumba::Activity.new
|
114
|
+
actor = Nelumba::Activity.new
|
115
|
+
|
116
|
+
activity.actor = actor
|
117
|
+
|
118
|
+
activity.actor_id.must_equal actor.id
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should assign actor_type appropriately for a given Nelumba::Person" do
|
122
|
+
activity = Nelumba::Activity.new
|
123
|
+
actor = Nelumba::Person.new
|
124
|
+
|
125
|
+
activity.actor = actor
|
126
|
+
|
127
|
+
activity.actor_type.must_equal "Person"
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should assign actor_type appropriately for a given Nelumba::Activity" do
|
131
|
+
activity = Nelumba::Activity.new
|
132
|
+
actor = Nelumba::Activity.new
|
133
|
+
|
134
|
+
activity.actor = actor
|
135
|
+
|
136
|
+
activity.actor_type.must_equal "Activity"
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should return the given object instead of querying the database" do
|
140
|
+
activity = Nelumba::Activity.new
|
141
|
+
actor = Nelumba::Activity.new
|
142
|
+
|
143
|
+
activity.actor = actor
|
144
|
+
|
145
|
+
activity.actor.id.must_equal actor.id
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "#actor" do
|
150
|
+
it "should retrieve a stored Nelumba::Person" do
|
151
|
+
actor = Nelumba::Person.create
|
152
|
+
activity = Nelumba::Activity.new(:actor_id => actor.id,
|
153
|
+
:actor_type => "Person")
|
154
|
+
|
155
|
+
activity.actor.id.must_equal actor.id
|
156
|
+
activity.actor.class.must_equal Nelumba::Person
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should retrieve a stored Nelumba::Activity" do
|
160
|
+
actor = Nelumba::Activity.create
|
161
|
+
activity = Nelumba::Activity.new(:actor_id => actor.id,
|
162
|
+
:actor_type => "Activity")
|
163
|
+
|
164
|
+
activity.actor.id.must_equal actor.id
|
165
|
+
activity.actor.class.must_equal Nelumba::Activity
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
describe "find_or_create_by_uid!" do
|
170
|
+
it "should return the existing Nelumba::Activity" do
|
171
|
+
activity = Nelumba::Activity.create!(:uid => "UID",
|
172
|
+
:url => "URL")
|
173
|
+
|
174
|
+
Nelumba::Activity.find_or_create_by_uid!(:uid => "UID").uid.must_equal activity.uid
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should return the existing Nelumba::Activity via Nelumba::Activity" do
|
178
|
+
activity = Nelumba::Activity.create!(:uid => "UID",
|
179
|
+
:url => "URL")
|
180
|
+
|
181
|
+
nelumba_activity = Nelumba::Activity.new(:uid => "UID")
|
182
|
+
|
183
|
+
Nelumba::Activity.find_or_create_by_uid!(nelumba_activity).uid.must_equal activity.uid
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should create when the Nelumba::Activity is not found" do
|
187
|
+
Nelumba::Activity.expects(:create!).with({:uid => "UID"})
|
188
|
+
Nelumba::Activity.find_or_create_by_uid!(:uid => "UID")
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should save the given Nelumba::Activity when not found" do
|
192
|
+
nelumba_activity = Nelumba::Activity.new
|
193
|
+
nelumba_activity.stubs(:id).returns("UID")
|
194
|
+
|
195
|
+
nelumba_activity.expects(:save)
|
196
|
+
Nelumba::Activity.find_or_create_by_uid!(nelumba_activity)
|
197
|
+
end
|
198
|
+
|
199
|
+
it "should create a Nelumba::Activity from a hash when not found" do
|
200
|
+
hash = {:uid => "UID"}
|
201
|
+
|
202
|
+
Nelumba::Activity.expects(:create!).with(hash)
|
203
|
+
Nelumba::Activity.find_or_create_by_uid!(hash)
|
204
|
+
end
|
205
|
+
|
206
|
+
it "should account for race condition where entry was created after find" do
|
207
|
+
Nelumba::Activity.stubs(:first).returns(nil).then.returns("activity")
|
208
|
+
Nelumba::Activity.stubs(:create!).raises("")
|
209
|
+
Nelumba::Activity.find_or_create_by_uid!(:uid => "UID").must_equal "activity"
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should save the attached author found in the given hash" do
|
213
|
+
author_hash = {:uid => "PERSON_UID"}
|
214
|
+
hash = {:uid => "UID", :author => author_hash}
|
215
|
+
|
216
|
+
Nelumba::Person.expects(:find_or_create_by_uid!).with(author_hash)
|
217
|
+
Nelumba::Activity.find_or_create_by_uid!(hash)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
describe "discover!" do
|
222
|
+
it "should call out to Nelumba to discover the given Nelumba::Activity" do
|
223
|
+
Nelumba::Discover.expects(:activity).with("activity_url")
|
224
|
+
Nelumba::Activity.discover!("activity_url")
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should return false when the Nelumba::Activity cannot be discovered" do
|
228
|
+
Nelumba::Discover.stubs(:activity).returns(false)
|
229
|
+
Nelumba::Activity.discover!("activity_url").must_equal false
|
230
|
+
end
|
231
|
+
|
232
|
+
it "should return the existing Nelumba::Activity if it is found by url" do
|
233
|
+
activity = Nelumba::Activity.create!(:url => "activity_url",
|
234
|
+
:uid => "uid")
|
235
|
+
Nelumba::Activity.discover!("activity_url").id.must_equal activity.id
|
236
|
+
end
|
237
|
+
|
238
|
+
it "should return the existing Nelumba::Activity if uid matches" do
|
239
|
+
activity = Nelumba::Activity.create!(:url => "activity_url",
|
240
|
+
:uid => "ID")
|
241
|
+
|
242
|
+
nelumba_activity = Nelumba::Activity.new(:uid => "ID")
|
243
|
+
|
244
|
+
Nelumba::Discover.stubs(:activity).returns(nelumba_activity)
|
245
|
+
Nelumba::Activity.discover!("alternative_url").uid.must_equal activity.uid
|
246
|
+
end
|
247
|
+
|
248
|
+
it "should create a new Nelumba::Activity from the discovered Nelumba::Activity" do
|
249
|
+
nelumba_activity = Nelumba::Activity.new
|
250
|
+
nelumba_activity.stubs(:id).returns("ID")
|
251
|
+
|
252
|
+
Nelumba::Discover.stubs(:activity).returns(nelumba_activity)
|
253
|
+
Nelumba::Activity.expects(:create!).returns("new_activity")
|
254
|
+
Nelumba::Activity.discover!("alternative_url")
|
255
|
+
end
|
256
|
+
|
257
|
+
it "should return the new Nelumba::Activity from the discovered Nelumba::Activity" do
|
258
|
+
nelumba_activity = Nelumba::Activity.new
|
259
|
+
nelumba_activity.stubs(:id).returns("ID")
|
260
|
+
|
261
|
+
Nelumba::Discover.stubs(:activity).returns(nelumba_activity)
|
262
|
+
Nelumba::Activity.stubs(:create!).returns("new_activity")
|
263
|
+
Nelumba::Activity.discover!("alternative_url").must_equal "new_activity"
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
describe "create_from_notification!" do
|
268
|
+
before do
|
269
|
+
activity_author = Nelumba::Person.create :url => "acct:wilkie@rstat.us",
|
270
|
+
:uid => "AUTHOR ID"
|
271
|
+
|
272
|
+
activity = Nelumba::Activity.new :verb => :follow,
|
273
|
+
:uid => "1",
|
274
|
+
:title => "New Title",
|
275
|
+
:url => "foo",
|
276
|
+
:actor => activity_author
|
277
|
+
|
278
|
+
@notification = mock('Nelumba::Notification')
|
279
|
+
@notification.stubs(:activity).returns(activity)
|
280
|
+
@notification.stubs(:account).returns("acct:wilkie@rstat.us")
|
281
|
+
@notification.stubs(:verified?).returns(true)
|
282
|
+
|
283
|
+
Nelumba::Person.stubs(:find_or_create_by_uid!).returns(activity_author)
|
284
|
+
Nelumba::Person.stubs(:find_by_id).returns(activity_author)
|
285
|
+
|
286
|
+
@identity = Nelumba::Identity.new
|
287
|
+
@identity.stubs(:return_or_discover_public_key).returns("RSA_PUBLIC_KEY")
|
288
|
+
@identity.stubs(:discover_person!)
|
289
|
+
@identity.stubs(:author).returns(activity_author)
|
290
|
+
|
291
|
+
Nelumba::Identity.stubs(:discover!).with("acct:wilkie@rstat.us").returns(@identity)
|
292
|
+
end
|
293
|
+
|
294
|
+
it "should verify the content" do
|
295
|
+
@notification.expects(:verified?).with("RSA_PUBLIC_KEY").returns(true)
|
296
|
+
|
297
|
+
Nelumba::Activity.create_from_notification! @notification
|
298
|
+
end
|
299
|
+
|
300
|
+
it "should discover the account that sent the salmon" do
|
301
|
+
Nelumba::Identity.expects(:discover!).with(@notification.account).returns(@identity)
|
302
|
+
|
303
|
+
Nelumba::Activity.create_from_notification! @notification
|
304
|
+
end
|
305
|
+
|
306
|
+
it "should return nil when the payload is not verified" do
|
307
|
+
@notification.stubs(:verified?).returns(false)
|
308
|
+
Nelumba::Activity.create_from_notification!(@notification).must_equal nil
|
309
|
+
end
|
310
|
+
|
311
|
+
it "should return the new activity" do
|
312
|
+
Nelumba::Activity.create_from_notification!(@notification)
|
313
|
+
.class.must_equal Nelumba::Activity
|
314
|
+
end
|
315
|
+
|
316
|
+
it "should return the old activity when already exists" do
|
317
|
+
old = Nelumba::Activity.create_from_notification!(@notification)
|
318
|
+
Nelumba::Activity.create_from_notification!(@notification).must_equal old
|
319
|
+
end
|
320
|
+
|
321
|
+
it "should return nil if the update exists under a different author" do
|
322
|
+
old = Nelumba::Activity.create_from_notification!(@notification)
|
323
|
+
|
324
|
+
activity_author = Nelumba::Person.create :url => "acct:bogus@rstat.us",
|
325
|
+
:uid => "AUTHOR ID"
|
326
|
+
activity = Nelumba::Activity.new :verb => :follow,
|
327
|
+
:uid => "1",
|
328
|
+
:title => "New Title",
|
329
|
+
:url => "foo",
|
330
|
+
:actor => activity_author
|
331
|
+
|
332
|
+
@notification.stubs(:activity).returns(activity)
|
333
|
+
|
334
|
+
Nelumba::Activity.create_from_notification!(@notification).must_equal nil
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require_relative 'helper'
|
2
|
+
|
3
|
+
describe Nelumba::Article do
|
4
|
+
describe "Schema" do
|
5
|
+
it "should have a title" do
|
6
|
+
Nelumba::Article.keys.keys.must_include "title"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should have a content" do
|
10
|
+
Nelumba::Article.keys.keys.must_include "content"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should have a uid" do
|
14
|
+
Nelumba::Article.keys.keys.must_include "uid"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should have a url" do
|
18
|
+
Nelumba::Article.keys.keys.must_include "url"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should have a display_name" do
|
22
|
+
Nelumba::Article.keys.keys.must_include "display_name"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should have a summary" do
|
26
|
+
Nelumba::Article.keys.keys.must_include "summary"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should have an image" do
|
30
|
+
Nelumba::Article.keys.keys.must_include "image"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should have an author_id" do
|
34
|
+
Nelumba::Article.keys.keys.must_include "author_id"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should have a published" do
|
38
|
+
Nelumba::Article.keys.keys.must_include "published"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should have a updated" do
|
42
|
+
Nelumba::Article.keys.keys.must_include "updated"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "self.find_by_id" do
|
47
|
+
it "should not find a different type of object" do
|
48
|
+
note = Nelumba::Note.new(:content => "foo",
|
49
|
+
:title => "bar")
|
50
|
+
activity = Nelumba::Activity.create :object => note
|
51
|
+
|
52
|
+
Nelumba::Article.find_by_id(note.id).must_equal nil
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should not find by BSON id" do
|
56
|
+
article = Nelumba::Article.new(:content => "foo",
|
57
|
+
:title => "bar")
|
58
|
+
activity = Nelumba::Activity.create :object => article
|
59
|
+
|
60
|
+
Nelumba::Article.find_by_id(article.id).must_equal article
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should not find by string id" do
|
64
|
+
article = Nelumba::Article.new(:content => "foo",
|
65
|
+
:title => "bar")
|
66
|
+
activity = Nelumba::Activity.create :object => article
|
67
|
+
|
68
|
+
Nelumba::Article.find_by_id(article.id).must_equal article
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,514 @@
|
|
1
|
+
require_relative 'helper'
|
2
|
+
|
3
|
+
require 'xml'
|
4
|
+
|
5
|
+
module Nelumba
|
6
|
+
BCRYPT_ROUNDS = 1234
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_authorization(params)
|
10
|
+
params["domain"] ||= "www.example.com"
|
11
|
+
|
12
|
+
Nelumba::Authorization.stubs(:hash_password).returns("hashed")
|
13
|
+
|
14
|
+
keypair = Struct.new(:public_key, :private_key).new("PUBKEY", "PRIVKEY")
|
15
|
+
Nelumba::Crypto.stubs(:new_keypair).returns(keypair)
|
16
|
+
|
17
|
+
authorization = Nelumba::Authorization.new(params)
|
18
|
+
|
19
|
+
authorization
|
20
|
+
end
|
21
|
+
|
22
|
+
describe Nelumba::Authorization do
|
23
|
+
describe "Schema" do
|
24
|
+
it "should have a person_id" do
|
25
|
+
Nelumba::Authorization.keys.keys.must_include "person_id"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should have an identity_id" do
|
29
|
+
Nelumba::Authorization.keys.keys.must_include "identity_id"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should belong to a identity" do
|
33
|
+
Nelumba::Authorization.belongs_to?(:identity).must_equal true
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should have a username" do
|
37
|
+
Nelumba::Authorization.keys.keys.must_include "username"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should have a private_key" do
|
41
|
+
Nelumba::Authorization.keys.keys.must_include "private_key"
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should have a hashed_password" do
|
45
|
+
Nelumba::Authorization.keys.keys.must_include "hashed_password"
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should have an updated_at" do
|
49
|
+
Nelumba::Authorization.keys.keys.must_include "updated_at"
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should have a created_at" do
|
53
|
+
Nelumba::Authorization.keys.keys.must_include "created_at"
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should not have a password" do
|
57
|
+
Nelumba::Authorization.keys.keys.wont_include "password"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "create" do
|
62
|
+
before do
|
63
|
+
Nelumba::Authorization.stubs(:hash_password).returns("hashed")
|
64
|
+
|
65
|
+
keypair = Struct.new(:public_key, :private_key).new("PUBKEY", "PRIVKEY")
|
66
|
+
Nelumba::Crypto.stubs(:new_keypair).returns(keypair)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should create a person attached to this authorization" do
|
70
|
+
person = Nelumba::Person.new_local "wilkie", "www.example.com", nil, true
|
71
|
+
Nelumba::Person.expects(:new_local).returns(person)
|
72
|
+
|
73
|
+
Nelumba::Authorization.new("username" => "wilkie",
|
74
|
+
"password" => "foobar",
|
75
|
+
"domain" => "www.example.com",
|
76
|
+
"ssl" => true)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should save the person attached to this authorization" do
|
80
|
+
person = Nelumba::Person.new_local "wilkie", "www.example.com", nil, true
|
81
|
+
Nelumba::Person.stubs(:new_local).returns(person)
|
82
|
+
|
83
|
+
Nelumba::Authorization.new("username" => "wilkie",
|
84
|
+
"password" => "foobar",
|
85
|
+
"domain" => "www.example.com",
|
86
|
+
"ssl" => true)
|
87
|
+
|
88
|
+
Nelumba::Person.first(:id => person.id).activities_id.wont_equal nil
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should create a Person with the given username" do
|
92
|
+
person = Nelumba::Person.new_local "wilkie", "www.example.com", nil, true
|
93
|
+
Nelumba::Person.expects(:new_local)
|
94
|
+
.with("wilkie", anything, anything, anything)
|
95
|
+
.returns(person)
|
96
|
+
|
97
|
+
Nelumba::Authorization.new("username" => "wilkie",
|
98
|
+
"password" => "foobar",
|
99
|
+
"domain" => "www.example.com",
|
100
|
+
"ssl" => true)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should create a Person with the given domain" do
|
104
|
+
person = Nelumba::Person.new_local "wilkie", "www.example.com", nil, true
|
105
|
+
Nelumba::Person.expects(:new_local)
|
106
|
+
.with(anything, "www.example.com", anything, anything)
|
107
|
+
.returns(person)
|
108
|
+
|
109
|
+
Nelumba::Authorization.new("username" => "wilkie",
|
110
|
+
"password" => "foobar",
|
111
|
+
"domain" => "www.example.com",
|
112
|
+
"ssl" => true)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should create a Person with the given ssl requirements" do
|
116
|
+
person = Nelumba::Person.new_local "wilkie", "www.example.com", nil, true
|
117
|
+
Nelumba::Person.expects(:new_local)
|
118
|
+
.with(anything, anything, anything, true)
|
119
|
+
.returns(person)
|
120
|
+
|
121
|
+
Nelumba::Authorization.new("username" => "wilkie",
|
122
|
+
"password" => "foobar",
|
123
|
+
"domain" => "www.example.com",
|
124
|
+
"ssl" => true)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should create an Nelumba::Identity" do
|
128
|
+
Nelumba::Identity.expects(:new_local)
|
129
|
+
.returns(Nelumba::Identity.new)
|
130
|
+
|
131
|
+
Nelumba::Authorization.new("username" => "wilkie",
|
132
|
+
"password" => "foobar",
|
133
|
+
"domain" => "www.example.com",
|
134
|
+
"ssl" => true)
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should create an Nelumba::Identity with the generated public key" do
|
138
|
+
Nelumba::Identity.expects(:new_local)
|
139
|
+
.with(anything, anything, anything, anything, anything, "PUBKEY")
|
140
|
+
.returns(Nelumba::Identity.new)
|
141
|
+
|
142
|
+
Nelumba::Authorization.new("username" => "wilkie",
|
143
|
+
"password" => "foobar",
|
144
|
+
"domain" => "www.example.com",
|
145
|
+
"ssl" => true)
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should create an Nelumba::Identity with the given username" do
|
149
|
+
Nelumba::Identity.expects(:new_local)
|
150
|
+
.with(anything, "wilkie", anything, anything, anything, anything)
|
151
|
+
.returns(Nelumba::Identity.new)
|
152
|
+
|
153
|
+
Nelumba::Authorization.new("username" => "wilkie",
|
154
|
+
"password" => "foobar",
|
155
|
+
"domain" => "www.example.com",
|
156
|
+
"ssl" => true)
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should create an Nelumba::Identity with the given domain" do
|
160
|
+
Nelumba::Identity.expects(:new_local)
|
161
|
+
.with(anything, anything, "www.example.com", anything, anything, anything)
|
162
|
+
.returns(Nelumba::Identity.new)
|
163
|
+
|
164
|
+
Nelumba::Authorization.new("username" => "wilkie",
|
165
|
+
"password" => "foobar",
|
166
|
+
"domain" => "www.example.com",
|
167
|
+
"ssl" => true)
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should create an Nelumba::Identity with the given ssl requirements" do
|
171
|
+
Nelumba::Identity.expects(:new_local)
|
172
|
+
.with(anything, anything, anything, anything, true, anything)
|
173
|
+
.returns(Nelumba::Identity.new)
|
174
|
+
|
175
|
+
Nelumba::Authorization.new("username" => "wilkie",
|
176
|
+
"password" => "foobar",
|
177
|
+
"domain" => "www.example.com",
|
178
|
+
"ssl" => true)
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should create an Nelumba::Identity with the new person's author" do
|
182
|
+
person = Nelumba::Person.new_local "wilkie", "www.example.com", nil, true
|
183
|
+
Nelumba::Person.stubs(:new_local).returns(person)
|
184
|
+
|
185
|
+
Nelumba::Identity.expects(:new_local)
|
186
|
+
.with(person, anything, anything, anything, anything, anything)
|
187
|
+
.returns(Nelumba::Identity.new)
|
188
|
+
|
189
|
+
Nelumba::Authorization.new("username" => "wilkie",
|
190
|
+
"password" => "foobar",
|
191
|
+
"domain" => "www.example.com",
|
192
|
+
"ssl" => true)
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should associate a new Nelumba::Identity with this Nelumba::Authorization" do
|
196
|
+
person = Nelumba::Person.new_local "wilkie", "www.example.com", nil, true
|
197
|
+
Nelumba::Person.stubs(:new_local).returns(person)
|
198
|
+
|
199
|
+
auth = Nelumba::Authorization.new("username" => "wilkie",
|
200
|
+
"password" => "foobar",
|
201
|
+
"domain" => "www.example.com",
|
202
|
+
"ssl" => true)
|
203
|
+
|
204
|
+
auth.identity_id.must_equal person.identity.id
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should store the private key" do
|
208
|
+
auth = Nelumba::Authorization.new("username" => "wilkie",
|
209
|
+
"password" => "foobar",
|
210
|
+
"domain" => "www.example.com",
|
211
|
+
"ssl" => true)
|
212
|
+
|
213
|
+
auth.private_key.must_equal "PRIVKEY"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe "lrdd" do
|
218
|
+
it "returns nil when the username cannot be found" do
|
219
|
+
Nelumba::Authorization.stubs(:find_by_username).returns(nil)
|
220
|
+
Nelumba::Authorization.lrdd("bogus@www.example.com").must_equal nil
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should contain a subject matching their webfinger" do
|
224
|
+
authorization = create_authorization("username" => "wilkie",
|
225
|
+
"password" => "foobar")
|
226
|
+
Nelumba::Authorization.stubs(:find_by_username).returns(authorization)
|
227
|
+
Nelumba::Authorization.lrdd("wilkie@www.example.com")[:subject]
|
228
|
+
.must_equal "acct:wilkie@www.example.com"
|
229
|
+
end
|
230
|
+
|
231
|
+
it "should contain an alias to the profile" do
|
232
|
+
authorization = create_authorization("username" => "wilkie",
|
233
|
+
"password" => "foobar")
|
234
|
+
Nelumba::Authorization.stubs(:find_by_username).returns(authorization)
|
235
|
+
Nelumba::Authorization.lrdd("wilkie@www.example.com")[:aliases]
|
236
|
+
.must_include "http://www.example.com/people/#{authorization.person.id}"
|
237
|
+
end
|
238
|
+
|
239
|
+
it "should contain an alias to the profile" do
|
240
|
+
authorization = create_authorization("username" => "wilkie",
|
241
|
+
"password" => "foobar")
|
242
|
+
Nelumba::Authorization.stubs(:find_by_username).returns(authorization)
|
243
|
+
Nelumba::Authorization.lrdd("wilkie@www.example.com")[:aliases]
|
244
|
+
.must_include "http://www.example.com/people/#{authorization.person.id}"
|
245
|
+
end
|
246
|
+
|
247
|
+
it "should contain an alias to the feed" do
|
248
|
+
authorization = create_authorization("username" => "wilkie",
|
249
|
+
"password" => "foobar")
|
250
|
+
Nelumba::Authorization.stubs(:find_by_username).returns(authorization)
|
251
|
+
Nelumba::Authorization.lrdd("wilkie@www.example.com")[:aliases].must_include(
|
252
|
+
"http://www.example.com/feeds/#{authorization.identity.outbox.id}")
|
253
|
+
end
|
254
|
+
|
255
|
+
it "should contain profile-page link" do
|
256
|
+
authorization = create_authorization("username" => "wilkie",
|
257
|
+
"password" => "foobar")
|
258
|
+
person_id = authorization.person.id
|
259
|
+
|
260
|
+
Nelumba::Authorization.stubs(:find_by_username).returns(authorization)
|
261
|
+
Nelumba::Authorization.lrdd("wilkie@www.example.com")[:links]
|
262
|
+
.must_include({:rel => "http://webfinger.net/rel/profile-page",
|
263
|
+
:href => "http://www.example.com/people/#{person_id}"})
|
264
|
+
end
|
265
|
+
|
266
|
+
it "should contain updates-from link" do
|
267
|
+
authorization = create_authorization("username" => "wilkie",
|
268
|
+
"password" => "foobar")
|
269
|
+
feed_id = authorization.identity.outbox.id
|
270
|
+
|
271
|
+
Nelumba::Authorization.stubs(:find_by_username).returns(authorization)
|
272
|
+
Nelumba::Authorization.lrdd("wilkie@www.example.com")[:links]
|
273
|
+
.must_include({:rel => "http://schemas.google.com/g/2010#updates-from",
|
274
|
+
:href => "http://www.example.com/feeds/#{feed_id}"})
|
275
|
+
end
|
276
|
+
|
277
|
+
it "should contain salmon link" do
|
278
|
+
authorization = create_authorization("username" => "wilkie",
|
279
|
+
"password" => "foobar")
|
280
|
+
person_id = authorization.person.id
|
281
|
+
|
282
|
+
Nelumba::Authorization.stubs(:find_by_username).returns(authorization)
|
283
|
+
Nelumba::Authorization.lrdd("wilkie@www.example.com")[:links]
|
284
|
+
.must_include(:rel => "salmon",
|
285
|
+
:href => "http://www.example.com/people/#{person_id}/salmon")
|
286
|
+
end
|
287
|
+
|
288
|
+
it "should contain salmon-replies link" do
|
289
|
+
authorization = create_authorization("username" => "wilkie",
|
290
|
+
"password" => "foobar")
|
291
|
+
person_id = authorization.person.id
|
292
|
+
|
293
|
+
Nelumba::Authorization.stubs(:find_by_username).returns(authorization)
|
294
|
+
Nelumba::Authorization.lrdd("wilkie@www.example.com")[:links]
|
295
|
+
.must_include(:rel => "http://salmon-protocol.org/ns/salmon-replies",
|
296
|
+
:href => "http://www.example.com/people/#{person_id}/salmon")
|
297
|
+
end
|
298
|
+
|
299
|
+
it "should contain salmon-mention link" do
|
300
|
+
authorization = create_authorization("username" => "wilkie",
|
301
|
+
"password" => "foobar")
|
302
|
+
person_id = authorization.person.id
|
303
|
+
|
304
|
+
Nelumba::Authorization.stubs(:find_by_username).returns(authorization)
|
305
|
+
Nelumba::Authorization.lrdd("wilkie@www.example.com")[:links]
|
306
|
+
.must_include(:rel => "http://salmon-protocol.org/ns/salmon-mention",
|
307
|
+
:href => "http://www.example.com/people/#{person_id}/salmon")
|
308
|
+
end
|
309
|
+
|
310
|
+
it "should contain magic-public-key link" do
|
311
|
+
authorization = create_authorization("username" => "wilkie",
|
312
|
+
"password" => "foobar")
|
313
|
+
person_id = authorization.person.id
|
314
|
+
|
315
|
+
authorization.identity.public_key = "PUBLIC_KEY"
|
316
|
+
|
317
|
+
Nelumba::Authorization.stubs(:find_by_username).returns(authorization)
|
318
|
+
Nelumba::Authorization.lrdd("wilkie@www.example.com")[:links]
|
319
|
+
.must_include(:rel => "magic-public-key",
|
320
|
+
:href => "data:application/magic-public-key,PUBLIC_KEY")
|
321
|
+
end
|
322
|
+
|
323
|
+
it "should contain an expires link that is 1 month away from retrieval" do
|
324
|
+
authorization = create_authorization("username" => "wilkie",
|
325
|
+
"password" => "foobar")
|
326
|
+
|
327
|
+
check_date = Date.new(2012, 1, 1)
|
328
|
+
Date.any_instance.expects(:>>).with(1).returns(check_date)
|
329
|
+
|
330
|
+
Nelumba::Authorization.stubs(:find_by_username).returns(authorization)
|
331
|
+
Nelumba::Authorization.lrdd("wilkie@www.example.com")[:expires].must_equal(
|
332
|
+
"#{check_date.xmlschema}Z")
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
describe "jrd" do
|
337
|
+
it "should simply take the lrdd and run to_json" do
|
338
|
+
lrdd_hash = {}
|
339
|
+
Nelumba::Authorization.stubs(:lrdd).with("wilkie@www.example.com").returns(lrdd_hash)
|
340
|
+
lrdd_hash.stubs(:to_json).returns("JSON")
|
341
|
+
|
342
|
+
Nelumba::Authorization.jrd("wilkie@www.example.com").must_equal "JSON"
|
343
|
+
end
|
344
|
+
|
345
|
+
it "should return nil when lrdd returns nil" do
|
346
|
+
Nelumba::Authorization.stubs(:lrdd).returns(nil)
|
347
|
+
Nelumba::Authorization.jrd("bogus@www.example.com").must_equal nil
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
describe "xrd" do
|
352
|
+
before do
|
353
|
+
@authorization = create_authorization("username" => "wilkie",
|
354
|
+
"password" => "foobar")
|
355
|
+
|
356
|
+
Nelumba::Authorization.stubs(:lrdd).returns(:subject => "Subject",
|
357
|
+
:expires => "Date",
|
358
|
+
:aliases => ["alias_a",
|
359
|
+
"alias_b"],
|
360
|
+
:links => [
|
361
|
+
{:rel => "a rel",
|
362
|
+
:href => "a href"},
|
363
|
+
{:rel => "b rel",
|
364
|
+
:href => "b href"}])
|
365
|
+
|
366
|
+
@xrd = Nelumba::Authorization.xrd("wilkie@www.example.com")
|
367
|
+
|
368
|
+
@xml = XML::Parser.string(@xrd).parse
|
369
|
+
end
|
370
|
+
|
371
|
+
it "should return nil when lrdd returns nil" do
|
372
|
+
Nelumba::Authorization.stubs(:lrdd).returns(nil)
|
373
|
+
Nelumba::Authorization.xrd("bogus@www.example.com").must_equal nil
|
374
|
+
end
|
375
|
+
|
376
|
+
it "should publish a version of 1.0" do
|
377
|
+
@xrd.must_match /^<\?xml[^>]*\sversion="1\.0"/
|
378
|
+
end
|
379
|
+
|
380
|
+
it "should encode in utf-8" do
|
381
|
+
@xrd.must_match /^<\?xml[^>]*\sencoding="UTF-8"/
|
382
|
+
end
|
383
|
+
|
384
|
+
it "should contain the XRD namespace" do
|
385
|
+
@xml.root.namespaces
|
386
|
+
.find_by_href('http://docs.oasis-open.org/ns/xri/xrd-1.0').to_s
|
387
|
+
.must_equal 'http://docs.oasis-open.org/ns/xri/xrd-1.0'
|
388
|
+
end
|
389
|
+
|
390
|
+
it "should contain the xsi namespace" do
|
391
|
+
@xml.root.namespaces
|
392
|
+
.find_by_prefix('xsi').to_s
|
393
|
+
.must_equal 'xsi:http://www.w3.org/2001/XMLSchema-instance'
|
394
|
+
end
|
395
|
+
|
396
|
+
it "should contain the <Subject>" do
|
397
|
+
@xml.root.find_first('xmlns:Subject',
|
398
|
+
'xmlns:http://docs.oasis-open.org/ns/xri/xrd-1.0')
|
399
|
+
.content.must_equal Nelumba::Authorization.lrdd("wilkie@www.example.com")[:subject]
|
400
|
+
end
|
401
|
+
|
402
|
+
it "should contain the <Expires>" do
|
403
|
+
@xml.root.find_first('xmlns:Expires',
|
404
|
+
'xmlns:http://docs.oasis-open.org/ns/xri/xrd-1.0')
|
405
|
+
.content.must_equal Nelumba::Authorization.lrdd("wilkie@www.example.com")[:expires]
|
406
|
+
end
|
407
|
+
|
408
|
+
it "should contain the <Alias> tags" do
|
409
|
+
aliases = Nelumba::Authorization.lrdd("wilkie@www.example.com")[:aliases]
|
410
|
+
@xml.root.find('xmlns:Alias',
|
411
|
+
'xmlns:http://docs.oasis-open.org/ns/xri/xrd-1.0').each do |t|
|
412
|
+
index = aliases.index(t.content)
|
413
|
+
index.wont_equal nil
|
414
|
+
|
415
|
+
aliases.delete_at index
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
it "should contain the <Link> tags" do
|
420
|
+
links = Nelumba::Authorization.lrdd("wilkie@www.example.com")[:links]
|
421
|
+
@xml.root.find('xmlns:Link',
|
422
|
+
'xmlns:http://docs.oasis-open.org/ns/xri/xrd-1.0').each do |t|
|
423
|
+
link = {:rel => t.attributes.get_attribute('rel').value,
|
424
|
+
:href => t.attributes.get_attribute('href').value}
|
425
|
+
index = links.index(link)
|
426
|
+
index.wont_equal nil
|
427
|
+
|
428
|
+
links.delete_at index
|
429
|
+
end
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
describe "hash_password" do
|
434
|
+
it "should call bcrypt with the application specified number of rounds" do
|
435
|
+
BCrypt::Password.expects(:create).with(anything, has_entry(:cost, 1234))
|
436
|
+
Nelumba::Authorization.hash_password("foobar")
|
437
|
+
end
|
438
|
+
|
439
|
+
it "should call bcrypt with the given password" do
|
440
|
+
BCrypt::Password.expects(:create).with("foobar", anything)
|
441
|
+
Nelumba::Authorization.hash_password("foobar")
|
442
|
+
end
|
443
|
+
|
444
|
+
it "should return the hashed password" do
|
445
|
+
BCrypt::Password.expects(:create).returns("hashed!")
|
446
|
+
Nelumba::Authorization.hash_password("foobar").must_equal "hashed!"
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
describe "#authenticated?" do
|
451
|
+
it "should compare the given password with the stored password" do
|
452
|
+
authorization = create_authorization("username" => "wilkie",
|
453
|
+
"password" => "foobar")
|
454
|
+
|
455
|
+
checker = stub('String')
|
456
|
+
BCrypt::Password.stubs(:new).with("hashed").returns(checker)
|
457
|
+
|
458
|
+
checker.expects(:==).with("foobar")
|
459
|
+
authorization.authenticated?("foobar")
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
describe "sanitize_params" do
|
464
|
+
it "should allow Nelumba::Authorization keys" do
|
465
|
+
hash = {}
|
466
|
+
Nelumba::Authorization.keys.keys.each do |k|
|
467
|
+
next if ["_id"].include? k
|
468
|
+
hash[k] = "foobar"
|
469
|
+
end
|
470
|
+
|
471
|
+
hash = Nelumba::Authorization.sanitize_params(hash)
|
472
|
+
|
473
|
+
Nelumba::Authorization.keys.keys.each do |k|
|
474
|
+
next if ["_id"].include? k
|
475
|
+
hash[k.intern].must_equal "foobar"
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
it "should remove password key" do
|
480
|
+
hash = {"password" => "foobar"}
|
481
|
+
hash = Nelumba::Authorization.sanitize_params(hash)
|
482
|
+
hash.keys.wont_include :password
|
483
|
+
end
|
484
|
+
|
485
|
+
it "should convert strings to symbols" do
|
486
|
+
hash = {}
|
487
|
+
Nelumba::Authorization.keys.keys.each do |k|
|
488
|
+
next if ["_id"].include? k
|
489
|
+
hash[k] = "foobar"
|
490
|
+
end
|
491
|
+
|
492
|
+
hash = Nelumba::Authorization.sanitize_params(hash)
|
493
|
+
|
494
|
+
Nelumba::Authorization.keys.keys.each do |k|
|
495
|
+
next if ["_id"].include? k
|
496
|
+
hash[k.intern].must_equal "foobar"
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
it "should not allow _id" do
|
501
|
+
hash = {"_id" => "bogus"}
|
502
|
+
hash = Nelumba::Authorization.sanitize_params(hash)
|
503
|
+
hash.keys.wont_include :_id
|
504
|
+
end
|
505
|
+
|
506
|
+
it "should not allow arbitrary keys" do
|
507
|
+
hash = {:bogus => "foobar"}
|
508
|
+
|
509
|
+
hash = Nelumba::Authorization.sanitize_params(hash)
|
510
|
+
|
511
|
+
hash.keys.wont_include :bogus
|
512
|
+
end
|
513
|
+
end
|
514
|
+
end
|