json-crud-api 0.0.5 → 0.0.7

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: 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