namely 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +51 -0
  6. data/LICENSE +22 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +125 -0
  9. data/Rakefile +16 -0
  10. data/lib/namely.rb +114 -0
  11. data/lib/namely/authenticator.rb +164 -0
  12. data/lib/namely/country.rb +9 -0
  13. data/lib/namely/currency_type.rb +9 -0
  14. data/lib/namely/event.rb +9 -0
  15. data/lib/namely/exceptions.rb +13 -0
  16. data/lib/namely/field.rb +9 -0
  17. data/lib/namely/job_tier.rb +9 -0
  18. data/lib/namely/profile.rb +13 -0
  19. data/lib/namely/report.rb +9 -0
  20. data/lib/namely/resource_gateway.rb +81 -0
  21. data/lib/namely/restful_model.rb +150 -0
  22. data/lib/namely/version.rb +3 -0
  23. data/namely.gemspec +30 -0
  24. data/spec/fixtures/vcr_cassettes/country_head.yml +51 -0
  25. data/spec/fixtures/vcr_cassettes/country_head_missing.yml +50 -0
  26. data/spec/fixtures/vcr_cassettes/country_index.yml +121 -0
  27. data/spec/fixtures/vcr_cassettes/country_show.yml +68 -0
  28. data/spec/fixtures/vcr_cassettes/country_show_missing.yml +54 -0
  29. data/spec/fixtures/vcr_cassettes/currencytype_index.yml +64 -0
  30. data/spec/fixtures/vcr_cassettes/event_head.yml +51 -0
  31. data/spec/fixtures/vcr_cassettes/event_head_missing.yml +50 -0
  32. data/spec/fixtures/vcr_cassettes/event_index.yml +88 -0
  33. data/spec/fixtures/vcr_cassettes/event_show.yml +62 -0
  34. data/spec/fixtures/vcr_cassettes/event_show_missing.yml +54 -0
  35. data/spec/fixtures/vcr_cassettes/field_index.yml +207 -0
  36. data/spec/fixtures/vcr_cassettes/jobtier_index.yml +103 -0
  37. data/spec/fixtures/vcr_cassettes/profile_create.yml +85 -0
  38. data/spec/fixtures/vcr_cassettes/profile_create_failed.yml +54 -0
  39. data/spec/fixtures/vcr_cassettes/profile_head.yml +51 -0
  40. data/spec/fixtures/vcr_cassettes/profile_head_missing.yml +50 -0
  41. data/spec/fixtures/vcr_cassettes/profile_index.yml +979 -0
  42. data/spec/fixtures/vcr_cassettes/profile_show.yml +91 -0
  43. data/spec/fixtures/vcr_cassettes/profile_show_missing.yml +54 -0
  44. data/spec/fixtures/vcr_cassettes/profile_show_updated.yml +91 -0
  45. data/spec/fixtures/vcr_cassettes/profile_update.yml +95 -0
  46. data/spec/fixtures/vcr_cassettes/profile_update_revert.yml +95 -0
  47. data/spec/fixtures/vcr_cassettes/report_head.yml +51 -0
  48. data/spec/fixtures/vcr_cassettes/report_head_missing.yml +50 -0
  49. data/spec/fixtures/vcr_cassettes/report_show.yml +185 -0
  50. data/spec/fixtures/vcr_cassettes/report_show_missing.yml +54 -0
  51. data/spec/fixtures/vcr_cassettes/token.yml +57 -0
  52. data/spec/fixtures/vcr_cassettes/token_refresh.yml +57 -0
  53. data/spec/namely/authenticator_spec.rb +143 -0
  54. data/spec/namely/configuration_spec.rb +33 -0
  55. data/spec/namely/country_spec.rb +11 -0
  56. data/spec/namely/currency_type_spec.rb +5 -0
  57. data/spec/namely/event_spec.rb +11 -0
  58. data/spec/namely/field_spec.rb +5 -0
  59. data/spec/namely/job_tier_spec.rb +5 -0
  60. data/spec/namely/profile_spec.rb +25 -0
  61. data/spec/namely/report_spec.rb +8 -0
  62. data/spec/namely/resource_gateway_spec.rb +93 -0
  63. data/spec/shared_examples/a_model_with_a_create_action.rb +24 -0
  64. data/spec/shared_examples/a_model_with_a_show_action.rb +38 -0
  65. data/spec/shared_examples/a_model_with_an_index_action.rb +17 -0
  66. data/spec/shared_examples/a_model_with_an_update_action.rb +37 -0
  67. data/spec/spec_helper.rb +49 -0
  68. metadata +280 -0
@@ -0,0 +1,50 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: head
5
+ uri: https://<TEST_SUBDOMAIN>.namely.com/api/v1/reports/this-is-almost-certainly-not-the-id-of-any-model?access_token=<TEST_ACCESS_TOKEN>
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/json
12
+ Accept-Encoding:
13
+ - gzip, deflate
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 404
19
+ message: Not Found
20
+ headers:
21
+ Cache-Control:
22
+ - no-cache
23
+ Content-Encoding:
24
+ - gzip
25
+ Content-Type:
26
+ - application/json; charset=utf-8
27
+ Date:
28
+ - Tue, 04 Nov 2014 16:34:50 GMT
29
+ Server:
30
+ - nginx/1.6.2
31
+ Status:
32
+ - 404 Not Found
33
+ Strict-Transport-Security:
34
+ - max-age=31536000
35
+ Vary:
36
+ - Accept-Encoding
37
+ X-Rack-Cache:
38
+ - miss
39
+ X-Request-Id:
40
+ - d7d37c67-ed05-4344-a6ff-cdfdf35552cc
41
+ X-Runtime:
42
+ - '0.024991'
43
+ Connection:
44
+ - keep-alive
45
+ body:
46
+ encoding: UTF-8
47
+ string: ''
48
+ http_version:
49
+ recorded_at: Tue, 04 Nov 2014 16:34:50 GMT
50
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,185 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://<TEST_SUBDOMAIN>.namely.com/api/v1/reports/bbf089f6-90c5-473c-8928-058014a462c9?access_token=<TEST_ACCESS_TOKEN>
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/json
12
+ Accept-Encoding:
13
+ - gzip, deflate
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Cache-Control:
22
+ - max-age=0, private, must-revalidate
23
+ Content-Encoding:
24
+ - gzip
25
+ Content-Type:
26
+ - application/json; charset=utf-8
27
+ Date:
28
+ - Tue, 04 Nov 2014 16:34:49 GMT
29
+ Server:
30
+ - nginx
31
+ Status:
32
+ - 200 OK
33
+ Strict-Transport-Security:
34
+ - max-age=31536000
35
+ - max-age=31536000; includeSubDomains;
36
+ Vary:
37
+ - Accept-Encoding
38
+ X-Rack-Cache:
39
+ - miss
40
+ X-Request-Id:
41
+ - 977b6e70-4437-4f03-b138-0dc56ceafea1
42
+ X-Runtime:
43
+ - '0.114426'
44
+ Content-Length:
45
+ - '5918'
46
+ Connection:
47
+ - keep-alive
48
+ body:
49
+ encoding: ASCII-8BIT
50
+ string: !binary |-
51
+ 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
182
+ U0igsPD3Bmz+hCAdb/kvtPocsn5oAAA=
183
+ http_version:
184
+ recorded_at: Tue, 04 Nov 2014 16:34:49 GMT
185
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,54 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://<TEST_SUBDOMAIN>.namely.com/api/v1/reports/this-is-almost-certainly-not-the-id-of-any-model?access_token=<TEST_ACCESS_TOKEN>
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/json
12
+ Accept-Encoding:
13
+ - gzip, deflate
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 404
19
+ message: Not Found
20
+ headers:
21
+ Cache-Control:
22
+ - no-cache
23
+ Content-Encoding:
24
+ - gzip
25
+ Content-Type:
26
+ - application/json; charset=utf-8
27
+ Date:
28
+ - Tue, 04 Nov 2014 16:34:49 GMT
29
+ Server:
30
+ - nginx/1.6.2
31
+ Status:
32
+ - 404 Not Found
33
+ Strict-Transport-Security:
34
+ - max-age=31536000
35
+ Vary:
36
+ - Accept-Encoding
37
+ X-Rack-Cache:
38
+ - miss
39
+ X-Request-Id:
40
+ - 52e1e643-65de-487a-8b28-2be8291d2f1b
41
+ X-Runtime:
42
+ - '0.025837'
43
+ Content-Length:
44
+ - '64'
45
+ Connection:
46
+ - keep-alive
47
+ body:
48
+ encoding: ASCII-8BIT
49
+ string: !binary |-
50
+ H4sIAAAAAAAAA6tWyk0tLk5MT1WyUgpKLcgvKlHIyy9RSMsvzUtR0lFKLSrK
51
+ LypWssorzcmpBQBUHrxBLAAAAA==
52
+ http_version:
53
+ recorded_at: Tue, 04 Nov 2014 16:34:49 GMT
54
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,57 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://<TEST_SUBDOMAIN>.namely.com/api/v1/oauth2/token?redirect_uri=<CLIENT_REDIRECT_URI>
6
+ body:
7
+ encoding: US-ASCII
8
+ string: grant_type=authorization_code&client_id=<CLIENT_ID>&client_secret=<CLIENT_SECRET>&code=<AUTH_CODE>
9
+ headers:
10
+ Accept:
11
+ - "*/*; q=0.5, application/xml"
12
+ Accept-Encoding:
13
+ - gzip, deflate
14
+ Content-Length:
15
+ - '189'
16
+ Content-Type:
17
+ - application/x-www-form-urlencoded
18
+ User-Agent:
19
+ - Ruby
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Cache-Control:
26
+ - no-store
27
+ Content-Type:
28
+ - application/json
29
+ Date:
30
+ - Tue, 04 Nov 2014 16:38:10 GMT
31
+ Etag:
32
+ - '"fc3490b779796351d40312ba491c69c2"'
33
+ Pragma:
34
+ - no-cache
35
+ Server:
36
+ - nginx
37
+ Status:
38
+ - 200 OK
39
+ Strict-Transport-Security:
40
+ - max-age=31536000
41
+ - max-age=31536000; includeSubDomains;
42
+ X-Rack-Cache:
43
+ - invalidate, pass
44
+ X-Request-Id:
45
+ - 386d8523-f838-4023-a096-f74bc6c6291e
46
+ X-Runtime:
47
+ - '0.059499'
48
+ Content-Length:
49
+ - '141'
50
+ Connection:
51
+ - keep-alive
52
+ body:
53
+ encoding: UTF-8
54
+ string: '{"access_token":"<%= access_token %>","refresh_token":"<%= refresh_token %>","token_type":"bearer","expires_in":899}'
55
+ http_version:
56
+ recorded_at: Tue, 04 Nov 2014 16:38:11 GMT
57
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,57 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://<TEST_SUBDOMAIN>.namely.com/api/v1/oauth2/token?redirect_uri=<CLIENT_REDIRECT_URI>
6
+ body:
7
+ encoding: US-ASCII
8
+ string: grant_type=refresh_token&client_id=<CLIENT_ID>&client_secret=<CLIENT_SECRET>&refresh_token=<TEST_REFRESH_TOKEN>
9
+ headers:
10
+ Accept:
11
+ - "*/*; q=0.5, application/xml"
12
+ Accept-Encoding:
13
+ - gzip, deflate
14
+ Content-Length:
15
+ - '193'
16
+ Content-Type:
17
+ - application/x-www-form-urlencoded
18
+ User-Agent:
19
+ - Ruby
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Cache-Control:
26
+ - no-store
27
+ Content-Type:
28
+ - application/json
29
+ Date:
30
+ - Tue, 04 Nov 2014 17:06:29 GMT
31
+ Etag:
32
+ - '"c4566dc1eddea53969e88a3bc69cdfb3"'
33
+ Pragma:
34
+ - no-cache
35
+ Server:
36
+ - nginx/1.6.2
37
+ Status:
38
+ - 200 OK
39
+ Strict-Transport-Security:
40
+ - max-age=31536000
41
+ - max-age=31536000; includeSubDomains;
42
+ X-Rack-Cache:
43
+ - invalidate, pass
44
+ X-Request-Id:
45
+ - e2d5a360-d44d-4198-8528-ceb6ad91bd6c
46
+ X-Runtime:
47
+ - '0.045489'
48
+ Content-Length:
49
+ - '90'
50
+ Connection:
51
+ - keep-alive
52
+ body:
53
+ encoding: UTF-8
54
+ string: '{"access_token":"<%= access_token %>","token_type":"bearer","expires_in":899}'
55
+ http_version:
56
+ recorded_at: Tue, 04 Nov 2014 17:06:29 GMT
57
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,143 @@
1
+ require "spec_helper"
2
+ require "cgi"
3
+ require "uri"
4
+
5
+ describe Namely::Authenticator do
6
+ describe "#auth_code_url" do
7
+ it "returns a URL to begin the authorization code URL flow" do
8
+ authenticator = described_class.new(
9
+ client_id: "MY_CLIENT_ID",
10
+ client_secret: "MY_CLIENT_SECRET",
11
+ )
12
+
13
+ authorization_code_url = authenticator.authorization_code_url(
14
+ subdomain: "ellingsonmineral",
15
+ redirect_uri: "http://www.example.com/authenticated",
16
+ )
17
+
18
+ parsed_uri = URI(authorization_code_url)
19
+ parsed_query = CGI.parse(parsed_uri.query)
20
+ expect(parsed_uri.scheme).to eq "https"
21
+ expect(parsed_uri.host).to eq "ellingsonmineral.namely.com"
22
+ expect(parsed_uri.path).to eq "/api/v1/oauth2/authorize"
23
+ expect(parsed_query).to eq(
24
+ "response_type" => ["code"],
25
+ "approve" => ["true"],
26
+ "client_id" => ["MY_CLIENT_ID"],
27
+ "redirect_uri" => ["http://www.example.com/authenticated"],
28
+ )
29
+ end
30
+
31
+ it "allows the redirect_uri to be omitted" do
32
+ authenticator = described_class.new(
33
+ client_id: "MY_CLIENT_ID",
34
+ client_secret: "MY_CLIENT_SECRET",
35
+ )
36
+
37
+ authorization_code_url = authenticator.authorization_code_url(
38
+ subdomain: "ellingsonmineral",
39
+ )
40
+
41
+ parsed_uri = URI(authorization_code_url)
42
+ parsed_query = CGI.parse(parsed_uri.query)
43
+ expect(parsed_query).to eq(
44
+ "response_type" => ["code"],
45
+ "approve" => ["true"],
46
+ "client_id" => ["MY_CLIENT_ID"],
47
+ )
48
+ end
49
+
50
+ it "escapes reserved characters in query parameters" do
51
+ authenticator = described_class.new(
52
+ client_id: "MY_CLIENT_ID",
53
+ client_secret: "MY_CLIENT_SECRET",
54
+ )
55
+ redirect_uri = "http://example.com/?auth=true&provider=namely"
56
+
57
+ authorization_code_url = authenticator.authorization_code_url(
58
+ subdomain: "ellingsonmineral",
59
+ redirect_uri: redirect_uri,
60
+ )
61
+
62
+ parsed_uri = URI(authorization_code_url)
63
+ parsed_query = CGI.parse(parsed_uri.query)
64
+ expect(parsed_query["redirect_uri"]).to eq [redirect_uri]
65
+ end
66
+
67
+ it "allows the host and protocol to be overridden" do
68
+ authenticator = described_class.new(
69
+ client_id: "MY_CLIENT_ID",
70
+ client_secret: "MY_CLIENT_SECRET",
71
+ )
72
+
73
+ authorization_code_url = authenticator.authorization_code_url(
74
+ protocol: "http",
75
+ host: "testing.example.com",
76
+ )
77
+
78
+ parsed_uri = URI(authorization_code_url)
79
+ expect(parsed_uri.scheme).to eq "http"
80
+ expect(parsed_uri.host).to eq "testing.example.com"
81
+ end
82
+ end
83
+
84
+ describe "#retrieve_tokens" do
85
+ it "exchanges an authorization code for access and refresh tokens" do
86
+ erb_settings = {
87
+ erb: {
88
+ access_token: "MY_ACCESS_TOKEN",
89
+ refresh_token: "MY_REFRESH_TOKEN",
90
+ }
91
+ }
92
+
93
+ VCR.use_cassette("token", erb_settings) do
94
+ authenticator = described_class.new(
95
+ client_id: ENV.fetch("CLIENT_ID"),
96
+ client_secret: ENV.fetch("CLIENT_SECRET"),
97
+ )
98
+
99
+ tokens = authenticator.retrieve_tokens(
100
+ subdomain: ENV.fetch("TEST_SUBDOMAIN"),
101
+ code: ENV.fetch("AUTH_CODE"),
102
+ redirect_uri: ENV.fetch("CLIENT_REDIRECT_URI"),
103
+ )
104
+
105
+ expect(tokens).to eq(
106
+ "access_token" => "MY_ACCESS_TOKEN",
107
+ "refresh_token" => "MY_REFRESH_TOKEN",
108
+ "expires_in" => 899,
109
+ "token_type" => "bearer",
110
+ )
111
+ end
112
+ end
113
+ end
114
+
115
+ describe "#refresh_access_token" do
116
+ it "uses a refresh token to retrieve a new access token" do
117
+ erb_settings = {
118
+ erb: {
119
+ access_token: "MY_ACCESS_TOKEN",
120
+ }
121
+ }
122
+
123
+ VCR.use_cassette("token_refresh", erb_settings) do
124
+ authenticator = described_class.new(
125
+ client_id: ENV.fetch("CLIENT_ID"),
126
+ client_secret: ENV.fetch("CLIENT_SECRET"),
127
+ )
128
+
129
+ tokens = authenticator.refresh_access_token(
130
+ subdomain: ENV.fetch("TEST_SUBDOMAIN"),
131
+ refresh_token: ENV.fetch("TEST_REFRESH_TOKEN"),
132
+ redirect_uri: ENV.fetch("CLIENT_REDIRECT_URI"),
133
+ )
134
+
135
+ expect(tokens).to eq(
136
+ "access_token" => "MY_ACCESS_TOKEN",
137
+ "expires_in" => 899,
138
+ "token_type" => "bearer",
139
+ )
140
+ end
141
+ end
142
+ end
143
+ end