litmus-instant 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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