Browse Source

Grab access tokens from the GithubService and use them

Currently only an authenticated client is used to lookup expansion issues.
kegan/github-service
Kegan Dougal 9 years ago
parent
commit
55fda3c115
  1. 2
      src/github.com/matrix-org/go-neb/api.go
  2. 20
      src/github.com/matrix-org/go-neb/realms/github/github.go
  3. 59
      src/github.com/matrix-org/go-neb/services/github/github.go

2
src/github.com/matrix-org/go-neb/api.go

@ -200,7 +200,7 @@ func (s *configureServiceHandler) OnIncomingRequest(req *http.Request) (interfac
err := service.Register() err := service.Register()
if err != nil { if err != nil {
return nil, &errors.HTTPError{err, "Failed to register service", 500}
return nil, &errors.HTTPError{err, "Failed to register service: " + err.Error(), 500}
} }
client, err := s.clients.Client(service.ServiceUserID()) client, err := s.clients.Client(service.ServiceUserID())

20
src/github.com/matrix-org/go-neb/realms/github/github.go

@ -19,23 +19,29 @@ type githubRealm struct {
RedirectBaseURI string RedirectBaseURI string
} }
type githubSession struct {
// GithubSession represents an authenticated github session
type GithubSession struct {
// AccessToken is the github access token for the user
AccessToken string AccessToken string
// Scopes are the set of *ALLOWED* scopes (which may not be the same as the requested scopes)
Scopes string Scopes string
id string id string
userID string userID string
realmID string realmID string
} }
func (s *githubSession) UserID() string {
// UserID returns the user_id who authorised with Github
func (s *GithubSession) UserID() string {
return s.userID return s.userID
} }
func (s *githubSession) RealmID() string {
// RealmID returns the realm ID of the realm which performed the authentication
func (s *GithubSession) RealmID() string {
return s.realmID return s.realmID
} }
func (s *githubSession) ID() string {
// ID returns the session ID
func (s *GithubSession) ID() string {
return s.id return s.id
} }
@ -61,7 +67,7 @@ func (r *githubRealm) RequestAuthSession(userID string, req json.RawMessage) int
// TODO: Path is from goneb.go - we should probably factor it out. // TODO: Path is from goneb.go - we should probably factor it out.
q.Set("redirect_uri", r.RedirectBaseURI+"/realms/redirects/"+r.ID()) q.Set("redirect_uri", r.RedirectBaseURI+"/realms/redirects/"+r.ID())
u.RawQuery = q.Encode() u.RawQuery = q.Encode()
session := &githubSession{
session := &GithubSession{
id: state, // key off the state for redirects id: state, // key off the state for redirects
userID: userID, userID: userID,
realmID: r.ID(), realmID: r.ID(),
@ -96,7 +102,7 @@ func (r *githubRealm) OnReceiveRedirect(w http.ResponseWriter, req *http.Request
failWith(logger, w, 400, "Provided ?state= param is not recognised.", err) failWith(logger, w, 400, "Provided ?state= param is not recognised.", err)
return return
} }
ghSession, ok := session.(*githubSession)
ghSession, ok := session.(*GithubSession)
if !ok { if !ok {
failWith(logger, w, 500, "Unexpected session found.", nil) failWith(logger, w, 500, "Unexpected session found.", nil)
return return
@ -136,7 +142,7 @@ func (r *githubRealm) OnReceiveRedirect(w http.ResponseWriter, req *http.Request
} }
func (r *githubRealm) AuthSession(id, userID, realmID string) types.AuthSession { func (r *githubRealm) AuthSession(id, userID, realmID string) types.AuthSession {
return &githubSession{
return &GithubSession{
id: id, id: id,
userID: userID, userID: userID,
realmID: realmID, realmID: realmID,

59
src/github.com/matrix-org/go-neb/services/github/github.go

@ -4,8 +4,10 @@ import (
"fmt" "fmt"
log "github.com/Sirupsen/logrus" log "github.com/Sirupsen/logrus"
"github.com/google/go-github/github" "github.com/google/go-github/github"
"github.com/matrix-org/go-neb/database"
"github.com/matrix-org/go-neb/matrix" "github.com/matrix-org/go-neb/matrix"
"github.com/matrix-org/go-neb/plugin" "github.com/matrix-org/go-neb/plugin"
"github.com/matrix-org/go-neb/realms/github"
"github.com/matrix-org/go-neb/services/github/webhook" "github.com/matrix-org/go-neb/services/github/webhook"
"github.com/matrix-org/go-neb/types" "github.com/matrix-org/go-neb/types"
"golang.org/x/oauth2" "golang.org/x/oauth2"
@ -23,6 +25,7 @@ type githubService struct {
id string id string
BotUserID string BotUserID string
GithubUserID string GithubUserID string
RealmID string
WebhookRooms map[string][]string // room_id => ["push","issue","pull_request"] WebhookRooms map[string][]string // room_id => ["push","issue","pull_request"]
} }
@ -42,7 +45,7 @@ func (s *githubService) Plugin(roomID string) plugin.Plugin {
plugin.Command{ plugin.Command{
Path: []string{"github", "create"}, Path: []string{"github", "create"},
Command: func(roomID, userID string, args []string) (interface{}, error) { Command: func(roomID, userID string, args []string) (interface{}, error) {
cli := githubClientFor(userID, false)
cli := s.githubClientFor(userID, false)
if cli == nil { if cli == nil {
// TODO: send starter link // TODO: send starter link
return &matrix.TextMessage{"m.notice", return &matrix.TextMessage{"m.notice",
@ -56,7 +59,7 @@ func (s *githubService) Plugin(roomID string) plugin.Plugin {
plugin.Expansion{ plugin.Expansion{
Regexp: ownerRepoIssueRegex, Regexp: ownerRepoIssueRegex,
Expand: func(roomID, userID, matchingText string) interface{} { Expand: func(roomID, userID, matchingText string) interface{} {
cli := githubClientFor(userID, true)
cli := s.githubClientFor(userID, true)
owner, repo, num, err := ownerRepoNumberFromText(matchingText) owner, repo, num, err := ownerRepoNumberFromText(matchingText)
if err != nil { if err != nil {
log.WithError(err).WithField("text", matchingText).Print( log.WithError(err).WithField("text", matchingText).Print(
@ -115,18 +118,58 @@ func (s *githubService) OnReceiveWebhook(w http.ResponseWriter, req *http.Reques
w.WriteHeader(200) w.WriteHeader(200)
} }
func (s *githubService) Register() error { func (s *githubService) Register() error {
if s.RealmID == "" || s.BotUserID == "" {
return fmt.Errorf("RealmID and BotUserID are required")
}
// check realm exists
realm, err := database.GetServiceDB().LoadAuthRealm(s.RealmID)
if err != nil {
return err
}
// make sure the realm is of the type we expect
if realm.Type() != "github" {
return fmt.Errorf("Realm is of type '%s', not 'github'", realm.Type())
}
return nil return nil
} }
func githubClientFor(userID string, allowUnauth bool) *github.Client {
var cli *github.Client
func (s *githubService) githubClientFor(userID string, allowUnauth bool) *github.Client {
token, err := getTokenForUser(s.RealmID, userID)
if err != nil {
log.WithFields(log.Fields{
log.ErrorKey: err,
"user_id": userID,
"realm_id": s.RealmID,
}).Print("Failed to get token for user")
}
if token != "" {
return githubClient(token)
} else if allowUnauth {
return githubClient("")
} else {
return nil
}
}
// TODO get the token for this user
func getTokenForUser(realmID, userID string) (string, error) {
realm, err := database.GetServiceDB().LoadAuthRealm(realmID)
if err != nil {
return "", err
}
if realm.Type() != "github" {
return "", fmt.Errorf("Bad realm type: %s", realm.Type())
}
if cli == nil && allowUnauth {
return githubClient("")
// pull out the token (TODO: should the service know how the realm stores this?)
session, err := database.GetServiceDB().LoadAuthSessionByUser(realm.ID(), userID)
if err != nil {
return "", err
}
ghSession, ok := session.(*realms.GithubSession)
if !ok {
return "", fmt.Errorf("Session is not a github session: %s", session.ID())
} }
return cli
return ghSession.AccessToken, nil
} }
// githubClient returns a github Client which can perform Github API operations. // githubClient returns a github Client which can perform Github API operations.

Loading…
Cancel
Save