json-crud-api 0.0.5 → 0.0.7

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: 79b2e0ca071a00b36b5255b2f4168b274e16f0bf
4
- data.tar.gz: 767ca5c4018742511b7e539fcdf10fa0c34a2498
3
+ metadata.gz: 449673186265d26d910abcbee096846f98b417ae
4
+ data.tar.gz: 8c11a8db9c5a320fa0da8ba9d373dca3a8f073e3
5
5
  SHA512:
6
- metadata.gz: 42c783872ea7f4e68a32d1d48f86a5baa960fa82a53f94045c8ca1c2099c51ea0448a9a02f7cb18bbbc63a6a8f492caff3621abd47538eb63c2167905d26458e
7
- data.tar.gz: 64c631939a0817a09aae149993dd853a23e5d0fd302f4f4716c426f4a2eadf2eccaf94d767c6a2d200388cb65aca57cddb2a4c2fcc38a0f3041733ee74911887
6
+ metadata.gz: 2845c4c9df02675b8c0a178f5c1d1f3c4b73e775ead310bfb296ba8cff3e1b6f37aa05526644ad8da71547a0af4e56722fef515027608827cadb68810a981586
7
+ data.tar.gz: 97f9dd8748df1a814977e2193df3830d8a85bcc24ff3892c6ed9d8f270b8c3b0525f68347797943de34ceeeb8da267e2045f24cea6c677db741385abd403541f
@@ -4,7 +4,10 @@ require 'sinatra'
4
4
  module JsonCrudApi
5
5
  class API < Sinatra::Base
6
6
 
7
+ register JsonCrudApi::Session
8
+ register JsonCrudApi::JsonPayload
7
9
  register JsonCrudApi::Crud
10
+ register JsonCrudApi::JsonErrors
8
11
 
9
12
  before do
10
13
  # HTTPS Only (if configured)
@@ -12,38 +15,14 @@ module JsonCrudApi
12
15
  fail_with_error 403, 'SSL_ONLY', 'The API can only be accessed over SSL (HTTPS)'
13
16
  end
14
17
 
15
- # JSON Errors
16
- @errors = []
17
-
18
18
  # No-Cache by default
19
19
  cache_control :no_cache, :max_age => 0
20
20
 
21
21
  # Session
22
- @user = nil
23
- @logged_in = false
24
- if settings.respond_to? :auth_client
25
- @session_id = env['HTTP_X_SESSION_ID']
26
- unless @session_id.nil?
27
- @user = settings.auth_client.get(@session_id)
28
- @logged_in = !@user.nil?
29
- end
30
- end
31
- settings.services.each do |k,service|
32
- service.set_user @user if service.respond_to? :set_user
33
- end
22
+ process_session
34
23
 
35
24
  # JSON Payload
36
- request.body.rewind
37
- body = request.body.read
38
- if body.length > 2
39
- begin
40
- @payload = JSON.parse body, :symbolize_names => true
41
- rescue JSON::ParserError
42
- fail_with_error 422, 'JSON_PARSE_ERROR', 'The JSON payload cannot be parsed'
43
- end
44
- else
45
- @payload = nil
46
- end
25
+ process_json_payload
47
26
 
48
27
  # CORS
49
28
  content_type 'application/json; charset=utf-8'
@@ -51,45 +30,6 @@ module JsonCrudApi
51
30
  response.headers['Access-Control-Allow-Headers'] = 'Content-Type'
52
31
  end
53
32
 
54
- def logged_in?
55
- @logged_in
56
- end
57
-
58
- def add_error(code, message, reference = nil)
59
- @errors = [] if @errors.nil?
60
-
61
- error = {
62
- :code => code,
63
- :message => message,
64
- }
65
- error[:reference] = reference unless reference.nil?
66
- @errors.push error
67
- end
68
-
69
- def fail_with_error(status, code, message, reference = nil)
70
- add_error code,message,reference
71
- fail_with_errors status
72
- end
73
-
74
- def fail_with_errors(status = 422)
75
- halt status, JSON.fast_generate({
76
- :success => false,
77
- :errors => @errors
78
- })
79
- end
80
-
81
- def fail_not_found
82
- fail_with_error 404, 'NOT_FOUND','The resource cannot be found.'
83
- end
84
-
85
- def fail_unauthorized
86
- fail_with_error 401, 'UNAUTHORIZED','Authorization is required to perform this operation on the resource.'
87
- end
88
-
89
- def fail_forbidden
90
- fail_with_error 403, 'FORBIDDEN','The user is not allowed to perform this operation on the resource.'
91
- end
92
-
93
33
  not_found do
94
34
  fail_not_found
95
35
  end
@@ -1,71 +1,69 @@
1
+ require 'json'
2
+
1
3
  module JsonCrudApi
2
4
  module Crud
3
5
 
4
6
  def crud_api(url, key, options = [])
5
7
 
6
8
  unless options.include? :disable_read
9
+ get url do crud_get_all(key) end unless options.include? :disable_get_all
10
+ get url+"/:id" do crud_get(key) end unless options.include? :disable_get
11
+ end
7
12
 
8
- unless options.include? :disable_get_all
9
- get url do
10
- service = settings.services[key]
11
- presenter = settings.presenters[key]
12
- fail_unauthorized unless service.user_authorized_for? :get_all
13
- entities = service.get_all
14
- fail_not_found if entities.nil?
13
+ unless options.include? :disable_write
14
+ post url do crud_post(key) end unless options.include? :disable_post
15
+ put url+"/:id" do crud_put(key) end unless options.include? :disable_put
16
+ delete url+"/:id" do crud_delete(key) end unless options.include? :disable_delete
17
+ end
15
18
 
16
- JSON.fast_generate settings.presenters[key].render(entities, :get_all)
17
- end
18
- end
19
+ end
19
20
 
20
- unless options.include? :disable_get
21
- get url+"/:id" do
22
- service = settings.services[key]
23
- presenter = settings.presenters[key]
24
- fail_unauthorized unless service.user_authorized_for? :get
25
- entity = service.get(params["id"])
26
- fail_not_found if entity.nil?
21
+ private
27
22
 
28
- JSON.fast_generate settings.presenters[key].render(entity, :get)
29
- end
30
- end
23
+ def crud_get_all(key)
24
+ service = settings.services[key]
25
+ presenter = settings.presenters[key]
26
+ return fail_unauthorized unless service.user_authorized_for? :get_all
27
+ entities = service.get_all
28
+ return fail_not_found if entities.nil?
31
29
 
32
- end
30
+ JSON.fast_generate presenter.render(entities, :get_all)
31
+ end
33
32
 
34
- unless options.include? :disable_write
33
+ def crud_get(key)
34
+ service = settings.services[key]
35
+ presenter = settings.presenters[key]
36
+ return fail_unauthorized unless service.user_authorized_for? :get
37
+ entity = service.get(params["id"])
38
+ return fail_not_found if entity.nil?
35
39
 
36
- unless options.include? :disable_post
37
- post url do
38
- service = settings.services[key]
39
- presenter = settings.presenters[key]
40
- fail_unauthorized unless service.user_authorized_for? :create
41
- entity = service.create(presenter.parse(@payload, :post))
40
+ JSON.fast_generate presenter.render(entity, :get)
41
+ end
42
42
 
43
- JSON.fast_generate settings.presenters[key].render(entity, :post)
44
- end
45
- end
43
+ def crud_post(key)
44
+ service = settings.services[key]
45
+ presenter = settings.presenters[key]
46
+ return fail_unauthorized unless service.user_authorized_for? :create
47
+ entity = service.create(presenter.parse(@payload, :post))
46
48
 
47
- unless options.include? :disable_put
48
- put url+"/:id" do
49
- service = settings.services[key]
50
- presenter = settings.presenters[key]
51
- fail_unauthorized unless service.user_authorized_for? :update
52
- fail_not_found unless service.update(params["id"], presenter.parse(@payload, :put))
53
- entity = service.get(params["id"])
54
- JSON.fast_generate settings.presenters[key].render(entity, :put)
55
- end
56
- end
49
+ JSON.fast_generate presenter.render(entity, :post)
50
+ end
57
51
 
58
- unless options.include? :disable_delete
59
- delete url+"/:id" do
60
- service = settings.services[key]
61
- presenter = settings.presenters[key]
62
- fail_unauthorized unless service.user_authorized_for? :delete
63
- fail_not_found unless service.delete(params["id"])
64
- 204
65
- end
66
- end
52
+ def crud_put(key)
53
+ service = settings.services[key]
54
+ presenter = settings.presenters[key]
55
+ return fail_unauthorized unless service.user_authorized_for? :update
56
+ return fail_not_found unless service.update(params["id"], presenter.parse(@payload, :put))
57
+ entity = service.get(params["id"])
58
+ JSON.fast_generate presenter.render(entity, :put)
59
+ end
67
60
 
68
- end
61
+ def crud_delete(key)
62
+ service = settings.services[key]
63
+ presenter = settings.presenters[key]
64
+ return fail_unauthorized unless service.user_authorized_for? :delete
65
+ return fail_not_found unless service.delete(params["id"])
66
+ 204
69
67
  end
70
68
  end
71
69
  end
@@ -0,0 +1,45 @@
1
+ require 'json'
2
+
3
+ module JsonCrudApi
4
+ module JsonErrors
5
+
6
+ def clear_errors
7
+ @errors = []
8
+ end
9
+
10
+ def add_error(code, message, reference = nil)
11
+ @errors = [] if @errors.nil?
12
+
13
+ error = {
14
+ :code => code,
15
+ :message => message,
16
+ }
17
+ error[:reference] = reference unless reference.nil?
18
+ @errors.push error
19
+ end
20
+
21
+ def fail_with_error(status, code, message, reference = nil)
22
+ add_error code,message,reference
23
+ fail_with_errors status
24
+ end
25
+
26
+ def fail_with_errors(status = 422)
27
+ halt status, JSON.fast_generate({
28
+ :success => false,
29
+ :errors => @errors
30
+ })
31
+ end
32
+
33
+ def fail_not_found
34
+ fail_with_error 404, 'NOT_FOUND','The resource cannot be found.'
35
+ end
36
+
37
+ def fail_unauthorized
38
+ fail_with_error 401, 'UNAUTHORIZED','Authorization is required to perform this operation on the resource.'
39
+ end
40
+
41
+ def fail_forbidden
42
+ fail_with_error 403, 'FORBIDDEN','The user is not allowed to perform this operation on the resource.'
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,21 @@
1
+ require 'json'
2
+
3
+ module JsonCrudApi
4
+ module JsonPayload
5
+ def process_json_payload
6
+ request.body.rewind
7
+ body = request.body.read
8
+ unless body.length > 2
9
+ @payload = nil
10
+ return
11
+ end
12
+
13
+ begin
14
+ @payload = JSON.parse body, :symbolize_names => true
15
+ rescue JSON::ParserError
16
+ @payload = nil
17
+ fail_with_error 422, 'JSON_PARSE_ERROR', 'The JSON payload cannot be parsed'
18
+ end
19
+ end
20
+ end
21
+ end
@@ -8,41 +8,49 @@ module JsonCrudApi
8
8
  @exclude = options[:exclude]
9
9
  @include = options[:include]
10
10
 
11
+ # Properties Cache
12
+ @properties = { :render => {}, :parse => {} }
13
+
11
14
  throw "Model must be defined" if @model.nil?
12
15
  end
13
16
 
14
17
  def render(data, operation = nil)
15
18
  return data.map {|d| render(d, operation) } if data.is_a?(Array)
16
19
 
17
- Hash[get_properties(:render, operation).map { |p| [p, data.send(p)] }]
20
+ unless @properties[:render].has_key? operation
21
+ @properties[:render][operation] = get_properties(:render, operation)
22
+ end
23
+ Hash[@properties[:render][operation].map { |p| [p, data.send(p)] }]
18
24
  end
19
25
 
20
26
  def parse(data, operation = nil)
21
27
  return data.map {|d| parse(d, operation) } if data.is_a?(Array)
22
28
 
23
- Hash[get_properties(:parse, operation).map { |p| [p,data[p]] }]
29
+ unless @properties[:parse].has_key? operation
30
+ @properties[:parse][operation] = get_properties(:parse, operation)
31
+ end
32
+
33
+ out = Hash.new
34
+ data.each_pair { |k,v| out[k] = v if @properties[:parse][operation].include?(k) }
35
+ out
24
36
  end
25
37
 
26
38
  def get_properties(method, operation)
27
39
  properties = @model.properties.map { |p| p.name.to_sym }
28
- unless @exclude.nil?
29
- properties -= @exclude[:all] unless @exclude[:all].nil?
30
- properties -= @exclude[operation] unless @exclude[operation].nil?
31
- unless @exclude[method].nil?
32
- properties -= @exclude[method][:all] unless @exclude[method][:all].nil?
33
- properties -= @exclude[method][operation] unless @exclude[method][operation].nil?
34
- end
35
- end
36
- unless @include.nil?
37
- properties += @include[:all] unless @include[:all].nil?
38
- properties += @include[operation] unless @include[operation].nil?
39
- unless @include[method].nil?
40
- properties += @include[method][:all] unless @include[method][:all].nil?
41
- properties += @include[method][operation] unless @include[method][operation].nil?
42
- end
43
- end
40
+ properties -= filter_properties @exclude, method, operation unless @exclude.nil?
41
+ properties += filter_properties @include, method, operation unless @include.nil?
44
42
  properties
45
43
  end
46
44
 
45
+ def filter_properties(parameter, method, operation)
46
+ properties = []
47
+ properties += parameter[:all] unless parameter[:all].nil?
48
+ properties += parameter[operation] unless parameter[operation].nil?
49
+ unless parameter[method].nil?
50
+ properties += parameter[method][:all] unless parameter[method][:all].nil?
51
+ properties += parameter[method][operation] unless parameter[method][operation].nil?
52
+ end
53
+ properties
54
+ end
47
55
  end
48
56
  end
@@ -0,0 +1,24 @@
1
+ require 'json'
2
+
3
+ module JsonCrudApi
4
+ module Session
5
+ def process_session
6
+ @user = nil
7
+ @logged_in = false
8
+ if settings.respond_to? :auth_client
9
+ @session_id = env['HTTP_X_SESSION_ID']
10
+ unless @session_id.nil?
11
+ @user = settings.auth_client.get(@session_id)
12
+ @logged_in = !@user.nil?
13
+ end
14
+ end
15
+ settings.services.each do |k,service|
16
+ service.set_user @user if service.respond_to? :set_user
17
+ end
18
+ end
19
+
20
+ def logged_in?
21
+ @logged_in
22
+ end
23
+ end
24
+ end
data/lib/json-crud-api.rb CHANGED
@@ -1,5 +1,8 @@
1
+ require "json-crud-api/session"
1
2
  require "json-crud-api/presenter"
2
3
  require "json-crud-api/service"
3
4
  require "json-crud-api/crud"
4
- require "json-crud-api/api"
5
- require "json-crud-api/auth_client"
5
+ require "json-crud-api/json_payload"
6
+ require "json-crud-api/json_errors"
7
+ require "json-crud-api/auth_client"
8
+ require "json-crud-api/api"
@@ -0,0 +1,9 @@
1
+ require "codeclimate-test-reporter"
2
+ CodeClimate::TestReporter.start
3
+
4
+ require 'rack/test'
5
+
6
+ require "json-crud-api"
7
+
8
+ RSpec.configure do |c|
9
+ end
@@ -0,0 +1,11 @@
1
+ require "spec_helper"
2
+
3
+ describe JsonCrudApi::API do
4
+ include Rack::Test::Methods
5
+
6
+ def app
7
+ JsonCrudApi::API
8
+ end
9
+
10
+ # TODO: Moar Specs!
11
+ end
@@ -1,4 +1,4 @@
1
- require "helper"
1
+ require "spec_helper"
2
2
 
3
3
  describe JsonCrudApi::AuthClient do
4
4
  before(:each) do
@@ -13,89 +13,89 @@ describe JsonCrudApi::AuthClient do
13
13
 
14
14
  describe '#initialize' do
15
15
  it 'should inject dependencies correctly' do
16
- @client.redis.should be @mock_redis
17
- @client.session_ttl.should be 200
18
- @client.prefix.should be 789
16
+ expect(@client.redis).to be @mock_redis
17
+ expect(@client.session_ttl).to be 200
18
+ expect(@client.prefix).to be 789
19
19
  end
20
20
  end
21
21
 
22
22
  describe '#get' do
23
23
  it 'should call get_redis_key and redis get' do
24
- @client.should_receive(:get_redis_key).with('one')
25
- @mock_redis.should_receive(:get).and_return nil
24
+ expect(@client).to receive(:get_redis_key).with('one')
25
+ expect(@mock_redis).to receive(:get).and_return nil
26
26
  @client.get('one')
27
27
  end
28
28
 
29
29
  it 'should return nil if redis get return nil' do
30
- @mock_redis.should_receive(:get).and_return nil
31
- @client.get('one').should be nil
30
+ expect(@mock_redis).to receive(:get).and_return nil
31
+ expect(@client.get('one')).to be_nil
32
32
  end
33
33
 
34
34
  it 'should call touch if redis get is non nil' do
35
- @mock_redis.should_receive(:get).and_return '{}'
36
- @client.should_receive(:touch).with('789one')
35
+ expect(@mock_redis).to receive(:get).and_return '{}'
36
+ expect(@client).to receive(:touch).with('789one')
37
37
  @client.get('one')
38
38
  end
39
39
 
40
40
  it 'should parse JSON from redis get' do
41
- @mock_redis.should_receive(:get).and_return '{"five":5}'
42
- @client.should_receive(:touch).with('789one')
43
- @client.get('one').should eq({ :five => 5 })
41
+ expect(@mock_redis).to receive(:get).and_return '{"five":5}'
42
+ expect(@client).to receive(:touch).with('789one')
43
+ expect(@client.get('one')).to eq({ :five => 5 })
44
44
  end
45
45
  end
46
46
 
47
47
  describe '#delete' do
48
48
  it 'should call get_redis_key and redis exists and return false if exists is false' do
49
- @client.should_receive(:get_redis_key).with('one')
50
- @mock_redis.should_receive(:exists).and_return false
51
- @client.delete('one').should be false
49
+ expect(@client).to receive(:get_redis_key).with('one')
50
+ expect(@mock_redis).to receive(:exists).and_return false
51
+ expect(@client.delete('one')).to be false
52
52
  end
53
53
 
54
54
  it 'should call redis del and return true if redis exists is true' do
55
- @mock_redis.should_receive(:exists).and_return true
56
- @mock_redis.should_receive(:del).with('789one')
57
- @client.delete('one').should be true
55
+ expect(@mock_redis).to receive(:exists).and_return true
56
+ expect(@mock_redis).to receive(:del).with('789one')
57
+ expect(@client.delete('one')).to be true
58
58
  end
59
59
  end
60
60
 
61
61
  describe '#touch' do
62
62
  it 'should call get_redis_key and redis exists and return false if exists is false' do
63
- @client.should_receive(:get_redis_key).with('one')
64
- @mock_redis.should_receive(:exists).and_return false
65
- @client.touch('one').should be false
63
+ expect(@client).to receive(:get_redis_key).with('one')
64
+ expect(@mock_redis).to receive(:exists).and_return false
65
+ expect(@client.touch('one')).to be false
66
66
  end
67
67
 
68
68
  it 'should call redis expire and return true if redis exists is true' do
69
- @mock_redis.should_receive(:exists).and_return true
70
- @mock_redis.should_receive(:expire).with('789one', 200)
71
- @client.touch('one').should be true
69
+ expect(@mock_redis).to receive(:exists).and_return true
70
+ expect(@mock_redis).to receive(:expire).with('789one', 200)
71
+ expect(@client.touch('one')).to be true
72
72
  end
73
73
  end
74
74
 
75
75
  describe '#get_redis_key' do
76
76
  it 'should return key if prefix is nil' do
77
77
  @client.prefix = nil
78
- @client.get_redis_key('one').should eq 'one'
78
+ expect(@client.get_redis_key('one')).to eq 'one'
79
79
  end
80
80
 
81
81
  it 'should return key.to_s if prefix is nil' do
82
82
  @client.prefix = nil
83
- @client.get_redis_key(1).should eq '1'
83
+ expect(@client.get_redis_key(1)).to eq '1'
84
84
  end
85
85
 
86
86
  it 'should return prefix plus key if prefix is not nil' do
87
87
  @client.prefix = 'pre-'
88
- @client.get_redis_key('one').should eq 'pre-one'
88
+ expect(@client.get_redis_key('one')).to eq 'pre-one'
89
89
  end
90
90
 
91
91
  it 'should return prefix plus key.to_s if prefix is not nil' do
92
92
  @client.prefix = 'post-'
93
- @client.get_redis_key(1).should eq 'post-1'
93
+ expect(@client.get_redis_key(1)).to eq 'post-1'
94
94
  end
95
95
 
96
96
  it 'should return prefix.to_s plus key.to_s if prefix is not nil' do
97
97
  @client.prefix = 5
98
- @client.get_redis_key(1).should eq '51'
98
+ expect(@client.get_redis_key(1)).to eq '51'
99
99
  end
100
100
  end
101
101
  end