sinatra-rest-json 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
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