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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4ec995c778fa1380bda1308281b30d8d143ad78a
4
- data.tar.gz: a87ce301ef34291b8c1679c2c9c01cad51453631
3
+ metadata.gz: f7b745a34a03293650d40a5d016eaca8eaa520cd
4
+ data.tar.gz: 3f7a21b2a041fc50f51fc9dd3d88525cfeeb8e21
5
5
  SHA512:
6
- metadata.gz: 2ba195c43226ec745e1d345675cd5ebaa00c0b0c08e6e1536e5dce6f8dcddf695bb89974b9f1e3e2ab02c6d4897ac715097c0a905af49f3c6d3c7145dcd8ca63
7
- data.tar.gz: 02c061df9794ec1ba497fbda7e593c9fc80e5dae445b5517a902a49f86cf00fbee24ca091de265de77449365a2d1ce78c28e7f61ebb20b5c4dafe0bfae18bf85
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
@@ -1,6 +1,5 @@
1
1
  /.bundle/
2
2
  /.yardoc
3
- /Gemfile.lock
4
3
  /_yardoc/
5
4
  /coverage/
6
5
  /doc/
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
@@ -12,3 +12,4 @@ module RealSavvy
12
12
  end
13
13
 
14
14
  require 'real_savvy/client'
15
+ require 'real_savvy/jwt'
File without changes
@@ -0,0 +1,8 @@
1
+ require 'jwt'
2
+
3
+ module RealSavvy::JWT
4
+
5
+ end
6
+
7
+ require 'real_savvy/jwt/token'
8
+ Dir[File.dirname(__FILE__) + '/jwt/*.rb'].each {|file| require file }
@@ -0,0 +1,6 @@
1
+ module RealSavvy
2
+ module JWT
3
+ class BadCredentials < StandardError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,9 @@
1
+ module RealSavvy
2
+ module JWT
3
+ module Imposter
4
+ def is_real_savvy_imposter
5
+ true
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module RealSavvy
2
+ module JWT
3
+ module Site
4
+ def is_real_savvy_site?
5
+ true
6
+ end
7
+ end
8
+ end
9
+ end
@@ -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
@@ -0,0 +1,6 @@
1
+ module RealSavvy
2
+ module JWT
3
+ class Unauthorized < StandardError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,9 @@
1
+ module RealSavvy
2
+ module JWT
3
+ module User
4
+ def is_real_savvy_user?
5
+ true
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,3 +1,3 @@
1
1
  module RealSavvy
2
- VERSION = [0,0,3]
2
+ VERSION = [0,0,4]
3
3
  end
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.3
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-02-12 00:00:00.000000000 Z
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/markets.rb
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