json-crud-api 0.0.1
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 +7 -0
- data/lib/json-crud-api.rb +4 -0
- data/lib/json-crud-api/api.rb +102 -0
- data/lib/json-crud-api/auth_client.rb +41 -0
- data/lib/json-crud-api/crud.rb +71 -0
- data/lib/json-crud-api/service.rb +85 -0
- data/spec/helper.rb +12 -0
- data/spec/helpers_spec.rb +3 -0
- data/spec/unit/auth_client_spec.rb +101 -0
- data/spec/unit/service_spec.rb +219 -0
- metadata +240 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d29a60e6d78b872ce5373491643e567e2c6131d8
|
4
|
+
data.tar.gz: ec36f07906e2cb7c7fa18811b586c33331879ddf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 58cb2c22a099f4898bf5ccea53481e7ee8e1ae625991f319603cc58e824058e17c232242f7b0715e02283004225b6b51ad09d64a061411b8ed03b02f09a5d7c7
|
7
|
+
data.tar.gz: 7e4112a6b627e591b1017a9ceed570f880dddf526e8589368e6eb1c544f7c92f824877a9e04df0634f40602f6e6a6254a5ed585dc1a0ba8d3a1d153dfc1e3164
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sinatra'
|
3
|
+
|
4
|
+
module JsonCrudApi
|
5
|
+
class API < Sinatra::Base
|
6
|
+
|
7
|
+
register JsonCrudApi::Crud
|
8
|
+
|
9
|
+
before do
|
10
|
+
# HTTPS Only (if configured)
|
11
|
+
if settings.respond_to? :https_only and settings.https_only and env['HTTPS'] != 'on' and env['HTTP_X_FORWARDED_PROTO'] != 'https'
|
12
|
+
fail_with_error 403, 'SSL_ONLY', 'The API can only be accessed over SSL (HTTPS)'
|
13
|
+
end
|
14
|
+
|
15
|
+
# JSON Errors
|
16
|
+
@errors = []
|
17
|
+
|
18
|
+
# No-Cache by default
|
19
|
+
cache_control :no_cache, :max_age => 0
|
20
|
+
|
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
|
34
|
+
|
35
|
+
# 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
|
47
|
+
|
48
|
+
# CORS
|
49
|
+
content_type 'application/json; charset=utf-8'
|
50
|
+
response.headers['Access-Control-Allow-Origin'] = '*'
|
51
|
+
response.headers['Access-Control-Allow-Headers'] = 'Content-Type'
|
52
|
+
end
|
53
|
+
|
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
|
+
not_found do
|
94
|
+
fail_not_found
|
95
|
+
end
|
96
|
+
|
97
|
+
error do
|
98
|
+
fail_with_error 500, 'INTERNAL_ERROR','The server has encountered an unknown error.'
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
module JsonCrudApi
|
4
|
+
class AuthClient
|
5
|
+
|
6
|
+
attr_accessor :redis, :session_ttl, :prefix
|
7
|
+
|
8
|
+
def initialize(options)
|
9
|
+
@redis = options[:redis_client]
|
10
|
+
@session_ttl = options[:session_ttl]
|
11
|
+
@prefix = options[:key_prefix]
|
12
|
+
end
|
13
|
+
|
14
|
+
def get(key)
|
15
|
+
key = get_redis_key(key)
|
16
|
+
data = @redis.get(key)
|
17
|
+
return nil if data.nil?
|
18
|
+
touch(key)
|
19
|
+
JSON.parse(data, :symbolize_names => true)
|
20
|
+
end
|
21
|
+
|
22
|
+
def delete(key)
|
23
|
+
key = get_redis_key(key)
|
24
|
+
return false unless @redis.exists(key)
|
25
|
+
@redis.del(key)
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
def touch(key)
|
30
|
+
key = get_redis_key(key)
|
31
|
+
return false unless @redis.exists(key)
|
32
|
+
@redis.expire(key, @session_ttl)
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_redis_key(key)
|
37
|
+
return key.to_s if @prefix.nil?
|
38
|
+
@prefix.to_s+key.to_s
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module JsonCrudApi
|
2
|
+
module Crud
|
3
|
+
|
4
|
+
def crud_api(url, key, options = [])
|
5
|
+
|
6
|
+
unless options.include? :disable_read
|
7
|
+
|
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?
|
15
|
+
|
16
|
+
JSON.fast_generate settings.presenters[key].render(entities)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
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?
|
27
|
+
|
28
|
+
JSON.fast_generate settings.presenters[key].render(entity)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
unless options.include? :disable_write
|
35
|
+
|
36
|
+
unless options.include? :disable_post
|
37
|
+
post url do
|
38
|
+
service = settings.services[key]
|
39
|
+
presenter = settings.presenters[key]
|
40
|
+
fail_unauthorized 'create' unless service.user_authorized_for? :create
|
41
|
+
entity = service.create(presenter.parse(@payload))
|
42
|
+
|
43
|
+
JSON.fast_generate settings.presenters[key].render(entity)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
unless options.include? :disable_put
|
48
|
+
put url+"/:id" do
|
49
|
+
service = settings.services[key]
|
50
|
+
presenter = settings.presenters[key]
|
51
|
+
fail_unauthorized 'update' unless service.user_authorized_for? :update
|
52
|
+
fail_not_found unless service.update(params["id"], presenter.parse(@payload))
|
53
|
+
entity = service.get(params["id"])
|
54
|
+
JSON.fast_generate settings.presenters[key].render(entity)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
unless options.include? :disable_delete
|
59
|
+
delete url+"/:id" do
|
60
|
+
service = settings.services[key]
|
61
|
+
presenter = settings.presenters[key]
|
62
|
+
fail_unauthorized 'delete' unless service.user_authorized_for? :delete
|
63
|
+
fail_not_found unless service.delete(params["id"])
|
64
|
+
204
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
module JsonCrudApi
|
4
|
+
class Service
|
5
|
+
|
6
|
+
attr_accessor :log_service, :repo, :user, :scope_map, :user_scopes
|
7
|
+
|
8
|
+
def initialize(options)
|
9
|
+
@log_service = options[:log_service]
|
10
|
+
@repo = options[:repository]
|
11
|
+
@scope_map = options[:scope_map]
|
12
|
+
@user = nil
|
13
|
+
@user_scopes = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
# Create a record with the given attributes
|
17
|
+
def create(params)
|
18
|
+
@repo.create(params)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Determine if a record with the given id exists
|
22
|
+
def exists?(id)
|
23
|
+
@repo.all(:id => id).count > 0
|
24
|
+
end
|
25
|
+
|
26
|
+
# Get all records
|
27
|
+
def get_all
|
28
|
+
@repo.all
|
29
|
+
end
|
30
|
+
|
31
|
+
# Get the first record with the given id
|
32
|
+
def get(id)
|
33
|
+
@repo.first(:id => id)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Update a record with the given id with the given attributes
|
37
|
+
# Returns false if the record does not exist.
|
38
|
+
def update(id, params)
|
39
|
+
record = get(id)
|
40
|
+
return false if record.nil?
|
41
|
+
|
42
|
+
record.update(params)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Delete a record with the given id
|
46
|
+
# Returns false if the record does not exist.
|
47
|
+
def delete(id)
|
48
|
+
record = get(id)
|
49
|
+
return false if record.nil?
|
50
|
+
|
51
|
+
record.destroy
|
52
|
+
end
|
53
|
+
|
54
|
+
# Set the current user
|
55
|
+
def set_user(user)
|
56
|
+
@user = user
|
57
|
+
set_user_scopes(user[:scopes]) unless @user.nil?
|
58
|
+
end
|
59
|
+
|
60
|
+
# Set the current user scopes
|
61
|
+
def set_user_scopes(user_scopes)
|
62
|
+
@user_scopes = user_scopes
|
63
|
+
end
|
64
|
+
|
65
|
+
# Determine if the current user is authorized for the given operation
|
66
|
+
def user_authorized_for?(operation)
|
67
|
+
# Auth is disabled if scope map is nil
|
68
|
+
return true if @scope_map.nil?
|
69
|
+
# Auth succeeds if there is no map for this operation
|
70
|
+
return true if @scope_map[operation].nil?
|
71
|
+
# Auth fails if user is not logged in
|
72
|
+
return false if @user.nil?
|
73
|
+
# Auth fails if user has no scopes
|
74
|
+
return false if @user_scopes.nil? or @user_scopes.empty?
|
75
|
+
|
76
|
+
if @scope_map[operation].is_a?(Array)
|
77
|
+
# Auth succeeds if the intersection of allowed scopes and mapped scopes is non-empty.
|
78
|
+
return !((@scope_map[operation] & @user_scopes).empty?)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Auth succeeds if the mapped scope is singular and the user posesses it
|
82
|
+
@user_scopes.include?(@scope_map[operation])
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/spec/helper.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
describe JsonCrudApi::AuthClient do
|
4
|
+
before(:each) do
|
5
|
+
@mock_redis = double('redis')
|
6
|
+
|
7
|
+
@client = JsonCrudApi::AuthClient.new({
|
8
|
+
:redis_client => @mock_redis,
|
9
|
+
:session_ttl => 200,
|
10
|
+
:key_prefix => 789
|
11
|
+
})
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#initialize' do
|
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
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#get' do
|
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
|
26
|
+
@client.get('one')
|
27
|
+
end
|
28
|
+
|
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
|
32
|
+
end
|
33
|
+
|
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')
|
37
|
+
@client.get('one')
|
38
|
+
end
|
39
|
+
|
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 })
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#delete' do
|
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
|
52
|
+
end
|
53
|
+
|
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
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#touch' do
|
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
|
66
|
+
end
|
67
|
+
|
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
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#get_redis_key' do
|
76
|
+
it 'should return key if prefix is nil' do
|
77
|
+
@client.prefix = nil
|
78
|
+
@client.get_redis_key('one').should eq 'one'
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should return key.to_s if prefix is nil' do
|
82
|
+
@client.prefix = nil
|
83
|
+
@client.get_redis_key(1).should eq '1'
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should return prefix plus key if prefix is not nil' do
|
87
|
+
@client.prefix = 'pre-'
|
88
|
+
@client.get_redis_key('one').should eq 'pre-one'
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should return prefix plus key.to_s if prefix is not nil' do
|
92
|
+
@client.prefix = 'post-'
|
93
|
+
@client.get_redis_key(1).should eq 'post-1'
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should return prefix.to_s plus key.to_s if prefix is not nil' do
|
97
|
+
@client.prefix = 5
|
98
|
+
@client.get_redis_key(1).should eq '51'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,219 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
describe JsonCrudApi::Service do
|
4
|
+
before(:each) do
|
5
|
+
@mock_repo = double('repo')
|
6
|
+
@mock_log = double('Log')
|
7
|
+
@mock_map = double('Map')
|
8
|
+
|
9
|
+
@service = JsonCrudApi::Service.new({
|
10
|
+
:log_service => @mock_log,
|
11
|
+
:repository => @mock_repo,
|
12
|
+
:scope_map => @mock_map
|
13
|
+
})
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#initialize' do
|
17
|
+
it 'should inject dependencies correctly' do
|
18
|
+
@service.log_service.should be @mock_log
|
19
|
+
@service.repo.should be @mock_repo
|
20
|
+
@service.scope_map.should be @mock_map
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should initialize user and scopes to nil' do
|
24
|
+
@service.user.should be nil
|
25
|
+
@service.user_scopes.should be nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#create' do
|
30
|
+
it 'should call create on repo with params' do
|
31
|
+
params = { :one => 'one', :two => 'two' }
|
32
|
+
@mock_repo.should_receive(:create).with(params).and_return(2)
|
33
|
+
@service.create(params).should eq 2
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#exists?' do
|
38
|
+
it 'should call all on repo with correct id' do
|
39
|
+
query_object = OpenStruct.new :count => 1
|
40
|
+
@mock_repo.should_receive(:all).with(:id => 3)
|
41
|
+
.and_return(query_object)
|
42
|
+
@service.exists?(3).should eq true
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should return false when count is zero' do
|
46
|
+
query_object = OpenStruct.new :count => 0
|
47
|
+
@mock_repo.should_receive(:all).with(:id => 3)
|
48
|
+
.and_return(query_object)
|
49
|
+
@service.exists?(3).should eq false
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should return true when count is one' do
|
53
|
+
query_object = OpenStruct.new :count => 1
|
54
|
+
@mock_repo.should_receive(:all).with(:id => 3)
|
55
|
+
.and_return(query_object)
|
56
|
+
@service.exists?(3).should eq true
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should return true when count is more than one' do
|
60
|
+
query_object = OpenStruct.new :count => 2
|
61
|
+
@mock_repo.should_receive(:all).with(:id => 3)
|
62
|
+
.and_return(query_object)
|
63
|
+
@service.exists?(3).should eq true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#get_all' do
|
68
|
+
it 'should call all on repo and return output' do
|
69
|
+
@mock_repo.should_receive(:all).with().and_return(67)
|
70
|
+
@service.get_all.should eq 67
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#get' do
|
75
|
+
it 'should call first on repo with correct id and return result' do
|
76
|
+
@mock_repo.should_receive(:first).with({:id=>8}).and_return(123)
|
77
|
+
@service.get(8).should eq 123
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe '#update' do
|
82
|
+
it 'should call get on service with correct id' do
|
83
|
+
@service.should_receive(:get).with(5).and_return(nil)
|
84
|
+
@service.update(5,nil)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should return false if get returns nil' do
|
88
|
+
@service.should_receive(:get).with(5).and_return(nil)
|
89
|
+
@service.update(5,nil).should eq false
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should call update on record with correct params' do
|
93
|
+
params = { :one => 'one', :two => 'two' }
|
94
|
+
record = double('entity')
|
95
|
+
@service.should_receive(:get).with(5)
|
96
|
+
.and_return(record)
|
97
|
+
record.should_receive(:update).with(params)
|
98
|
+
.and_return(789)
|
99
|
+
@service.update(5,params).should eq 789
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe '#delete' do
|
104
|
+
it 'should call get on service with correct id' do
|
105
|
+
@service.should_receive(:get).with(5).and_return(nil)
|
106
|
+
@service.delete(5)
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should return false if get returns nil' do
|
110
|
+
@service.should_receive(:get).with(5).and_return(nil)
|
111
|
+
@service.delete(5).should eq false
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'should call delete on record' do
|
115
|
+
record = double('entity')
|
116
|
+
@service.should_receive(:get).with(5)
|
117
|
+
.and_return(record)
|
118
|
+
record.should_receive(:destroy).and_return(109)
|
119
|
+
@service.delete(5).should eq 109
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe '#set_user' do
|
124
|
+
it 'should set user in service to param' do
|
125
|
+
@service.set_user(nil)
|
126
|
+
@service.user.should eq nil
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should not call set_user_scopes if user is nil' do
|
130
|
+
@service.should_not_receive(:set_user_scopes)
|
131
|
+
@service.set_user(nil)
|
132
|
+
@service.user.should eq nil
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'should call set_user_scopes if user is not' do
|
136
|
+
user = { :scopes => [1,2] }
|
137
|
+
@service.should_receive(:set_user_scopes).with([1,2])
|
138
|
+
@service.set_user(user)
|
139
|
+
@service.user.should eq user
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe '#set_user_scopes' do
|
144
|
+
it 'should set user_scopes in service to param' do
|
145
|
+
@service.set_user_scopes(nil)
|
146
|
+
@service.user_scopes.should eq nil
|
147
|
+
|
148
|
+
@service.set_user_scopes(234234)
|
149
|
+
@service.user_scopes.should eq 234234
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe '#user_authorized_for?' do
|
154
|
+
it 'should return true if scope_map is nil' do
|
155
|
+
@service.scope_map = nil
|
156
|
+
@service.user_authorized_for?(:one).should be true
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'should return true if scope_map is not nil but no map for operation' do
|
160
|
+
@service.scope_map = { :two => 'TWO' }
|
161
|
+
@service.user_authorized_for?(:one).should be true
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'should return false if user is nil' do
|
165
|
+
@service.scope_map = { :two => 'TWO' }
|
166
|
+
@service.user = nil
|
167
|
+
@service.user_authorized_for?(:two).should be false
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'should return false if user has nil scopes' do
|
171
|
+
@service.scope_map = { :two => 'TWO' }
|
172
|
+
@service.user = { :name => "Tom" }
|
173
|
+
@service.user_scopes = nil
|
174
|
+
@service.user_authorized_for?(:two).should be false
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'should return false if user has empty scopes' do
|
178
|
+
@service.scope_map = { :two => 'TWO' }
|
179
|
+
@service.user = { :name => "Tom" }
|
180
|
+
@service.user_scopes = []
|
181
|
+
@service.user_authorized_for?(:two).should be false
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'should return true if scope map exists in user scopes' do
|
185
|
+
@service.scope_map = { :two => 'FIVE'}
|
186
|
+
@service.user = { :name => "Tom" }
|
187
|
+
@service.user_scopes = [ 'ONE', 'TWO', 'FIVE']
|
188
|
+
@service.user_authorized_for?(:two).should be true
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'should return false if scope map does not exist in user scopes' do
|
192
|
+
@service.scope_map = { :two => 'SEVEN'}
|
193
|
+
@service.user = { :name => "Tom" }
|
194
|
+
@service.user_scopes = [ 'ONE', 'TWO', 'FIVE']
|
195
|
+
@service.user_authorized_for?(:two).should be false
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'should return true if scope map is array and shares one scope with user' do
|
199
|
+
@service.scope_map = { :two => ['TWO'] }
|
200
|
+
@service.user = { :name => "Tom" }
|
201
|
+
@service.user_scopes = [ 'ONE', 'TWO', 'THREE']
|
202
|
+
@service.user_authorized_for?(:two).should be true
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'should return true if scope map is array and shares more than one scope with user' do
|
206
|
+
@service.scope_map = { :two => ['TWO','THREE'] }
|
207
|
+
@service.user = { :name => "Tom" }
|
208
|
+
@service.user_scopes = [ 'ONE', 'TWO', 'THREE']
|
209
|
+
@service.user_authorized_for?(:two).should be true
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'should return false if scope map is array and does not share scopes with user' do
|
213
|
+
@service.scope_map = { :two => ['FOUR'] }
|
214
|
+
@service.user = { :name => "Tom" }
|
215
|
+
@service.user_scopes = [ 'ONE', 'TWO', 'THREE']
|
216
|
+
@service.user_authorized_for?(:two).should be false
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
metadata
ADDED
@@ -0,0 +1,240 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: json-crud-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tom Cully
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: coveralls
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dotenv
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec-mocks
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rack-test
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: dalli
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ~>
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 2.6.4
|
104
|
+
- - '>='
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: 2.6.4
|
107
|
+
type: :runtime
|
108
|
+
prerelease: false
|
109
|
+
version_requirements: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ~>
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: 2.6.4
|
114
|
+
- - '>='
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 2.6.4
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: json
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ~>
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: 1.8.0
|
124
|
+
- - '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: 1.8.0
|
127
|
+
type: :runtime
|
128
|
+
prerelease: false
|
129
|
+
version_requirements: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ~>
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 1.8.0
|
134
|
+
- - '>='
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: 1.8.0
|
137
|
+
- !ruby/object:Gem::Dependency
|
138
|
+
name: mysql2
|
139
|
+
requirement: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ~>
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: 0.3.13
|
144
|
+
- - '>='
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: 0.3.13
|
147
|
+
type: :runtime
|
148
|
+
prerelease: false
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ~>
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: 0.3.13
|
154
|
+
- - '>='
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: 0.3.13
|
157
|
+
- !ruby/object:Gem::Dependency
|
158
|
+
name: sinatra
|
159
|
+
requirement: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
161
|
+
- - ~>
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: 1.4.3
|
164
|
+
- - '>='
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: 1.4.3
|
167
|
+
type: :runtime
|
168
|
+
prerelease: false
|
169
|
+
version_requirements: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ~>
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: 1.4.3
|
174
|
+
- - '>='
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: 1.4.3
|
177
|
+
- !ruby/object:Gem::Dependency
|
178
|
+
name: datamapper
|
179
|
+
requirement: !ruby/object:Gem::Requirement
|
180
|
+
requirements:
|
181
|
+
- - ~>
|
182
|
+
- !ruby/object:Gem::Version
|
183
|
+
version: 1.2.0
|
184
|
+
- - '>='
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
version: 1.2.0
|
187
|
+
type: :runtime
|
188
|
+
prerelease: false
|
189
|
+
version_requirements: !ruby/object:Gem::Requirement
|
190
|
+
requirements:
|
191
|
+
- - ~>
|
192
|
+
- !ruby/object:Gem::Version
|
193
|
+
version: 1.2.0
|
194
|
+
- - '>='
|
195
|
+
- !ruby/object:Gem::Version
|
196
|
+
version: 1.2.0
|
197
|
+
description: A set of classes to simplify JSON APIs
|
198
|
+
email: tomhughcully@gmail.com
|
199
|
+
executables: []
|
200
|
+
extensions: []
|
201
|
+
extra_rdoc_files: []
|
202
|
+
files:
|
203
|
+
- lib/json-crud-api/api.rb
|
204
|
+
- lib/json-crud-api/auth_client.rb
|
205
|
+
- lib/json-crud-api/crud.rb
|
206
|
+
- lib/json-crud-api/service.rb
|
207
|
+
- lib/json-crud-api.rb
|
208
|
+
- spec/helper.rb
|
209
|
+
- spec/helpers_spec.rb
|
210
|
+
- spec/unit/auth_client_spec.rb
|
211
|
+
- spec/unit/service_spec.rb
|
212
|
+
homepage: http://rubygems.org/gems/json-crud-api
|
213
|
+
licenses:
|
214
|
+
- MIT
|
215
|
+
metadata: {}
|
216
|
+
post_install_message:
|
217
|
+
rdoc_options: []
|
218
|
+
require_paths:
|
219
|
+
- lib
|
220
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
221
|
+
requirements:
|
222
|
+
- - '>='
|
223
|
+
- !ruby/object:Gem::Version
|
224
|
+
version: 2.0.0
|
225
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - '>='
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '0'
|
230
|
+
requirements: []
|
231
|
+
rubyforge_project:
|
232
|
+
rubygems_version: 2.1.11
|
233
|
+
signing_key:
|
234
|
+
specification_version: 4
|
235
|
+
summary: Sinatra JSON API Framework Classes
|
236
|
+
test_files:
|
237
|
+
- spec/helper.rb
|
238
|
+
- spec/helpers_spec.rb
|
239
|
+
- spec/unit/auth_client_spec.rb
|
240
|
+
- spec/unit/service_spec.rb
|