diff --git a/src/github.com/matrix-org/go-neb/api.go b/src/github.com/matrix-org/go-neb/api.go index ff1da59..f2235c1 100644 --- a/src/github.com/matrix-org/go-neb/api.go +++ b/src/github.com/matrix-org/go-neb/api.go @@ -1,6 +1,7 @@ package main import ( + "database/sql" "encoding/json" log "github.com/Sirupsen/logrus" "github.com/matrix-org/go-neb/clients" @@ -228,3 +229,72 @@ func (s *configureServiceHandler) OnIncomingRequest(req *http.Request) (interfac NewConfig types.Service }{body.ID, body.Type, oldService, service}, nil } + +type getServiceHandler struct { + db *database.ServiceDB +} + +func (h *getServiceHandler) OnIncomingRequest(req *http.Request) (interface{}, *errors.HTTPError) { + if req.Method != "POST" { + return nil, &errors.HTTPError{nil, "Unsupported Method", 405} + } + var body struct { + ID string + } + if err := json.NewDecoder(req.Body).Decode(&body); err != nil { + return nil, &errors.HTTPError{err, "Error parsing request JSON", 400} + } + + if body.ID == "" { + return nil, &errors.HTTPError{nil, `Must supply a "ID"`, 400} + } + + srv, err := h.db.LoadService(body.ID) + if err != nil { + if err == sql.ErrNoRows { + return nil, &errors.HTTPError{err, `Service not found`, 404} + } + return nil, &errors.HTTPError{err, `Failed to load service`, 500} + } + + return &struct { + ID string + Type string + Config types.Service + }{srv.ServiceID(), srv.ServiceType(), srv}, nil +} + +type getSessionHandler struct { + db *database.ServiceDB +} + +func (h *getSessionHandler) OnIncomingRequest(req *http.Request) (interface{}, *errors.HTTPError) { + if req.Method != "POST" { + return nil, &errors.HTTPError{nil, "Unsupported Method", 405} + } + var body struct { + RealmID string + UserID string + } + if err := json.NewDecoder(req.Body).Decode(&body); err != nil { + return nil, &errors.HTTPError{err, "Error parsing request JSON", 400} + } + + if body.RealmID == "" || body.UserID == "" { + return nil, &errors.HTTPError{nil, `Must supply a "RealmID" and "UserID"`, 400} + } + + session, err := h.db.LoadAuthSessionByUser(body.RealmID, body.UserID) + if err != nil { + if err == sql.ErrNoRows { + return nil, &errors.HTTPError{err, `Session not found`, 404} + } + return nil, &errors.HTTPError{err, `Failed to load session`, 500} + } + + return &struct { + ID string + Authenticated bool + Session types.AuthSession + }{session.ID(), session.Authenticated(), session}, nil +} diff --git a/src/github.com/matrix-org/go-neb/goneb.go b/src/github.com/matrix-org/go-neb/goneb.go index 2e22ef9..9a93067 100644 --- a/src/github.com/matrix-org/go-neb/goneb.go +++ b/src/github.com/matrix-org/go-neb/goneb.go @@ -40,6 +40,8 @@ func main() { } http.Handle("/test", server.MakeJSONAPI(&heartbeatHandler{})) + http.Handle("/admin/getService", server.MakeJSONAPI(&getServiceHandler{db: db})) + http.Handle("/admin/getSession", server.MakeJSONAPI(&getSessionHandler{db: db})) http.Handle("/admin/configureClient", server.MakeJSONAPI(&configureClientHandler{db: db, clients: clients})) http.Handle("/admin/configureService", server.MakeJSONAPI(&configureServiceHandler{db: db, clients: clients})) http.Handle("/admin/configureAuthRealm", server.MakeJSONAPI(&configureAuthRealmHandler{db: db})) diff --git a/src/github.com/matrix-org/go-neb/realms/github/github.go b/src/github.com/matrix-org/go-neb/realms/github/github.go index 7d624e4..5ce18b1 100644 --- a/src/github.com/matrix-org/go-neb/realms/github/github.go +++ b/src/github.com/matrix-org/go-neb/realms/github/github.go @@ -12,11 +12,13 @@ import ( "net/url" ) -type githubRealm struct { +// GithubRealm can handle OAuth processes with github.com +type GithubRealm struct { id string redirectURL string ClientSecret string ClientID string + StarterLink string } // GithubSession represents an authenticated github session @@ -30,6 +32,11 @@ type GithubSession struct { realmID string } +// Authenticated returns true if the user has completed the auth process +func (s *GithubSession) Authenticated() bool { + return s.AccessToken != "" +} + // UserID returns the user_id who authorised with Github func (s *GithubSession) UserID() string { return s.userID @@ -45,23 +52,28 @@ func (s *GithubSession) ID() string { return s.id } -func (r *githubRealm) ID() string { +// ID returns the realm ID +func (r *GithubRealm) ID() string { return r.id } -func (r *githubRealm) Type() string { +// Type is github +func (r *GithubRealm) Type() string { return "github" } -func (r *githubRealm) Init() error { +// Init does nothing. +func (r *GithubRealm) Init() error { return nil } -func (r *githubRealm) Register() error { +// Register does nothing. +func (r *GithubRealm) Register() error { return nil } -func (r *githubRealm) RequestAuthSession(userID string, req json.RawMessage) interface{} { +// RequestAuthSession generates an OAuth2 URL for this user to auth with github via. +func (r *GithubRealm) RequestAuthSession(userID string, req json.RawMessage) interface{} { state, err := randomString(10) if err != nil { log.WithError(err).Print("Failed to generate state param") @@ -90,7 +102,8 @@ func (r *githubRealm) RequestAuthSession(userID string, req json.RawMessage) int }{u.String()} } -func (r *githubRealm) OnReceiveRedirect(w http.ResponseWriter, req *http.Request) { +// OnReceiveRedirect processes OAuth redirect requests from Github +func (r *GithubRealm) OnReceiveRedirect(w http.ResponseWriter, req *http.Request) { // parse out params from the request code := req.URL.Query().Get("code") state := req.URL.Query().Get("state") @@ -148,7 +161,8 @@ func (r *githubRealm) OnReceiveRedirect(w http.ResponseWriter, req *http.Request w.Write([]byte("OK!")) } -func (r *githubRealm) AuthSession(id, userID, realmID string) types.AuthSession { +// AuthSession returns a GithubSession for this user +func (r *GithubRealm) AuthSession(id, userID, realmID string) types.AuthSession { return &GithubSession{ id: id, userID: userID, @@ -175,6 +189,6 @@ func randomString(length int) (string, error) { func init() { types.RegisterAuthRealm(func(realmID, redirectURL string) types.AuthRealm { - return &githubRealm{id: realmID, redirectURL: redirectURL} + return &GithubRealm{id: realmID, redirectURL: redirectURL} }) } diff --git a/src/github.com/matrix-org/go-neb/realms/jira/jira.go b/src/github.com/matrix-org/go-neb/realms/jira/jira.go index 68532cc..765f2a8 100644 --- a/src/github.com/matrix-org/go-neb/realms/jira/jira.go +++ b/src/github.com/matrix-org/go-neb/realms/jira/jira.go @@ -47,6 +47,11 @@ type JIRASession struct { AccessSecret string } +// Authenticated returns true if the user has completed the auth process +func (s *JIRASession) Authenticated() bool { + return s.AccessToken != "" && s.AccessSecret != "" +} + // UserID returns the ID of the user performing the authentication. func (s *JIRASession) UserID() string { return s.userID diff --git a/src/github.com/matrix-org/go-neb/services/github/github.go b/src/github.com/matrix-org/go-neb/services/github/github.go index 75bc820..e363c79 100644 --- a/src/github.com/matrix-org/go-neb/services/github/github.go +++ b/src/github.com/matrix-org/go-neb/services/github/github.go @@ -28,7 +28,6 @@ type githubService struct { ClientUserID string RealmID string SecretToken string - StarterLink string Rooms map[string]struct { // room_id => {} Repos map[string]struct { // owner/repo => { events: ["push","issue","pull_request"] } Events []string @@ -50,9 +49,17 @@ func (s *githubService) RoomIDs() []string { func (s *githubService) cmdGithubCreate(roomID, userID string, args []string) (interface{}, error) { cli := s.githubClientFor(userID, false) if cli == nil { + r, err := database.GetServiceDB().LoadAuthRealm(s.RealmID) + if err != nil { + return nil, err + } + ghRealm, ok := r.(*realms.GithubRealm) + if !ok { + return nil, fmt.Errorf("Failed to cast realm %s into a GithubRealm", s.RealmID) + } return matrix.StarterLinkMessage{ Body: "You need to OAuth with Github before you can create issues.", - Link: s.StarterLink, + Link: ghRealm.StarterLink, }, nil } diff --git a/src/github.com/matrix-org/go-neb/types/types.go b/src/github.com/matrix-org/go-neb/types/types.go index 14febc5..5e68cfe 100644 --- a/src/github.com/matrix-org/go-neb/types/types.go +++ b/src/github.com/matrix-org/go-neb/types/types.go @@ -123,4 +123,5 @@ type AuthSession interface { ID() string UserID() string RealmID() string + Authenticated() bool }