sinatra_resource 0.2.6 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|