sinatra-rest-json 0.1 → 0.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: daf0fd1316a9beb76a91a4e42900046b18e45694
4
- data.tar.gz: 7f3cacb357a23e1de9e11ab13d0087d0de1ab0f1
3
+ metadata.gz: c4081e93189dcd0b6bbc54a6b1ee169c5afc28a3
4
+ data.tar.gz: 3721f4624f2adb52b8e2ee6d797713bd8b0885f8
5
5
  SHA512:
6
- metadata.gz: d04e344828d494ab5bff1befcaec243594b5c58c30254932b5dfea154f109b8ede48d48a4343bcab467c54a5ef8764fd483b378b46d8647f825b64ca271c5321
7
- data.tar.gz: 244e427c9b11c64ce3dde86f91f7271470ad267c95f8e252f96640a4b9b868556bb2872becdef088b1719c1e7a4e0fa8ce26a24d0e38a49419c6b667b359d2cb
6
+ metadata.gz: f4daf6ec26cc4fed06a496d6f07def6366ad4e25f695d1308ad2c42228681a3647d1ecd575c127cc03c4f9d2634c7d9747e4add7ac16b526df3935507db0b705
7
+ data.tar.gz: 3c12b6468e34c69cc155483fd9d954a658e22480cb4c1b1976b6fbe3d5f0696683e90f17358901eb1c9047a72f90cfe70f901da1295b5604ebf1007352ad98da
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # Easy REST JSON APIs for Sinatra & Active Record
2
2
 
3
3
 
4
- Getting started
4
+ ## Getting started
5
5
 
6
- ## 1. Setup your Gemfile
6
+ ### 1. Setup your Gemfile
7
7
 
8
8
  ```ruby
9
9
  # Gemfile
@@ -15,7 +15,7 @@ gem "json"
15
15
 
16
16
  ```
17
17
 
18
- ## 2. Setup your Sinatra App
18
+ ### 2. Setup your Sinatra App
19
19
 
20
20
  ```ruby
21
21
  require 'sinatra'
@@ -39,9 +39,9 @@ end
39
39
  # Set up your REST routes
40
40
  rest_json Product
41
41
  ```
42
- ## 3. Profit
42
+ ### 3. Profit
43
43
 
44
- ### Now your app automatically has the following routes which returns JSON data from your model:
44
+ #### Now your app automatically has the following routes which returns JSON data from your model:
45
45
 
46
46
  - **GET** /products (all)
47
47
  - **GET** /products/:id (find)
@@ -55,3 +55,21 @@ rest_json Product
55
55
  *Note for POST/PUT operations the data parameters should be like so: { product: { name: "foo", price: 1 }}
56
56
 
57
57
 
58
+ ### 4. Authentication
59
+
60
+ Basic support for authentication is provided like so:
61
+
62
+ ```ruby
63
+ # inside your sinatra app
64
+
65
+ rest_json Product, :authenticate => {
66
+ :all => lambda { true }, # allowed
67
+ :find => lambda { true }, #allowed
68
+ :create => lambda { false }, #not authorized
69
+ :update => lambda { false }, #not authorized
70
+ :delete => lambda { false } #not authorized
71
+ }
72
+ ```
73
+
74
+ You can pass in any ruby object that has a call method which returns a value (e.g. proc or lambda). Naturally you can drop in whatever authentication you'd like
75
+
@@ -6,18 +6,43 @@ module Sinatra
6
6
  NOT_FOUND = { :errors => ["record doesn't exist"] }.to_json
7
7
  MODEL_REGEX = /([A-Z0-9]{1}[a-z0-9]+)/
8
8
 
9
+ NO_AUTH = lambda { true }
10
+ DEFAULT_AUTH = {
11
+ :all => NO_AUTH,
12
+ :find => NO_AUTH,
13
+ :create => NO_AUTH,
14
+ :update => NO_AUTH,
15
+ :delete => NO_AUTH
16
+ }
17
+
9
18
  def rest_json(model_class, opts = {})
10
19
  model_name = model_class.name.scan(MODEL_REGEX).join("_").downcase
11
20
  route_name = model_class.table_name
12
21
 
22
+ options = opts.clone
23
+ options[:authenticate] ||= {}
24
+ authenticate = DEFAULT_AUTH.merge(options[:authenticate])
25
+
13
26
  # all
14
27
  get "/#{route_name}" do
28
+ authorized = authenticate[:all].call
29
+
30
+ unless authorized
31
+ halt 401, "Not authorized\n"
32
+ end
33
+
15
34
  content_type :json
16
35
  "[" + model_class.all.collect { |m| m.to_json }.join(",") + "]"
17
36
  end
18
37
 
19
38
  # find
20
39
  get "/#{route_name}/:id" do
40
+ authorized = authenticate[:find].call
41
+
42
+ unless authorized
43
+ halt 401, "Not authorized\n"
44
+ end
45
+
21
46
  content_type :json
22
47
  model = model_class.find(params[:id].to_i)
23
48
 
@@ -29,7 +54,13 @@ module Sinatra
29
54
  end
30
55
 
31
56
  # create
32
- put "/#{route_name}" do
57
+ post "/#{route_name}" do
58
+ authorized = authenticate[:create].call
59
+
60
+ unless authorized
61
+ halt 401, "Not authorized\n"
62
+ end
63
+
33
64
  content_type :json
34
65
 
35
66
  model = model_class.new(params[model_name])
@@ -42,7 +73,13 @@ module Sinatra
42
73
  end
43
74
 
44
75
  # update
45
- post "/#{route_name}/:id" do
76
+ put "/#{route_name}/:id" do
77
+ authorized = authenticate[:update].call
78
+
79
+ unless authorized
80
+ halt 401, "Not authorized\n"
81
+ end
82
+
46
83
  content_type :json
47
84
 
48
85
  model = model_class.find(params[:id].to_i)
@@ -60,6 +97,13 @@ module Sinatra
60
97
 
61
98
  # delete
62
99
  delete "/#{route_name}/:id" do
100
+
101
+ authorized = authenticate[:delete].call
102
+
103
+ unless authorized
104
+ halt 401, "Not authorized\n"
105
+ end
106
+
63
107
  content_type :json
64
108
 
65
109
  model = model_class.find(params[:id].to_i)
@@ -74,5 +118,6 @@ module Sinatra
74
118
 
75
119
  end
76
120
 
121
+
77
122
  register REST
78
123
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'sinatra-rest-json'
3
- s.version = '0.1'
3
+ s.version = '0.2'
4
4
 
5
5
  s.date = '2014-05-05'
6
6
  s.summary = "Easy rest routes for Sinatra Applciations"
@@ -4,7 +4,7 @@ require 'rack/test'
4
4
  require "minitest/autorun"
5
5
 
6
6
  require 'sinatra/base'
7
- require 'sinatra/rest-json'
7
+ require 'sinatra/rest_json'
8
8
  require 'json'
9
9
 
10
10
  require File.join(File.dirname(__FILE__), "helper")
@@ -15,6 +15,7 @@ class TestApp < Sinatra::Base
15
15
  end
16
16
 
17
17
 
18
+
18
19
  describe "app" do
19
20
  include Rack::Test::Methods
20
21
 
@@ -103,5 +104,71 @@ describe "app" do
103
104
  assert_equal FooModel.all.size, 0
104
105
  end
105
106
  end
107
+ end
108
+
109
+
110
+ class AuthenticatedTestApp < Sinatra::Base
111
+ register Sinatra::REST
112
+ rest_json FooModel, :authenticate => {
113
+ :all => lambda { true },
114
+ :find => lambda { true },
115
+ :create => lambda { false },
116
+ :update => lambda { false },
117
+ :delete => lambda { false }
118
+ }
119
+ end
120
+
121
+ describe "authenticated app" do
122
+ include Rack::Test::Methods
123
+
124
+ def app
125
+ AuthenticatedTestApp
126
+ end
127
+
128
+ before do
129
+ FooModel.destroy_all
130
+ end
131
+
132
+
133
+ describe "GET /" do
134
+ it "should allow all when data" do
135
+ FooModel.create(:name => "foo1")
136
+
137
+ get "/foo_models"
138
+ assert_equal last_response.status, 200
139
+ end
140
+ end
141
+
142
+ describe "GET /foo_models/:id" do
143
+ it "should allow finding a model" do
144
+ FooModel.create(:name => "foo1")
145
+ get "/foo_models/1"
146
+ assert_equal last_response.status, 200
147
+ end
148
+ end
149
+
150
+ describe "POST /foo_models" do
151
+ it "should not allow creation" do
152
+ assert_equal FooModel.all.size, 0
153
+ post "/foo_models", { :foo_model => { :name => "foo1" } }
154
+ assert_equal last_response.status, 401
155
+ end
156
+ end
106
157
 
158
+
159
+ describe "PUT /foo_models/:id" do
160
+ it "should not allow updating" do
161
+ FooModel.create(:name => "foo1")
162
+ put "/foo_models/1", { :foo_model => { :name => "boo" } }
163
+ assert_equal last_response.status, 401
164
+ end
165
+ end
166
+
167
+ describe "DELETE /foo_models/:id" do
168
+ it "should now allow deletion" do
169
+ FooModel.create(:name => "foo1")
170
+ delete "/foo_models/1"
171
+ assert_equal last_response.status, 401
172
+ end
173
+ end
107
174
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinatra-rest-json
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.1'
4
+ version: '0.2'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Carver
@@ -49,7 +49,6 @@ files:
49
49
  - LICENSE
50
50
  - README.md
51
51
  - Rakefile
52
- - lib/sinatra/rest-json.rb
53
52
  - lib/sinatra/rest_json.rb
54
53
  - sinatra-rest-json.gemspec
55
54
  - test/helper.rb
@@ -1,78 +0,0 @@
1
- require 'sinatra/base'
2
- require 'json'
3
-
4
- module Sinatra
5
- module REST
6
- NOT_FOUND = { :errors => ["record doesn't exist"] }.to_json
7
- MODEL_REGEX = /([A-Z0-9]{1}[a-z0-9]+)/
8
-
9
- def rest_json(model_class, opts = {})
10
- model_name = model_class.name.scan(MODEL_REGEX).join("_").downcase
11
- route_name = model_class.table_name
12
-
13
- # all
14
- get "/#{route_name}" do
15
- content_type :json
16
- "[" + model_class.all.collect { |m| m.to_json }.join(",") + "]"
17
- end
18
-
19
- # find
20
- get "/#{route_name}/:id" do
21
- content_type :json
22
- model = model_class.find(params[:id].to_i)
23
-
24
- if model.nil?
25
- NOT_FOUND
26
- else
27
- model.to_json
28
- end
29
- end
30
-
31
- # create
32
- post "/#{route_name}" do
33
- content_type :json
34
-
35
- model = model_class.new(params[model_name])
36
-
37
- if model.save
38
- model.to_json
39
- else
40
- { :errors => model.errors }.to_json
41
- end
42
- end
43
-
44
- # update
45
- put "/#{route_name}/:id" do
46
- content_type :json
47
-
48
- model = model_class.find(params[:id].to_i)
49
-
50
- if model.nil?
51
- NOT_FOUND
52
- else
53
- if model.update_attributes(params[model_name])
54
- model.to_json
55
- else
56
- { :errors => model.errors }.to_json
57
- end
58
- end
59
- end
60
-
61
- # delete
62
- delete "/#{route_name}/:id" do
63
- content_type :json
64
-
65
- model = model_class.find(params[:id].to_i)
66
-
67
- if model.nil?
68
- NOT_FOUND
69
- else
70
- model.destroy.to_json
71
- end
72
- end
73
- end
74
-
75
- end
76
-
77
- register REST
78
- end