/
githubapi.go
94 lines (82 loc) · 2.49 KB
/
githubapi.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// Package githubapi implements users.Service using GitHub API client.
package githubapi
import (
"context"
"errors"
"fmt"
"net/http"
"github.com/google/go-github/github"
"github.com/shurcooL/users"
)
// NewService creates a GitHub-backed users.Service using given GitHub client.
// At this time it infers the current user from the client (its authentication info),
// and cannot be used to serve multiple users.
func NewService(client *github.Client) (users.Service, error) {
if client == nil {
client = github.NewClient(nil)
}
var currentUser users.User
switch u, _, err := client.Users.Get(context.Background(), ""); {
case err == nil:
currentUser = ghUser(u)
case isUnauthorized(err):
// There's no authenticated user.
currentUser = users.User{}
default:
return nil, err
}
return service{
cl: client,
currentUser: currentUser,
}, nil
}
// isUnauthorized reports whether err is an unauthorized error response from GitHub.
func isUnauthorized(err error) bool {
e, ok := err.(*github.ErrorResponse)
return ok && e.Response.StatusCode == http.StatusUnauthorized
}
type service struct {
cl *github.Client
currentUser users.User
}
func (s service) Get(ctx context.Context, user users.UserSpec) (users.User, error) {
if user.Domain != "github.com" {
return users.User{}, fmt.Errorf("user %v not found", user)
}
ghUser, _, err := s.cl.Users.GetByID(ctx, int64(user.ID))
if err != nil {
return users.User{}, err
}
if ghUser.ID == nil || ghUser.Login == nil || ghUser.AvatarURL == nil || ghUser.HTMLURL == nil {
return users.User{}, fmt.Errorf("github user missing fields: %#v", ghUser)
}
if uint64(*ghUser.ID) != user.ID {
return users.User{}, fmt.Errorf("got github user ID %v, but wanted ID %v", *ghUser.ID, user.ID)
}
return users.User{
UserSpec: user,
Login: *ghUser.Login,
AvatarURL: *ghUser.AvatarURL,
HTMLURL: *ghUser.HTMLURL,
}, nil
}
func (s service) GetAuthenticated(ctx context.Context) (users.User, error) {
return s.currentUser, nil
}
func (s service) GetAuthenticatedSpec(ctx context.Context) (users.UserSpec, error) {
return s.currentUser.UserSpec, nil
}
func (s service) Edit(ctx context.Context, er users.EditRequest) (users.User, error) {
return users.User{}, errors.New("Edit is not implemented")
}
func ghUser(user *github.User) users.User {
return users.User{
UserSpec: users.UserSpec{
ID: uint64(*user.ID),
Domain: "github.com",
},
Login: *user.Login,
AvatarURL: *user.AvatarURL,
HTMLURL: *user.HTMLURL,
}
}