litmus-instant 0.1.0 → 0.2.0

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.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/Procfile +1 -0
  4. data/README.md +15 -0
  5. data/examples/Gemfile +1 -0
  6. data/examples/Gemfile.lock +3 -2
  7. data/examples/README.md +2 -0
  8. data/examples/config.ru +2 -0
  9. data/fixtures/vcr_cassettes/Litmus_Instant/Litmus_Instant_Client_provides_Litmus_Instant_class_methods_as_instance_methods.yml +191 -0
  10. data/fixtures/vcr_cassettes/Litmus_Instant/Litmus_Instant_Client_uses_its_own_config.yml +85 -0
  11. data/fixtures/vcr_cassettes/Litmus_Instant/client_configurations/returns_a_Hash_of_clients_and_their_available_options.yml +107 -11
  12. data/fixtures/vcr_cassettes/Litmus_Instant/clients/returns_an_array_of_client_names.yml +15 -4
  13. data/fixtures/vcr_cassettes/Litmus_Instant/create_email/authenticated_with_invalid_email_Hash_raise_a_request_error.yml +5 -41
  14. data/fixtures/vcr_cassettes/Litmus_Instant/create_email/authenticated_with_valid_email_Hash_optional_end_user_id_is_relayed.yml +6 -4
  15. data/fixtures/vcr_cassettes/Litmus_Instant/create_email/authenticated_with_valid_email_Hash_prerequest_configurations_is_relayed.yml +6 -4
  16. data/fixtures/vcr_cassettes/Litmus_Instant/create_email/authenticated_with_valid_email_Hash_response_.yml +6 -42
  17. data/fixtures/vcr_cassettes/Litmus_Instant/create_email/unauthenticated_raises_an_authentication_error.yml +5 -5
  18. data/fixtures/vcr_cassettes/Litmus_Instant/get_preview/raises_NotFound_for_an_expired_email_guid.yml +2 -1630
  19. data/fixtures/vcr_cassettes/Litmus_Instant/get_preview/raises_RequestError_for_an_invalid_client.yml +9 -7
  20. data/fixtures/vcr_cassettes/Litmus_Instant/get_preview/raises_RequestError_for_an_invalid_email_guid.yml +2 -2
  21. data/fixtures/vcr_cassettes/Litmus_Instant/get_preview/returns_a_Hash_of_the_image_types.yml +13 -11
  22. data/fixtures/vcr_cassettes/Litmus_Instant/get_preview/supports_optional_capture_configuration.yml +13 -47
  23. data/fixtures/vcr_cassettes/Litmus_Instant/prefetch_previews/raises_RequestError_for_an_invalid_email_guid.yml +2 -2
  24. data/fixtures/vcr_cassettes/Litmus_Instant/prefetch_previews/raises_RequestError_if_any_invalid_configurations_are_present.yml +11 -9
  25. data/fixtures/vcr_cassettes/Litmus_Instant/prefetch_previews/responds_with_an_array_of_the_requested_configurations.yml +9 -7
  26. data/lib/litmus/instant.rb +106 -13
  27. data/lib/litmus/instant/version.rb +2 -2
  28. metadata +7 -4
@@ -2,7 +2,7 @@
2
2
  http_interactions:
3
3
  - request:
4
4
  method: post
5
- uri: https://<API_KEY>:@instant-api.litmus.com/v1/emails
5
+ uri: https://instant-api.litmus.com/v1/emails
6
6
  body:
7
7
  encoding: UTF-8
8
8
  string: '{"plain_text":"Hej världen! Kärlek, den svenska kocken."}'
@@ -11,6 +11,8 @@ http_interactions:
11
11
  - application/json
12
12
  Accept:
13
13
  - application/json
14
+ Authorization:
15
+ - Basic Y3hkNHR1c3F3b2tnZ2dseGl6ZDl2cDd6bXV4dmo2eG95a2UxOg==
14
16
  response:
15
17
  status:
16
18
  code: 200
@@ -19,7 +21,7 @@ http_interactions:
19
21
  Server:
20
22
  - nginx
21
23
  Date:
22
- - Tue, 06 Oct 2015 10:40:05 GMT
24
+ - Mon, 20 Jun 2016 11:43:50 GMT
23
25
  Content-Type:
24
26
  - application/json;charset=utf-8
25
27
  Content-Length:
@@ -36,13 +38,13 @@ http_interactions:
36
38
  encoding: UTF-8
37
39
  string: |-
38
40
  {
39
- "email_guid": "6c8862e2-b10d-4753-85d8-340c91c0b071"
41
+ "email_guid": "92d9cb6d-6ea0-4b46-813c-3025214f80fd"
40
42
  }
41
43
  http_version:
42
- recorded_at: Tue, 06 Oct 2015 10:40:39 GMT
44
+ recorded_at: Mon, 20 Jun 2016 11:43:52 GMT
43
45
  - request:
44
46
  method: get
45
- uri: https://instant-api.litmus.com/v1/emails/6c8862e2-b10d-4753-85d8-340c91c0b071/previews/OL2001MYSPACEODYSSEY
47
+ uri: https://instant-api.litmus.com/v1/emails/92d9cb6d-6ea0-4b46-813c-3025214f80fd/previews/OL2001MYSPACEODYSSEY
46
48
  body:
47
49
  encoding: US-ASCII
48
50
  string: ''
@@ -59,7 +61,7 @@ http_interactions:
59
61
  Server:
60
62
  - nginx
61
63
  Date:
62
- - Tue, 06 Oct 2015 10:40:36 GMT
64
+ - Mon, 20 Jun 2016 11:43:50 GMT
63
65
  Content-Type:
64
66
  - application/json;charset=utf-8
65
67
  Content-Length:
@@ -75,5 +77,5 @@ http_interactions:
75
77
  "description": "'client' must be valid, see /clients"
76
78
  }
77
79
  http_version:
78
- recorded_at: Tue, 06 Oct 2015 10:40:40 GMT
80
+ recorded_at: Mon, 20 Jun 2016 11:43:53 GMT
79
81
  recorded_with: VCR 2.9.3
@@ -19,7 +19,7 @@ http_interactions:
19
19
  Server:
20
20
  - nginx
21
21
  Date:
22
- - Tue, 06 Oct 2015 10:40:35 GMT
22
+ - Mon, 20 Jun 2016 11:43:50 GMT
23
23
  Content-Type:
24
24
  - application/json;charset=utf-8
25
25
  Content-Length:
@@ -35,5 +35,5 @@ http_interactions:
35
35
  "description": "'email_guid' must match format of a standard GUID"
36
36
  }
37
37
  http_version:
38
- recorded_at: Tue, 06 Oct 2015 10:40:38 GMT
38
+ recorded_at: Mon, 20 Jun 2016 11:43:52 GMT
39
39
  recorded_with: VCR 2.9.3
@@ -2,7 +2,7 @@
2
2
  http_interactions:
3
3
  - request:
4
4
  method: post
5
- uri: https://<API_KEY>:@instant-api.litmus.com/v1/emails
5
+ uri: https://instant-api.litmus.com/v1/emails
6
6
  body:
7
7
  encoding: UTF-8
8
8
  string: '{"plain_text":"Hej världen! Kärlek, den svenska kocken."}'
@@ -11,6 +11,8 @@ http_interactions:
11
11
  - application/json
12
12
  Accept:
13
13
  - application/json
14
+ Authorization:
15
+ - Basic Y3hkNHR1c3F3b2tnZ2dseGl6ZDl2cDd6bXV4dmo2eG95a2UxOg==
14
16
  response:
15
17
  status:
16
18
  code: 200
@@ -19,7 +21,7 @@ http_interactions:
19
21
  Server:
20
22
  - nginx
21
23
  Date:
22
- - Tue, 06 Oct 2015 10:40:37 GMT
24
+ - Mon, 20 Jun 2016 11:43:52 GMT
23
25
  Content-Type:
24
26
  - application/json;charset=utf-8
25
27
  Content-Length:
@@ -36,13 +38,13 @@ http_interactions:
36
38
  encoding: UTF-8
37
39
  string: |-
38
40
  {
39
- "email_guid": "6c8862e2-b10d-4753-85d8-340c91c0b071"
41
+ "email_guid": "92d9cb6d-6ea0-4b46-813c-3025214f80fd"
40
42
  }
41
43
  http_version:
42
- recorded_at: Tue, 06 Oct 2015 10:40:41 GMT
44
+ recorded_at: Mon, 20 Jun 2016 11:43:54 GMT
43
45
  - request:
44
46
  method: get
45
- uri: https://instant-api.litmus.com/v1/emails/6c8862e2-b10d-4753-85d8-340c91c0b071/previews/PLAINTEXT
47
+ uri: https://instant-api.litmus.com/v1/emails/92d9cb6d-6ea0-4b46-813c-3025214f80fd/previews/PLAINTEXT
46
48
  body:
47
49
  encoding: US-ASCII
48
50
  string: ''
@@ -59,11 +61,11 @@ http_interactions:
59
61
  Server:
60
62
  - nginx
61
63
  Date:
62
- - Tue, 06 Oct 2015 10:40:09 GMT
64
+ - Mon, 20 Jun 2016 11:43:56 GMT
63
65
  Content-Type:
64
66
  - application/json;charset=utf-8
65
67
  Content-Length:
66
- - '421'
68
+ - '436'
67
69
  Connection:
68
70
  - keep-alive
69
71
  Strict-Transport-Security:
@@ -76,10 +78,10 @@ http_interactions:
76
78
  encoding: UTF-8
77
79
  string: |-
78
80
  {
79
- "full_url": "https://PLAINTEXT.capture.litmuscdn.com/6c8862e2-b10d-4753-85d8-340c91c0b071/results/plaintext-vertical-allowed.png",
80
- "thumb_url": "https://PLAINTEXT.capture.litmuscdn.com/6c8862e2-b10d-4753-85d8-340c91c0b071/results/plaintext-vertical-allowed-thumb.png",
81
- "thumb450_url": "https://PLAINTEXT.capture.litmuscdn.com/6c8862e2-b10d-4753-85d8-340c91c0b071/results/plaintext-vertical-allowed-thumb450.png"
81
+ "full_url": "https://plaintext.capture.litmuscdn.com/92d9cb6d-6ea0-4b46-813c-3025214f80fd/results/plaintext-vertical-allowed-1366.png",
82
+ "thumb_url": "https://plaintext.capture.litmuscdn.com/92d9cb6d-6ea0-4b46-813c-3025214f80fd/results/plaintext-vertical-allowed-1366-thumb.png",
83
+ "thumb450_url": "https://plaintext.capture.litmuscdn.com/92d9cb6d-6ea0-4b46-813c-3025214f80fd/results/plaintext-vertical-allowed-1366-thumb450.png"
82
84
  }
83
85
  http_version:
84
- recorded_at: Tue, 06 Oct 2015 10:40:43 GMT
86
+ recorded_at: Mon, 20 Jun 2016 11:43:58 GMT
85
87
  recorded_with: VCR 2.9.3
@@ -2,7 +2,7 @@
2
2
  http_interactions:
3
3
  - request:
4
4
  method: post
5
- uri: https://<API_KEY>:@instant-api.litmus.com/v1/emails
5
+ uri: https://instant-api.litmus.com/v1/emails
6
6
  body:
7
7
  encoding: UTF-8
8
8
  string: '{"plain_text":"Hej världen! Kärlek, den svenska kocken."}'
@@ -11,6 +11,8 @@ http_interactions:
11
11
  - application/json
12
12
  Accept:
13
13
  - application/json
14
+ Authorization:
15
+ - Basic Y3hkNHR1c3F3b2tnZ2dseGl6ZDl2cDd6bXV4dmo2eG95a2UxOg==
14
16
  response:
15
17
  status:
16
18
  code: 200
@@ -19,7 +21,7 @@ http_interactions:
19
21
  Server:
20
22
  - nginx
21
23
  Date:
22
- - Thu, 08 Oct 2015 15:56:11 GMT
24
+ - Mon, 20 Jun 2016 11:43:56 GMT
23
25
  Content-Type:
24
26
  - application/json;charset=utf-8
25
27
  Content-Length:
@@ -36,49 +38,13 @@ http_interactions:
36
38
  encoding: UTF-8
37
39
  string: |-
38
40
  {
39
- "email_guid": "93b5954d-c7b5-437d-96d9-9ad6c1717f84"
41
+ "email_guid": "92d9cb6d-6ea0-4b46-813c-3025214f80fd"
40
42
  }
41
43
  http_version:
42
- recorded_at: Thu, 08 Oct 2015 15:56:15 GMT
44
+ recorded_at: Mon, 20 Jun 2016 11:43:59 GMT
43
45
  - request:
44
46
  method: get
45
- uri: https://instant-api.litmus.com/v1/emails/93b5954d-c7b5-437d-96d9-9ad6c1717f84/previews/IPAD?images=blocked&orientation=vertical
46
- body:
47
- encoding: US-ASCII
48
- string: ''
49
- headers:
50
- Content-Type:
51
- - application/json
52
- Accept:
53
- - application/json
54
- response:
55
- status:
56
- code: 400
57
- message: Bad Request
58
- headers:
59
- Server:
60
- - nginx
61
- Date:
62
- - Thu, 08 Oct 2015 15:55:40 GMT
63
- Content-Type:
64
- - application/json;charset=utf-8
65
- Content-Length:
66
- - '170'
67
- Connection:
68
- - keep-alive
69
- body:
70
- encoding: UTF-8
71
- string: |-
72
- {
73
- "status": 400,
74
- "title": "Bad Request",
75
- "description": "Invalid client configuration - 'blocked' images option not valid for 'IPAD', see /clients/configurations"
76
- }
77
- http_version:
78
- recorded_at: Thu, 08 Oct 2015 15:56:15 GMT
79
- - request:
80
- method: get
81
- uri: https://instant-api.litmus.com/v1/emails/93b5954d-c7b5-437d-96d9-9ad6c1717f84/previews/OL2010?images=blocked&orientation=vertical
47
+ uri: https://instant-api.litmus.com/v1/emails/92d9cb6d-6ea0-4b46-813c-3025214f80fd/previews/OL2010?images=blocked&orientation=vertical
82
48
  body:
83
49
  encoding: US-ASCII
84
50
  string: ''
@@ -95,11 +61,11 @@ http_interactions:
95
61
  Server:
96
62
  - nginx
97
63
  Date:
98
- - Thu, 08 Oct 2015 15:56:28 GMT
64
+ - Mon, 20 Jun 2016 11:44:04 GMT
99
65
  Content-Type:
100
66
  - application/json;charset=utf-8
101
67
  Content-Length:
102
- - '403'
68
+ - '418'
103
69
  Connection:
104
70
  - keep-alive
105
71
  Strict-Transport-Security:
@@ -112,10 +78,10 @@ http_interactions:
112
78
  encoding: UTF-8
113
79
  string: |-
114
80
  {
115
- "full_url": "https://OL2010.capture.litmuscdn.com/93b5954d-c7b5-437d-96d9-9ad6c1717f84/results/ol2010-vertical-blocked.png",
116
- "thumb_url": "https://OL2010.capture.litmuscdn.com/93b5954d-c7b5-437d-96d9-9ad6c1717f84/results/ol2010-vertical-blocked-thumb.png",
117
- "thumb450_url": "https://OL2010.capture.litmuscdn.com/93b5954d-c7b5-437d-96d9-9ad6c1717f84/results/ol2010-vertical-blocked-thumb450.png"
81
+ "full_url": "https://ol2010.capture.litmuscdn.com/92d9cb6d-6ea0-4b46-813c-3025214f80fd/results/ol2010-vertical-blocked-1366.png",
82
+ "thumb_url": "https://ol2010.capture.litmuscdn.com/92d9cb6d-6ea0-4b46-813c-3025214f80fd/results/ol2010-vertical-blocked-1366-thumb.png",
83
+ "thumb450_url": "https://ol2010.capture.litmuscdn.com/92d9cb6d-6ea0-4b46-813c-3025214f80fd/results/ol2010-vertical-blocked-1366-thumb450.png"
118
84
  }
119
85
  http_version:
120
- recorded_at: Thu, 08 Oct 2015 15:56:32 GMT
86
+ recorded_at: Mon, 20 Jun 2016 11:44:05 GMT
121
87
  recorded_with: VCR 2.9.3
@@ -19,7 +19,7 @@ http_interactions:
19
19
  Server:
20
20
  - nginx
21
21
  Date:
22
- - Tue, 06 Oct 2015 10:40:11 GMT
22
+ - Mon, 20 Jun 2016 11:44:04 GMT
23
23
  Content-Type:
24
24
  - application/json;charset=utf-8
25
25
  Content-Length:
@@ -35,5 +35,5 @@ http_interactions:
35
35
  "description": "'email_guid' must match format of a standard GUID"
36
36
  }
37
37
  http_version:
38
- recorded_at: Tue, 06 Oct 2015 10:40:45 GMT
38
+ recorded_at: Mon, 20 Jun 2016 11:44:07 GMT
39
39
  recorded_with: VCR 2.9.3
@@ -2,7 +2,7 @@
2
2
  http_interactions:
3
3
  - request:
4
4
  method: post
5
- uri: https://<API_KEY>:@instant-api.litmus.com/v1/emails
5
+ uri: https://instant-api.litmus.com/v1/emails
6
6
  body:
7
7
  encoding: UTF-8
8
8
  string: '{"plain_text":"Hej världen! Kärlek, den svenska kocken."}'
@@ -11,6 +11,8 @@ http_interactions:
11
11
  - application/json
12
12
  Accept:
13
13
  - application/json
14
+ Authorization:
15
+ - Basic Y3hkNHR1c3F3b2tnZ2dseGl6ZDl2cDd6bXV4dmo2eG95a2UxOg==
14
16
  response:
15
17
  status:
16
18
  code: 200
@@ -19,7 +21,7 @@ http_interactions:
19
21
  Server:
20
22
  - nginx
21
23
  Date:
22
- - Tue, 06 Oct 2015 10:40:10 GMT
24
+ - Mon, 20 Jun 2016 11:44:03 GMT
23
25
  Content-Type:
24
26
  - application/json;charset=utf-8
25
27
  Content-Length:
@@ -36,13 +38,13 @@ http_interactions:
36
38
  encoding: UTF-8
37
39
  string: |-
38
40
  {
39
- "email_guid": "6c8862e2-b10d-4753-85d8-340c91c0b071"
41
+ "email_guid": "92d9cb6d-6ea0-4b46-813c-3025214f80fd"
40
42
  }
41
43
  http_version:
42
- recorded_at: Tue, 06 Oct 2015 10:40:44 GMT
44
+ recorded_at: Mon, 20 Jun 2016 11:44:06 GMT
43
45
  - request:
44
46
  method: post
45
- uri: https://instant-api.litmus.com/v1/emails/6c8862e2-b10d-4753-85d8-340c91c0b071/previews/prefetch
47
+ uri: https://instant-api.litmus.com/v1/emails/92d9cb6d-6ea0-4b46-813c-3025214f80fd/previews/prefetch
46
48
  body:
47
49
  encoding: UTF-8
48
50
  string: '{"configurations":[{"client":"OL2010"},{"client":"OL2001MYSPACEODYSSEY"}]}'
@@ -59,11 +61,11 @@ http_interactions:
59
61
  Server:
60
62
  - nginx
61
63
  Date:
62
- - Tue, 06 Oct 2015 10:40:41 GMT
64
+ - Mon, 20 Jun 2016 11:44:04 GMT
63
65
  Content-Type:
64
66
  - application/json;charset=utf-8
65
67
  Content-Length:
66
- - '124'
68
+ - '126'
67
69
  Connection:
68
70
  - keep-alive
69
71
  body:
@@ -72,8 +74,8 @@ http_interactions:
72
74
  {
73
75
  "status": 400,
74
76
  "title": "Bad Request",
75
- "description": "Each client must be valid, OL2001MYSPACEODYSSEY is unknown"
77
+ "description": "Each client must be valid, 'OL2001MYSPACEODYSSEY' is unknown"
76
78
  }
77
79
  http_version:
78
- recorded_at: Tue, 06 Oct 2015 10:40:45 GMT
80
+ recorded_at: Mon, 20 Jun 2016 11:44:06 GMT
79
81
  recorded_with: VCR 2.9.3
@@ -2,7 +2,7 @@
2
2
  http_interactions:
3
3
  - request:
4
4
  method: post
5
- uri: https://<API_KEY>:@instant-api.litmus.com/v1/emails
5
+ uri: https://instant-api.litmus.com/v1/emails
6
6
  body:
7
7
  encoding: UTF-8
8
8
  string: '{"plain_text":"Hej världen! Kärlek, den svenska kocken."}'
@@ -11,6 +11,8 @@ http_interactions:
11
11
  - application/json
12
12
  Accept:
13
13
  - application/json
14
+ Authorization:
15
+ - Basic Y3hkNHR1c3F3b2tnZ2dseGl6ZDl2cDd6bXV4dmo2eG95a2UxOg==
14
16
  response:
15
17
  status:
16
18
  code: 200
@@ -19,7 +21,7 @@ http_interactions:
19
21
  Server:
20
22
  - nginx
21
23
  Date:
22
- - Tue, 06 Oct 2015 10:40:42 GMT
24
+ - Mon, 20 Jun 2016 11:44:05 GMT
23
25
  Content-Type:
24
26
  - application/json;charset=utf-8
25
27
  Content-Length:
@@ -36,13 +38,13 @@ http_interactions:
36
38
  encoding: UTF-8
37
39
  string: |-
38
40
  {
39
- "email_guid": "6c8862e2-b10d-4753-85d8-340c91c0b071"
41
+ "email_guid": "92d9cb6d-6ea0-4b46-813c-3025214f80fd"
40
42
  }
41
43
  http_version:
42
- recorded_at: Tue, 06 Oct 2015 10:40:46 GMT
44
+ recorded_at: Mon, 20 Jun 2016 11:44:08 GMT
43
45
  - request:
44
46
  method: post
45
- uri: https://instant-api.litmus.com/v1/emails/6c8862e2-b10d-4753-85d8-340c91c0b071/previews/prefetch
47
+ uri: https://instant-api.litmus.com/v1/emails/92d9cb6d-6ea0-4b46-813c-3025214f80fd/previews/prefetch
46
48
  body:
47
49
  encoding: UTF-8
48
50
  string: '{"configurations":[{"client":"OL2010","images":"allowed"},{"client":"IPAD","orientation":"vertical"}]}'
@@ -59,7 +61,7 @@ http_interactions:
59
61
  Server:
60
62
  - nginx
61
63
  Date:
62
- - Tue, 06 Oct 2015 10:40:43 GMT
64
+ - Mon, 20 Jun 2016 11:44:06 GMT
63
65
  Content-Type:
64
66
  - application/json;charset=utf-8
65
67
  Content-Length:
@@ -84,5 +86,5 @@ http_interactions:
84
86
  ]
85
87
  }
86
88
  http_version:
87
- recorded_at: Tue, 06 Oct 2015 10:40:46 GMT
89
+ recorded_at: Mon, 20 Jun 2016 11:44:08 GMT
88
90
  recorded_with: VCR 2.9.3
@@ -4,7 +4,7 @@ require "uri"
4
4
  require "cgi"
5
5
 
6
6
  module Litmus
7
- module Instant
7
+ class Instant
8
8
  include HTTParty
9
9
 
10
10
  base_uri "https://instant-api.litmus.com/v1"
@@ -16,6 +16,11 @@ module Litmus
16
16
  class ApiError < Error; end
17
17
  class RequestError < ApiError; end
18
18
  class AuthenticationError < ApiError; end
19
+ class AuthorizationError < ApiError; end
20
+ class InvalidOAuthToken < AuthenticationError; end
21
+ class InvalidOAuthScope < AuthorizationError; end
22
+ class InactiveUserError < AuthorizationError; end
23
+
19
24
  class ServiceError < ApiError; end
20
25
  class TimeoutError < ApiError; end
21
26
  class NotFound < ApiError; end
@@ -42,16 +47,64 @@ module Litmus
42
47
  end
43
48
  end
44
49
 
50
+ # This allows us to create API Client instances, useful primarily with
51
+ # OAuth, to set a token for each authorized user in a thread safe manner
52
+ # All the class methods on `Instant` are made available on the instance
53
+ class Client
54
+ class << self
55
+ def new(oauth_token: nil, api_key: nil)
56
+ Class.new(Instant) do |klass|
57
+ extend Forwardable
58
+
59
+ def_delegators(
60
+ :"self.class",
61
+ *(Litmus::Instant.methods - Object.methods)
62
+ )
63
+
64
+ klass.oauth_token = oauth_token if oauth_token
65
+ klass.api_key = api_key if api_key
66
+ end.new
67
+ end
68
+ end
69
+ end
70
+
45
71
  # Get or set your Instant API key
46
72
  # @return [String]
47
- def self.api_key(key=nil)
48
- if key
49
- @key = key
50
- self.basic_auth key, ""
51
- end
73
+ def self.api_key(key = nil)
74
+ self.api_key = key if key
52
75
  @key
53
76
  end
54
- singleton_class.send(:alias_method, :api_key=, :api_key)
77
+
78
+ # Set your Instant API key
79
+ def self.api_key=(key)
80
+ self.default_options.delete :basic_auth
81
+ basic_auth key, "" if key
82
+ @key = key
83
+ end
84
+
85
+ # Get or set a global OAuth token to use
86
+ # This is *not* thread safe, if you intend to authorize multiple end users
87
+ # within the same application use
88
+ #
89
+ # Litmus::Instant::Client.new(oauth_token: "XXX")
90
+ #
91
+ # @return [String]
92
+ def self.oauth_token(token = nil)
93
+ self.api_token = token if token
94
+ @token
95
+ end
96
+
97
+ # Set an OAuth token to be used globally
98
+ # This is *not* thread safe, if you intend to authorize multiple end users
99
+ # within the same application use
100
+ #
101
+ # Litmus::Instant::Client.new(oauth_token: "XXX")
102
+ #
103
+ def self.oauth_token=(token)
104
+ self.default_options[:headers].delete "Authorization"
105
+ self.headers("Authorization" => "Bearer #{token}") if token
106
+ @token = token
107
+ end
55
108
 
56
109
  # Describe an email’s content and metadata and, in exchange, receive an
57
110
  # +email_guid+ required to capture previews of it
@@ -85,6 +138,10 @@ module Litmus
85
138
  # possible. This can be a useful performance optimisation.
86
139
  # See +.prefetch_previews+ for further detail on format.
87
140
  #
141
+ # @param [String] token
142
+ # optional OAuth authentication token when calling on behalf of a Litmus
143
+ # user. This will be different for each OAuth connected user.
144
+ #
88
145
  # @return [Hash] the response containing the +email_guid+ and also
89
146
  # confirmation of +end_user_id+ and +configurations+ if provided
90
147
  def self.create_email(email)
@@ -189,22 +246,37 @@ module Litmus
189
246
  end
190
247
  end
191
248
 
192
- private
249
+ #
250
+ # Private ==================================================================
251
+ #
252
+
253
+ # This deliberately allows for multiple authentication challenges within
254
+ # WWW-Authenticate
255
+ BEARER_REGEX = /Bearer realm=\"([^\"]*)\"\, error=\"(?<name>[^\"]*)\"\, error_description=\"(?<description>[^\"]*)\"/
193
256
 
194
257
  # This avoids browser per domain connection limits
195
258
  def self.sharded_base_uri(client)
196
- base_uri.gsub("://","://#{client}.")
259
+ # only shard where it's supported
260
+ if base_uri =~ /\/\/instant-api/
261
+ base_uri.gsub("://","://#{client}.")
262
+ else
263
+ base_uri
264
+ end
197
265
  end
198
266
 
199
267
  def self.raise_on_failure(response)
200
268
  unless response.success?
201
269
  message = response["description"] || ""
202
270
 
271
+ bearer_error = extract_bearer_error(response.headers)
272
+ raise bearer_error if bearer_error
273
+
203
274
  raise AuthenticationError.new(message) if response.code == 401
204
- raise RequestError.new(message) if response.code == 400
205
- raise NotFound.new(message) if response.code == 404
206
- raise TimeoutError.new(message) if response.code == 504
207
- raise ServiceError.new(message) if response.code == 500
275
+ raise AuthorizationError.new(message) if response.code == 403
276
+ raise RequestError.new(message) if response.code == 400
277
+ raise NotFound.new(message) if response.code == 404
278
+ raise TimeoutError.new(message) if response.code == 504
279
+ raise ServiceError.new(message) if response.code == 500
208
280
 
209
281
  # For all other errors
210
282
  raise ApiError.new(message)
@@ -212,5 +284,26 @@ module Litmus
212
284
 
213
285
  response
214
286
  end
287
+
288
+ def self.extract_bearer_error(headers)
289
+ matches = headers["WWW-Authenticate"] &&
290
+ headers["WWW-Authenticate"].match(BEARER_REGEX)
291
+
292
+ return unless matches
293
+
294
+ name = matches[:name]
295
+ message = matches[:description]
296
+
297
+ klass = case name
298
+ when "invalid_token" then InvalidOAuthToken
299
+ when "invalid_scope" then InvalidOAuthScope
300
+ when "inactive_user" then InactiveUserError
301
+ end
302
+
303
+ klass && klass.new(message)
304
+ end
305
+
306
+ private_constant :BEARER_REGEX
307
+ private_class_method :sharded_base_uri, :raise_on_failure, :extract_bearer_error
215
308
  end
216
309
  end