cronofy 0.0.5 → 0.37.7

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