rackjson 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,114 +12,131 @@ RackJSON uses MongoDB for persistence so you also need to install MongoDB.
12
12
 
13
13
  In your rackup file:
14
14
 
15
- `require mongo
16
- require rackjson`
17
-
18
- `use Rack::JSON::Resource, :collections => [:notes], :db => Mongo::Connection.new.db("mydb")`
19
-
20
- `run lambda { |env|
21
- [404, {'Content-Length' => '9', 'Content-Type' => 'text/plain'}, "Not Found"]
22
- }`
15
+ require mongo
16
+ require rackjson
17
+
18
+ expose_resource :collections => [:notes], :db => Mongo::Connection.new.db("mydb")
19
+
20
+ run lambda { |env|
21
+ [404, {'Content-Length' => '9', 'Content-Type' => 'text/plain'}, "Not Found"]
22
+ }
23
23
 
24
24
  This will set up a RESTful resource called 'notes' at /notes which will store any JSON document.
25
25
 
26
- ### REST API
26
+ ### Restricting Access
27
27
 
28
- To see what actions are available on the notes resource:
28
+ There are three ways of mounting a restful resource with rackjson:
29
29
 
30
- `curl -i -XOPTIONS http://localhost:9292/notes`
30
+ `expose_resource :collections => [:notes], :db => Mongo::Connection.new.db("mydb")`
31
31
 
32
- `HTTP/1.1 200 OK`
33
- `Connection: close`
34
- `Date: Sun, 11 Apr 2010 11:09:40 GMT`
35
- `Content-Type: text/plain`
36
- `Content-Length: 0`
37
- `Allow: GET, POST`
32
+ Using `expose_resource` won't restrict access to the resource at all, all requests by anyone will succeed.
38
33
 
39
- Listing the existing notes:
34
+ `public_resource :collections => [:notes], :filters => [:user_id], :db => Mongo::Connection.new.db("mydb")`
40
35
 
41
- `curl -i http://localhost:9292/notes`
36
+ Using `public_resource` will allow everyone to perform GET requests against the resource, however to make POST, PUT or DELETE requests the requester must have a specific session param, and will only be able to make requests to documents which match this session param. In the above example this session param is set to user_id and could be set when logging in.
42
37
 
43
- `HTTP/1.1 200 OK
44
- Connection: close
45
- Date: Sun, 11 Apr 2010 11:12:04 GMT
46
- Content-Type: application/json
47
- Content-Length: 2`
38
+ `public_resource :collections => [:notes], :filters => [:user_id], :db => Mongo::Connection.new.db("mydb")`
48
39
 
49
- `[]`
40
+ Private resource is very similar except that all requests, including GET requests must also satisfy the pre-condition of having a specific session param.
50
41
 
51
- Currently there are no notes, create one with a post request:
42
+ When creating resources with either the public or private resources the specified session param will be included in the document automatically.
52
43
 
53
- `curl -i -XPOST -d'{"title":"hello world!"}' http://localhost:9292/notes`
44
+ ### REST API
54
45
 
55
- `HTTP/1.1 201 Created
56
- Connection: close
57
- Date: Sun, 11 Apr 2010 11:14:17 GMT
58
- Content-Type: application/json
59
- Content-Length: 149`
46
+ To see what actions are available on the notes resource:
60
47
 
61
- `{"updated_at":"Sun Apr 11 12:14:17 +0100 2010","title":"hello world!","_id":"4bc1af0934701204fd000001","created_at":"Sun Apr 11 12:14:17 +0100 2010"}`
48
+ curl -i -XOPTIONS http://localhost:9292/notes
49
+
50
+ HTTP/1.1 200 OK
51
+ Connection: close
52
+ Date: Sun, 11 Apr 2010 11:09:40 GMT
53
+ Content-Type: text/plain
54
+ Content-Length: 0
55
+ Allow: GET, POST
62
56
 
63
- RackJSON will assign an id to this resource as _id. This can be used to access this resource directly
57
+ Listing the existing notes:
64
58
 
65
- `curl -i http://localhost:9292/notes/4bc1af0934701204fd000001`
59
+ curl -i http://localhost:9292/notes
60
+
61
+ HTTP/1.1 200 OK
62
+ Connection: close
63
+ Date: Sun, 11 Apr 2010 11:12:04 GMT
64
+ Content-Type: application/json
65
+ Content-Length: 2
66
+
67
+ []
66
68
 
67
- `HTTP/1.1 200 OK
68
- Connection: close
69
- Date: Sun, 11 Apr 2010 11:16:30 GMT
70
- Content-Type: application/json
71
- Content-Length: 147`
69
+ Currently there are no notes, create one with a post request:
72
70
 
73
- `[{"updated_at":"Sun Apr 11 11:14:17 UTC 2010","title":"hello world!","_id":"4bc1af0934701204fd000001","created_at":"Sun Apr 11 11:14:17 UTC 2010"}]`
71
+ curl -i -XPOST -d'{"title":"hello world!"}' http://localhost:9292/notes
72
+
73
+ HTTP/1.1 201 Created
74
+ Connection: close
75
+ Date: Sun, 11 Apr 2010 11:14:17 GMT
76
+ Content-Type: application/json
77
+ Content-Length: 149
78
+
79
+ {"updated_at":"Sun Apr 11 12:14:17 +0100 2010","title":"hello world!","_id":"4bc1af0934701204fd000001","created_at":"Sun Apr 11 12:14:17 +0100 2010"}
74
80
 
75
- This resource will also appear in the index of notes resources
81
+ RackJSON will assign an id to this resource as _id. This can be used to access this resource directly
76
82
 
77
- `curl -i http://localhost:9292/notes`
83
+ curl -i http://localhost:9292/notes/4bc1af0934701204fd000001
84
+
85
+ HTTP/1.1 200 OK
86
+ Connection: close
87
+ Date: Sun, 11 Apr 2010 11:16:30 GMT
88
+ Content-Type: application/json
89
+ Content-Length: 147
90
+
91
+ [{"updated_at":"Sun Apr 11 11:14:17 UTC 2010","title":"hello world!","_id":"4bc1af0934701204fd000001","created_at":"Sun Apr 11 11:14:17 UTC 2010"}]
78
92
 
79
- `HTTP/1.1 200 OK
80
- Connection: close
81
- Date: Sun, 11 Apr 2010 11:17:27 GMT
82
- Content-Type: application/json
83
- Content-Length: 147`
93
+ This resource will also appear in the index of notes resources
84
94
 
85
- `[{"updated_at":"Sun Apr 11 11:14:17 UTC 2010","title":"hello world!","_id":"4bc1af0934701204fd000001","created_at":"Sun Apr 11 11:14:17 UTC 2010"}]`
95
+ curl -i http://localhost:9292/notes
96
+
97
+ HTTP/1.1 200 OK
98
+ Connection: close
99
+ Date: Sun, 11 Apr 2010 11:17:27 GMT
100
+ Content-Type: application/json
101
+ Content-Length: 147
102
+
103
+ [{"updated_at":"Sun Apr 11 11:14:17 UTC 2010","title":"hello world!","_id":"4bc1af0934701204fd000001","created_at":"Sun Apr 11 11:14:17 UTC 2010"}]
86
104
 
87
105
  Update a resource using a PUT request
88
106
 
89
- `curl -i -XPUT -d'{"title":"updated"}' http://localhost:9292/notes/4bc1af0934701204fd000001`
90
-
91
- `HTTP/1.1 200 OK
92
- Connection: close
93
- Date: Sun, 11 Apr 2010 11:25:04 GMT
94
- Content-Type: application/json
95
- Content-Length: 144`
96
-
97
- `{"updated_at":"Sun Apr 11 12:25:04 +0100 2010","title":"updated","_id":"4bc1af0934701204fd000001","created_at":"Sun Apr 11 12:25:04 +0100 2010"}`
107
+ curl -i -XPUT -d'{"title":"updated"}' http://localhost:9292/notes/4bc1af0934701204fd000001
108
+
109
+ HTTP/1.1 200 OK
110
+ Connection: close
111
+ Date: Sun, 11 Apr 2010 11:25:04 GMT
112
+ Content-Type: application/json
113
+ Content-Length: 144
114
+
115
+ {"updated_at":"Sun Apr 11 12:25:04 +0100 2010","title":"updated","_id":"4bc1af0934701204fd000001","created_at":"Sun Apr 11 12:25:04 +0100 2010"}
98
116
 
99
117
  A PUT request can also be used to create a resource at the given location:
100
118
 
101
- `curl -i -XPUT -d'{"foo":"bar"}' http://localhost:9292/notes/1`
102
-
103
- `HTTP/1.1 200 OK
104
- Connection: close
105
- Date: Sun, 11 Apr 2010 11:27:13 GMT
106
- Content-Type: application/json
107
- Content-Length: 113`
108
-
109
- `{"updated_at":"Sun Apr 11 12:27:13 +0100 2010","_id":1,"foo":"bar","created_at":"Sun Apr 11 12:27:13 +0100 2010"}`
119
+ curl -i -XPUT -d'{"foo":"bar"}' http://localhost:9292/notes/1
120
+
121
+ HTTP/1.1 200 OK
122
+ Connection: close
123
+ Date: Sun, 11 Apr 2010 11:27:13 GMT
124
+ Content-Type: application/json
125
+ Content-Length: 113
126
+
127
+ {"updated_at":"Sun Apr 11 12:27:13 +0100 2010","_id":1,"foo":"bar","created_at":"Sun Apr 11 12:27:13 +0100 2010"}
110
128
 
111
129
  Finally a resource can be deleted using a DELETE request
112
130
 
113
- `curl -i -XDELETE http://localhost:9292/notes/1`
114
-
115
- `HTTP/1.1 200 OK
116
- Connection: close
117
- Date: Sun, 11 Apr 2010 11:29:14 GMT
118
- Content-Type: application/json
119
- Content-Length: 12
120
- `
121
-
122
- `{"ok": "true"}`
131
+ curl -i -XDELETE http://localhost:9292/notes/1
132
+
133
+ HTTP/1.1 200 OK
134
+ Connection: close
135
+ Date: Sun, 11 Apr 2010 11:29:14 GMT
136
+ Content-Type: application/json
137
+ Content-Length: 12
138
+
139
+ {"ok": "true"}
123
140
 
124
141
  ### JSON Query
125
142
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1
1
+ 0.3.0
@@ -3,9 +3,12 @@ require 'json'
3
3
  require 'rack'
4
4
  require 'mongo'
5
5
  require 'time'
6
+ require 'rackjson/rack/builder'
6
7
 
7
8
  module Rack::JSON
8
9
 
10
+ autoload :BaseDocument, 'rackjson/base_document'
11
+ autoload :Builder, 'rackjson/rack/builder'
9
12
  autoload :EndPoint, 'rackjson/end_point'
10
13
  autoload :Collection, 'rackjson/collection'
11
14
  autoload :Filter, 'rackjson/filter'
@@ -0,0 +1,18 @@
1
+ module Rack::JSON
2
+ module BaseDocument
3
+
4
+ private
5
+
6
+ def set_attribute_created_at
7
+ @attributes["created_at"] = Time.now unless @attributes["created_at"]
8
+ end
9
+
10
+ def set_attributes
11
+ private_methods.each do |method|
12
+ if method.match /^set_attribute_\w*$/
13
+ send method
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -15,6 +15,10 @@ module Rack::JSON
15
15
  !@methods.include?(request.request_method.downcase.to_sym)
16
16
  end
17
17
 
18
+ def invalid_json error
19
+ render (error.class.to_s + " :" + error.message), :status => 422
20
+ end
21
+
18
22
  def render body, options={}
19
23
  Rack::JSON::Response.new(body, options).to_a
20
24
  end
@@ -33,6 +33,8 @@ module Rack::JSON
33
33
  end
34
34
  append_filters_to_document_in request if request.post? || request.put?
35
35
  @app.call(request.env)
36
+ rescue JSON::ParserError => error
37
+ return invalid_json error
36
38
  end
37
39
 
38
40
  def pre_condition_not_met
@@ -1,5 +1,6 @@
1
1
  module Rack::JSON
2
2
  class JSONDocument
3
+ include Rack::JSON::BaseDocument
3
4
 
4
5
  attr_reader :attributes
5
6
 
@@ -14,10 +15,6 @@ module Rack::JSON
14
15
 
15
16
  private
16
17
 
17
- def set_attribute_created_at
18
- @attributes["created_at"] = Time.now unless @attributes["created_at"]
19
- end
20
-
21
18
  def set_attribute_dates
22
19
  @attributes.each_pair do |key, value|
23
20
  if value.class == String && value.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/)
@@ -35,13 +32,5 @@ module Rack::JSON
35
32
  def set_attribute_updated_at
36
33
  @attributes["updated_at"] = Time.now
37
34
  end
38
-
39
- def set_attributes
40
- private_methods.each do |method|
41
- if method.match /^set_attribute_\w*$/
42
- send method
43
- end
44
- end
45
- end
46
35
  end
47
36
  end
@@ -1,11 +1,11 @@
1
1
  module Rack::JSON
2
2
  class MongoDocument
3
+ include Rack::JSON::BaseDocument
3
4
 
4
5
  attr_accessor :attributes
5
6
 
6
7
  def initialize(row)
7
8
  @attributes = row
8
- set_created_at
9
9
  set_attributes
10
10
  end
11
11
 
@@ -14,19 +14,5 @@ module Rack::JSON
14
14
  def set_attribute_ids
15
15
  @attributes["_id"] = @attributes["_id"].to_s if (@attributes["_id"].is_a? BSON::ObjectID)
16
16
  end
17
-
18
- def set_created_at
19
- if @attributes["_id"].is_a? BSON::ObjectID
20
- @attributes["created_at"] = @attributes["_id"].generation_time unless @attributes["created_at"]
21
- end
22
- end
23
-
24
- def set_attributes
25
- private_methods.each do |method|
26
- if method.match /^set_attribute_\w*$/
27
- send method
28
- end
29
- end
30
- end
31
17
  end
32
18
  end
@@ -0,0 +1,44 @@
1
+ module Rack
2
+ class Builder
3
+ # Setup resource collections without authentication.
4
+ #
5
+ # ===Example
6
+ # expose_resource :collections => [:notes, :projects], :db => @mongo_db
7
+ #
8
+ def expose_resource options
9
+ @ins << lambda do |app|
10
+ Rack::JSON::Resource.new app, options
11
+ end
12
+ end
13
+
14
+ # Setup resource collections with public read access but write access only
15
+ # given to the owner of the document, determened from the session var passed
16
+ # as filter.
17
+ #
18
+ # ===Example
19
+ # public_resource :collections => [:notes, :projects], :db => @mongo_db, :filters => [:user_id]
20
+ #
21
+ def public_resource options
22
+ @ins << lambda do |app|
23
+ Rack::JSON::Filter.new(
24
+ Rack::JSON::Resource.new(app, options),
25
+ options.merge(:methods => [:post, :put, :delete]))
26
+ end
27
+ end
28
+
29
+ # Setup resource collections with no public access. Read and write access only
30
+ # given to the owner of the document, determened from the session vars passed
31
+ # as filters.
32
+ #
33
+ # ===Example
34
+ # private_resource :collections => [:notes, :projects], :db => @mongo_db, :filters => [:user_id]
35
+ #
36
+ def private_resource options
37
+ @ins << lambda do |app|
38
+ Rack::JSON::Filter.new(
39
+ Rack::JSON::Resource.new(app, options),
40
+ options.merge(:methods => [:get, :post, :put, :delete]))
41
+ end
42
+ end
43
+ end
44
+ end
@@ -44,7 +44,7 @@ module Rack::JSON
44
44
  end
45
45
 
46
46
  def session
47
- @env['rack.session']
47
+ @env['rack.session'] || {}
48
48
  end
49
49
 
50
50
  def set_body json
@@ -57,13 +57,13 @@ module Rack::JSON
57
57
  @collection.create(document.attributes)
58
58
  render document.to_json, :status => 201
59
59
  rescue JSON::ParserError => error
60
- render (error.class.to_s + " :" + error.message), :status => 422
60
+ invalid_json error
61
61
  end
62
62
 
63
63
  def put(request)
64
64
  @collection.exists?(request.resource_id) ? update(request) : upsert(request)
65
65
  rescue JSON::ParserError => error
66
- render (error.class.to_s + " :" + error.message), :status => 422
66
+ invalid_json error
67
67
  end
68
68
 
69
69
  def update(request)
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rackjson}
8
- s.version = "0.2.1"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Oliver Nightingale"]
12
- s.date = %q{2010-04-29}
12
+ s.date = %q{2010-05-06}
13
13
  s.description = %q{A rack end point for storing json documents.}
14
14
  s.email = %q{oliver.n@new-bamboo.co.uk}
15
15
  s.extra_rdoc_files = [
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
24
24
  "Rakefile",
25
25
  "VERSION",
26
26
  "lib/rackjson.rb",
27
+ "lib/rackjson/base_document.rb",
27
28
  "lib/rackjson/collection.rb",
28
29
  "lib/rackjson/document.rb",
29
30
  "lib/rackjson/end_point.rb",
@@ -31,6 +32,7 @@ Gem::Specification.new do |s|
31
32
  "lib/rackjson/json_document.rb",
32
33
  "lib/rackjson/json_query.rb",
33
34
  "lib/rackjson/mongo_document.rb",
35
+ "lib/rackjson/rack/builder.rb",
34
36
  "lib/rackjson/request.rb",
35
37
  "lib/rackjson/resource.rb",
36
38
  "lib/rackjson/response.rb",
@@ -43,6 +45,7 @@ Gem::Specification.new do |s|
43
45
  "test/test_json_document.rb",
44
46
  "test/test_json_query.rb",
45
47
  "test/test_mongo_document.rb",
48
+ "test/test_rack_builder.rb",
46
49
  "test/test_resource.rb",
47
50
  "test/test_response.rb"
48
51
  ]
@@ -60,6 +63,7 @@ Gem::Specification.new do |s|
60
63
  "test/test_json_document.rb",
61
64
  "test/test_json_query.rb",
62
65
  "test/test_mongo_document.rb",
66
+ "test/test_rack_builder.rb",
63
67
  "test/test_resource.rb",
64
68
  "test/test_response.rb"
65
69
  ]
@@ -13,7 +13,9 @@ class CollectionTest < Test::Unit::TestCase
13
13
 
14
14
  test "finding a single document by id" do
15
15
  mongo_document = @mongo_collection.save({:testing => true, :rating => 5, :title => 'testing', :_id => 1})
16
- assert_equal @collection.find(1).attributes, @mongo_collection.find_one(:_id => 1)
16
+ assert_equal @collection.find(1).attributes['testing'], @mongo_collection.find_one(:_id => 1)['testing']
17
+ assert_equal @collection.find(1).attributes['rating'], @mongo_collection.find_one(:_id => 1)['rating']
18
+ assert_equal @collection.find(1).attributes['title'], @mongo_collection.find_one(:_id => 1)['title']
17
19
  assert_kind_of Rack::JSON::Document, @collection.find(1)
18
20
  end
19
21
 
@@ -21,7 +23,7 @@ class CollectionTest < Test::Unit::TestCase
21
23
  mongo_document = @mongo_collection.save({:testing => true, :rating => 5, :title => 'testing', :_id => 1})
22
24
  mongo_results = []
23
25
  @mongo_collection.find(:testing => true).each { |row| mongo_results << row }
24
- assert_equal @collection.find(:testing => true).first.attributes, mongo_results.first
26
+ assert_equal @collection.find(:testing => true, :rating => 5).first.attributes['testing'], mongo_results.first['testing']
25
27
  assert_kind_of Rack::JSON::Document, @collection.find(:testing => true).first
26
28
  end
27
29
 
@@ -30,7 +32,7 @@ class CollectionTest < Test::Unit::TestCase
30
32
  mongo_results = []
31
33
  @mongo_collection.find(:testing => true, :rating => 5).each { |row| mongo_results << row }
32
34
  assert_equal @collection.find(:testing => true, :rating => 5).length, mongo_results.length
33
- assert_equal @collection.find(:testing => true, :rating => 5).first.attributes, mongo_results.first
35
+ assert_equal @collection.find(:testing => true, :rating => 5).first.attributes['testing'], mongo_results.first['testing']
34
36
  end
35
37
 
36
38
  def test_finding_no_documents_using_search_conditions
@@ -44,6 +44,21 @@ class DocumentTest < Test::Unit::TestCase
44
44
  assert_equal(Time.now.to_s, document.attributes["updated_at"].to_s)
45
45
  end
46
46
 
47
+ test "creating from json with single nested document" do
48
+ json = '{"test":"hello", "nested":{"foo":"bar"}}'
49
+ document = Rack::JSON::Document.new(json)
50
+ assert document.attributes['nested'].is_a?(Hash)
51
+ assert_equal 'bar', document.attributes['nested']['foo']
52
+ end
53
+
54
+ test "creating from json with multiple nested documents" do
55
+ json = '{"test":"hello", "nested":[{"foo":"bar"}, {"boo":"far"}]}'
56
+ document = Rack::JSON::Document.new(json)
57
+ assert document.attributes['nested'].is_a?(Array)
58
+ assert_equal({'foo' => 'bar'}, document.attributes['nested'][0])
59
+ assert_equal 'far', document.attributes['nested'][1]['boo']
60
+ end
61
+
47
62
  def test_adding_id
48
63
  json = '{"test":"hello"}'
49
64
  document = Rack::JSON::Document.new(json)
@@ -69,4 +69,10 @@ class FilterTest < Test::Unit::TestCase
69
69
  post '/testing', '{ "title": "hello!" }'
70
70
  assert_match /"user_id":1/, last_response.body
71
71
  end
72
+
73
+ test "handling invalid json" do
74
+ get '/login'
75
+ post '/testing', 'invalid json'
76
+ assert_equal 422, last_response.status
77
+ end
72
78
  end
@@ -3,7 +3,7 @@ require 'helper'
3
3
  class MongoDocumentTest < Test::Unit::TestCase
4
4
 
5
5
  def test_stringifying_mongo_object_ids
6
- hash = { "_id" => BSON::ObjectID.from_string("4ba7e82ca04014011c000001") }
6
+ hash = {"_id" => BSON::ObjectID.from_string("4ba7e82ca04014011c000001")}
7
7
  doc = Rack::JSON::MongoDocument.new(hash).attributes
8
8
  assert_equal("4ba7e82ca04014011c000001", doc["_id"])
9
9
  end
@@ -11,14 +11,6 @@ class MongoDocumentTest < Test::Unit::TestCase
11
11
  def test_not_stringifying_non_mongo_object_ids
12
12
  hash = { "_id" => 1 }
13
13
  doc = Rack::JSON::MongoDocument.new(hash).attributes
14
- assert_equal({ "_id" => 1 }, doc)
15
- end
16
-
17
- def test_setting_the_created_at_stamp
18
- hash = { "_id" => BSON::ObjectID.from_string("4ba7e82ca04014011c000001") }
19
- doc = Rack::JSON::MongoDocument.new(hash).attributes
20
- assert_equal({ "_id" => "4ba7e82ca04014011c000001",
21
- "created_at" => BSON::ObjectID.from_string("4ba7e82ca04014011c000001").generation_time
22
- }, doc)
14
+ assert_equal(1, doc["_id"])
23
15
  end
24
16
  end
@@ -0,0 +1,124 @@
1
+ require 'helper'
2
+
3
+ class BuilderTest < Test::Unit::TestCase
4
+ include Rack::Test::Methods
5
+ include Rack::Utils
6
+
7
+ def setup
8
+ @db = Mongo::Connection.new.db("test")
9
+ @collection = @db['testing']
10
+ end
11
+
12
+ def teardown
13
+ @collection.drop
14
+ end
15
+
16
+ def public_resource_app
17
+ Rack::Builder.app do
18
+ use Rack::Session::Cookie
19
+ public_resource :collections => [:testing], :filters => [:user_id], :db => Mongo::Connection.new.db("test")
20
+ run lambda { |env|
21
+ # this is doing some pretend login by simply setting a session var
22
+ request = Rack::JSON::Request.new(env)
23
+ env['rack.session'] = {}
24
+ env['rack.session']['user_id'] = 1
25
+ [200, {'Content-Length' => "6", 'Content-Type' => 'text/plain'}, ["Hello!"]]
26
+ }
27
+ end
28
+ end
29
+
30
+ def private_resource_app
31
+ Rack::Builder.app do
32
+ use Rack::Session::Cookie
33
+ private_resource :collections => [:testing], :filters => [:user_id], :db => Mongo::Connection.new.db("test")
34
+ run lambda { |env|
35
+ # this is doing some pretend login by simply setting a session var
36
+ request = Rack::JSON::Request.new(env)
37
+ env['rack.session'] = {}
38
+ env['rack.session']['user_id'] = 1
39
+ [200, {'Content-Length' => "6", 'Content-Type' => 'text/plain'}, ["Hello!"]]
40
+ }
41
+ end
42
+ end
43
+
44
+ def expose_resource_app
45
+ Rack::Builder.app do
46
+ expose_resource :collections => [:testing], :db => Mongo::Connection.new.db("test")
47
+ run lambda { |env| [404, {'Content-Length' => '9', 'Content-Type' => 'text/plain'}, ["Not Found"]] }
48
+ end
49
+ end
50
+
51
+ def use_expose_resource
52
+ BuilderTest.class_eval { def app; expose_resource_app; end }
53
+ end
54
+
55
+ def use_public_resource
56
+ BuilderTest.class_eval { def app; public_resource_app; end }
57
+ end
58
+
59
+ def use_private_resource
60
+ BuilderTest.class_eval { def app; private_resource_app; end }
61
+ end
62
+
63
+ test "using expose_resource we can still bypass rack json" do
64
+ BuilderTest.class_eval { def app; expose_resource_app; end }
65
+
66
+ get '/blah'
67
+ assert_equal 404, last_response.status
68
+ end
69
+
70
+ test "using expose_resource still gives access to Rack::JSON::Resource" do
71
+ use_expose_resource
72
+
73
+ @collection.save({:testing => true})
74
+ get '/testing'
75
+ assert last_response.ok?
76
+ assert_match /"testing":true/, last_response.body
77
+ end
78
+
79
+ test "using public_resource still can bypass Rack::JSON" do
80
+ use_public_resource
81
+
82
+ get '/blah'
83
+ assert_equal 200, last_response.status
84
+ end
85
+
86
+ test "using public_resource still gives access to Rack::JSON::Resource" do
87
+ use_public_resource
88
+
89
+ @collection.save({:testing => true})
90
+ get '/testing'
91
+ assert last_response.ok?
92
+ assert_match /"testing":true/, last_response.body
93
+ end
94
+
95
+ test "using public_resource should restrict non get requests to the resources" do
96
+ use_public_resource
97
+
98
+ post '/testing', '{"test":"yes"}'
99
+ assert_equal 412, last_response.status
100
+ end
101
+
102
+ test "using public resource should not restrict requests when the pre-conditions are met" do
103
+ use_public_resource
104
+
105
+ get '/login' # pretend to login
106
+ post '/testing', '{"test":"yes"}'
107
+ assert_equal 201, last_response.status
108
+ end
109
+
110
+ test "using private resource should restrict all requests to the resource" do
111
+ use_private_resource
112
+
113
+ get '/testing'
114
+ assert_equal 412, last_response.status
115
+ end
116
+
117
+ test "using private resource should not restrict requests when the pre-conditions are met" do
118
+ use_private_resource
119
+
120
+ get '/login' # pretend to login
121
+ get '/testing'
122
+ assert last_response.ok?
123
+ end
124
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rackjson
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oliver Nightingale
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-04-29 00:00:00 +01:00
12
+ date: 2010-05-06 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -69,6 +69,7 @@ files:
69
69
  - Rakefile
70
70
  - VERSION
71
71
  - lib/rackjson.rb
72
+ - lib/rackjson/base_document.rb
72
73
  - lib/rackjson/collection.rb
73
74
  - lib/rackjson/document.rb
74
75
  - lib/rackjson/end_point.rb
@@ -76,6 +77,7 @@ files:
76
77
  - lib/rackjson/json_document.rb
77
78
  - lib/rackjson/json_query.rb
78
79
  - lib/rackjson/mongo_document.rb
80
+ - lib/rackjson/rack/builder.rb
79
81
  - lib/rackjson/request.rb
80
82
  - lib/rackjson/resource.rb
81
83
  - lib/rackjson/response.rb
@@ -88,6 +90,7 @@ files:
88
90
  - test/test_json_document.rb
89
91
  - test/test_json_query.rb
90
92
  - test/test_mongo_document.rb
93
+ - test/test_rack_builder.rb
91
94
  - test/test_resource.rb
92
95
  - test/test_response.rb
93
96
  has_rdoc: true
@@ -127,5 +130,6 @@ test_files:
127
130
  - test/test_json_document.rb
128
131
  - test/test_json_query.rb
129
132
  - test/test_mongo_document.rb
133
+ - test/test_rack_builder.rb
130
134
  - test/test_resource.rb
131
135
  - test/test_response.rb