diff --git a/README.md b/README.md index 6000a91..2c2dea6 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,6 @@ curl -X POST localhost:4050/admin/configureService --data-binary '{ "RealmID": "mygithubrealm", "BotUserID": "@goneb:localhost", "ClientUserID": "@example:localhost", - "WebhookBaseURI": "https://public.path.to.neb", "Rooms": { "!EmwxeXCVubhskuWvaw:localhost": { "Repos": { diff --git a/src/github.com/matrix-org/go-neb/goneb.go b/src/github.com/matrix-org/go-neb/goneb.go index 692d2e2..1f59d32 100644 --- a/src/github.com/matrix-org/go-neb/goneb.go +++ b/src/github.com/matrix-org/go-neb/goneb.go @@ -8,6 +8,7 @@ import ( "github.com/matrix-org/go-neb/server" _ "github.com/matrix-org/go-neb/services/echo" _ "github.com/matrix-org/go-neb/services/github" + "github.com/matrix-org/go-neb/types" _ "github.com/mattn/go-sqlite3" "net/http" _ "net/http/pprof" @@ -18,6 +19,12 @@ func main() { bindAddress := os.Getenv("BIND_ADDRESS") databaseType := os.Getenv("DATABASE_TYPE") databaseURL := os.Getenv("DATABASE_URL") + baseURL := os.Getenv("BASE_URL") + + err := types.BaseURL(baseURL) + if err != nil { + log.Panic(err) + } db, err := database.Open(databaseType, databaseURL) if err != nil { diff --git a/src/github.com/matrix-org/go-neb/services/echo/echo.go b/src/github.com/matrix-org/go-neb/services/echo/echo.go index 3631cce..69eaf25 100644 --- a/src/github.com/matrix-org/go-neb/services/echo/echo.go +++ b/src/github.com/matrix-org/go-neb/services/echo/echo.go @@ -37,7 +37,7 @@ func (e *echoService) OnReceiveWebhook(w http.ResponseWriter, req *http.Request, } func init() { - types.RegisterService(func(serviceID string) types.Service { + types.RegisterService(func(serviceID, webhookEndpointURL string) types.Service { return &echoService{id: serviceID} }) } 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 b61ea91..f0b2bb6 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 @@ -22,13 +22,13 @@ import ( var ownerRepoIssueRegex = regexp.MustCompile("([A-z0-9-_]+)/([A-z0-9-_]+)#([0-9]+)") type githubService struct { - id string - BotUserID string - ClientUserID string - RealmID string - SecretToken string - WebhookBaseURI string - Rooms map[string]struct { // room_id => {} + id string + webhookEndpointURL string + BotUserID string + ClientUserID string + RealmID string + SecretToken string + Rooms map[string]struct { // room_id => {} Repos map[string]struct { // owner/repo => { events: ["push","issue","pull_request"] } Events []string } @@ -183,7 +183,8 @@ func (s *githubService) Register() error { // In order to register the GH service, you must have authed with GH. cli := s.githubClientFor(s.ClientUserID, false) if cli == nil { - return fmt.Errorf("User %s does not have a Github auth session.", s.ClientUserID) + return fmt.Errorf( + "User %s does not have a Github auth session with realm %s.", s.ClientUserID, realm.ID()) } return nil @@ -215,14 +216,6 @@ func (s *githubService) PostRegister(oldService types.Service) { } func modifyWebhooks(s *githubService, cli *github.Client, removeHooks bool) { - // TODO: This makes assumptions about how Go-NEB maps services to webhook endpoints. - // We should factor this out to a function called GetWebhookEndpoint(Service) or something. - trailingSlash := "" - if !strings.HasSuffix(s.WebhookBaseURI, "/") { - trailingSlash = "/" - } - webhookEndpointURL := s.WebhookBaseURI + trailingSlash + "services/hooks/" + s.id - ownerRepoSet := make(map[string]bool) for _, roomCfg := range s.Rooms { for ownerRepo := range roomCfg.Repos { @@ -244,13 +237,13 @@ func modifyWebhooks(s *githubService, cli *github.Client, removeHooks bool) { "repo": repo, }) if removeHooks { - removeHook(logger, cli, owner, repo, webhookEndpointURL) + removeHook(logger, cli, owner, repo, s.webhookEndpointURL) } else { // make a hook for all GH events since we'll filter it when we receive webhook requests name := "web" // https://developer.github.com/v3/repos/hooks/#create-a-hook cfg := map[string]interface{}{ "content_type": "json", - "url": webhookEndpointURL, + "url": s.webhookEndpointURL, } if s.SecretToken != "" { cfg["secret"] = s.SecretToken @@ -375,7 +368,10 @@ func removeHook(logger *log.Entry, cli *github.Client, owner, repo, webhookEndpo } func init() { - types.RegisterService(func(serviceID string) types.Service { - return &githubService{id: serviceID} + types.RegisterService(func(serviceID, webhookEndpointURL string) types.Service { + return &githubService{ + id: serviceID, + webhookEndpointURL: webhookEndpointURL, + } }) } 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 5e22639..ed3197d 100644 --- a/src/github.com/matrix-org/go-neb/types/types.go +++ b/src/github.com/matrix-org/go-neb/types/types.go @@ -7,6 +7,7 @@ import ( "github.com/matrix-org/go-neb/plugin" "net/http" "net/url" + "strings" ) // A ClientConfig is the configuration for a matrix client for a bot to use. @@ -39,11 +40,29 @@ type Service interface { PostRegister(oldService Service) } -var servicesByType = map[string]func(string) Service{} +var baseURL = "" + +// BaseURL sets the base URL of NEB to the url given. This URL must be accessible from the +// public internet. +func BaseURL(u string) error { + if u == "" { + return errors.New("BASE_URL not found") + } + if !strings.HasPrefix(u, "http://") && !strings.HasPrefix(u, "https://") { + return errors.New("BASE_URL must start with http[s]://") + } + if !strings.HasSuffix(u, "/") { + u = u + "/" + } + baseURL = u + return nil +} + +var servicesByType = map[string]func(string, string) Service{} // RegisterService registers a factory for creating Service instances. -func RegisterService(factory func(string) Service) { - servicesByType[factory("").ServiceType()] = factory +func RegisterService(factory func(string, string) Service) { + servicesByType[factory("", "").ServiceType()] = factory } // CreateService creates a Service of the given type and serviceID. @@ -53,7 +72,8 @@ func CreateService(serviceID, serviceType string) Service { if f == nil { return nil } - return f(serviceID) + webhookEndpointURL := baseURL + "services/hooks/" + serviceID + return f(serviceID, webhookEndpointURL) } // AuthRealm represents a place where a user can authenticate themselves.