cronofy 0.0.5 → 0.37.7
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 +5 -5
- data/CHANGELOG.md +262 -0
- data/Gemfile +2 -0
- data/README.md +100 -46
- data/cronofy.gemspec +16 -13
- data/lib/cronofy/api_key.rb +73 -0
- data/lib/cronofy/auth.rb +149 -46
- data/lib/cronofy/client.rb +1928 -72
- data/lib/cronofy/errors.rb +68 -8
- data/lib/cronofy/response_parser.rb +36 -3
- data/lib/cronofy/time_encoding.rb +31 -0
- data/lib/cronofy/types.rb +420 -0
- data/lib/cronofy/version.rb +1 -1
- data/lib/cronofy.rb +68 -4
- data/spec/lib/cronofy/auth_spec.rb +559 -0
- data/spec/lib/cronofy/client_spec.rb +3712 -0
- data/spec/lib/cronofy/date_or_time_spec.rb +12 -0
- data/spec/lib/cronofy/errors_spec.rb +81 -0
- data/spec/lib/cronofy/event_spec.rb +121 -0
- data/spec/response_parser_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -0
- metadata +73 -21
- data/.gitignore +0 -14
- data/.travis.yml +0 -16
- data/script/ci +0 -7
data/lib/cronofy/auth.rb
CHANGED
@@ -1,66 +1,101 @@
|
|
1
1
|
require "oauth2"
|
2
2
|
|
3
3
|
module Cronofy
|
4
|
+
# Internal: Class for dealing with authentication and authorization issues.
|
4
5
|
class Auth
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
:expires_at,
|
9
|
-
:expires_in,
|
10
|
-
:refresh_token
|
11
|
-
|
12
|
-
def initialize(oauth_token)
|
13
|
-
@access_token = oauth_token.token
|
14
|
-
@expires_at = oauth_token.expires_at
|
15
|
-
@expires_in = oauth_token.expires_in
|
16
|
-
@refresh_token = oauth_token.refresh_token
|
17
|
-
end
|
6
|
+
attr_reader :access_token
|
7
|
+
attr_reader :api_key
|
8
|
+
attr_reader :api_client
|
18
9
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
}
|
26
|
-
end
|
27
|
-
end
|
10
|
+
def initialize(options = {})
|
11
|
+
access_token = options[:access_token]
|
12
|
+
client_id = options[:client_id]
|
13
|
+
client_secret = options[:client_secret]
|
14
|
+
data_center = options[:data_center]
|
15
|
+
refresh_token = options[:refresh_token]
|
28
16
|
|
29
|
-
|
17
|
+
@client_credentials_missing = blank?(client_id) || blank?(client_secret)
|
30
18
|
|
31
|
-
|
32
|
-
@
|
33
|
-
@api_client = OAuth2::Client.new(client_id, client_secret, site: ::Cronofy.api_url)
|
19
|
+
@auth_client = OAuth2::Client.new(client_id, client_secret, site: ::Cronofy.app_url(data_center), connection_opts: { headers: { "User-Agent" => "Cronofy Ruby #{::Cronofy::VERSION}" } })
|
20
|
+
@api_client = OAuth2::Client.new(client_id, client_secret, site: ::Cronofy.api_url(data_center), connection_opts: { headers: { "User-Agent" => "Cronofy Ruby #{::Cronofy::VERSION}" } })
|
34
21
|
|
35
|
-
set_access_token(
|
22
|
+
set_access_token(access_token, refresh_token) if access_token || refresh_token
|
23
|
+
set_api_key(client_secret) if client_secret
|
36
24
|
end
|
37
25
|
|
38
|
-
#
|
26
|
+
# Internal: generate a URL for authorizing the application with Cronofy
|
27
|
+
#
|
28
|
+
# redirect_uri - A String specifing the URI to return the user to once they
|
29
|
+
# have completed the authorization steps.
|
30
|
+
# options - The Hash options used to refine the selection
|
31
|
+
# (default: {}):
|
32
|
+
# :scope - Array or String of scopes describing the access to
|
33
|
+
# request from the user to the users calendars
|
34
|
+
# (required).
|
35
|
+
# :state - Array of states to retain during the OAuth
|
36
|
+
# authorization process (optional).
|
39
37
|
#
|
40
|
-
#
|
41
|
-
# scope Array of String, the scope requested
|
42
|
-
# Default: [read_account, list_calendars, read_events, create_event, delete_event]
|
43
|
-
# see: http://www.cronofy.com/developers/api#authorization
|
38
|
+
# See http://www.cronofy.com/developers/api#authorization for reference.
|
44
39
|
#
|
45
|
-
# Returns
|
46
|
-
def user_auth_link(redirect_uri,
|
47
|
-
scope
|
40
|
+
# Returns the URL as a String.
|
41
|
+
def user_auth_link(redirect_uri, options = {})
|
42
|
+
raise ArgumentError.new(":scope is required") unless options[:scope]
|
48
43
|
|
49
|
-
|
44
|
+
params = options.merge(redirect_uri: redirect_uri, response_type: 'code')
|
45
|
+
|
46
|
+
# Reformat params as needed
|
47
|
+
params.delete(:state) if params[:state].nil?
|
48
|
+
|
49
|
+
if params[:scope].respond_to?(:join)
|
50
|
+
params[:scope] = params[:scope].join(' ')
|
51
|
+
end
|
52
|
+
|
53
|
+
@auth_client.auth_code.authorize_url(params)
|
50
54
|
end
|
51
55
|
|
52
56
|
def get_token_from_code(code, redirect_uri)
|
53
|
-
|
54
|
-
|
55
|
-
|
57
|
+
do_request do
|
58
|
+
@access_token = @auth_client.auth_code.get_token(code, redirect_uri: redirect_uri)
|
59
|
+
Credentials.new(@access_token)
|
60
|
+
end
|
56
61
|
end
|
57
62
|
|
58
|
-
#
|
59
|
-
#
|
63
|
+
# Internal: Refreshes the access token
|
64
|
+
#
|
65
|
+
# Returns Hash of token elements to allow client to update in local store
|
66
|
+
# for user
|
67
|
+
#
|
68
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
60
69
|
def refresh!
|
61
|
-
|
62
|
-
|
63
|
-
|
70
|
+
raise CredentialsMissingError.new("No credentials to refresh") unless access_token
|
71
|
+
raise CredentialsMissingError.new("No refresh_token provided") unless access_token.refresh_token
|
72
|
+
|
73
|
+
do_request do
|
74
|
+
@access_token = access_token.refresh!
|
75
|
+
Credentials.new(@access_token)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Internal: Obtains access to an application calendar
|
80
|
+
#
|
81
|
+
# application_calendar_id - A String to identify the application calendar
|
82
|
+
# which is to be accessed.
|
83
|
+
#
|
84
|
+
# Returns Hash of token elements to allow client to update in local store
|
85
|
+
# for user
|
86
|
+
#
|
87
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
88
|
+
def application_calendar(application_calendar_id)
|
89
|
+
do_request do
|
90
|
+
body = {
|
91
|
+
client_id: @api_client.id,
|
92
|
+
client_secret: @api_client.secret,
|
93
|
+
application_calendar_id: application_calendar_id,
|
94
|
+
}
|
95
|
+
|
96
|
+
@response = @api_client.request(:post, "/v1/application_calendars", body: body)
|
97
|
+
Credentials.new(OAuth2::AccessToken.from_hash(@api_client, @response.parsed))
|
98
|
+
end
|
64
99
|
end
|
65
100
|
|
66
101
|
def set_access_token_from_auth_token(auth_token)
|
@@ -68,8 +103,76 @@ module Cronofy
|
|
68
103
|
end
|
69
104
|
|
70
105
|
def set_access_token(token, refresh_token)
|
71
|
-
@access_token = OAuth2::AccessToken.new(@api_client, token,
|
106
|
+
@access_token = OAuth2::AccessToken.new(@api_client, token, refresh_token: refresh_token)
|
107
|
+
end
|
108
|
+
|
109
|
+
def set_api_key(client_secret)
|
110
|
+
@api_key = ApiKey.new(@api_client, client_secret)
|
72
111
|
end
|
73
112
|
|
113
|
+
# Internal: Revokes the refresh token and corresponding access tokens.
|
114
|
+
#
|
115
|
+
# Returns nothing.
|
116
|
+
#
|
117
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
118
|
+
def revoke!
|
119
|
+
raise CredentialsMissingError.new("No credentials to revoke") unless access_token
|
120
|
+
|
121
|
+
token = access_token.refresh_token || access_token.token
|
122
|
+
revoke_by_token(token)
|
123
|
+
@access_token = nil
|
124
|
+
end
|
125
|
+
|
126
|
+
# Internal: Revokes an authorization by the sub
|
127
|
+
#
|
128
|
+
# Returns nothing.
|
129
|
+
#
|
130
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
131
|
+
def revoke_by_sub(sub)
|
132
|
+
do_revoke(sub: sub)
|
133
|
+
end
|
134
|
+
|
135
|
+
# Internal: Revokes an authorization via the token
|
136
|
+
#
|
137
|
+
# Returns nothing.
|
138
|
+
#
|
139
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
140
|
+
def revoke_by_token(token)
|
141
|
+
do_revoke(token: token)
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def do_revoke(token: nil, sub: nil)
|
147
|
+
raise CredentialsMissingError.new("No credentials to revoke") unless token || sub
|
148
|
+
|
149
|
+
do_request do
|
150
|
+
body = {
|
151
|
+
client_id: @api_client.id,
|
152
|
+
client_secret: @api_client.secret,
|
153
|
+
}
|
154
|
+
|
155
|
+
if token
|
156
|
+
body.merge!(token: token)
|
157
|
+
else
|
158
|
+
body.merge!(sub: sub)
|
159
|
+
end
|
160
|
+
|
161
|
+
@api_client.request(:post, "/oauth/token/revoke", body: body)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def do_request(&block)
|
166
|
+
if @client_credentials_missing
|
167
|
+
raise CredentialsMissingError.new("OAuth client_id and client_secret must be set")
|
168
|
+
end
|
169
|
+
block.call
|
170
|
+
rescue OAuth2::Error => e
|
171
|
+
raise Errors.map_error(e)
|
172
|
+
end
|
173
|
+
|
174
|
+
def blank?(value)
|
175
|
+
value.nil? || value.strip.empty?
|
176
|
+
end
|
74
177
|
end
|
75
|
-
end
|
178
|
+
end
|