Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
github
hub
提交
1105d204
H
hub
项目概览
github
/
hub
大约 1 年 前同步成功
通知
3
Star
22523
Fork
2406
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
H
hub
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
1105d204
编写于
12月 24, 2014
作者:
J
Jingwen Owen Ou
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Improve auth process
This is to follow implementation in
https://github.com/github/hub/pull/738
上级
f94c31cc
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
102 addition
and
64 deletion
+102
-64
github/client.go
github/client.go
+74
-57
github/client_test.go
github/client_test.go
+16
-0
github/config.go
github/config.go
+12
-7
未找到文件。
github/client.go
浏览文件 @
1105d204
...
...
@@ -5,6 +5,7 @@ import (
"io"
"net/url"
"os"
"os/user"
"strings"
"github.com/github/hub/Godeps/_workspace/src/github.com/octokit/go-octokit/octokit"
...
...
@@ -14,7 +15,6 @@ const (
GitHubHost
string
=
"github.com"
GitHubApiHost
string
=
"api.github.com"
UserAgent
string
=
"Hub"
OAuthAppName
string
=
"hub"
OAuthAppURL
string
=
"http://hub.github.com/"
)
...
...
@@ -27,18 +27,23 @@ func NewClientWithHost(host *Host) *Client {
}
type
AuthError
struct
{
error
Err
error
}
func
(
e
*
AuthError
)
Error
()
string
{
return
e
.
erro
r
.
Error
()
return
e
.
Er
r
.
Error
()
}
func
(
e
*
AuthError
)
Is
2FA
Error
()
bool
{
re
,
ok
:=
e
.
erro
r
.
(
*
octokit
.
ResponseError
)
func
(
e
*
AuthError
)
Is
Required2FACode
Error
()
bool
{
re
,
ok
:=
e
.
Er
r
.
(
*
octokit
.
ResponseError
)
return
ok
&&
re
.
Type
==
octokit
.
ErrorOneTimePasswordRequired
}
func
(
e
*
AuthError
)
IsDuplicatedTokenError
()
bool
{
re
,
ok
:=
e
.
Err
.
(
*
octokit
.
ResponseError
)
return
ok
&&
re
.
Type
==
octokit
.
ErrorUnprocessableEntity
}
type
Client
struct
{
Host
*
Host
}
...
...
@@ -455,55 +460,39 @@ func (client *Client) FindOrCreateToken(user, password, twoFactorCode string) (t
c
:=
client
.
newOctokitClient
(
basicAuth
)
authsService
:=
c
.
Authorizations
(
client
.
requestURL
(
authUrl
))
if
twoFactorCode
==
""
{
// dummy request to trigger a 2FA SMS since a HTTP GET won't do it
authsService
.
Create
(
nil
)
authParam
:=
octokit
.
AuthorizationParams
{
Scopes
:
[]
string
{
"repo"
},
NoteURL
:
OAuthAppURL
,
}
auths
,
result
:=
authsService
.
All
()
if
result
.
HasError
()
{
err
=
&
AuthError
{
result
.
Err
}
return
}
var
moreAuths
[]
octokit
.
Authorization
for
result
.
NextPage
!=
nil
{
authUrl
,
e
:=
result
.
NextPage
.
Expand
(
nil
)
count
:=
0
for
{
note
,
e
:=
authTokenNote
(
count
)
if
e
!=
nil
{
return
""
,
e
}
authUrl
,
_
=
url
.
Parse
(
authUrl
.
RequestURI
())
as
:=
c
.
Authorizations
(
authUrl
)
moreAuths
,
result
=
as
.
All
()
if
result
.
HasError
()
{
err
=
&
AuthError
{
result
.
Err
}
err
=
e
return
}
auths
=
append
(
auths
,
moreAuths
...
)
}
for
_
,
auth
:=
range
auths
{
if
auth
.
Note
==
OAuthAppName
||
auth
.
NoteURL
==
OAuthAppURL
{
authParam
.
Note
=
note
auth
,
result
:=
authsService
.
Create
(
authParam
)
if
!
result
.
HasError
()
{
token
=
auth
.
Token
break
}
}
if
token
==
""
{
authParam
:=
octokit
.
AuthorizationParams
{}
authParam
.
Scopes
=
append
(
authParam
.
Scopes
,
"repo"
)
authParam
.
Note
=
OAuthAppName
authParam
.
NoteURL
=
OAuthAppURL
auth
,
result
:=
authsService
.
Create
(
authParam
)
if
result
.
HasError
()
{
err
=
&
AuthError
{
result
.
Err
}
return
authErr
:=
&
AuthError
{
result
.
Err
}
if
authErr
.
IsDuplicatedTokenError
()
{
if
count
>=
8
{
err
=
authErr
break
}
else
{
count
++
continue
}
}
else
{
err
=
authErr
break
}
token
=
auth
.
Token
}
return
...
...
@@ -577,6 +566,8 @@ func FormatError(action string, err error) (ee error) {
switch
e
:=
err
.
(
type
)
{
default
:
ee
=
err
case
*
AuthError
:
return
FormatError
(
action
,
e
.
Err
)
case
*
octokit
.
ResponseError
:
statusCode
:=
e
.
Response
.
StatusCode
var
reason
string
...
...
@@ -586,26 +577,33 @@ func FormatError(action string, err error) (ee error) {
errStr
:=
fmt
.
Sprintf
(
"Error %s: %s (HTTP %d)"
,
action
,
reason
,
statusCode
)
var
messages
[]
string
if
statusCode
==
422
{
if
e
.
Message
!=
""
{
messages
=
append
(
messages
,
e
.
Message
)
var
errorSentences
[]
string
for
_
,
err
:=
range
e
.
Errors
{
switch
err
.
Code
{
case
"custom"
:
errorSentences
=
append
(
errorSentences
,
err
.
Message
)
case
"missing_field"
:
errorSentences
=
append
(
errorSentences
,
fmt
.
Sprintf
(
"Missing filed:
\"
%s
\"
"
,
err
.
Field
))
case
"already_exists"
:
errorSentences
=
append
(
errorSentences
,
fmt
.
Sprintf
(
"Duplicate value for
\"
%s
\"
"
,
err
.
Field
))
case
"invalid"
:
errorSentences
=
append
(
errorSentences
,
fmt
.
Sprintf
(
"Invalid value for
\"
%s
\"
"
,
err
.
Field
))
case
"unauthorized"
:
errorSentences
=
append
(
errorSentences
,
fmt
.
Sprintf
(
"Not allowed to change field
\"
%s
\"
"
,
err
.
Field
))
}
}
if
len
(
e
.
Errors
)
>
0
{
for
_
,
e
:=
range
e
.
Errors
{
messages
=
append
(
messages
,
e
.
Error
()
)
}
}
var
errorMessage
string
if
len
(
errorSentences
)
>
0
{
errorMessage
=
strings
.
Join
(
errorSentences
,
"
\n
"
)
}
else
{
errorMessage
=
e
.
Message
}
if
len
(
messages
)
>
0
{
errStr
=
fmt
.
Sprintf
(
"%s
\n
%s"
,
errStr
,
strings
.
Join
(
messages
,
"
\n
"
)
)
if
errorMessage
!=
""
{
errStr
=
fmt
.
Sprintf
(
"%s
\n
%s"
,
errStr
,
errorMessage
)
}
ee
=
fmt
.
Errorf
(
errStr
)
case
*
AuthError
:
errStr
:=
fmt
.
Sprintf
(
"Error %s: Unauthorized (HTTP 401)"
,
action
)
ee
=
fmt
.
Errorf
(
errStr
)
}
...
...
@@ -625,3 +623,22 @@ func warnExistenceOfRepo(project *Project, ee error) (err error) {
return
}
func
authTokenNote
(
num
int
)
(
string
,
error
)
{
u
,
err
:=
user
.
Current
()
if
err
!=
nil
{
return
""
,
err
}
n
:=
u
.
Username
h
,
err
:=
os
.
Hostname
()
if
err
!=
nil
{
return
""
,
err
}
if
num
>
0
{
return
fmt
.
Sprintf
(
"hub for %s@%s %d"
,
n
,
h
,
num
),
nil
}
return
fmt
.
Sprintf
(
"hub for %s@%s"
,
n
,
h
),
nil
}
github/client_test.go
浏览文件 @
1105d204
...
...
@@ -3,6 +3,7 @@ package github
import
(
"fmt"
"net/http"
"regexp"
"testing"
"github.com/github/hub/Godeps/_workspace/src/github.com/bmizerany/assert"
...
...
@@ -62,3 +63,18 @@ func TestClient_warnExistenceOfRepo(t *testing.T) {
err
:=
warnExistenceOfRepo
(
project
,
e
)
assert
.
Equal
(
t
,
"Are you sure that github.com/github/hub exists?"
,
fmt
.
Sprintf
(
"%s"
,
err
))
}
func
TestAuthTokenNote
(
t
*
testing
.
T
)
{
note
,
err
:=
authTokenNote
(
0
)
assert
.
Equal
(
t
,
nil
,
err
)
reg
:=
regexp
.
MustCompile
(
"hub for (.+)@(.+)"
)
assert
.
T
(
t
,
reg
.
MatchString
(
note
))
note
,
err
=
authTokenNote
(
2
)
assert
.
Equal
(
t
,
nil
,
err
)
reg
=
regexp
.
MustCompile
(
"hub for (.+)@(.+) 2"
)
assert
.
T
(
t
,
reg
.
MatchString
(
note
))
}
github/config.go
浏览文件 @
1105d204
...
...
@@ -8,8 +8,8 @@ import (
"path/filepath"
"strconv"
"github.com/github/hub/utils"
"github.com/github/hub/Godeps/_workspace/src/github.com/howeyc/gopass"
"github.com/github/hub/utils"
)
var
(
...
...
@@ -45,13 +45,18 @@ func (c *Config) PromptForHost(host string) (h *Host, err error) {
pass
:=
c
.
PromptForPassword
(
host
,
user
)
client
:=
NewClient
(
host
)
token
,
e
:=
client
.
FindOrCreateToken
(
user
,
pass
,
""
)
if
e
!=
nil
{
if
ae
,
ok
:=
e
.
(
*
AuthError
);
ok
&&
ae
.
Is2FAError
()
{
code
:=
c
.
PromptForOTP
()
token
,
err
=
client
.
FindOrCreateToken
(
user
,
pass
,
code
)
var
code
,
token
string
for
{
token
,
err
=
client
.
FindOrCreateToken
(
user
,
pass
,
code
)
if
err
==
nil
{
break
}
if
ae
,
ok
:=
err
.
(
*
AuthError
);
ok
&&
ae
.
IsRequired2FACodeError
()
{
fmt
.
Fprintln
(
os
.
Stderr
,
"warning: invalid two-factor code"
)
code
=
c
.
PromptForOTP
()
}
else
{
err
=
e
break
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录