sinatra_resource 0.2.6 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/examples/datacatalog/lib/resource.rb +1 -1
- data/examples/datacatalog/models/note.rb +38 -0
- data/examples/datacatalog/resources/categories.rb +4 -1
- data/examples/datacatalog/resources/categories_sources.rb +4 -1
- data/examples/datacatalog/resources/notes.rb +28 -0
- data/examples/datacatalog/resources/sources.rb +4 -1
- data/examples/datacatalog/resources/users.rb +4 -1
- data/examples/datacatalog/test/helpers/lib/model_factories.rb +7 -0
- data/examples/datacatalog/test/helpers/shared/model_counts.rb +26 -0
- data/examples/datacatalog/test/models/note_test.rb +42 -0
- data/examples/datacatalog/test/resources/notes/notes_get_many_test.rb +102 -0
- data/examples/datacatalog/test/resources/notes/notes_get_one_test.rb +85 -0
- data/examples/datacatalog/test/resources/notes/notes_post_test.rb +91 -0
- data/lib/builder/action_definitions.rb +5 -3
- data/lib/builder/helpers.rb +22 -25
- data/lib/builder/mongo_helpers.rb +1 -1
- data/lib/builder.rb +2 -2
- data/lib/resource.rb +8 -2
- data/lib/roles.rb +7 -2
- data/sinatra_resource.gemspec +17 -5
- metadata +15 -3
data/Rakefile
CHANGED
@@ -14,7 +14,7 @@ begin
|
|
14
14
|
gem.add_dependency 'djsun-mongo_mapper', '>= 0.5.6.3'
|
15
15
|
gem.add_dependency 'mongo', '>= 0.15.1'
|
16
16
|
gem.add_dependency 'sinatra', '>= 0.9.4'
|
17
|
-
gem.add_dependency 'query_string_filter', '>= 0.1.
|
17
|
+
gem.add_dependency 'query_string_filter', '>= 0.1.2'
|
18
18
|
|
19
19
|
gem.add_development_dependency 'crack', '>= 0.1.4'
|
20
20
|
gem.add_development_dependency 'djsun-context', '>= 0.5.6'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
@@ -62,7 +62,7 @@ module DataCatalog
|
|
62
62
|
def user_for(api_key)
|
63
63
|
user = User.first(:conditions => { :_api_key => api_key })
|
64
64
|
return nil unless user
|
65
|
-
raise "API key found, but user has no role" unless user.role
|
65
|
+
raise Error, "API key found, but user has no role" unless user.role
|
66
66
|
user
|
67
67
|
end
|
68
68
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module DataCatalog
|
2
|
+
|
3
|
+
class Note
|
4
|
+
|
5
|
+
include MongoMapper::Document
|
6
|
+
|
7
|
+
# == Attributes
|
8
|
+
|
9
|
+
key :text, String
|
10
|
+
key :user_id, String
|
11
|
+
timestamps!
|
12
|
+
|
13
|
+
# == Indices
|
14
|
+
|
15
|
+
# == Associations
|
16
|
+
|
17
|
+
belongs_to :user
|
18
|
+
|
19
|
+
# == Validations
|
20
|
+
|
21
|
+
validates_presence_of :text
|
22
|
+
validates_presence_of :user_id
|
23
|
+
|
24
|
+
validate :general_validation
|
25
|
+
|
26
|
+
def general_validation
|
27
|
+
if user.nil?
|
28
|
+
errors.add(:user_id, "must be valid")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# == Class Methods
|
33
|
+
|
34
|
+
# == Various Instance Methods
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -8,8 +8,11 @@ module DataCatalog
|
|
8
8
|
# == Permissions
|
9
9
|
|
10
10
|
roles Roles
|
11
|
+
permission :list => :basic
|
11
12
|
permission :read => :basic
|
12
|
-
permission :
|
13
|
+
permission :create => :curator
|
14
|
+
permission :update => :curator
|
15
|
+
permission :delete => :curator
|
13
16
|
|
14
17
|
# == Properties
|
15
18
|
|
@@ -25,8 +25,11 @@ module DataCatalog
|
|
25
25
|
# == Permissions
|
26
26
|
|
27
27
|
roles Roles
|
28
|
+
permission :list => :basic
|
28
29
|
permission :read => :basic
|
29
|
-
permission :
|
30
|
+
permission :create => :curator
|
31
|
+
permission :update => :curator
|
32
|
+
permission :delete => :curator
|
30
33
|
|
31
34
|
# == Properties
|
32
35
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module DataCatalog
|
2
|
+
|
3
|
+
class Notes < Base
|
4
|
+
include Resource
|
5
|
+
|
6
|
+
model Note
|
7
|
+
|
8
|
+
# == Permissions
|
9
|
+
|
10
|
+
roles Roles
|
11
|
+
permission :list => :basic
|
12
|
+
permission :read => :owner
|
13
|
+
permission :create => :basic
|
14
|
+
permission :update => :owner
|
15
|
+
permission :delete => :owner
|
16
|
+
|
17
|
+
# == Properties
|
18
|
+
|
19
|
+
property :text
|
20
|
+
property :user_id
|
21
|
+
|
22
|
+
# == Callbacks
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
Notes.build
|
27
|
+
|
28
|
+
end
|
@@ -8,8 +8,11 @@ module DataCatalog
|
|
8
8
|
# == Permissions
|
9
9
|
|
10
10
|
roles Roles
|
11
|
+
permission :list => :basic
|
11
12
|
permission :read => :basic
|
12
|
-
permission :
|
13
|
+
permission :create => :curator
|
14
|
+
permission :update => :curator
|
15
|
+
permission :delete => :curator
|
13
16
|
|
14
17
|
# == Properties
|
15
18
|
|
@@ -8,8 +8,11 @@ module DataCatalog
|
|
8
8
|
# == Permissions
|
9
9
|
|
10
10
|
roles Roles
|
11
|
+
permission :list => :basic
|
11
12
|
permission :read => :basic
|
12
|
-
permission :
|
13
|
+
permission :create => :admin
|
14
|
+
permission :update => :owner
|
15
|
+
permission :delete => :owner
|
13
16
|
|
14
17
|
# == Properties
|
15
18
|
|
@@ -19,6 +19,13 @@ module ModelFactories
|
|
19
19
|
:category_id => "",
|
20
20
|
})
|
21
21
|
end
|
22
|
+
|
23
|
+
def create_note(custom={})
|
24
|
+
create_model!(DataCatalog::Note, custom, {
|
25
|
+
:text => "Sample Note",
|
26
|
+
:user_id => "",
|
27
|
+
})
|
28
|
+
end
|
22
29
|
|
23
30
|
def create_user(custom={})
|
24
31
|
create_model!(DataCatalog::User, custom, {
|
@@ -26,6 +26,32 @@ class ResourceTestCase
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
# == notes
|
30
|
+
|
31
|
+
shared "no change in note count" do
|
32
|
+
test "should not change number of note documents in database" do
|
33
|
+
assert_equal @note_count, DataCatalog::Note.all.length
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
shared "one less note" do
|
38
|
+
test "should remove one note document from database" do
|
39
|
+
assert_equal @note_count - 1, DataCatalog::Note.all.length
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
shared "one new note" do
|
44
|
+
test "should add one note document to database" do
|
45
|
+
assert_equal @note_count + 1, DataCatalog::Note.all.length
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
shared "note unchanged" do
|
50
|
+
test "should not change note in database" do
|
51
|
+
assert_equal @note_copy, DataCatalog::Note.find_by_id(@note.id)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
29
55
|
# == sources
|
30
56
|
|
31
57
|
shared "no change in source count" do
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../helpers/model_test_helper')
|
2
|
+
|
3
|
+
class NoteTest < ModelTestCase
|
4
|
+
|
5
|
+
include DataCatalog
|
6
|
+
|
7
|
+
context "Note" do
|
8
|
+
before do
|
9
|
+
@user = create_user
|
10
|
+
@required = {
|
11
|
+
:text => "Example Note",
|
12
|
+
:user_id => @user.id
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
after do
|
17
|
+
@user.destroy
|
18
|
+
end
|
19
|
+
|
20
|
+
context "correct params" do
|
21
|
+
before do
|
22
|
+
@note = Note.new(@required)
|
23
|
+
end
|
24
|
+
|
25
|
+
test "should be valid" do
|
26
|
+
assert_equal true, @note.valid?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
[:text, :user_id].each do |missing|
|
31
|
+
context "missing #{missing}" do
|
32
|
+
before do
|
33
|
+
@note = Note.new(@required.delete_if { |k, v| k == missing })
|
34
|
+
end
|
35
|
+
|
36
|
+
missing_key(:note, missing)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../helpers/resource_test_helper')
|
2
|
+
|
3
|
+
class NotesGetManyResourceTest < ResourceTestCase
|
4
|
+
|
5
|
+
include DataCatalog
|
6
|
+
|
7
|
+
def app; Notes end
|
8
|
+
|
9
|
+
before do
|
10
|
+
Note.destroy_all unless Note.count == 0
|
11
|
+
@users = 3.times.map do |i|
|
12
|
+
create_user(
|
13
|
+
:name => "User #{i}"
|
14
|
+
)
|
15
|
+
end
|
16
|
+
@notes = 3.times.map do |i|
|
17
|
+
create_note(
|
18
|
+
:text => "Note #{i}",
|
19
|
+
:user_id => @users[i].id
|
20
|
+
)
|
21
|
+
end
|
22
|
+
@note_texts = ["Note 0", "Note 1", "Note 2"].sort
|
23
|
+
end
|
24
|
+
|
25
|
+
after do
|
26
|
+
@notes.each { |x| x.destroy } if @notes
|
27
|
+
@users.each { |x| x.destroy }
|
28
|
+
end
|
29
|
+
|
30
|
+
context "get /" do
|
31
|
+
context "anonymous" do
|
32
|
+
before do
|
33
|
+
get "/"
|
34
|
+
end
|
35
|
+
|
36
|
+
use "return 401 because the API key is missing"
|
37
|
+
end
|
38
|
+
|
39
|
+
context "incorrect API key" do
|
40
|
+
before do
|
41
|
+
get "/", :api_key => BAD_API_KEY
|
42
|
+
end
|
43
|
+
|
44
|
+
use "return 401 because the API key is invalid"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
%w(basic curator).each do |role|
|
49
|
+
context "#{role} : get /" do
|
50
|
+
before do
|
51
|
+
get "/", :api_key => api_key_for(role)
|
52
|
+
end
|
53
|
+
|
54
|
+
use "return 200 Ok"
|
55
|
+
|
56
|
+
test "body should have an empty list" do
|
57
|
+
assert_equal [], parsed_response_body
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "owner : get /" do
|
63
|
+
before do
|
64
|
+
get "/", :api_key => @users[0]._api_key
|
65
|
+
end
|
66
|
+
|
67
|
+
use "return 200 Ok"
|
68
|
+
|
69
|
+
test "body should have 1 note" do
|
70
|
+
assert_equal 1, parsed_response_body.length
|
71
|
+
end
|
72
|
+
|
73
|
+
test "body should have correct note text" do
|
74
|
+
actual = parsed_response_body.map { |e| e["text"] }
|
75
|
+
assert_equal ["Note 0"], actual.sort
|
76
|
+
end
|
77
|
+
|
78
|
+
docs_properties %w(text user_id id created_at updated_at)
|
79
|
+
end
|
80
|
+
|
81
|
+
%w(admin).each do |role|
|
82
|
+
context "#{role} : get /" do
|
83
|
+
before do
|
84
|
+
get "/", :api_key => api_key_for(role)
|
85
|
+
end
|
86
|
+
|
87
|
+
use "return 200 Ok"
|
88
|
+
|
89
|
+
test "body should have 3 notes" do
|
90
|
+
assert_equal 3, parsed_response_body.length
|
91
|
+
end
|
92
|
+
|
93
|
+
test "body should have correct note text" do
|
94
|
+
actual = parsed_response_body.map { |e| e["text"] }
|
95
|
+
assert_equal @note_texts, actual.sort
|
96
|
+
end
|
97
|
+
|
98
|
+
docs_properties %w(text user_id id created_at updated_at)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../helpers/resource_test_helper')
|
2
|
+
|
3
|
+
class NotesGetOneResourceTest < ResourceTestCase
|
4
|
+
|
5
|
+
include DataCatalog
|
6
|
+
|
7
|
+
def app; Notes end
|
8
|
+
|
9
|
+
before do
|
10
|
+
@user = create_user
|
11
|
+
@note = create_note(
|
12
|
+
:user_id => @user.id
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
after do
|
17
|
+
@note.destroy
|
18
|
+
@user.destroy
|
19
|
+
end
|
20
|
+
|
21
|
+
context "get /:id" do
|
22
|
+
context "anonymous" do
|
23
|
+
before do
|
24
|
+
get "/#{@note.id}"
|
25
|
+
end
|
26
|
+
|
27
|
+
use "return 401 because the API key is missing"
|
28
|
+
end
|
29
|
+
|
30
|
+
context "incorrect API key" do
|
31
|
+
before do
|
32
|
+
get "/#{@note.id}", :api_key => BAD_API_KEY
|
33
|
+
end
|
34
|
+
|
35
|
+
use "return 401 because the API key is invalid"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
%w(basic curator).each do |role|
|
40
|
+
context "#{role} : get /:fake_id" do
|
41
|
+
before do
|
42
|
+
get "/#{FAKE_ID}", :api_key => api_key_for(role)
|
43
|
+
end
|
44
|
+
|
45
|
+
use "return 401 because the API key is unauthorized"
|
46
|
+
end
|
47
|
+
|
48
|
+
context "#{role} : get /:id" do
|
49
|
+
before do
|
50
|
+
get "/#{@note.id}", :api_key => api_key_for(role)
|
51
|
+
end
|
52
|
+
|
53
|
+
use "return 401 because the API key is unauthorized"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "owner : get /:id" do
|
58
|
+
before do
|
59
|
+
get "/#{@note.id}", :api_key => @user._api_key
|
60
|
+
end
|
61
|
+
|
62
|
+
use "return 200 Ok"
|
63
|
+
doc_properties %w(text user_id id created_at updated_at)
|
64
|
+
end
|
65
|
+
|
66
|
+
%w(admin).each do |role|
|
67
|
+
context "#{role} : get /:fake_id" do
|
68
|
+
before do
|
69
|
+
get "/#{FAKE_ID}", :api_key => api_key_for(role)
|
70
|
+
end
|
71
|
+
|
72
|
+
use "return 404 Not Found with empty response body"
|
73
|
+
end
|
74
|
+
|
75
|
+
context "#{role} : get /:id" do
|
76
|
+
before do
|
77
|
+
get "/#{@note.id}", :api_key => api_key_for(role)
|
78
|
+
end
|
79
|
+
|
80
|
+
use "return 200 Ok"
|
81
|
+
doc_properties %w(text user_id id created_at updated_at)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../helpers/resource_test_helper')
|
2
|
+
|
3
|
+
class NotesPostResourceTest < ResourceTestCase
|
4
|
+
|
5
|
+
include DataCatalog
|
6
|
+
|
7
|
+
def app; Notes end
|
8
|
+
|
9
|
+
before do
|
10
|
+
@note_count = Note.all.length
|
11
|
+
@user = create_user
|
12
|
+
@valid_params = {
|
13
|
+
:text => "New Note",
|
14
|
+
:user_id => @user.id
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
after do
|
19
|
+
@user.destroy
|
20
|
+
end
|
21
|
+
|
22
|
+
context "post /" do
|
23
|
+
context "anonymous" do
|
24
|
+
before do
|
25
|
+
post "/", @valid_params
|
26
|
+
end
|
27
|
+
|
28
|
+
use "return 401 because the API key is missing"
|
29
|
+
use "no change in note count"
|
30
|
+
end
|
31
|
+
|
32
|
+
context "incorrect API key" do
|
33
|
+
before do
|
34
|
+
post "/", @valid_params.merge(:api_key => BAD_API_KEY)
|
35
|
+
end
|
36
|
+
|
37
|
+
use "return 401 because the API key is invalid"
|
38
|
+
use "no change in note count"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
%w(basic curator admin).each do |role|
|
43
|
+
[:text, :user_id].each do |missing|
|
44
|
+
context "#{role} : post / but missing #{missing}" do
|
45
|
+
before do
|
46
|
+
post "/", valid_params_for(role).delete_if { |k, v| k == missing }
|
47
|
+
end
|
48
|
+
|
49
|
+
use "return 400 Bad Request"
|
50
|
+
use "no change in note count"
|
51
|
+
missing_param missing
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
[:id, :created_at, :updated_at, :junk].each do |invalid|
|
56
|
+
context "#{role} : post / but with #{invalid}" do
|
57
|
+
before do
|
58
|
+
post "/", valid_params_for(role).merge(invalid => 9)
|
59
|
+
end
|
60
|
+
|
61
|
+
use "return 400 Bad Request"
|
62
|
+
use "no change in note count"
|
63
|
+
invalid_param invalid
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "#{role} : post / with valid params" do
|
68
|
+
before do
|
69
|
+
post "/", valid_params_for(role)
|
70
|
+
end
|
71
|
+
|
72
|
+
after do
|
73
|
+
Note.find_by_id(parsed_response_body["id"]).destroy
|
74
|
+
end
|
75
|
+
|
76
|
+
use "return 201 Created"
|
77
|
+
location_header "notes"
|
78
|
+
use "one new note"
|
79
|
+
doc_properties %w(text user_id id created_at updated_at)
|
80
|
+
|
81
|
+
test "should set all fields in database" do
|
82
|
+
note = Note.find_by_id(parsed_response_body["id"])
|
83
|
+
raise "Cannot find note" unless note
|
84
|
+
@valid_params.each_pair do |key, value|
|
85
|
+
assert_equal value, note[key]
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
@@ -14,9 +14,11 @@ module SinatraResource
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def documents_for_get_many(role, model, resource_config, leaf, parent_document, association)
|
17
|
-
check_permission(:
|
18
|
-
check_params(:
|
19
|
-
documents = find_documents!(model)
|
17
|
+
check_permission(:list, role, resource_config)
|
18
|
+
check_params(:list, role, resource_config, leaf)
|
19
|
+
documents = find_documents!(model).select do |document|
|
20
|
+
authorized?(:read, lookup_role(document), resource_config)
|
21
|
+
end
|
20
22
|
# TODO: A more performant approach would be to modify find_documents!
|
21
23
|
# so that it returns the correct results in one query.
|
22
24
|
if resource_config[:parent]
|
data/lib/builder/helpers.rb
CHANGED
@@ -45,7 +45,7 @@ module SinatraResource
|
|
45
45
|
# Halt unless the current params are ok for +action+ and +role+.
|
46
46
|
#
|
47
47
|
# @param [Symbol] action
|
48
|
-
# :read, :create, :update, or :delete
|
48
|
+
# :list, :read, :create, :update, or :delete
|
49
49
|
#
|
50
50
|
# @param [Symbol] role
|
51
51
|
# a role (such as :anonymous, :basic, or :admin)
|
@@ -66,7 +66,7 @@ module SinatraResource
|
|
66
66
|
# Halt unless the current role has permission to carry out +action+
|
67
67
|
#
|
68
68
|
# @param [Symbol] action
|
69
|
-
# :read, :create, :update, or :delete
|
69
|
+
# :list, :read, :create, :update, or :delete
|
70
70
|
#
|
71
71
|
# @param [Symbol] role
|
72
72
|
# a role (such as :anonymous, :basic, or :admin)
|
@@ -97,11 +97,17 @@ module SinatraResource
|
|
97
97
|
|
98
98
|
# Display +object+ as appropriate for +action+.
|
99
99
|
#
|
100
|
+
# @param [Symbol] action
|
101
|
+
# :list, :read, :create, :update, or :delete
|
102
|
+
#
|
100
103
|
# @param [Object] object
|
101
104
|
#
|
105
|
+
# @param [Hash] resource_config
|
106
|
+
#
|
102
107
|
# @return [String]
|
103
108
|
def display(action, object, resource_config)
|
104
109
|
case action
|
110
|
+
when :list
|
105
111
|
when :read
|
106
112
|
when :create
|
107
113
|
response.status = 201
|
@@ -110,6 +116,8 @@ module SinatraResource
|
|
110
116
|
when :update
|
111
117
|
when :delete
|
112
118
|
response.status = 204
|
119
|
+
else
|
120
|
+
raise Error, "Unexpected: #{action.inspect}"
|
113
121
|
end
|
114
122
|
convert(object)
|
115
123
|
end
|
@@ -151,7 +159,7 @@ module SinatraResource
|
|
151
159
|
# +property+.
|
152
160
|
#
|
153
161
|
# @param [Symbol] action
|
154
|
-
# :read, :create, :update, or :delete
|
162
|
+
# :list, :read, :create, :update, or :delete
|
155
163
|
#
|
156
164
|
# @param [Hash] resource_config
|
157
165
|
#
|
@@ -161,7 +169,9 @@ module SinatraResource
|
|
161
169
|
# a role (such as :anonymous, :basic, or :admin)
|
162
170
|
def minimum_role(action, resource_config, property=nil)
|
163
171
|
if property.nil?
|
164
|
-
resource_config[:permission]
|
172
|
+
p = resource_config[:permission]
|
173
|
+
raise Error, "undefined #{action.inspect} permission" unless p
|
174
|
+
p[action]
|
165
175
|
else
|
166
176
|
hash = resource_config[:properties][property]
|
167
177
|
hash ? hash[to_r_or_w(action)] : :nobody
|
@@ -176,7 +186,7 @@ module SinatraResource
|
|
176
186
|
# a role (such as :anonymous, :basic, or :admin)
|
177
187
|
#
|
178
188
|
# @param [Symbol] action
|
179
|
-
# :read, :create, :update, or :delete
|
189
|
+
# :list, :read, :create, :update, or :delete
|
180
190
|
#
|
181
191
|
# @param [Hash] resource_config
|
182
192
|
#
|
@@ -199,7 +209,7 @@ module SinatraResource
|
|
199
209
|
# Applications must override this method.
|
200
210
|
#
|
201
211
|
# @param [Symbol] action
|
202
|
-
# :read, :create, :update, or :delete
|
212
|
+
# :list, :read, :create, :update, or :delete
|
203
213
|
#
|
204
214
|
# @param [Symbol] role
|
205
215
|
# a role (such as :anonymous, :basic, or :admin)
|
@@ -253,7 +263,7 @@ module SinatraResource
|
|
253
263
|
# Are the params suitable for +action+? Raise 400 Bad Request if not.
|
254
264
|
#
|
255
265
|
# @param [Symbol] action
|
256
|
-
# :read, :create, :update, or :delete
|
266
|
+
# :list, :read, :create, :update, or :delete
|
257
267
|
#
|
258
268
|
# @param [Boolean] leaf
|
259
269
|
# If a simple resource, should be true.
|
@@ -262,6 +272,8 @@ module SinatraResource
|
|
262
272
|
# @return [undefined]
|
263
273
|
def params_check_action(action)
|
264
274
|
case action
|
275
|
+
when :list
|
276
|
+
# TODO: is anything needed here?
|
265
277
|
when :read
|
266
278
|
unless params.reject { |k, v| k == FILTER_KEY }.empty?
|
267
279
|
error 400, convert(body_for(:non_empty_params))
|
@@ -277,6 +289,8 @@ module SinatraResource
|
|
277
289
|
unless params.empty?
|
278
290
|
error 400, convert(body_for(:non_empty_params))
|
279
291
|
end
|
292
|
+
else
|
293
|
+
raise Error, "Unexpected: #{action.inspect}"
|
280
294
|
end
|
281
295
|
end
|
282
296
|
|
@@ -284,7 +298,7 @@ module SinatraResource
|
|
284
298
|
# +role+. Raises a 400 Bad Request if not authorized.
|
285
299
|
#
|
286
300
|
# @param [Symbol] action
|
287
|
-
# :read, :create, :update, or :delete
|
301
|
+
# :list, :read, :create, :update, or :delete
|
288
302
|
#
|
289
303
|
# @param [Symbol] role
|
290
304
|
# a role (such as :anonymous, :basic, or :admin)
|
@@ -321,23 +335,6 @@ module SinatraResource
|
|
321
335
|
end
|
322
336
|
end
|
323
337
|
|
324
|
-
# Converts +action+ to (:read or :modify).
|
325
|
-
#
|
326
|
-
# @param [Symbol] action
|
327
|
-
# :read, :create, :update, or :delete
|
328
|
-
#
|
329
|
-
# @return [Symbol]
|
330
|
-
# :read or :modify
|
331
|
-
def to_read_or_modify(action)
|
332
|
-
case action
|
333
|
-
when :read then :read
|
334
|
-
when :create then :modify
|
335
|
-
when :update then :modify
|
336
|
-
when :delete then :modify
|
337
|
-
else raise "Unexpected action : #{action.inspect}"
|
338
|
-
end
|
339
|
-
end
|
340
|
-
|
341
338
|
# Lookup +attribute+ in +document+
|
342
339
|
#
|
343
340
|
# @param [Symbol] attribute
|
data/lib/builder.rb
CHANGED
@@ -63,7 +63,7 @@ module SinatraResource
|
|
63
63
|
role = get_role(model)
|
64
64
|
documents = documents_for_get_many(role, model, resource_config, true, nil, nil)
|
65
65
|
resources = build_resources(documents, resource_config)
|
66
|
-
display(:
|
66
|
+
display(:list, resources, resource_config)
|
67
67
|
end
|
68
68
|
else
|
69
69
|
association = @child_association
|
@@ -78,7 +78,7 @@ module SinatraResource
|
|
78
78
|
role = get_role(model)
|
79
79
|
documents = documents_for_get_many(role, model, resource_config, true, parent_document, association)
|
80
80
|
resources = build_resources(documents, resource_config)
|
81
|
-
display(:
|
81
|
+
display(:list, resources, resource_config)
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
data/lib/resource.rb
CHANGED
@@ -109,16 +109,21 @@ module SinatraResource
|
|
109
109
|
# or writing.
|
110
110
|
#
|
111
111
|
# @example
|
112
|
+
# permission :list => :basic
|
112
113
|
# permission :read => :basic
|
113
|
-
# permission :
|
114
|
+
# permission :create => :basic
|
115
|
+
# permission :update => :owner
|
116
|
+
# permission :delete => :owner
|
114
117
|
#
|
115
118
|
# @param [Hash<Symbol => Symbol>] access_rules
|
116
|
-
# valid keys are
|
119
|
+
# valid keys are:
|
120
|
+
# :list, :read, :create, :update, :delete
|
117
121
|
# values should be a role (such as :admin)
|
118
122
|
#
|
119
123
|
# @return [undefined]
|
120
124
|
def permission(access_rules)
|
121
125
|
access_rules.each_pair do |verb, role|
|
126
|
+
@resource_config[:roles].validate_role(role)
|
122
127
|
@resource_config[:permission][verb] = role
|
123
128
|
end
|
124
129
|
end
|
@@ -145,6 +150,7 @@ module SinatraResource
|
|
145
150
|
@resource_config[:properties][name][:read_proc] = block
|
146
151
|
else
|
147
152
|
access_rules.each_pair do |kind, role|
|
153
|
+
@resource_config[:roles].validate_role(role)
|
148
154
|
@resource_config[:properties][name][kind] = role
|
149
155
|
end
|
150
156
|
end
|
data/lib/roles.rb
CHANGED
@@ -71,13 +71,18 @@ module SinatraResource
|
|
71
71
|
def setup
|
72
72
|
@role_config = {}
|
73
73
|
@satisfies_cache = {}
|
74
|
+
create_role(:nobody)
|
74
75
|
end
|
75
76
|
|
76
|
-
#
|
77
|
+
# Return +role+ if it is defined, raise exception otherwise.
|
77
78
|
#
|
78
79
|
# @raise [UndefinedRole] if role undefined
|
80
|
+
#
|
81
|
+
# @return [Symbol]
|
79
82
|
def validate_role(role)
|
80
|
-
|
83
|
+
if @role_config.include?(role)
|
84
|
+
role
|
85
|
+
else
|
81
86
|
raise UndefinedRole, "#{role.inspect} not defined"
|
82
87
|
end
|
83
88
|
end
|
data/sinatra_resource.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{sinatra_resource}
|
8
|
-
s.version = "0.
|
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 = ["David James"]
|
12
|
-
s.date = %q{2009-10-
|
12
|
+
s.date = %q{2009-10-28}
|
13
13
|
s.description = %q{A DSL for creating RESTful actions with Sinatra and MongoMapper. It embraces the Resource Oriented Architecture as explained by Leonard Richardson and Sam Ruby.}
|
14
14
|
s.email = %q{djames@sunlightfoundation.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -33,10 +33,12 @@ Gem::Specification.new do |s|
|
|
33
33
|
"examples/datacatalog/lib/roles.rb",
|
34
34
|
"examples/datacatalog/models/categorization.rb",
|
35
35
|
"examples/datacatalog/models/category.rb",
|
36
|
+
"examples/datacatalog/models/note.rb",
|
36
37
|
"examples/datacatalog/models/source.rb",
|
37
38
|
"examples/datacatalog/models/user.rb",
|
38
39
|
"examples/datacatalog/resources/categories.rb",
|
39
40
|
"examples/datacatalog/resources/categories_sources.rb",
|
41
|
+
"examples/datacatalog/resources/notes.rb",
|
40
42
|
"examples/datacatalog/resources/sources.rb",
|
41
43
|
"examples/datacatalog/resources/users.rb",
|
42
44
|
"examples/datacatalog/tasks/db.rake",
|
@@ -57,6 +59,7 @@ Gem::Specification.new do |s|
|
|
57
59
|
"examples/datacatalog/test/helpers/test_helper.rb",
|
58
60
|
"examples/datacatalog/test/models/categorization_test.rb",
|
59
61
|
"examples/datacatalog/test/models/category_test.rb",
|
62
|
+
"examples/datacatalog/test/models/note_test.rb",
|
60
63
|
"examples/datacatalog/test/models/source_test.rb",
|
61
64
|
"examples/datacatalog/test/models/user_test.rb",
|
62
65
|
"examples/datacatalog/test/resources/categories/categories_delete_test.rb",
|
@@ -69,6 +72,9 @@ Gem::Specification.new do |s|
|
|
69
72
|
"examples/datacatalog/test/resources/categories_sources/categories_sources_get_one_test.rb",
|
70
73
|
"examples/datacatalog/test/resources/categories_sources/categories_sources_post_test.rb",
|
71
74
|
"examples/datacatalog/test/resources/categories_sources/categories_sources_put_test.rb",
|
75
|
+
"examples/datacatalog/test/resources/notes/notes_get_many_test.rb",
|
76
|
+
"examples/datacatalog/test/resources/notes/notes_get_one_test.rb",
|
77
|
+
"examples/datacatalog/test/resources/notes/notes_post_test.rb",
|
72
78
|
"examples/datacatalog/test/resources/sources/sources_delete_test.rb",
|
73
79
|
"examples/datacatalog/test/resources/sources/sources_get_many_search_test.rb",
|
74
80
|
"examples/datacatalog/test/resources/sources/sources_get_many_test.rb",
|
@@ -116,10 +122,12 @@ Gem::Specification.new do |s|
|
|
116
122
|
"examples/datacatalog/lib/roles.rb",
|
117
123
|
"examples/datacatalog/models/categorization.rb",
|
118
124
|
"examples/datacatalog/models/category.rb",
|
125
|
+
"examples/datacatalog/models/note.rb",
|
119
126
|
"examples/datacatalog/models/source.rb",
|
120
127
|
"examples/datacatalog/models/user.rb",
|
121
128
|
"examples/datacatalog/resources/categories.rb",
|
122
129
|
"examples/datacatalog/resources/categories_sources.rb",
|
130
|
+
"examples/datacatalog/resources/notes.rb",
|
123
131
|
"examples/datacatalog/resources/sources.rb",
|
124
132
|
"examples/datacatalog/resources/users.rb",
|
125
133
|
"examples/datacatalog/test/helpers/assertions/assert_include.rb",
|
@@ -138,6 +146,7 @@ Gem::Specification.new do |s|
|
|
138
146
|
"examples/datacatalog/test/helpers/test_helper.rb",
|
139
147
|
"examples/datacatalog/test/models/categorization_test.rb",
|
140
148
|
"examples/datacatalog/test/models/category_test.rb",
|
149
|
+
"examples/datacatalog/test/models/note_test.rb",
|
141
150
|
"examples/datacatalog/test/models/source_test.rb",
|
142
151
|
"examples/datacatalog/test/models/user_test.rb",
|
143
152
|
"examples/datacatalog/test/resources/categories/categories_delete_test.rb",
|
@@ -150,6 +159,9 @@ Gem::Specification.new do |s|
|
|
150
159
|
"examples/datacatalog/test/resources/categories_sources/categories_sources_get_one_test.rb",
|
151
160
|
"examples/datacatalog/test/resources/categories_sources/categories_sources_post_test.rb",
|
152
161
|
"examples/datacatalog/test/resources/categories_sources/categories_sources_put_test.rb",
|
162
|
+
"examples/datacatalog/test/resources/notes/notes_get_many_test.rb",
|
163
|
+
"examples/datacatalog/test/resources/notes/notes_get_one_test.rb",
|
164
|
+
"examples/datacatalog/test/resources/notes/notes_post_test.rb",
|
153
165
|
"examples/datacatalog/test/resources/sources/sources_delete_test.rb",
|
154
166
|
"examples/datacatalog/test/resources/sources/sources_get_many_search_test.rb",
|
155
167
|
"examples/datacatalog/test/resources/sources/sources_get_many_test.rb",
|
@@ -171,7 +183,7 @@ Gem::Specification.new do |s|
|
|
171
183
|
s.add_runtime_dependency(%q<djsun-mongo_mapper>, [">= 0.5.6.3"])
|
172
184
|
s.add_runtime_dependency(%q<mongo>, [">= 0.15.1"])
|
173
185
|
s.add_runtime_dependency(%q<sinatra>, [">= 0.9.4"])
|
174
|
-
s.add_runtime_dependency(%q<query_string_filter>, [">= 0.1.
|
186
|
+
s.add_runtime_dependency(%q<query_string_filter>, [">= 0.1.2"])
|
175
187
|
s.add_development_dependency(%q<crack>, [">= 0.1.4"])
|
176
188
|
s.add_development_dependency(%q<djsun-context>, [">= 0.5.6"])
|
177
189
|
s.add_development_dependency(%q<jeremymcanally-pending>, [">= 0.1"])
|
@@ -181,7 +193,7 @@ Gem::Specification.new do |s|
|
|
181
193
|
s.add_dependency(%q<djsun-mongo_mapper>, [">= 0.5.6.3"])
|
182
194
|
s.add_dependency(%q<mongo>, [">= 0.15.1"])
|
183
195
|
s.add_dependency(%q<sinatra>, [">= 0.9.4"])
|
184
|
-
s.add_dependency(%q<query_string_filter>, [">= 0.1.
|
196
|
+
s.add_dependency(%q<query_string_filter>, [">= 0.1.2"])
|
185
197
|
s.add_dependency(%q<crack>, [">= 0.1.4"])
|
186
198
|
s.add_dependency(%q<djsun-context>, [">= 0.5.6"])
|
187
199
|
s.add_dependency(%q<jeremymcanally-pending>, [">= 0.1"])
|
@@ -192,7 +204,7 @@ Gem::Specification.new do |s|
|
|
192
204
|
s.add_dependency(%q<djsun-mongo_mapper>, [">= 0.5.6.3"])
|
193
205
|
s.add_dependency(%q<mongo>, [">= 0.15.1"])
|
194
206
|
s.add_dependency(%q<sinatra>, [">= 0.9.4"])
|
195
|
-
s.add_dependency(%q<query_string_filter>, [">= 0.1.
|
207
|
+
s.add_dependency(%q<query_string_filter>, [">= 0.1.2"])
|
196
208
|
s.add_dependency(%q<crack>, [">= 0.1.4"])
|
197
209
|
s.add_dependency(%q<djsun-context>, [">= 0.5.6"])
|
198
210
|
s.add_dependency(%q<jeremymcanally-pending>, [">= 0.1"])
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sinatra_resource
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David James
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-10-
|
12
|
+
date: 2009-10-28 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - ">="
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 0.1.
|
53
|
+
version: 0.1.2
|
54
54
|
version:
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: crack
|
@@ -128,10 +128,12 @@ files:
|
|
128
128
|
- examples/datacatalog/lib/roles.rb
|
129
129
|
- examples/datacatalog/models/categorization.rb
|
130
130
|
- examples/datacatalog/models/category.rb
|
131
|
+
- examples/datacatalog/models/note.rb
|
131
132
|
- examples/datacatalog/models/source.rb
|
132
133
|
- examples/datacatalog/models/user.rb
|
133
134
|
- examples/datacatalog/resources/categories.rb
|
134
135
|
- examples/datacatalog/resources/categories_sources.rb
|
136
|
+
- examples/datacatalog/resources/notes.rb
|
135
137
|
- examples/datacatalog/resources/sources.rb
|
136
138
|
- examples/datacatalog/resources/users.rb
|
137
139
|
- examples/datacatalog/tasks/db.rake
|
@@ -152,6 +154,7 @@ files:
|
|
152
154
|
- examples/datacatalog/test/helpers/test_helper.rb
|
153
155
|
- examples/datacatalog/test/models/categorization_test.rb
|
154
156
|
- examples/datacatalog/test/models/category_test.rb
|
157
|
+
- examples/datacatalog/test/models/note_test.rb
|
155
158
|
- examples/datacatalog/test/models/source_test.rb
|
156
159
|
- examples/datacatalog/test/models/user_test.rb
|
157
160
|
- examples/datacatalog/test/resources/categories/categories_delete_test.rb
|
@@ -164,6 +167,9 @@ files:
|
|
164
167
|
- examples/datacatalog/test/resources/categories_sources/categories_sources_get_one_test.rb
|
165
168
|
- examples/datacatalog/test/resources/categories_sources/categories_sources_post_test.rb
|
166
169
|
- examples/datacatalog/test/resources/categories_sources/categories_sources_put_test.rb
|
170
|
+
- examples/datacatalog/test/resources/notes/notes_get_many_test.rb
|
171
|
+
- examples/datacatalog/test/resources/notes/notes_get_one_test.rb
|
172
|
+
- examples/datacatalog/test/resources/notes/notes_post_test.rb
|
167
173
|
- examples/datacatalog/test/resources/sources/sources_delete_test.rb
|
168
174
|
- examples/datacatalog/test/resources/sources/sources_get_many_search_test.rb
|
169
175
|
- examples/datacatalog/test/resources/sources/sources_get_many_test.rb
|
@@ -233,10 +239,12 @@ test_files:
|
|
233
239
|
- examples/datacatalog/lib/roles.rb
|
234
240
|
- examples/datacatalog/models/categorization.rb
|
235
241
|
- examples/datacatalog/models/category.rb
|
242
|
+
- examples/datacatalog/models/note.rb
|
236
243
|
- examples/datacatalog/models/source.rb
|
237
244
|
- examples/datacatalog/models/user.rb
|
238
245
|
- examples/datacatalog/resources/categories.rb
|
239
246
|
- examples/datacatalog/resources/categories_sources.rb
|
247
|
+
- examples/datacatalog/resources/notes.rb
|
240
248
|
- examples/datacatalog/resources/sources.rb
|
241
249
|
- examples/datacatalog/resources/users.rb
|
242
250
|
- examples/datacatalog/test/helpers/assertions/assert_include.rb
|
@@ -255,6 +263,7 @@ test_files:
|
|
255
263
|
- examples/datacatalog/test/helpers/test_helper.rb
|
256
264
|
- examples/datacatalog/test/models/categorization_test.rb
|
257
265
|
- examples/datacatalog/test/models/category_test.rb
|
266
|
+
- examples/datacatalog/test/models/note_test.rb
|
258
267
|
- examples/datacatalog/test/models/source_test.rb
|
259
268
|
- examples/datacatalog/test/models/user_test.rb
|
260
269
|
- examples/datacatalog/test/resources/categories/categories_delete_test.rb
|
@@ -267,6 +276,9 @@ test_files:
|
|
267
276
|
- examples/datacatalog/test/resources/categories_sources/categories_sources_get_one_test.rb
|
268
277
|
- examples/datacatalog/test/resources/categories_sources/categories_sources_post_test.rb
|
269
278
|
- examples/datacatalog/test/resources/categories_sources/categories_sources_put_test.rb
|
279
|
+
- examples/datacatalog/test/resources/notes/notes_get_many_test.rb
|
280
|
+
- examples/datacatalog/test/resources/notes/notes_get_one_test.rb
|
281
|
+
- examples/datacatalog/test/resources/notes/notes_post_test.rb
|
270
282
|
- examples/datacatalog/test/resources/sources/sources_delete_test.rb
|
271
283
|
- examples/datacatalog/test/resources/sources/sources_get_many_search_test.rb
|
272
284
|
- examples/datacatalog/test/resources/sources/sources_get_many_test.rb
|