提交 ff5a1775 编写于 作者: M Mislav Marohnić

Fix API 422 error: `Duplicate value for "description"`

When looking up an existing hub token among user's authorizations, be
sure to fetch all results by following pagination links. Previously we
just stopped at the 1st page, and if the token for hub didn't appear
there we would try to create it, which would result in a 422 validation
error if it already existed.

References 1e4477b5

Fixes #531, fixes #558, fixes #563
上级 67728bcb
......@@ -88,6 +88,40 @@ Feature: OAuth authentication
And the exit status should be 0
And the file "../home/.config/hub" should contain "oauth_token: OTOKEN"
Scenario: Re-use existing authorization found on page 3
Given the GitHub API server:
"""
get('/authorizations') {
assert_basic_auth 'mislav', 'kitty'
page = (params[:page] || 1).to_i
if page < 3
response.headers['Link'] = %(<#{url}?page=#{page+1}>; rel="next")
json []
else
json [
{:token => 'OTOKEN', :note => 'hub', :note_url => 'http://hub.github.com/'}
]
end
}
post('/authorizations') {
status 422
json :message => "Validation Failed",
:errors => [{:resource => "OauthAccess", :code => "already_exists", :field => "description"}]
}
get('/user') {
json :login => 'mislav'
}
post('/user/repos') {
json :full_name => 'mislav/dotfiles'
}
"""
When I run `hub create` interactively
When I type "mislav"
And I type "kitty"
Then the output should contain "github.com password for mislav (never stored):"
And the exit status should be 0
And the file "../home/.config/hub" should contain "oauth_token: OTOKEN"
Scenario: Credentials from GITHUB_USER & GITHUB_PASSWORD
Given the GitHub API server:
"""
......
......@@ -192,12 +192,33 @@ module Hub
end
end.compact if data['errors']
end
def links
@links ||= self['link'].to_s.scan(/<(.+?)>; rel="(.+?)"/).inject({}) do |map, (url, rel)|
map.update(rel.to_sym => URI.parse(url))
end
end
def next_url() links[:next] end
end
def get url, &block
perform_request url, :Get, &block
end
def get_all url, &block
previous_res = nil
user = url.user
while url
res = get(url, &block)
if url = res.next_url
url = url.dup
url.user = user
end
res.data.unshift(*previous_res.data) if res.success? && previous_res
previous_res = res
end
res
end
def post url, params = nil
perform_request url, :Post do |req|
if params
......@@ -299,7 +320,7 @@ module Hub
module OAuth
def apply_authentication req, url
if req.path =~ %r{^(/api/v3)?/authorizations$}
if req.path =~ %r{^(/api/v3)?/authorizations\b}
super
else
user = url.user ? CGI.unescape(url.user) : config.username(url.host)
......@@ -317,7 +338,7 @@ module Hub
post(auth_url) if !two_factor_code
# first try to fetch existing authorization
res = get(auth_url) do |req|
res = get_all(auth_url) do |req|
req['X-GitHub-OTP'] = two_factor_code if two_factor_code
end
unless res.success?
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册