real_savvy 0.0.3 → 0.0.4
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 +4 -4
- data/.circleci/config.yml +57 -0
- data/.gitignore +0 -1
- data/Gemfile.lock +55 -0
- data/lib/real_savvy.rb +1 -0
- data/lib/real_savvy/adapter/{markets.rb → market.rb} +0 -0
- data/lib/real_savvy/jwt.rb +8 -0
- data/lib/real_savvy/jwt/bad_credentials.rb +6 -0
- data/lib/real_savvy/jwt/imposter.rb +9 -0
- data/lib/real_savvy/jwt/site.rb +9 -0
- data/lib/real_savvy/jwt/token.rb +187 -0
- data/lib/real_savvy/jwt/unauthorized.rb +6 -0
- data/lib/real_savvy/jwt/user.rb +9 -0
- data/lib/real_savvy/version.rb +1 -1
- data/real_savvy.gemspec +2 -0
- metadata +40 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f7b745a34a03293650d40a5d016eaca8eaa520cd
|
4
|
+
data.tar.gz: 3f7a21b2a041fc50f51fc9dd3d88525cfeeb8e21
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 749686a2e8f5800286e6fa1fc6b312aac07160f3edc281a5ef865c66422d03291ceffc3d3b18264dba42863800bdc6afb292c446a9226f2e4b3916e0883008e8
|
7
|
+
data.tar.gz: e0d40049f1d30440f505cc54e335b4a8991d285887fcb9bde52ffea859ba8265f3139bc16bee9cd2da963a76c4af42fa20a2e071fe3b68dfa35a458f90d90ab1
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Ruby CircleCI 2.0 configuration file
|
2
|
+
#
|
3
|
+
# Check https://circleci.com/docs/2.0/language-ruby/ for more details
|
4
|
+
#
|
5
|
+
version: 2
|
6
|
+
jobs:
|
7
|
+
build:
|
8
|
+
docker:
|
9
|
+
# specify the version you desire here
|
10
|
+
- image: circleci/ruby:2.4.1-node-browsers
|
11
|
+
|
12
|
+
# Specify service dependencies here if necessary
|
13
|
+
# CircleCI maintains a library of pre-built images
|
14
|
+
# documented at https://circleci.com/docs/2.0/circleci-images/
|
15
|
+
# - image: circleci/postgres:9.4
|
16
|
+
|
17
|
+
working_directory: ~/repo
|
18
|
+
|
19
|
+
steps:
|
20
|
+
- checkout
|
21
|
+
|
22
|
+
# Download and cache dependencies
|
23
|
+
- restore_cache:
|
24
|
+
keys:
|
25
|
+
- v1-dependencies-{{ checksum "Gemfile.lock" }}
|
26
|
+
# fallback to using the latest cache if no exact match is found
|
27
|
+
- v1-dependencies-
|
28
|
+
|
29
|
+
- run:
|
30
|
+
name: install dependencies
|
31
|
+
command: |
|
32
|
+
bundle install --jobs=4 --retry=3 --path vendor/bundle
|
33
|
+
|
34
|
+
- save_cache:
|
35
|
+
paths:
|
36
|
+
- ./vendor/bundle
|
37
|
+
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
|
38
|
+
|
39
|
+
# run tests!
|
40
|
+
- run:
|
41
|
+
name: run tests
|
42
|
+
command: |
|
43
|
+
mkdir /tmp/test-results
|
44
|
+
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
|
45
|
+
|
46
|
+
bundle exec rspec --format progress \
|
47
|
+
--format RspecJunitFormatter \
|
48
|
+
--out /tmp/test-results/rspec.xml \
|
49
|
+
--format progress \
|
50
|
+
$TEST_FILES
|
51
|
+
|
52
|
+
# collect reports
|
53
|
+
- store_test_results:
|
54
|
+
path: /tmp/test-results
|
55
|
+
- store_artifacts:
|
56
|
+
path: /tmp/test-results
|
57
|
+
destination: test-results
|
data/.gitignore
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
real_savvy (0.0.4)
|
5
|
+
faraday (>= 0.10.0)
|
6
|
+
faraday_middleware (>= 0.10.0)
|
7
|
+
jwt (>= 1.0.0)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
coderay (1.1.1)
|
13
|
+
diff-lcs (1.3)
|
14
|
+
faraday (0.14.0)
|
15
|
+
multipart-post (>= 1.2, < 3)
|
16
|
+
faraday_middleware (0.12.2)
|
17
|
+
faraday (>= 0.7.4, < 1.0)
|
18
|
+
jwt (1.5.6)
|
19
|
+
method_source (0.8.2)
|
20
|
+
multipart-post (2.0.0)
|
21
|
+
pry (0.10.4)
|
22
|
+
coderay (~> 1.1.0)
|
23
|
+
method_source (~> 0.8.1)
|
24
|
+
slop (~> 3.4)
|
25
|
+
rake (10.5.0)
|
26
|
+
rspec (3.7.0)
|
27
|
+
rspec-core (~> 3.7.0)
|
28
|
+
rspec-expectations (~> 3.7.0)
|
29
|
+
rspec-mocks (~> 3.7.0)
|
30
|
+
rspec-core (3.7.1)
|
31
|
+
rspec-support (~> 3.7.0)
|
32
|
+
rspec-expectations (3.7.0)
|
33
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
34
|
+
rspec-support (~> 3.7.0)
|
35
|
+
rspec-mocks (3.7.0)
|
36
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
37
|
+
rspec-support (~> 3.7.0)
|
38
|
+
rspec-support (3.7.0)
|
39
|
+
rspec_junit_formatter (0.3.0)
|
40
|
+
rspec-core (>= 2, < 4, != 2.12.0)
|
41
|
+
slop (3.6.0)
|
42
|
+
|
43
|
+
PLATFORMS
|
44
|
+
ruby
|
45
|
+
|
46
|
+
DEPENDENCIES
|
47
|
+
bundler (~> 1.14)
|
48
|
+
pry (~> 0.10)
|
49
|
+
rake (~> 10.0)
|
50
|
+
real_savvy!
|
51
|
+
rspec (~> 3.0)
|
52
|
+
rspec_junit_formatter (~> 0.3)
|
53
|
+
|
54
|
+
BUNDLED WITH
|
55
|
+
1.15.4
|
data/lib/real_savvy.rb
CHANGED
File without changes
|
@@ -0,0 +1,187 @@
|
|
1
|
+
module RealSavvy
|
2
|
+
module JWT
|
3
|
+
class Token
|
4
|
+
# In order of access level
|
5
|
+
SCOPE_VERBS = %w{public read write admin}.freeze
|
6
|
+
|
7
|
+
attr_reader :scopes, :user, :site, :token
|
8
|
+
|
9
|
+
def initialize(token)
|
10
|
+
@token = token
|
11
|
+
retrieve_claims
|
12
|
+
retrieve_scopes
|
13
|
+
retrieve_audience
|
14
|
+
retrieve_site
|
15
|
+
retrieve_subject
|
16
|
+
retrieve_user
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.public_key
|
20
|
+
if block_given?
|
21
|
+
@public_key = Proc.new
|
22
|
+
else
|
23
|
+
result = @public_key.is_a?(Proc) ? @public_key.call : @public_key
|
24
|
+
result.is_a?(OpenSSL::PKey::RSA) ? result : OpenSSL::PKey::RSA.new(result)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.public_key= value
|
29
|
+
@public_key = value
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.retrieve_audience claims = nil
|
33
|
+
if block_given?
|
34
|
+
@retrieve_audience = Proc.new
|
35
|
+
else
|
36
|
+
@retrieve_audience.call(claims)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.retrieve_audience= value
|
41
|
+
@retrieve_audience = value
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.retrieve_subject claims = nil
|
45
|
+
if block_given?
|
46
|
+
@retrieve_subject = Proc.new
|
47
|
+
else
|
48
|
+
@retrieve_subject.call(claims)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.retrieve_subject= value
|
53
|
+
@retrieve_subject = value
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.validate_token token = nil
|
57
|
+
if block_given?
|
58
|
+
@validate_token = Proc.new
|
59
|
+
else
|
60
|
+
@validate_token.call(token)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.validate_token= value
|
65
|
+
@validate_token = value
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.decode(token)
|
69
|
+
new(token)
|
70
|
+
end
|
71
|
+
|
72
|
+
def scope_includes?(*scope_parts)
|
73
|
+
!scope_parts.empty? && (
|
74
|
+
scope_parts = scope_parts.dup.map(&:to_s)
|
75
|
+
verbs_matches = self.class.verbs_matches(scope_parts.pop)
|
76
|
+
|
77
|
+
(0..scope_parts.length).any? do |depth|
|
78
|
+
verbs_matches.any? do |verb|
|
79
|
+
(scope_parts[0...depth] + [verb]).inject(scopes) do |m, v|
|
80
|
+
m&.[](v)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
87
|
+
def scope_includes!(*scope_parts)
|
88
|
+
scope_includes?(*scope_parts) || fail(JWTUnauthorized)
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.verbs_matches(verb)
|
92
|
+
verb_index = SCOPE_VERBS.index(verb)
|
93
|
+
verb_index ? SCOPE_VERBS[verb_index..-1] : []
|
94
|
+
end
|
95
|
+
|
96
|
+
def for_site?
|
97
|
+
audience_is_site? && subject_is_site?
|
98
|
+
end
|
99
|
+
|
100
|
+
def for_site!
|
101
|
+
for_site? || fail(JWTUnauthorized)
|
102
|
+
end
|
103
|
+
|
104
|
+
def for_user?
|
105
|
+
audience_is_site? && (subject_is_user? || subject_is_imposter?)
|
106
|
+
end
|
107
|
+
|
108
|
+
def audience_is_site?
|
109
|
+
audience.respond_to?(:is_real_savvy_site?) &&
|
110
|
+
audience.is_real_savvy_site?
|
111
|
+
end
|
112
|
+
|
113
|
+
def subject_is_user?
|
114
|
+
subject.respond_to?(:is_real_savvy_user?) &&
|
115
|
+
subject.is_real_savvy_user?
|
116
|
+
end
|
117
|
+
|
118
|
+
def subject_is_imposter?
|
119
|
+
subject.respond_to?(:is_real_savvy_imposter?) &&
|
120
|
+
subject.is_real_savvy_imposter?
|
121
|
+
end
|
122
|
+
|
123
|
+
def subject_is_site?
|
124
|
+
subject.respond_to?(:is_real_savvy_site?) &&
|
125
|
+
subject.is_real_savvy_site?
|
126
|
+
end
|
127
|
+
|
128
|
+
def for_user!
|
129
|
+
for_user? || fail(JWTUnauthorized)
|
130
|
+
end
|
131
|
+
|
132
|
+
def valid?
|
133
|
+
claims && claims.length > 0 && (for_site? || for_user?) && self.class.validate_token(token)
|
134
|
+
end
|
135
|
+
|
136
|
+
def imposter?
|
137
|
+
@imposter ? true : false
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
attr_reader :claims, :audience, :subject
|
143
|
+
|
144
|
+
def retrieve_claims
|
145
|
+
@claims = ::JWT.decode(
|
146
|
+
token,
|
147
|
+
self.class.public_key,
|
148
|
+
true,
|
149
|
+
algorithm: 'RS256',
|
150
|
+
).first
|
151
|
+
rescue ::JWT::DecodeError => e
|
152
|
+
raise RealSavvy::JWT::BadCredentials.new(e.message)
|
153
|
+
end
|
154
|
+
|
155
|
+
def retrieve_audience
|
156
|
+
@audience = self.class.retrieve_audience(claims) if claims
|
157
|
+
end
|
158
|
+
|
159
|
+
def retrieve_subject
|
160
|
+
@subject = self.class.retrieve_subject(claims) if claims
|
161
|
+
end
|
162
|
+
|
163
|
+
def retrieve_site
|
164
|
+
@site = audience
|
165
|
+
end
|
166
|
+
|
167
|
+
def retrieve_user
|
168
|
+
if subject_is_user?
|
169
|
+
@user = subject
|
170
|
+
elsif subject_is_imposter?
|
171
|
+
@user = subject.user
|
172
|
+
@imposter = true
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def raw_scopes
|
177
|
+
claims&.fetch('scopes', nil).to_a
|
178
|
+
end
|
179
|
+
|
180
|
+
def retrieve_scopes
|
181
|
+
@scopes = raw_scopes.each_with_object({}) do |scope, result|
|
182
|
+
scope.split(':').inject(result) { |m, v| m[v] ||= {} }
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
data/lib/real_savvy/version.rb
CHANGED
data/real_savvy.gemspec
CHANGED
@@ -23,9 +23,11 @@ Gem::Specification.new do |spec|
|
|
23
23
|
|
24
24
|
spec.add_runtime_dependency 'faraday', ">= 0.10.0"
|
25
25
|
spec.add_runtime_dependency 'faraday_middleware', ">= 0.10.0"
|
26
|
+
spec.add_runtime_dependency 'jwt', ">= 1.0.0"
|
26
27
|
|
27
28
|
spec.add_development_dependency "bundler", "~> 1.14"
|
28
29
|
spec.add_development_dependency "rake", "~> 10.0"
|
29
30
|
spec.add_development_dependency "rspec", "~> 3.0"
|
30
31
|
spec.add_development_dependency "pry", "~> 0.10"
|
32
|
+
spec.add_development_dependency "rspec_junit_formatter", "~> 0.3"
|
31
33
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: real_savvy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Rauh
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2018-
|
13
|
+
date: 2018-03-14 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: faraday
|
@@ -40,6 +40,20 @@ dependencies:
|
|
40
40
|
- - ">="
|
41
41
|
- !ruby/object:Gem::Version
|
42
42
|
version: 0.10.0
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: jwt
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: 1.0.0
|
50
|
+
type: :runtime
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 1.0.0
|
43
57
|
- !ruby/object:Gem::Dependency
|
44
58
|
name: bundler
|
45
59
|
requirement: !ruby/object:Gem::Requirement
|
@@ -96,14 +110,30 @@ dependencies:
|
|
96
110
|
- - "~>"
|
97
111
|
- !ruby/object:Gem::Version
|
98
112
|
version: '0.10'
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: rspec_junit_formatter
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - "~>"
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0.3'
|
120
|
+
type: :development
|
121
|
+
prerelease: false
|
122
|
+
version_requirements: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - "~>"
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0.3'
|
99
127
|
description: A gem for connecting to RealSavvy V3 API
|
100
128
|
email: andrew@realsavvy.com
|
101
129
|
executables: []
|
102
130
|
extensions: []
|
103
131
|
extra_rdoc_files: []
|
104
132
|
files:
|
133
|
+
- ".circleci/config.yml"
|
105
134
|
- ".gitignore"
|
106
135
|
- Gemfile
|
136
|
+
- Gemfile.lock
|
107
137
|
- LICENSE.txt
|
108
138
|
- bin/console
|
109
139
|
- bin/setup
|
@@ -115,7 +145,7 @@ files:
|
|
115
145
|
- lib/real_savvy/adapter/base.rb
|
116
146
|
- lib/real_savvy/adapter/broker_office.rb
|
117
147
|
- lib/real_savvy/adapter/collection.rb
|
118
|
-
- lib/real_savvy/adapter/
|
148
|
+
- lib/real_savvy/adapter/market.rb
|
119
149
|
- lib/real_savvy/adapter/open_house.rb
|
120
150
|
- lib/real_savvy/adapter/property.rb
|
121
151
|
- lib/real_savvy/adapter/saved_search.rb
|
@@ -134,6 +164,13 @@ files:
|
|
134
164
|
- lib/real_savvy/concern/update_for_adapter.rb
|
135
165
|
- lib/real_savvy/connection.rb
|
136
166
|
- lib/real_savvy/document.rb
|
167
|
+
- lib/real_savvy/jwt.rb
|
168
|
+
- lib/real_savvy/jwt/bad_credentials.rb
|
169
|
+
- lib/real_savvy/jwt/imposter.rb
|
170
|
+
- lib/real_savvy/jwt/site.rb
|
171
|
+
- lib/real_savvy/jwt/token.rb
|
172
|
+
- lib/real_savvy/jwt/unauthorized.rb
|
173
|
+
- lib/real_savvy/jwt/user.rb
|
137
174
|
- lib/real_savvy/links.rb
|
138
175
|
- lib/real_savvy/meta.rb
|
139
176
|
- lib/real_savvy/resource.rb
|