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.
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
- class Credentials
6
-
7
- attr_reader :access_token,
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
- def to_hash
20
- {
21
- access_token: access_token,
22
- refresh_token: refresh_token,
23
- expires_in: expires_in,
24
- expires_at: expires_at
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
- attr_reader :access_token
17
+ @client_credentials_missing = blank?(client_id) || blank?(client_secret)
30
18
 
31
- def initialize(client_id, client_secret, token=nil, refresh_token=nil)
32
- @auth_client = OAuth2::Client.new(client_id, client_secret, site: ::Cronofy.app_url)
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(token, refresh_token) if 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
- # Public: generate a URL for authorizing the application with Cronofy
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
- # redirect_uri String, the URI to return to after authorization
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 String URL
46
- def user_auth_link(redirect_uri, scope=nil)
47
- scope ||= %w{read_account list_calendars read_events create_event delete_event}
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
- @auth_client.auth_code.authorize_url(:redirect_uri => redirect_uri, :response_type => 'code', :scope => scope.join(' '))
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
- auth_token = @auth_client.auth_code.get_token(code, :redirect_uri => redirect_uri)
54
- set_access_token_from_auth_token(auth_token)
55
- Credentials.new(@access_token)
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
- # Public: Refreshes the access token
59
- # Returns Hash of token elements to allow client to update in local store for user
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
- auth_token = access_token.refresh!
62
- set_access_token_from_auth_token(auth_token)
63
- Credentials.new(@access_token)
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, { refresh_token: refresh_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