vkontakte_api 1.0.4 → 1.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 1.1 (18.12.2012)
2
+
3
+ * Передача `redirect_uri` при получении токена
4
+ * Методы для работы с правами и сроком жизни токена
5
+ * Логгирование тела POST-запроса
6
+ * POST-запросы по умолчанию
7
+
1
8
  ## 1.0.4 (22.09.2012)
2
9
 
3
10
  * Пространство имен `orders`
data/Guardfile ADDED
@@ -0,0 +1,7 @@
1
+ guard 'rspec' do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { 'spec' }
5
+ end
6
+
7
+ notification :terminal_notifier, activate: 'com.googlecode.iTerm2'
data/README.md CHANGED
@@ -136,6 +136,41 @@ VkontakteApi.authorization_url(type: :client, scope: [:friends, :photos])
136
136
  @vk = VkontakteApi.authorize(type: :app_server)
137
137
  ```
138
138
 
139
+ ### Прочее
140
+
141
+ Если клиент API (объект класса `VkontakteApi::Client`) был создан с помощью метода `VkontakteApi.authorize`, он будет содержать информацию об id текущего пользователя (`user_id`) и о времени истечения токена (`expires_at`). Получить их можно с помощью соответствующих методов:
142
+
143
+ ``` ruby
144
+ vk = VkontakteApi.authorize(code: 'c1493e81f69fce1b43')
145
+ # => #<VkontakteApi::Client:0x007fa578f00ad0>
146
+ vk.user_id # => 628985
147
+ vk.expires_at # => 2012-12-18 23:22:55 +0400
148
+ # можно проверить, истекло ли время жизни токена
149
+ vk.expired? # => false
150
+ ```
151
+
152
+ Также можно получить список прав доступа, которые дает данный токен, в виде, аналогичном формату параметра `scope` в авторизации:
153
+
154
+ ``` ruby
155
+ vk.scope # => [:friends, :groups]
156
+ ```
157
+
158
+ Это работает на основе метода `getUserSettings`, причем результат запоминается после первого обращения.
159
+
160
+ Чтобы создать короткий синоним `VK` для модуля `VkontakteApi`, достаточно вызвать метод `VkontakteApi.register_alias`:
161
+
162
+ ``` ruby
163
+ VkontakteApi.register_alias
164
+ VK::Client.new # => #<VkontakteApi::Client:0x007fa578d6d948>
165
+ ```
166
+
167
+ При необходимости можно удалить синоним методом `VkontakteApi.unregister_alias`:
168
+
169
+ ``` ruby
170
+ VK.unregister_alias
171
+ VK # => NameError: uninitialized constant VK
172
+ ```
173
+
139
174
  ### Обработка ошибок
140
175
 
141
176
  Если ВКонтакте API возвращает ошибку, выбрасывается исключение класса `VkontakteApi::Error`.
@@ -179,7 +214,7 @@ VkontakteApi.configure do |config|
179
214
  # faraday-адаптер для сетевых запросов
180
215
  config.adapter = :net_http
181
216
  # HTTP-метод для вызова методов API (:get или :post)
182
- config.http_verb = :get
217
+ config.http_verb = :post
183
218
  # параметры для faraday-соединения
184
219
  config.faraday_options = {
185
220
  ssl: {
@@ -198,14 +233,11 @@ VkontakteApi.configure do |config|
198
233
  config.log_errors = true # ошибки
199
234
  config.log_responses = false # удачные ответы
200
235
  end
201
-
202
- # создание короткого алиаса VK для модуля VkontakteApi
203
- VkontakteApi.register_alias
204
236
  ```
205
237
 
206
238
  По умолчанию для HTTP-запросов используется `Net::HTTP`; можно выбрать [любой другой адаптер](https://github.com/technoweenie/faraday/blob/master/lib/faraday/adapter.rb), поддерживаемый `faraday`.
207
239
 
208
- ВКонтакте [позволяет](http://vk.com/developers.php?oid=-1&p=%D0%92%D1%8B%D0%BF%D0%BE%D0%BB%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%BE%D0%B2_%D0%BA_API) использовать как `GET`-, так и `POST`-запросы при вызове методов API. По умолчанию `vkontakte_api` использует `GET`, но в настройке `http_verb` можно указать `:post`, чтобы совершать `POST`-запросы.
240
+ ВКонтакте [позволяет](http://vk.com/developers.php?oid=-1&p=%D0%92%D1%8B%D0%BF%D0%BE%D0%BB%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%BE%D0%B2_%D0%BA_API) использовать как `GET`-, так и `POST`-запросы при вызове методов API. По умолчанию `vkontakte_api` использует `POST`, но в настройке `http_verb` можно указать `:get`, чтобы совершать `GET`-запросы.
209
241
 
210
242
  При необходимости можно указать параметры для faraday-соединения - например, параметры прокси-сервера или путь к SSL-сертификатам.
211
243
 
@@ -225,7 +257,8 @@ $ rails generate vkontakte_api:install
225
257
  ## Roadmap
226
258
 
227
259
  * метод, возвращающий права текущего токена в читабельной форме (используя `getUserSettings` и кэшируя результат)
228
- * сохранение параметра `expires_in` токена в объекте `VkontakteApi::Client` после авторизации через `VkontakteApi.authorize`
260
+ * сохранение параметра `expires_at` токена в объекте `VkontakteApi::Client` после авторизации через `VkontakteApi.authorize`
261
+ * метод `VkontakteApi::Client#offline?`, проверяющий, является ли токен бесконечным, используя значение `VkontakteApi::Client#expires_at`
229
262
  * `POST`-запросы по умолчанию
230
263
  * логгирование тела `POST`-запроса
231
264
 
@@ -45,12 +45,14 @@ module VkontakteApi
45
45
  def authorize(options = {})
46
46
  type = options.delete(:type) || :site
47
47
 
48
+ options[:redirect_uri] ||= VkontakteApi.redirect_uri
49
+
48
50
  case type
49
51
  when :site
50
52
  code = options.delete(:code)
51
- token = client.auth_code.get_token(code)
53
+ token = client.auth_code.get_token(code, options)
52
54
  when :app_server
53
- token = client.client_credentials.get_token({}, OPTIONS[:client_credentials])
55
+ token = client.client_credentials.get_token(options, OPTIONS[:client_credentials].dup)
54
56
  else
55
57
  raise ArgumentError, "Unknown authorization type #{type.inspect}"
56
58
  end
@@ -3,22 +3,48 @@ module VkontakteApi
3
3
  class Client
4
4
  include Resolver
5
5
 
6
+ # Access rights and their respective number representation.
7
+ SCOPE = {
8
+ :notify => 1,
9
+ :friends => 2,
10
+ :photos => 4,
11
+ :audio => 8,
12
+ :video => 16,
13
+ :offers => 32,
14
+ :questions => 64,
15
+ :pages => 128,
16
+ :status => 1024,
17
+ :notes => 2048,
18
+ :messages => 4096,
19
+ :wall => 8192,
20
+ :ads => 32768,
21
+ :docs => 131072,
22
+ :groups => 262144,
23
+ :notifications => 524288,
24
+ :stats => 1048576
25
+ }
26
+
6
27
  # An access token needed by authorized requests.
7
28
  # @return [String]
8
29
  attr_reader :token
9
30
  # Current user id.
10
31
  # @return [Integer]
11
32
  attr_reader :user_id
33
+ # Token expiration time
34
+ # @return [Time]
35
+ attr_reader :expires_at
12
36
 
13
37
  # A new API client.
14
38
  # If given an `OAuth2::AccessToken` instance, it extracts and keeps
15
- # the token string and the user id; otherwise it just stores the given token.
39
+ # the token string, the user id and the expiration time;
40
+ # otherwise it just stores the given token.
16
41
  # @param [String, OAuth2::AccessToken] token An access token.
17
42
  def initialize(token = nil)
18
43
  if token.respond_to?(:token) && token.respond_to?(:params)
19
44
  # token is an OAuth2::AccessToken
20
- @token = token.token
21
- @user_id = token.params['user_id']
45
+ @token = token.token
46
+ @user_id = token.params['user_id']
47
+ @expires_at = Time.at(token.expires_at) unless token.expires_at.nil?
22
48
  else
23
49
  # token is a String or nil
24
50
  @token = token
@@ -29,5 +55,23 @@ module VkontakteApi
29
55
  def authorized?
30
56
  !@token.nil?
31
57
  end
58
+
59
+ # Did the token already expire.
60
+ def expired?
61
+ @expires_at && @expires_at < Time.now
62
+ end
63
+
64
+ # Access rights of this token.
65
+ # @return [Array] An array of symbols representing the access rights.
66
+ def scope
67
+ SCOPE.reject do |access_scope, mask|
68
+ (settings & mask).zero?
69
+ end.keys
70
+ end
71
+
72
+ private
73
+ def settings
74
+ @settings ||= self.get_user_settings
75
+ end
32
76
  end
33
77
  end
@@ -29,7 +29,7 @@ module VkontakteApi
29
29
  DEFAULT_ADAPTER = Faraday.default_adapter
30
30
 
31
31
  # Default HTTP verb for API methods.
32
- DEFAULT_HTTP_VERB = :get
32
+ DEFAULT_HTTP_VERB = :post
33
33
 
34
34
  # Logger default options.
35
35
  DEFAULT_LOGGER_OPTIONS = {
@@ -15,6 +15,7 @@ module VkontakteApi
15
15
  def call(env)
16
16
  if VkontakteApi.log_requests?
17
17
  @logger.debug "#{env[:method].to_s.upcase} #{env[:url].to_s}"
18
+ @logger.debug "body: #{env[:body].inspect}" unless env[:method] == :get
18
19
  end
19
20
 
20
21
  super
@@ -1,4 +1,4 @@
1
1
  module VkontakteApi
2
2
  # Library version.
3
- VERSION = '1.0.4'
3
+ VERSION = '1.1'
4
4
  end
@@ -8,7 +8,7 @@ describe VkontakteApi::API do
8
8
  builder.response :mashify
9
9
  builder.response :oj, :preserve_raw => true
10
10
  builder.adapter :test do |stub|
11
- stub.get('/apiMethod') do
11
+ stub.post('/apiMethod') do
12
12
  [200, {}, Oj.dump(@result)]
13
13
  end
14
14
  end
@@ -13,8 +13,8 @@ describe VkontakteApi::Authorization do
13
13
  @token = stub("Token")
14
14
 
15
15
  @auth_code = stub("Authorization code strategy", :get_token => @token, :authorize_url => @url)
16
- @implicit = stub("Implicit strategy", :authorize_url => @url)
17
- @client_credentials = stub("Client credentials strategy", :get_token => @token)
16
+ @implicit = stub("Implicit strategy", :authorize_url => @url)
17
+ @client_credentials = stub("Client credentials strategy", :get_token => @token)
18
18
 
19
19
  @client = stub("OAuth2::Client instance", :auth_code => @auth_code, :implicit => @implicit, :client_credentials => @client_credentials)
20
20
  OAuth2::Client.stub(:new).and_return(@client)
@@ -70,14 +70,14 @@ describe VkontakteApi::Authorization do
70
70
  end
71
71
 
72
72
  it "gets the token" do
73
- @auth_code.should_receive(:get_token).with(@code)
73
+ @auth_code.should_receive(:get_token).with(@code, {:redirect_uri => @redirect_uri})
74
74
  @auth.authorize(:type => :site, :code => @code)
75
75
  end
76
76
  end
77
77
 
78
78
  context "with an app_server type" do
79
79
  it "gets the token" do
80
- @client_credentials.should_receive(:get_token).with({}, subject::OPTIONS[:client_credentials])
80
+ @client_credentials.should_receive(:get_token).with({:redirect_uri => @redirect_uri}, subject::OPTIONS[:client_credentials])
81
81
  @auth.authorize(:type => :app_server)
82
82
  end
83
83
  end
@@ -4,7 +4,12 @@ describe VkontakteApi::Client do
4
4
  before(:each) do
5
5
  @user_id = stub("User id")
6
6
  @string_token = stub("Access token as a String")
7
- @oauth2_token = stub("Access token as an OAuth2::AccessToken", :token => @string_token, :params => {'user_id' => @user_id})
7
+ @expires_at = Time.now - 2 * 60 * 60 # 2.hours.ago
8
+
9
+ @oauth2_token = stub("Access token as an OAuth2::AccessToken")
10
+ @oauth2_token.stub(:token).and_return(@string_token)
11
+ @oauth2_token.stub(:params).and_return('user_id' => @user_id)
12
+ @oauth2_token.stub(:expires_at).and_return(@expires_at)
8
13
  end
9
14
 
10
15
  describe "#initialize" do
@@ -28,6 +33,9 @@ describe VkontakteApi::Client do
28
33
  client = VkontakteApi::Client.new(@oauth2_token)
29
34
  client.token.should == @string_token
30
35
  client.user_id.should == @user_id
36
+
37
+ client.expires_at.should be_a(Time)
38
+ client.expires_at.should be < Time.now
31
39
  end
32
40
  end
33
41
  end
@@ -46,4 +54,62 @@ describe VkontakteApi::Client do
46
54
  end
47
55
  end
48
56
  end
57
+
58
+ describe "#expired?" do
59
+ context "with an expired token" do
60
+ before(:each) do
61
+ @client = VkontakteApi::Client.new(@oauth2_token)
62
+ end
63
+
64
+ it "returns true" do
65
+ @client.should be_expired
66
+ end
67
+ end
68
+
69
+ context "with an actual token" do
70
+ before(:each) do
71
+ @oauth2_token.stub(:expires_at).and_return(Time.now + 2 * 24 * 60 * 60) # 2.days.from_now
72
+ @client = VkontakteApi::Client.new(@oauth2_token)
73
+ end
74
+
75
+ it "returns false" do
76
+ @client.should_not be_expired
77
+ end
78
+ end
79
+
80
+ context "with a String token" do
81
+ before(:each) do
82
+ @client = VkontakteApi::Client.new(@string_token)
83
+ end
84
+
85
+ it "returns false" do
86
+ @client.should_not be_expired
87
+ end
88
+ end
89
+ end
90
+
91
+ describe "#scope" do
92
+ before(:each) do
93
+ @client = VkontakteApi::Client.new
94
+ @client.stub(:get_user_settings).and_return(865310)
95
+ end
96
+
97
+ it "returns an array of access rights" do
98
+ scopes_array = @client.scope
99
+
100
+ [
101
+ :friends,
102
+ :photos,
103
+ :audio,
104
+ :video,
105
+ :status,
106
+ :messages,
107
+ :wall,
108
+ :groups,
109
+ :notifications
110
+ ].each do |access_scope|
111
+ scopes_array.should include(access_scope)
112
+ end
113
+ end
114
+ end
49
115
  end
@@ -6,6 +6,7 @@ describe VkontakteApi::Logger do
6
6
  @fail_response = Oj.dump('error' => 404)
7
7
 
8
8
  @connection = Faraday.new(:url => 'http://example.com') do |builder|
9
+ builder.request :url_encoded
9
10
  builder.response :vk_logger
10
11
  builder.response :mashify
11
12
  builder.response :oj, :preserve_raw => true
@@ -14,6 +15,9 @@ describe VkontakteApi::Logger do
14
15
  stub.get('/success') do
15
16
  [200, {}, @success_response]
16
17
  end
18
+ stub.post('/success') do
19
+ [200, {}, @success_response]
20
+ end
17
21
  stub.get('/fail') do
18
22
  [200, {}, @fail_response]
19
23
  end
@@ -33,10 +37,18 @@ describe VkontakteApi::Logger do
33
37
  VkontakteApi.log_requests = true
34
38
  end
35
39
 
36
- it "logs the request" do
40
+ it "logs the request URL" do
37
41
  @logger.should_receive(:debug).with('GET http://example.com/success')
38
42
  @connection.get('/success')
39
43
  end
44
+
45
+ context "with a POST request" do
46
+ it "logs the request URL and the request body" do
47
+ @logger.should_receive(:debug).with('POST http://example.com/success')
48
+ @logger.should_receive(:debug).with('body: "param=1"')
49
+ @connection.post('/success', :param => 1)
50
+ end
51
+ end
40
52
  end
41
53
 
42
54
  context "without VkontakteApi.log_requests?" do
@@ -24,6 +24,9 @@ Gem::Specification.new do |s|
24
24
 
25
25
  s.add_development_dependency 'rake'
26
26
  s.add_development_dependency 'rspec'
27
+ s.add_development_dependency 'guard-rspec'
28
+ s.add_development_dependency 'rb-fsevent', '~> 0.9.1'
29
+ s.add_development_dependency 'terminal-notifier-guard'
27
30
  s.add_development_dependency 'pry'
28
31
  s.add_development_dependency 'awesome_print'
29
32
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vkontakte_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: '1.1'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-21 00:00:00.000000000 Z
12
+ date: 2012-12-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: faraday
@@ -123,6 +123,54 @@ dependencies:
123
123
  - - ! '>='
124
124
  - !ruby/object:Gem::Version
125
125
  version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: guard-rspec
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: rb-fsevent
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ~>
148
+ - !ruby/object:Gem::Version
149
+ version: 0.9.1
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ~>
156
+ - !ruby/object:Gem::Version
157
+ version: 0.9.1
158
+ - !ruby/object:Gem::Dependency
159
+ name: terminal-notifier-guard
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
126
174
  - !ruby/object:Gem::Dependency
127
175
  name: pry
128
176
  requirement: !ruby/object:Gem::Requirement
@@ -170,6 +218,7 @@ files:
170
218
  - .yardopts
171
219
  - CHANGELOG.md
172
220
  - Gemfile
221
+ - Guardfile
173
222
  - MIT-LICENSE
174
223
  - README.md
175
224
  - Rakefile