From dc6d7c593a390d396f73d6481e8155c98380ef28 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Tue, 1 Nov 2016 16:45:47 +0000 Subject: [PATCH 1/7] Add lots of HTTP and API docs This all gets formatted right by godoc so we can point the README to that instead of having the docs so far away from the code. --- src/github.com/matrix-org/go-neb/api/api.go | 81 +++++++++++--- .../matrix-org/go-neb/api/handlers/auth.go | 102 ++++++++++++++++-- .../matrix-org/go-neb/api/handlers/client.go | 27 ++++- .../go-neb/api/handlers/heartbeat.go | 23 ++-- .../matrix-org/go-neb/api/handlers/service.go | 48 +++++++++ .../matrix-org/go-neb/api/handlers/webhook.go | 9 +- 6 files changed, 256 insertions(+), 34 deletions(-) diff --git a/src/github.com/matrix-org/go-neb/api/api.go b/src/github.com/matrix-org/go-neb/api/api.go index e003a6a..15029e4 100644 --- a/src/github.com/matrix-org/go-neb/api/api.go +++ b/src/github.com/matrix-org/go-neb/api/api.go @@ -1,3 +1,11 @@ +// Package api contains the fundamental data types used by Go-NEB. +// +// Most HTTP API calls and/or config file sections are just ways of representing these +// data types. +// +// See also +// +// Package "api.handlers" for information on the HTTP API calls. package api import ( @@ -8,31 +16,68 @@ import ( // ConfigureAuthRealmRequest is a request to /configureAuthRealm type ConfigureAuthRealmRequest struct { - ID string - Type string + // An arbitrary unique identifier for this auth realm. This can be anything. + // Using the same ID will REPLACE the entire AuthRealm with the new information. + ID string + // The type of auth realm. This determines which code is loaded to execute the + // auth realm. It must be a known type. + Type string + // AuthRealm specific config information. See the docs for the auth realm you're interested in. + Config json.RawMessage +} + +// RequestAuthSessionRequest is a request to /requestAuthSession +type RequestAuthSessionRequest struct { + // The realm ID to request a new auth session on. The realm MUST already exist. + RealmID string + // The user ID of user requesting the auth session. If the auth is successful, + // this user ID will be associated with the third-party credentials obtained. + UserID string + // AuthRealm specific config information. See the docs for the auth realm you're interested in. Config json.RawMessage } // ConfigureServiceRequest is a request to /configureService type ConfigureServiceRequest struct { - ID string - Type string + // An arbitrary unique identifier for this service. This can be anything. + // Using the same ID will REPLACE the entire Service with the new information. + ID string + // The type of service. This determines which code is loaded to execute the + // service. It must be a known type. + Type string + // The user ID of the configured client who will be controlled by this service. + // The user MUST already be configured. UserID string + // Service-specific config information. See the docs for the service you're interested in. Config json.RawMessage } -// A ClientConfig is the configuration for a matrix client for a bot to use. It is -// a request to /configureClient +// A ClientConfig contains the configuration information for a matrix client so that +// Go-NEB can drive it. It forms the HTTP body to /configureClient requests. type ClientConfig struct { - UserID string // The matrix UserId to connect with. - HomeserverURL string // A URL with the host and port of the matrix server. E.g. https://matrix.org:8448 - AccessToken string // The matrix access token to authenticate the requests with. - Sync bool // True to start a sync stream for this user - AutoJoinRooms bool // True to automatically join all rooms for this user - DisplayName string // The display name to set for the matrix client + // The matrix User ID to connect with. E.g. @alice:matrix.org + UserID string + // A URL with the host and port of the matrix server. E.g. https://matrix.org:8448 + HomeserverURL string + // The matrix access token to authenticate the requests with. + AccessToken string + // True to start a sync stream for this user. If false, no /sync goroutine will be + // created and this client will be unable to receive new events from Matrix. For services + // which only SEND events into Matrix, it may be desirable to set Sync to false to reduce the + // number of goroutines Go-NEB has to maintain. For services which respond to !commands, + // Sync MUST be set to true in order to receive those commands. + Sync bool + // True to automatically join every room this client is invited to. + // This is desirable for services which have !commands as that means anyone can pull the bot + // into the room. It is up to the service to decide which, if any, users to respond to however. + AutoJoinRooms bool + // The desired display name for this client. + // This does not automatically set the display name for this client. See /configureClient. + DisplayName string } -// SessionRequest are usually multi-stage things so this type only exists for the config form +// SessionRequests are usually multi-stage things so this type only exists for the config form +// for use with ConfigFile. type SessionRequest struct { SessionID string RealmID string @@ -72,7 +117,7 @@ func (c *SessionRequest) Check() error { return nil } -// Check that the client has the correct fields. +// Check that the client has supplied the correct fields. func (c *ClientConfig) Check() error { if c.UserID == "" || c.HomeserverURL == "" || c.AccessToken == "" { return errors.New(`Must supply a "UserID", a "HomeserverURL", and an "AccessToken"`) @@ -82,3 +127,11 @@ func (c *ClientConfig) Check() error { } return nil } + +// Check that the request is valid. +func (r *RequestAuthSessionRequest) Check() error { + if r.UserID == "" || r.RealmID == "" || r.Config == nil { + return errors.New(`Must supply a "UserID", a "RealmID" and a "Config"`) + } + return nil +} diff --git a/src/github.com/matrix-org/go-neb/api/handlers/auth.go b/src/github.com/matrix-org/go-neb/api/handlers/auth.go index 7c8a7cf..4179397 100644 --- a/src/github.com/matrix-org/go-neb/api/handlers/auth.go +++ b/src/github.com/matrix-org/go-neb/api/handlers/auth.go @@ -15,19 +15,36 @@ import ( "github.com/matrix-org/go-neb/types" ) +// RequestAuthSession represents an HTTP handler capable of processing /admin/requestAuthSession requests. type RequestAuthSession struct { Db *database.ServiceDB } +// OnIncomingRequest handles POST requests to /admin/requestAuthSession. The HTTP body MUST be +// a JSON object representing type "api.RequestAuthSessionRequest". +// +// This will return HTTP 400 if there are missing fields or the Realm ID is unknown. +// For the format of the response, see the specific AuthRealm that the Realm ID corresponds to. +// +// Request: +// POST /admin/requestAuthSession +// { +// "RealmID": "github_realm_id", +// "UserID": "@my_user:localhost", +// "Config": { +// // AuthRealm specific config info +// } +// } +// Response: +// HTTP/1.1 200 OK +// { +// // AuthRealm-specific information +// } func (h *RequestAuthSession) 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 - Config json.RawMessage - } + var body api.RequestAuthSessionRequest if err := json.NewDecoder(req.Body).Decode(&body); err != nil { return nil, &errors.HTTPError{err, "Error parsing request JSON", 400} } @@ -36,8 +53,8 @@ func (h *RequestAuthSession) OnIncomingRequest(req *http.Request) (interface{}, "user_id": body.UserID, }).Print("Incoming auth session request") - if body.UserID == "" || body.RealmID == "" || body.Config == nil { - return nil, &errors.HTTPError{nil, `Must supply a "UserID", a "RealmID" and a "Config"`, 400} + if err := body.Check(); err != nil { + return nil, &errors.HTTPError{err, err.Error(), 400} } realm, err := h.Db.LoadAuthRealm(body.RealmID) @@ -55,10 +72,24 @@ func (h *RequestAuthSession) OnIncomingRequest(req *http.Request) (interface{}, return response, nil } +// RemoveAuthSession represents an HTTP handler capable of processing /admin/removeAuthSession requests. type RemoveAuthSession struct { Db *database.ServiceDB } +// OnIncomingRequest handles POST requests to /admin/removeAuthSession. +// +// The JSON object MUST contain the keys "RealmID" and "UserID" to identify the session to remove. +// +// Request +// POST /admin/removeAuthSession +// { +// "RealmID": "github-realm", +// "UserID": "@my_user:localhost" +// } +// Response: +// HTTP/1.1 200 OK +// {} func (h *RemoveAuthSession) OnIncomingRequest(req *http.Request) (interface{}, *errors.HTTPError) { if req.Method != "POST" { return nil, &errors.HTTPError{nil, "Unsupported Method", 405} @@ -91,10 +122,15 @@ func (h *RemoveAuthSession) OnIncomingRequest(req *http.Request) (interface{}, * return []byte(`{}`), nil } +// RealmRedirect represents an HTTP handler which can process incoming redirects for auth realms. type RealmRedirect struct { Db *database.ServiceDB } +// Handle requests for an auth realm. +// +// The last path segment of the URL MUST be the base64 form of the Realm ID. What response +// this returns depends on the specific AuthRealm implementation. func (rh *RealmRedirect) Handle(w http.ResponseWriter, req *http.Request) { segments := strings.Split(req.URL.Path, "/") // last path segment is the base64d realm ID which we will pass the incoming request to @@ -121,10 +157,35 @@ func (rh *RealmRedirect) Handle(w http.ResponseWriter, req *http.Request) { realm.OnReceiveRedirect(w, req) } +// ConfigureAuthRealm represents an HTTP handler capable of processing /admin/configureAuthRealm requests. type ConfigureAuthRealm struct { Db *database.ServiceDB } +// OnIncomingRequest handles POST requests to /admin/configureAuthRealm. The JSON object +// provided is of type "api.ConfigureAuthRealmRequest". +// +// Request: +// POST /admin/configureAuthRealm +// { +// "ID": "my-realm-id", +// "Type": "github", +// "Config": { +// // Realm-specific configuration information +// } +// } +// Response: +// HTTP/1.1 200 OK +// { +// "ID": "my-realm-id", +// "Type": "github", +// "OldConfig": { +// // Old auth realm config information +// }, +// "NewConfig": { +// // New auth realm config information +// }, +// } func (h *ConfigureAuthRealm) OnIncomingRequest(req *http.Request) (interface{}, *errors.HTTPError) { if req.Method != "POST" { return nil, &errors.HTTPError{nil, "Unsupported Method", 405} @@ -160,10 +221,37 @@ func (h *ConfigureAuthRealm) OnIncomingRequest(req *http.Request) (interface{}, }{body.ID, body.Type, oldRealm, realm}, nil } +// GetSession represents an HTTP handler capable of processing /admin/getSession requests. type GetSession struct { Db *database.ServiceDB } +// OnIncomingRequest handles POST requests to /admin/getSession. +// +// The JSON object provided MUST have a "RealmID" and "UserID" in order to fetch the +// correct AuthSession. If there is no session for this tuple of realm and user ID, +// a 200 OK is still returned with "Authenticated" set to false. +// +// Request: +// POST /admin/getSession +// { +// "RealmID": "my-realm", +// "UserID": "@my_user:localhost" +// } +// Response: +// HTTP/1.1 200 OK +// { +// "ID": "session_id", +// "Authenticated": true, +// "Info": { +// // Session-specific config info +// } +// } +// Response if session not found: +// HTTP/1.1 200 OK +// { +// "Authenticated": false +// } func (h *GetSession) OnIncomingRequest(req *http.Request) (interface{}, *errors.HTTPError) { if req.Method != "POST" { return nil, &errors.HTTPError{nil, "Unsupported Method", 405} diff --git a/src/github.com/matrix-org/go-neb/api/handlers/client.go b/src/github.com/matrix-org/go-neb/api/handlers/client.go index 036fe2f..a814dd3 100644 --- a/src/github.com/matrix-org/go-neb/api/handlers/client.go +++ b/src/github.com/matrix-org/go-neb/api/handlers/client.go @@ -9,11 +9,36 @@ import ( "github.com/matrix-org/go-neb/errors" ) -// ConfigureClient represents an HTTP handler capable of processing /configureClient requests +// ConfigureClient represents an HTTP handler capable of processing /admin/configureClient requests. type ConfigureClient struct { Clients *clients.Clients } +// OnIncomingRequest handles POST requests to /admin/configureClient. The JSON object provided +// is of type "api.ClientConfig". +// +// If a DisplayName is supplied, this request will set this client's display name +// if the old ClientConfig DisplayName differs from the new ClientConfig DisplayName. +// +// Request: +// POST /admin/configureClient +// { +// "UserID": "@my_bot:localhost", +// "HomeserverURL": "http://localhost:8008", +// "Sync": true, +// "DisplayName": "My Bot" +// } +// +// Response: +// HTTP/1.1 200 OK +// { +// "OldClient": { +// // The old api.ClientConfig +// }, +// "NewClient": { +// // The new api.ClientConfig +// } +// } func (s *ConfigureClient) OnIncomingRequest(req *http.Request) (interface{}, *errors.HTTPError) { if req.Method != "POST" { return nil, &errors.HTTPError{nil, "Unsupported Method", 405} diff --git a/src/github.com/matrix-org/go-neb/api/handlers/heartbeat.go b/src/github.com/matrix-org/go-neb/api/handlers/heartbeat.go index 817311a..1917971 100644 --- a/src/github.com/matrix-org/go-neb/api/handlers/heartbeat.go +++ b/src/github.com/matrix-org/go-neb/api/handlers/heartbeat.go @@ -1,8 +1,17 @@ +// Package handlers contains the HTTP handlers for Go-NEB. +// +// This includes detail on the API paths and top-level JSON keys. For specific service JSON, +// see the service you're interested in. +// +// See also +// +// Package "api" for the format of the JSON request bodies. package handlers import ( - "github.com/matrix-org/go-neb/errors" "net/http" + + "github.com/matrix-org/go-neb/errors" ) // Heartbeat implements the heartbeat API @@ -11,16 +20,12 @@ type Heartbeat struct{} // OnIncomingRequest returns an empty JSON object which can be used to detect liveness of Go-NEB. // // Request: -// ``` -// GET /test -// ``` +// GET /test +// // // Response: -// ``` -// HTTP/1.1 200 OK -// Content-Type: applicatoin/json -// {} -// ``` +// HTTP/1.1 200 OK +// {} func (*Heartbeat) OnIncomingRequest(req *http.Request) (interface{}, *errors.HTTPError) { return &struct{}{}, nil } diff --git a/src/github.com/matrix-org/go-neb/api/handlers/service.go b/src/github.com/matrix-org/go-neb/api/handlers/service.go index d6478bd..4b32605 100644 --- a/src/github.com/matrix-org/go-neb/api/handlers/service.go +++ b/src/github.com/matrix-org/go-neb/api/handlers/service.go @@ -16,6 +16,7 @@ import ( "github.com/matrix-org/go-neb/types" ) +// ConfigureService represents an HTTP handler which can process /admin/configureService requests. type ConfigureService struct { db *database.ServiceDB clients *clients.Clients @@ -23,6 +24,7 @@ type ConfigureService struct { mutexByServiceID map[string]*sync.Mutex } +// NewConfigureService creates a new ConfigureService handler func NewConfigureService(db *database.ServiceDB, clients *clients.Clients) *ConfigureService { return &ConfigureService{ db: db, @@ -45,6 +47,32 @@ func (s *ConfigureService) getMutexForServiceID(serviceID string) *sync.Mutex { return m } +// OnIncomingRequest handles POST requests to /admin/configureService. +// +// The request body MUST be of type "api.ConfigureServiceRequest". +// +// Request: +// POST /admin/configureService +// { +// "ID": "my_service_id", +// "Type": "service-type", +// "UserID": "@my_bot:localhost", +// "Config": { +// // service-specific config information +// } +// } +// Response: +// HTTP/1.1 200 OK +// { +// "ID": "my_service_id", +// "Type": "service-type", +// "OldConfig": { +// // old service-specific config information +// }, +// "NewConfig": { +// // new service-specific config information +// }, +// } func (s *ConfigureService) OnIncomingRequest(req *http.Request) (interface{}, *errors.HTTPError) { if req.Method != "POST" { return nil, &errors.HTTPError{nil, "Unsupported Method", 405} @@ -123,10 +151,30 @@ func (s *ConfigureService) createService(req *http.Request) (types.Service, *err return service, nil } +// GetService represents an HTTP handler which can process /admin/getService requests. type GetService struct { Db *database.ServiceDB } +// OnIncomingRequest handles POST requests to /admin/getService. +// +// The request body MUST be a JSON body which has an "ID" key which represents +// the service ID to get. +// +// Request: +// POST /admin/getService +// { +// "ID": "my_service_id" +// } +// Response: +// HTTP/1.1 200 OK +// { +// "ID": "my_service_id", +// "Type": "github", +// "Config": { +// // service-specific config information +// } +// } func (h *GetService) OnIncomingRequest(req *http.Request) (interface{}, *errors.HTTPError) { if req.Method != "POST" { return nil, &errors.HTTPError{nil, "Unsupported Method", 405} diff --git a/src/github.com/matrix-org/go-neb/api/handlers/webhook.go b/src/github.com/matrix-org/go-neb/api/handlers/webhook.go index 392a6ff..7229bc9 100644 --- a/src/github.com/matrix-org/go-neb/api/handlers/webhook.go +++ b/src/github.com/matrix-org/go-neb/api/handlers/webhook.go @@ -2,12 +2,13 @@ package handlers import ( "encoding/base64" + "net/http" + "strings" + log "github.com/Sirupsen/logrus" "github.com/matrix-org/go-neb/clients" "github.com/matrix-org/go-neb/database" "github.com/matrix-org/go-neb/metrics" - "net/http" - "strings" ) // Webhook represents an HTTP handler capable of accepting webhook requests on behalf of services. @@ -24,7 +25,9 @@ func NewWebhook(db *database.ServiceDB, cli *clients.Clients) *Webhook { // Handle an incoming webhook HTTP request. // // The webhook MUST have a known base64 encoded service ID as the last path segment -// in order for this request to be passed to the correct service. +// in order for this request to be passed to the correct service, or else this will return +// HTTP 400. If the base64 encoded service ID is unknown, this will return HTTP 404. +// Beyond this, the exact response is determined by the specific Service implementation. func (wh *Webhook) Handle(w http.ResponseWriter, req *http.Request) { log.WithField("path", req.URL.Path).Print("Incoming webhook request") segments := strings.Split(req.URL.Path, "/") From f91f6537043632834cbbc56cc1adab938fc763df Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Tue, 1 Nov 2016 16:57:26 +0000 Subject: [PATCH 2/7] Remove API docs from README which is duplicated --- README.md | 65 ++------------------- src/github.com/matrix-org/go-neb/api/api.go | 8 +-- 2 files changed, 8 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index 6b11b44..d006463 100644 --- a/README.md +++ b/README.md @@ -108,72 +108,17 @@ Go-NEB needs to be "configured" with clients and services before it will do anyt If you run Go-NEB with a `CONFIG_FILE` environment variable, it will load that file and use it for services, clients, etc. There is a [sample configuration file](config.sample.yaml) which explains all the options. In most cases, these are *direct mappings* to the corresponding HTTP API. ## Configuring Clients -Go-NEB needs to connect as a matrix user to receive messages. Go-NEB can listen for messages as multiple matrix users. The users are configured using an HTTP API and the config is stored in the database. To create a user: -```bash -curl -X POST localhost:4050/admin/configureClient --data-binary '{ - "UserID": "@goneb:localhost:8448", - "HomeserverURL": "http://localhost:8008", - "AccessToken": "", - "Sync": true, - "AutoJoinRooms": true, - "DisplayName": "My Bot" -}' -``` - - `UserID` is the complete user ID of the client to connect as. The user MUST already exist. - - `HomeserverURL` is the complete Homeserver URL for the given user ID. - - `AccessToken` is the user's access token. - - `Sync`, if `true`, will start a `/sync` stream so this client will receive incoming messages. This is required for services which need a live stream to the server (e.g. to respond to `!commands` and expand issues). It is not required for services which do not respond to Matrix users (e.g. webhook notifications). - - `AutoJoinRooms`, if `true`, will automatically join rooms when an invite is received. This option is only valid when `Sync: true`. - - `DisplayName`, if set, will set the given user's profile display name to the string given. +Go-NEB needs to connect as a matrix user to receive messages. Go-NEB can listen for messages as multiple matrix users. The users are configured using an HTTP API and the config is stored in the database. -Go-NEB will respond with the previous configuration for this client, if one exists, as well as echo back the complete configuration for the client: - -```json -{ - "OldClient": {}, - "NewClient": { - "UserID": "@goneb:localhost:8448", - "HomeserverURL": "http://localhost:8008", - "AccessToken": "", - "Sync": true, - "AutoJoinRooms": true, - "DisplayName": "My Bot" - } -} -``` +[http://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/handlers/#ConfigureClient.OnIncomingRequest](HTTP API Docs) ## Configuring Services Services contain all the useful functionality in Go-NEB. They require a client to operate. Services are configured using an HTTP API and the config is stored in the database. Services use one of the matrix users configured on Go-NEB to send/receive matrix messages. -Every service MUST have the following fields: - - `Type` : The type of service. This determines which code is executed. - - `Id` : An arbitrary string which you can use to identify this service. - - `UserID` : A user ID of a client which has been previously configured on Go-NEB. If this user does not exist, an error will be returned. - - `Config` : A JSON object. The contents of this object depends on the service. - -The information about a Service can be retrieved based on their `Id` like so: -```bash -curl -X POST localhost:4050/admin/getService --data-binary '{ - "Id": "myserviceid" -}' -``` -This will return: -```yaml -# HTTP 200 OK -{ - "Type": "echo", - "Id": "myserviceid", - "UserID": "@goneb:localhost:8448", - "Config": {} -} -``` -If the service is not found, this will return: -```yaml -# HTTP 404 Not Found -{ "message": "Service not found" } -``` + - [http://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/handlers/#ConfigureService.OnIncomingRequest](Configuring Services (HTTP API)) + + - [http://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/handlers/#GetService.OnIncomingRequest](Retrieving Services (HTTP API)) -If you configure an existing Service (based on ID), the entire service will be replaced with the new information. ### Echo Service The simplest service. This will echo back any `!echo` command. To configure one: diff --git a/src/github.com/matrix-org/go-neb/api/api.go b/src/github.com/matrix-org/go-neb/api/api.go index 15029e4..6fb6f6a 100644 --- a/src/github.com/matrix-org/go-neb/api/api.go +++ b/src/github.com/matrix-org/go-neb/api/api.go @@ -1,7 +1,5 @@ -// Package api contains the fundamental data types used by Go-NEB. -// -// Most HTTP API calls and/or config file sections are just ways of representing these -// data types. +// Package api contains the fundamental data types used by Go-NEB. Most HTTP API calls +// and/or config file sections are just ways of representing these data types. // // See also // @@ -76,7 +74,7 @@ type ClientConfig struct { DisplayName string } -// SessionRequests are usually multi-stage things so this type only exists for the config form +// SessionRequest is usually multi-stage so this type only exists for the config form // for use with ConfigFile. type SessionRequest struct { SessionID string From a4c58ae0ee6f8dbf6e0dcf87f83608a9ad6120f4 Mon Sep 17 00:00:00 2001 From: Kegsay Date: Tue, 1 Nov 2016 16:59:49 +0000 Subject: [PATCH 3/7] Make links work --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d006463..1951b1a 100644 --- a/README.md +++ b/README.md @@ -110,14 +110,14 @@ If you run Go-NEB with a `CONFIG_FILE` environment variable, it will load that f ## Configuring Clients Go-NEB needs to connect as a matrix user to receive messages. Go-NEB can listen for messages as multiple matrix users. The users are configured using an HTTP API and the config is stored in the database. -[http://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/handlers/#ConfigureClient.OnIncomingRequest](HTTP API Docs) +[HTTP API Docs](http://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/handlers/#ConfigureClient.OnIncomingRequest) ## Configuring Services Services contain all the useful functionality in Go-NEB. They require a client to operate. Services are configured using an HTTP API and the config is stored in the database. Services use one of the matrix users configured on Go-NEB to send/receive matrix messages. - - [http://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/handlers/#ConfigureService.OnIncomingRequest](Configuring Services (HTTP API)) + - [Configuring Services (HTTP API)](http://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/handlers/#ConfigureService.OnIncomingRequest) - - [http://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/handlers/#GetService.OnIncomingRequest](Retrieving Services (HTTP API)) + - [Retrieving Services (HTTP API)](http://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/handlers/#GetService.OnIncomingRequest) ### Echo Service From 2e9eb9caa863bf639044fd6f3ee40e9cd1988ea8 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 2 Nov 2016 11:09:05 +0000 Subject: [PATCH 4/7] Revert "Make links work" This reverts commit a4c58ae0ee6f8dbf6e0dcf87f83608a9ad6120f4. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1951b1a..d006463 100644 --- a/README.md +++ b/README.md @@ -110,14 +110,14 @@ If you run Go-NEB with a `CONFIG_FILE` environment variable, it will load that f ## Configuring Clients Go-NEB needs to connect as a matrix user to receive messages. Go-NEB can listen for messages as multiple matrix users. The users are configured using an HTTP API and the config is stored in the database. -[HTTP API Docs](http://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/handlers/#ConfigureClient.OnIncomingRequest) +[http://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/handlers/#ConfigureClient.OnIncomingRequest](HTTP API Docs) ## Configuring Services Services contain all the useful functionality in Go-NEB. They require a client to operate. Services are configured using an HTTP API and the config is stored in the database. Services use one of the matrix users configured on Go-NEB to send/receive matrix messages. - - [Configuring Services (HTTP API)](http://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/handlers/#ConfigureService.OnIncomingRequest) + - [http://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/handlers/#ConfigureService.OnIncomingRequest](Configuring Services (HTTP API)) - - [Retrieving Services (HTTP API)](http://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/handlers/#GetService.OnIncomingRequest) + - [http://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/handlers/#GetService.OnIncomingRequest](Retrieving Services (HTTP API)) ### Echo Service From 81e1859cb450c88dacd6103193962eee09187edf Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 2 Nov 2016 11:09:13 +0000 Subject: [PATCH 5/7] Revert "Remove API docs from README which is duplicated" This reverts commit f91f6537043632834cbbc56cc1adab938fc763df. --- README.md | 65 +++++++++++++++++++-- src/github.com/matrix-org/go-neb/api/api.go | 8 ++- 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index d006463..6b11b44 100644 --- a/README.md +++ b/README.md @@ -108,17 +108,72 @@ Go-NEB needs to be "configured" with clients and services before it will do anyt If you run Go-NEB with a `CONFIG_FILE` environment variable, it will load that file and use it for services, clients, etc. There is a [sample configuration file](config.sample.yaml) which explains all the options. In most cases, these are *direct mappings* to the corresponding HTTP API. ## Configuring Clients -Go-NEB needs to connect as a matrix user to receive messages. Go-NEB can listen for messages as multiple matrix users. The users are configured using an HTTP API and the config is stored in the database. +Go-NEB needs to connect as a matrix user to receive messages. Go-NEB can listen for messages as multiple matrix users. The users are configured using an HTTP API and the config is stored in the database. To create a user: +```bash +curl -X POST localhost:4050/admin/configureClient --data-binary '{ + "UserID": "@goneb:localhost:8448", + "HomeserverURL": "http://localhost:8008", + "AccessToken": "", + "Sync": true, + "AutoJoinRooms": true, + "DisplayName": "My Bot" +}' +``` + - `UserID` is the complete user ID of the client to connect as. The user MUST already exist. + - `HomeserverURL` is the complete Homeserver URL for the given user ID. + - `AccessToken` is the user's access token. + - `Sync`, if `true`, will start a `/sync` stream so this client will receive incoming messages. This is required for services which need a live stream to the server (e.g. to respond to `!commands` and expand issues). It is not required for services which do not respond to Matrix users (e.g. webhook notifications). + - `AutoJoinRooms`, if `true`, will automatically join rooms when an invite is received. This option is only valid when `Sync: true`. + - `DisplayName`, if set, will set the given user's profile display name to the string given. -[http://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/handlers/#ConfigureClient.OnIncomingRequest](HTTP API Docs) +Go-NEB will respond with the previous configuration for this client, if one exists, as well as echo back the complete configuration for the client: + +```json +{ + "OldClient": {}, + "NewClient": { + "UserID": "@goneb:localhost:8448", + "HomeserverURL": "http://localhost:8008", + "AccessToken": "", + "Sync": true, + "AutoJoinRooms": true, + "DisplayName": "My Bot" + } +} +``` ## Configuring Services Services contain all the useful functionality in Go-NEB. They require a client to operate. Services are configured using an HTTP API and the config is stored in the database. Services use one of the matrix users configured on Go-NEB to send/receive matrix messages. - - [http://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/handlers/#ConfigureService.OnIncomingRequest](Configuring Services (HTTP API)) - - - [http://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/handlers/#GetService.OnIncomingRequest](Retrieving Services (HTTP API)) +Every service MUST have the following fields: + - `Type` : The type of service. This determines which code is executed. + - `Id` : An arbitrary string which you can use to identify this service. + - `UserID` : A user ID of a client which has been previously configured on Go-NEB. If this user does not exist, an error will be returned. + - `Config` : A JSON object. The contents of this object depends on the service. + +The information about a Service can be retrieved based on their `Id` like so: +```bash +curl -X POST localhost:4050/admin/getService --data-binary '{ + "Id": "myserviceid" +}' +``` +This will return: +```yaml +# HTTP 200 OK +{ + "Type": "echo", + "Id": "myserviceid", + "UserID": "@goneb:localhost:8448", + "Config": {} +} +``` +If the service is not found, this will return: +```yaml +# HTTP 404 Not Found +{ "message": "Service not found" } +``` +If you configure an existing Service (based on ID), the entire service will be replaced with the new information. ### Echo Service The simplest service. This will echo back any `!echo` command. To configure one: diff --git a/src/github.com/matrix-org/go-neb/api/api.go b/src/github.com/matrix-org/go-neb/api/api.go index 6fb6f6a..15029e4 100644 --- a/src/github.com/matrix-org/go-neb/api/api.go +++ b/src/github.com/matrix-org/go-neb/api/api.go @@ -1,5 +1,7 @@ -// Package api contains the fundamental data types used by Go-NEB. Most HTTP API calls -// and/or config file sections are just ways of representing these data types. +// Package api contains the fundamental data types used by Go-NEB. +// +// Most HTTP API calls and/or config file sections are just ways of representing these +// data types. // // See also // @@ -74,7 +76,7 @@ type ClientConfig struct { DisplayName string } -// SessionRequest is usually multi-stage so this type only exists for the config form +// SessionRequests are usually multi-stage things so this type only exists for the config form // for use with ConfigFile. type SessionRequest struct { SessionID string From c66fdd1bdbc7919f86083a5cc131d4290e4b7f3c Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 2 Nov 2016 14:46:55 +0000 Subject: [PATCH 6/7] Review comments --- src/github.com/matrix-org/go-neb/api/api.go | 24 ++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/github.com/matrix-org/go-neb/api/api.go b/src/github.com/matrix-org/go-neb/api/api.go index 15029e4..5ee438c 100644 --- a/src/github.com/matrix-org/go-neb/api/api.go +++ b/src/github.com/matrix-org/go-neb/api/api.go @@ -17,10 +17,10 @@ import ( // ConfigureAuthRealmRequest is a request to /configureAuthRealm type ConfigureAuthRealmRequest struct { // An arbitrary unique identifier for this auth realm. This can be anything. - // Using the same ID will REPLACE the entire AuthRealm with the new information. + // Using an existing ID will REPLACE the entire existing AuthRealm with the new information. ID string // The type of auth realm. This determines which code is loaded to execute the - // auth realm. It must be a known type. + // auth realm. It must be a known type. E.g. "github". Type string // AuthRealm specific config information. See the docs for the auth realm you're interested in. Config json.RawMessage @@ -30,7 +30,7 @@ type ConfigureAuthRealmRequest struct { type RequestAuthSessionRequest struct { // The realm ID to request a new auth session on. The realm MUST already exist. RealmID string - // The user ID of user requesting the auth session. If the auth is successful, + // The Matrix user ID requesting the auth session. If the auth is successful, // this user ID will be associated with the third-party credentials obtained. UserID string // AuthRealm specific config information. See the docs for the auth realm you're interested in. @@ -40,12 +40,12 @@ type RequestAuthSessionRequest struct { // ConfigureServiceRequest is a request to /configureService type ConfigureServiceRequest struct { // An arbitrary unique identifier for this service. This can be anything. - // Using the same ID will REPLACE the entire Service with the new information. + // Using an existing ID will REPLACE the entire Service with the new information. ID string // The type of service. This determines which code is loaded to execute the - // service. It must be a known type. + // service. It must be a known type, e.g. "github". Type string - // The user ID of the configured client who will be controlled by this service. + // The user ID of the configured client that this service will use to communicate with Matrix. // The user MUST already be configured. UserID string // Service-specific config information. See the docs for the service you're interested in. @@ -62,7 +62,7 @@ type ClientConfig struct { // The matrix access token to authenticate the requests with. AccessToken string // True to start a sync stream for this user. If false, no /sync goroutine will be - // created and this client will be unable to receive new events from Matrix. For services + // created and this client won't listen for new events from Matrix. For services // which only SEND events into Matrix, it may be desirable to set Sync to false to reduce the // number of goroutines Go-NEB has to maintain. For services which respond to !commands, // Sync MUST be set to true in order to receive those commands. @@ -76,9 +76,9 @@ type ClientConfig struct { DisplayName string } -// SessionRequests are usually multi-stage things so this type only exists for the config form -// for use with ConfigFile. -type SessionRequest struct { +// Sessions contain the complete auth session information for a given user on a given realm. +// They are created for use with ConfigFile. +type Session struct { SessionID string RealmID string UserID string @@ -90,7 +90,7 @@ type ConfigFile struct { Clients []ClientConfig Realms []ConfigureAuthRealmRequest Services []ConfigureServiceRequest - Sessions []SessionRequest + Sessions []Session } // Check validates the /configureService request @@ -110,7 +110,7 @@ func (c *ConfigureAuthRealmRequest) Check() error { } // Check validates the session config request -func (c *SessionRequest) Check() error { +func (c *Session) Check() error { if c.SessionID == "" || c.UserID == "" || c.RealmID == "" || c.Config == nil { return errors.New(`Must supply a "SessionID", a "RealmID", a "UserID" and a "Config"`) } From 26f115d6f96b61e8cd0c0c783da64c761fe9ec66 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 2 Nov 2016 14:47:19 +0000 Subject: [PATCH 7/7] Appease golint --- src/github.com/matrix-org/go-neb/api/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/github.com/matrix-org/go-neb/api/api.go b/src/github.com/matrix-org/go-neb/api/api.go index 5ee438c..cbb8687 100644 --- a/src/github.com/matrix-org/go-neb/api/api.go +++ b/src/github.com/matrix-org/go-neb/api/api.go @@ -76,7 +76,7 @@ type ClientConfig struct { DisplayName string } -// Sessions contain the complete auth session information for a given user on a given realm. +// Session contains the complete auth session information for a given user on a given realm. // They are created for use with ConfigFile. type Session struct { SessionID string