mirror of
https://github.com/hoernschen/dendrite.git
synced 2024-12-29 08:18:27 +00:00
Third Party Proxy Support, 3PL endpoints authed
This commit is contained in:
parent
2bd33d4168
commit
2e6eff2012
15 changed files with 394 additions and 109 deletions
|
@ -23,12 +23,11 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/matrix-org/dendrite/appservice/types"
|
||||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||||
"github.com/matrix-org/dendrite/clientapi/auth/storage/accounts"
|
"github.com/matrix-org/dendrite/clientapi/auth/storage/accounts"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/appservice/types"
|
|
||||||
commonHTTP "github.com/matrix-org/dendrite/common/http"
|
commonHTTP "github.com/matrix-org/dendrite/common/http"
|
||||||
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
opentracing "github.com/opentracing/opentracing-go"
|
opentracing "github.com/opentracing/opentracing-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -75,7 +74,7 @@ type GetProtocolDefinitionRequest struct {
|
||||||
// GetProtocolDefinitionResponse is a response providing a protocol definition
|
// GetProtocolDefinitionResponse is a response providing a protocol definition
|
||||||
// for the given protocol ID
|
// for the given protocol ID
|
||||||
type GetProtocolDefinitionResponse struct {
|
type GetProtocolDefinitionResponse struct {
|
||||||
ProtocolDefinition string `json:"protocol_definition"`
|
ProtocolDefinition gomatrixserverlib.RawJSON `json:"protocol_definition"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllProtocolDefinitionsRequest is a request to the appservice component
|
// GetAllProtocolDefinitionsRequest is a request to the appservice component
|
||||||
|
@ -89,6 +88,22 @@ type GetAllProtocolDefinitionsResponse struct {
|
||||||
Protocols types.ThirdPartyProtocols `json:"protocols"`
|
Protocols types.ThirdPartyProtocols `json:"protocols"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ThirdPartyProxyRequest is a request from a client to a third party lookup
|
||||||
|
// endpoint on an application service. The job of the homeserver is simply to
|
||||||
|
// proxy the request, thus the same request/response format can be use for each
|
||||||
|
// third party lookup endpoint.
|
||||||
|
type ThirdPartyProxyRequest struct {
|
||||||
|
ProtocolID string `json:"protocol_id"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
Content gomatrixserverlib.RawJSON `json:"content"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ThirdPartyProxyResponse is a response from an application service to a client
|
||||||
|
// about a third party lookup request.
|
||||||
|
type ThirdPartyProxyResponse struct {
|
||||||
|
Content gomatrixserverlib.RawJSON `json:"content"`
|
||||||
|
}
|
||||||
|
|
||||||
// AppServiceQueryAPI is used to query user and room alias data from application
|
// AppServiceQueryAPI is used to query user and room alias data from application
|
||||||
// services
|
// services
|
||||||
type AppServiceQueryAPI interface {
|
type AppServiceQueryAPI interface {
|
||||||
|
@ -116,6 +131,11 @@ type AppServiceQueryAPI interface {
|
||||||
req *GetAllProtocolDefinitionsRequest,
|
req *GetAllProtocolDefinitionsRequest,
|
||||||
response *GetAllProtocolDefinitionsResponse,
|
response *GetAllProtocolDefinitionsResponse,
|
||||||
) error
|
) error
|
||||||
|
ThirdPartyProxy(
|
||||||
|
ctx context.Context,
|
||||||
|
req *ThirdPartyProxyRequest,
|
||||||
|
response *ThirdPartyProxyResponse,
|
||||||
|
) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// RoomAliasExistsPath is the HTTP path for the RoomAliasExists API
|
// RoomAliasExistsPath is the HTTP path for the RoomAliasExists API
|
||||||
|
@ -130,6 +150,9 @@ const GetAllProtocolDefinitionsPath = "/api/appservice/GetAllProtocolDefinitions
|
||||||
// AppServiceUserIDExistsPath is the HTTP path for the UserIDExists API
|
// AppServiceUserIDExistsPath is the HTTP path for the UserIDExists API
|
||||||
const AppServiceUserIDExistsPath = "/api/appservice/UserIDExists"
|
const AppServiceUserIDExistsPath = "/api/appservice/UserIDExists"
|
||||||
|
|
||||||
|
// ThirdPartyProxyPath is the HTTP path for the ThirdPartyProxy API
|
||||||
|
const ThirdPartyProxyPath = "/api/appservice/ThirdPartyProxy"
|
||||||
|
|
||||||
// httpAppServiceQueryAPI contains the URL to an appservice query API and a
|
// httpAppServiceQueryAPI contains the URL to an appservice query API and a
|
||||||
// reference to a httpClient used to reach it
|
// reference to a httpClient used to reach it
|
||||||
type httpAppServiceQueryAPI struct {
|
type httpAppServiceQueryAPI struct {
|
||||||
|
@ -244,3 +267,16 @@ func RetreiveUserProfile(
|
||||||
// profile should not be nil at this point
|
// profile should not be nil at this point
|
||||||
return profile, nil
|
return profile, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ThirdPartyProxy implements AppServiceQueryAPI
|
||||||
|
func (h *httpAppServiceQueryAPI) ThirdPartyProxy(
|
||||||
|
ctx context.Context,
|
||||||
|
request *ThirdPartyProxyRequest,
|
||||||
|
response *ThirdPartyProxyResponse,
|
||||||
|
) error {
|
||||||
|
span, ctx := opentracing.StartSpanFromContext(ctx, "appserviceThirdPartyProxy")
|
||||||
|
defer span.Finish()
|
||||||
|
|
||||||
|
apiURL := h.appserviceURL + ThirdPartyProxyPath
|
||||||
|
return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
|
||||||
|
}
|
||||||
|
|
|
@ -133,7 +133,10 @@ func setupWorkers(
|
||||||
workerStates []types.ApplicationServiceWorkerState,
|
workerStates []types.ApplicationServiceWorkerState,
|
||||||
) {
|
) {
|
||||||
// Clear all old protocol definitions on startup
|
// Clear all old protocol definitions on startup
|
||||||
appserviceDB.ClearProtocolDefinitions(context.TODO())
|
err := appserviceDB.ClearProtocolDefinitions(context.TODO())
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Fatalf("unable to clear appservice protocol definitions from db")
|
||||||
|
}
|
||||||
|
|
||||||
// Create a worker that handles transmitting events to a single homeserver
|
// Create a worker that handles transmitting events to a single homeserver
|
||||||
for _, workerState := range workerStates {
|
for _, workerState := range workerStates {
|
||||||
|
|
|
@ -17,23 +17,31 @@
|
||||||
package query
|
package query
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/appservice/api"
|
"github.com/matrix-org/dendrite/appservice/api"
|
||||||
"github.com/matrix-org/dendrite/appservice/storage"
|
"github.com/matrix-org/dendrite/appservice/storage"
|
||||||
"github.com/matrix-org/dendrite/common"
|
"github.com/matrix-org/dendrite/common"
|
||||||
"github.com/matrix-org/dendrite/common/config"
|
"github.com/matrix-org/dendrite/common/config"
|
||||||
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
opentracing "github.com/opentracing/opentracing-go"
|
opentracing "github.com/opentracing/opentracing-go"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
const roomAliasExistsPath = "/rooms/"
|
const (
|
||||||
const userIDExistsPath = "/users/"
|
roomAliasExistsPath = "/rooms/"
|
||||||
|
userIDExistsPath = "/users/"
|
||||||
|
)
|
||||||
|
|
||||||
// AppServiceQueryAPI is an implementation of api.AppServiceQueryAPI
|
// AppServiceQueryAPI is an implementation of api.AppServiceQueryAPI
|
||||||
type AppServiceQueryAPI struct {
|
type AppServiceQueryAPI struct {
|
||||||
|
@ -42,44 +50,6 @@ type AppServiceQueryAPI struct {
|
||||||
Db *storage.Database
|
Db *storage.Database
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetProtocolDefinition queries the database for the protocol definition of a
|
|
||||||
// protocol with given ID
|
|
||||||
func (a *AppServiceQueryAPI) GetProtocolDefinition(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.GetProtocolDefinitionRequest,
|
|
||||||
response *api.GetProtocolDefinitionResponse,
|
|
||||||
) error {
|
|
||||||
span, ctx := opentracing.StartSpanFromContext(ctx, "ApplicationServiceGetProtocolDefinition")
|
|
||||||
defer span.Finish()
|
|
||||||
|
|
||||||
protocolDefinition, err := a.Db.GetProtocolDefinition(ctx, request.ProtocolID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ProtocolDefinition = protocolDefinition
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAllProtocolDefinitions queries the database for all known protocol
|
|
||||||
// definitions and their IDs
|
|
||||||
func (a *AppServiceQueryAPI) GetAllProtocolDefinitions(
|
|
||||||
ctx context.Context,
|
|
||||||
request *api.GetAllProtocolDefinitionsRequest,
|
|
||||||
response *api.GetAllProtocolDefinitionsResponse,
|
|
||||||
) error {
|
|
||||||
span, ctx := opentracing.StartSpanFromContext(ctx, "ApplicationServiceGetAllProtocolDefinitions")
|
|
||||||
defer span.Finish()
|
|
||||||
|
|
||||||
protocolDefinitions, err := a.Db.GetAllProtocolDefinitions(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
response.Protocols = protocolDefinitions
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RoomAliasExists performs a request to '/room/{roomAlias}' on all known
|
// RoomAliasExists performs a request to '/room/{roomAlias}' on all known
|
||||||
// handling application services until one admits to owning the room
|
// handling application services until one admits to owning the room
|
||||||
func (a *AppServiceQueryAPI) RoomAliasExists(
|
func (a *AppServiceQueryAPI) RoomAliasExists(
|
||||||
|
@ -100,6 +70,10 @@ func (a *AppServiceQueryAPI) RoomAliasExists(
|
||||||
if appservice.URL != "" && appservice.IsInterestedInRoomAlias(request.Alias) {
|
if appservice.URL != "" && appservice.IsInterestedInRoomAlias(request.Alias) {
|
||||||
// The full path to the rooms API, includes hs token
|
// The full path to the rooms API, includes hs token
|
||||||
URL, err := url.Parse(appservice.URL + roomAliasExistsPath)
|
URL, err := url.Parse(appservice.URL + roomAliasExistsPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
URL.Path += request.Alias
|
URL.Path += request.Alias
|
||||||
apiURL := URL.String() + "?access_token=" + appservice.HSToken
|
apiURL := URL.String() + "?access_token=" + appservice.HSToken
|
||||||
|
|
||||||
|
@ -110,14 +84,13 @@ func (a *AppServiceQueryAPI) RoomAliasExists(
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
req = req.WithContext(ctx)
|
req = req.WithContext(ctx)
|
||||||
|
|
||||||
resp, err := a.HTTPClient.Do(req)
|
resp, err := a.HTTPClient.Do(req)
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
defer func() {
|
defer func() {
|
||||||
err = resp.Body.Close()
|
err = resp.Body.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"appservice_id": appservice.ID,
|
"appservice": appservice.ID,
|
||||||
"status_code": resp.StatusCode,
|
"status_code": resp.StatusCode,
|
||||||
}).WithError(err).Error("Unable to close application service response body")
|
}).WithError(err).Error("Unable to close application service response body")
|
||||||
}
|
}
|
||||||
|
@ -137,7 +110,7 @@ func (a *AppServiceQueryAPI) RoomAliasExists(
|
||||||
default:
|
default:
|
||||||
// Application service reported an error. Warn
|
// Application service reported an error. Warn
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"appservice_id": appservice.ID,
|
"appservice": appservice.ID,
|
||||||
"status_code": resp.StatusCode,
|
"status_code": resp.StatusCode,
|
||||||
}).Warn("Application service responded with non-OK status code")
|
}).Warn("Application service responded with non-OK status code")
|
||||||
}
|
}
|
||||||
|
@ -177,33 +150,29 @@ func (a *AppServiceQueryAPI) UserIDExists(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
resp, err := a.HTTPClient.Do(req.WithContext(ctx))
|
req = req.WithContext(ctx)
|
||||||
|
|
||||||
|
// Make a request to the application service
|
||||||
|
resp, err := a.HTTPClient.Do(req)
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
defer func() {
|
defer resp.Body.Close() // nolint: errcheck
|
||||||
err = resp.Body.Close()
|
|
||||||
if err != nil {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"appservice_id": appservice.ID,
|
|
||||||
"status_code": resp.StatusCode,
|
|
||||||
}).Error("Unable to close application service response body")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"appservice_id": appservice.ID,
|
"appservice": appservice.ID,
|
||||||
}).WithError(err).Error("issue querying user ID on application service")
|
}).WithError(err).Error("issue querying user ID on application service")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if resp.StatusCode == http.StatusOK {
|
if resp.StatusCode == http.StatusOK {
|
||||||
// StatusOK received from appservice. User ID exists
|
// StatusOK received from appservice. User ID exists
|
||||||
response.UserIDExists = true
|
response.UserIDExists = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log non OK
|
// Log if return code is not OK
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"appservice_id": appservice.ID,
|
"appservice": appservice.ID,
|
||||||
"status_code": resp.StatusCode,
|
"status_code": resp.StatusCode,
|
||||||
}).Warn("application service responded with non-OK status code")
|
}).Warn("application service responded with non-OK status code")
|
||||||
}
|
}
|
||||||
|
@ -213,6 +182,180 @@ func (a *AppServiceQueryAPI) UserIDExists(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetProtocolDefinition queries the database for the protocol definition of a
|
||||||
|
// protocol with given ID
|
||||||
|
func (a *AppServiceQueryAPI) GetProtocolDefinition(
|
||||||
|
ctx context.Context,
|
||||||
|
request *api.GetProtocolDefinitionRequest,
|
||||||
|
response *api.GetProtocolDefinitionResponse,
|
||||||
|
) error {
|
||||||
|
span, ctx := opentracing.StartSpanFromContext(ctx, "ApplicationServiceGetProtocolDefinition")
|
||||||
|
defer span.Finish()
|
||||||
|
|
||||||
|
protocolDefinition, err := a.Db.GetProtocolDefinition(ctx, request.ProtocolID)
|
||||||
|
if err != nil && err != sql.ErrNoRows {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
response.ProtocolDefinition = gomatrixserverlib.RawJSON(protocolDefinition)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAllProtocolDefinitions queries the database for all known protocol
|
||||||
|
// definitions and their IDs
|
||||||
|
func (a *AppServiceQueryAPI) GetAllProtocolDefinitions(
|
||||||
|
ctx context.Context,
|
||||||
|
request *api.GetAllProtocolDefinitionsRequest,
|
||||||
|
response *api.GetAllProtocolDefinitionsResponse,
|
||||||
|
) error {
|
||||||
|
span, ctx := opentracing.StartSpanFromContext(ctx, "ApplicationServiceGetAllProtocolDefinitions")
|
||||||
|
defer span.Finish()
|
||||||
|
|
||||||
|
protocolDefinitions, err := a.Db.GetAllProtocolDefinitions(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Protocols = protocolDefinitions
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ThirdPartyProxy will proxy a request for third party lookup information from
|
||||||
|
// a client to a connected application service. If a protocol ID is specified,
|
||||||
|
// the application service that handles it will solely be contacted, otherwise
|
||||||
|
// all application services will be contacted and their responses concatenated
|
||||||
|
func (a *AppServiceQueryAPI) ThirdPartyProxy(
|
||||||
|
ctx context.Context,
|
||||||
|
request *api.ThirdPartyProxyRequest,
|
||||||
|
response *api.ThirdPartyProxyResponse,
|
||||||
|
) error {
|
||||||
|
span, ctx := opentracing.StartSpanFromContext(ctx, "ApplicationServiceGetAllProtocolDefinitions")
|
||||||
|
defer span.Finish()
|
||||||
|
|
||||||
|
// Create an HTTP client if one does not already exist
|
||||||
|
if a.HTTPClient == nil {
|
||||||
|
a.HTTPClient = makeHTTPClient()
|
||||||
|
}
|
||||||
|
|
||||||
|
appservicesToContact := make([]config.ApplicationService, 0, len(a.Cfg.Derived.ApplicationServices))
|
||||||
|
if request.ProtocolID == "" {
|
||||||
|
// If no protocol ID was specified, send the request to all known application
|
||||||
|
// services in parallel and stitch together the results
|
||||||
|
appservicesToContact = a.Cfg.Derived.ApplicationServices
|
||||||
|
} else {
|
||||||
|
// Otherwise simply proxy the request to the application services handling
|
||||||
|
// this protocol and return the result
|
||||||
|
for _, as := range a.Cfg.Derived.ApplicationServices {
|
||||||
|
for _, protocol := range as.Protocols {
|
||||||
|
if request.ProtocolID == protocol {
|
||||||
|
appservicesToContact = append(appservicesToContact, as)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contact each application service in parallel, wait for all to finish before continuing
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
var err error
|
||||||
|
responseSlice := make([]interface{}, 0)
|
||||||
|
for _, appservice := range appservicesToContact {
|
||||||
|
// Increment goroutine waitgroup counter
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
go func(ctx context.Context,
|
||||||
|
h *http.Client,
|
||||||
|
req *api.ThirdPartyProxyRequest,
|
||||||
|
as config.ApplicationService,
|
||||||
|
r *[]interface{},
|
||||||
|
) {
|
||||||
|
// Decrement waitgroup counter once the request has finished
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
// Contact the application service, return nil or error if something went wrong
|
||||||
|
contactApplicationService(ctx, h, req, as, r)
|
||||||
|
}(ctx, a.HTTPClient, request, appservice, &responseSlice)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for all requests to finish
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
// Convert the slice of responses back to JSON
|
||||||
|
response.Content, err = json.Marshal(responseSlice)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// contactApplicationService proxies a third party lookup request to an
|
||||||
|
// application service
|
||||||
|
func contactApplicationService(
|
||||||
|
ctx context.Context,
|
||||||
|
httpClient *http.Client,
|
||||||
|
request *api.ThirdPartyProxyRequest,
|
||||||
|
as config.ApplicationService,
|
||||||
|
responseSlice *[]interface{},
|
||||||
|
) {
|
||||||
|
// Build the request with body and parameters to the application service
|
||||||
|
if as.URL == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a request to each application service. If one responds that it has
|
||||||
|
// created the room, immediately return.
|
||||||
|
requestURL := as.URL + request.Path
|
||||||
|
req, err := http.NewRequest(http.MethodGet, requestURL, bytes.NewReader(request.Content))
|
||||||
|
if err != nil {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"appservice": as.ID,
|
||||||
|
}).WithError(err).Error("problem building proxy request to application service")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req = req.WithContext(ctx)
|
||||||
|
|
||||||
|
// Make a request to the application service
|
||||||
|
resp, err := httpClient.Do(req)
|
||||||
|
if resp != nil {
|
||||||
|
defer resp.Body.Close() // nolint: errcheck
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"appservice": as.ID,
|
||||||
|
}).WithError(err).Warn("unable to proxy request to application service")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"appservice": as.ID,
|
||||||
|
"status_code": resp.StatusCode,
|
||||||
|
}).Warn("non-OK response from application server while proxying request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal response body into a generic slice and append to the slice of
|
||||||
|
// existing responses, to eventually be returned to the client
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"appservice": as.ID,
|
||||||
|
}).WithError(err).Warn("unable to read response from application server while proxying request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Temporary slice to unmarshal into
|
||||||
|
querySlice := make([]interface{}, 0)
|
||||||
|
err = json.Unmarshal(body, &querySlice)
|
||||||
|
if err != nil {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"appservice": as.ID,
|
||||||
|
}).WithError(err).Warn("unable to unmarshal response from application server while proxying request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append to existing responses
|
||||||
|
fmt.Println("Adding", querySlice)
|
||||||
|
*responseSlice = append(*responseSlice, querySlice...)
|
||||||
|
}
|
||||||
|
|
||||||
// makeHTTPClient creates an HTTP client with certain options that will be used for all query requests to application services
|
// makeHTTPClient creates an HTTP client with certain options that will be used for all query requests to application services
|
||||||
func makeHTTPClient() *http.Client {
|
func makeHTTPClient() *http.Client {
|
||||||
return &http.Client{
|
return &http.Client{
|
||||||
|
@ -279,4 +422,21 @@ func (a *AppServiceQueryAPI) SetupHTTP(servMux *http.ServeMux) {
|
||||||
return util.JSONResponse{Code: http.StatusOK, JSON: &response}
|
return util.JSONResponse{Code: http.StatusOK, JSON: &response}
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
servMux.Handle(
|
||||||
|
api.ThirdPartyProxyPath,
|
||||||
|
common.MakeInternalAPI("appserviceThirdPartyProxy", func(req *http.Request) util.JSONResponse {
|
||||||
|
var request api.ThirdPartyProxyRequest
|
||||||
|
var response api.ThirdPartyProxyResponse
|
||||||
|
if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
|
||||||
|
return util.ErrorResponse(err)
|
||||||
|
}
|
||||||
|
if err := a.ThirdPartyProxy(req.Context(), &request, &response); err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return util.JSONResponse{Code: http.StatusNotFound, JSON: &response}
|
||||||
|
}
|
||||||
|
return util.ErrorResponse(err)
|
||||||
|
}
|
||||||
|
return util.JSONResponse{Code: http.StatusOK, JSON: &response}
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,12 @@ import (
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
const pathPrefixApp = "/_matrix/app/r0"
|
const (
|
||||||
|
// PathPrefixApp for current stable application services API version
|
||||||
|
PathPrefixApp = "/_matrix/app/r0"
|
||||||
|
// PathPrefixAppUnstable is the unstable application services API version
|
||||||
|
PathPrefixAppUnstable = "/_matrix/app/unstable"
|
||||||
|
)
|
||||||
|
|
||||||
// Setup registers HTTP handlers with the given ServeMux. It also supplies the given http.Client
|
// Setup registers HTTP handlers with the given ServeMux. It also supplies the given http.Client
|
||||||
// to clients which need to make outbound HTTP requests.
|
// to clients which need to make outbound HTTP requests.
|
||||||
|
@ -38,7 +43,7 @@ func Setup(
|
||||||
federation *gomatrixserverlib.FederationClient, // nolint: unparam
|
federation *gomatrixserverlib.FederationClient, // nolint: unparam
|
||||||
transactionsCache *transactions.Cache, // nolint: unparam
|
transactionsCache *transactions.Cache, // nolint: unparam
|
||||||
) {
|
) {
|
||||||
appMux := apiMux.PathPrefix(pathPrefixApp).Subrouter()
|
appMux := apiMux.PathPrefix(PathPrefixApp).Subrouter()
|
||||||
|
|
||||||
appMux.Handle("/alias",
|
appMux.Handle("/alias",
|
||||||
common.MakeExternalAPI("alias", func(req *http.Request) util.JSONResponse {
|
common.MakeExternalAPI("alias", func(req *http.Request) util.JSONResponse {
|
||||||
|
|
|
@ -139,7 +139,7 @@ func (d *Database) StoreProtocolDefinition(
|
||||||
return d.thirdparty.insertProtocolDefinition(ctx, protocolID, protocolDefinition)
|
return d.thirdparty.insertProtocolDefinition(ctx, protocolID, protocolDefinition)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearProtocolDefinition clears all protocol definition entries in the
|
// ClearProtocolDefinitions clears all protocol definition entries in the
|
||||||
// database. This is done on each startup to wipe old protocol definitions from
|
// database. This is done on each startup to wipe old protocol definitions from
|
||||||
// previous application services.
|
// previous application services.
|
||||||
func (d *Database) ClearProtocolDefinitions(
|
func (d *Database) ClearProtocolDefinitions(
|
||||||
|
|
|
@ -26,8 +26,10 @@ import (
|
||||||
const thirdPartySchema = `
|
const thirdPartySchema = `
|
||||||
-- Stores protocol definitions for clients to later request
|
-- Stores protocol definitions for clients to later request
|
||||||
CREATE TABLE IF NOT EXISTS appservice_third_party_protocol_def (
|
CREATE TABLE IF NOT EXISTS appservice_third_party_protocol_def (
|
||||||
-- The ID of the procotol
|
-- The ID of the protocol
|
||||||
protocol_id TEXT NOT NULL PRIMARY KEY,
|
protocol_id TEXT NOT NULL PRIMARY KEY,
|
||||||
|
-- The URL of the application service handling this protocol
|
||||||
|
appservice_url TEXT NOT NULL,
|
||||||
-- The JSON-encoded protocol definition
|
-- The JSON-encoded protocol definition
|
||||||
protocol_definition TEXT NOT NULL,
|
protocol_definition TEXT NOT NULL,
|
||||||
UNIQUE(protocol_id)
|
UNIQUE(protocol_id)
|
||||||
|
@ -106,6 +108,7 @@ func (s *thirdPartyStatements) selectAllProtocolDefinitions(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
) (protocols types.ThirdPartyProtocols, err error) {
|
) (protocols types.ThirdPartyProtocols, err error) {
|
||||||
protocolDefinitionRows, err := s.selectAllProtocolDefinitionsStmt.QueryContext(ctx)
|
protocolDefinitionRows, err := s.selectAllProtocolDefinitionsStmt.QueryContext(ctx)
|
||||||
|
protocols = make(types.ThirdPartyProtocols)
|
||||||
if err != nil && err != sql.ErrNoRows {
|
if err != nil && err != sql.ErrNoRows {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -116,12 +119,14 @@ func (s *thirdPartyStatements) selectAllProtocolDefinitions(
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// Extract protocol information from each row
|
||||||
for protocolDefinitionRows.Next() {
|
for protocolDefinitionRows.Next() {
|
||||||
var protocolID, protocolDefinition string
|
var protocolID, protocolDefinition string
|
||||||
if err = protocolDefinitionRows.Scan(&protocolID, &protocolDefinition); err != nil {
|
if err = protocolDefinitionRows.Scan(&protocolID, &protocolDefinition); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store each protocol in a map indexed by protocol ID
|
||||||
protocols[protocolID] = gomatrixserverlib.RawJSON(protocolDefinition)
|
protocols[protocolID] = gomatrixserverlib.RawJSON(protocolDefinition)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +134,7 @@ func (s *thirdPartyStatements) selectAllProtocolDefinitions(
|
||||||
}
|
}
|
||||||
|
|
||||||
// insertProtocolDefinition inserts a protocol ID along with its definition in
|
// insertProtocolDefinition inserts a protocol ID along with its definition in
|
||||||
// order for clients to later retreive it from the client-server API.
|
// order for clients to later retrieve it from the client-server API.
|
||||||
func (s *thirdPartyStatements) insertProtocolDefinition(
|
func (s *thirdPartyStatements) insertProtocolDefinition(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
protocolID, protocolDefinition string,
|
protocolID, protocolDefinition string,
|
||||||
|
|
|
@ -79,7 +79,13 @@ func ThirdPartyWorker(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache protocol definition for clients to request later
|
// Cache protocol definition for clients to request later
|
||||||
storeProtocolDefinition(ctx, db, appservice, protocolID, protocolDefinition)
|
err = storeProtocolDefinition(ctx, db, protocolID, protocolDefinition)
|
||||||
|
if err != nil {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"appservice": appservice.ID,
|
||||||
|
"definition": protocolDefinition,
|
||||||
|
}).WithError(err).Fatalf("unable to store appservice protocol definition in db")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +150,6 @@ func retreiveProtocolInformation(
|
||||||
func storeProtocolDefinition(
|
func storeProtocolDefinition(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
db *storage.Database,
|
db *storage.Database,
|
||||||
appservice config.ApplicationService,
|
|
||||||
protocolID, protocolDefinition string,
|
protocolID, protocolDefinition string,
|
||||||
) error {
|
) error {
|
||||||
return db.StoreProtocolDefinition(ctx, protocolID, protocolDefinition)
|
return db.StoreProtocolDefinition(ctx, protocolID, protocolDefinition)
|
||||||
|
|
|
@ -158,6 +158,7 @@ func verifyAccessToken(req *http.Request, deviceDB DeviceDatabase) (device *auth
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
fmt.Println("Got token:", token)
|
||||||
device, err = deviceDB.GetDeviceByAccessToken(req.Context(), token)
|
device, err = deviceDB.GetDeviceByAccessToken(req.Context(), token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
|
|
|
@ -35,9 +35,14 @@ import (
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
const pathPrefixV1 = "/_matrix/client/api/v1"
|
const (
|
||||||
const pathPrefixR0 = "/_matrix/client/r0"
|
// PathPrefixClientAPI is the deprecated client server API version
|
||||||
const pathPrefixUnstable = "/_matrix/client/unstable"
|
PathPrefixClientAPI = "/_matrix/client/api/v1"
|
||||||
|
// PathPrefixClient is the current stable client server API version
|
||||||
|
PathPrefixClient = "/_matrix/client/r0"
|
||||||
|
// PathPrefixClientUnstable is the unstable client server API version
|
||||||
|
PathPrefixClientUnstable = "/_matrix/client/unstable"
|
||||||
|
)
|
||||||
|
|
||||||
// Setup registers HTTP handlers with the given ServeMux. It also supplies the given http.Client
|
// Setup registers HTTP handlers with the given ServeMux. It also supplies the given http.Client
|
||||||
// to clients which need to make outbound HTTP requests.
|
// to clients which need to make outbound HTTP requests.
|
||||||
|
@ -56,7 +61,6 @@ func Setup(
|
||||||
typingProducer *producers.TypingServerProducer,
|
typingProducer *producers.TypingServerProducer,
|
||||||
transactionsCache *transactions.Cache,
|
transactionsCache *transactions.Cache,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
apiMux.Handle("/_matrix/client/versions",
|
apiMux.Handle("/_matrix/client/versions",
|
||||||
common.MakeExternalAPI("versions", func(req *http.Request) util.JSONResponse {
|
common.MakeExternalAPI("versions", func(req *http.Request) util.JSONResponse {
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
|
@ -73,9 +77,9 @@ func Setup(
|
||||||
}),
|
}),
|
||||||
).Methods(http.MethodGet, http.MethodOptions)
|
).Methods(http.MethodGet, http.MethodOptions)
|
||||||
|
|
||||||
r0mux := apiMux.PathPrefix(pathPrefixR0).Subrouter()
|
r0mux := apiMux.PathPrefix(PathPrefixClient).Subrouter()
|
||||||
v1mux := apiMux.PathPrefix(pathPrefixV1).Subrouter()
|
v1mux := apiMux.PathPrefix(PathPrefixClientAPI).Subrouter()
|
||||||
unstableMux := apiMux.PathPrefix(pathPrefixUnstable).Subrouter()
|
unstableMux := apiMux.PathPrefix(PathPrefixClientUnstable).Subrouter()
|
||||||
|
|
||||||
authData := auth.Data{accountDB, deviceDB, cfg.Derived.ApplicationServices}
|
authData := auth.Data{accountDB, deviceDB, cfg.Derived.ApplicationServices}
|
||||||
|
|
||||||
|
@ -313,16 +317,6 @@ func Setup(
|
||||||
}),
|
}),
|
||||||
).Methods(http.MethodGet, http.MethodOptions)
|
).Methods(http.MethodGet, http.MethodOptions)
|
||||||
|
|
||||||
unstableMux.Handle("/thirdparty/protocols",
|
|
||||||
common.MakeExternalAPI("thirdparty_protocols", func(req *http.Request) util.JSONResponse {
|
|
||||||
// TODO: Return the third party protcols
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusOK,
|
|
||||||
JSON: struct{}{},
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
).Methods(http.MethodGet, http.MethodOptions)
|
|
||||||
|
|
||||||
r0mux.Handle("/rooms/{roomID}/initialSync",
|
r0mux.Handle("/rooms/{roomID}/initialSync",
|
||||||
common.MakeExternalAPI("rooms_initial_sync", func(req *http.Request) util.JSONResponse {
|
common.MakeExternalAPI("rooms_initial_sync", func(req *http.Request) util.JSONResponse {
|
||||||
// TODO: Allow people to peek into rooms.
|
// TODO: Allow people to peek into rooms.
|
||||||
|
@ -390,18 +384,44 @@ func Setup(
|
||||||
|
|
||||||
// Third party lookups
|
// Third party lookups
|
||||||
r0mux.Handle("/thirdparty/protocol/{protocolID}",
|
r0mux.Handle("/thirdparty/protocol/{protocolID}",
|
||||||
common.MakeExternalAPI("get_protocols", func(req *http.Request) util.JSONResponse {
|
common.MakeAuthAPI("third_party_protocols", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
||||||
vars := mux.Vars(req)
|
vars := mux.Vars(req)
|
||||||
return GetThirdPartyProtocol(req, asAPI, vars["protocolID"])
|
return GetThirdPartyProtocol(req, asAPI, vars["protocolID"])
|
||||||
}),
|
}),
|
||||||
).Methods(http.MethodGet, http.MethodOptions)
|
).Methods(http.MethodGet, http.MethodOptions)
|
||||||
|
|
||||||
r0mux.Handle("/thirdparty/protocols",
|
r0mux.Handle("/thirdparty/protocols",
|
||||||
common.MakeExternalAPI("get_protocols", func(req *http.Request) util.JSONResponse {
|
common.MakeAuthAPI("third_party_protocol", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
||||||
return GetThirdPartyProtocols(req, asAPI)
|
return GetThirdPartyProtocols(req, asAPI)
|
||||||
}),
|
}),
|
||||||
).Methods(http.MethodGet, http.MethodOptions)
|
).Methods(http.MethodGet, http.MethodOptions)
|
||||||
|
|
||||||
|
r0mux.Handle("/thirdparty/location/{protocolID}",
|
||||||
|
common.MakeAuthAPI("third_party_protocol", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
||||||
|
vars := mux.Vars(req)
|
||||||
|
return ThirdPartyProxy(req, asAPI, vars["protocolID"])
|
||||||
|
}),
|
||||||
|
).Methods(http.MethodGet, http.MethodOptions)
|
||||||
|
|
||||||
|
r0mux.Handle("/thirdparty/user/{protocolID}",
|
||||||
|
common.MakeAuthAPI("third_party_protocol", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
||||||
|
vars := mux.Vars(req)
|
||||||
|
return ThirdPartyProxy(req, asAPI, vars["protocolID"])
|
||||||
|
}),
|
||||||
|
).Methods(http.MethodGet, http.MethodOptions)
|
||||||
|
|
||||||
|
r0mux.Handle("/thirdparty/location",
|
||||||
|
common.MakeAuthAPI("third_party_protocol", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
||||||
|
return ThirdPartyProxy(req, asAPI, "")
|
||||||
|
}),
|
||||||
|
).Methods(http.MethodGet, http.MethodOptions)
|
||||||
|
|
||||||
|
r0mux.Handle("/thirdparty/user",
|
||||||
|
common.MakeAuthAPI("third_party_protocol", authData, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
||||||
|
return ThirdPartyProxy(req, asAPI, "")
|
||||||
|
}),
|
||||||
|
).Methods(http.MethodGet, http.MethodOptions)
|
||||||
|
|
||||||
// Stub implementations for sytest
|
// Stub implementations for sytest
|
||||||
r0mux.Handle("/events",
|
r0mux.Handle("/events",
|
||||||
common.MakeExternalAPI("events", func(req *http.Request) util.JSONResponse {
|
common.MakeExternalAPI("events", func(req *http.Request) util.JSONResponse {
|
||||||
|
|
|
@ -15,11 +15,14 @@
|
||||||
package routing
|
package routing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
|
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
|
||||||
|
appserviceRouting "github.com/matrix-org/dendrite/appservice/routing"
|
||||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||||
|
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -39,6 +42,14 @@ func GetThirdPartyProtocol(
|
||||||
return httputil.LogThenError(req, err)
|
return httputil.LogThenError(req, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Account for unknown protocol/empty definition
|
||||||
|
if len(queryRes.ProtocolDefinition) == 0 {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusNotFound,
|
||||||
|
JSON: jsonerror.NotFound("unknown protocol"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusOK,
|
Code: http.StatusOK,
|
||||||
JSON: queryRes.ProtocolDefinition,
|
JSON: queryRes.ProtocolDefinition,
|
||||||
|
@ -60,15 +71,44 @@ func GetThirdPartyProtocols(
|
||||||
|
|
||||||
// TODO: Check what we get if no protocols defined by anyone
|
// TODO: Check what we get if no protocols defined by anyone
|
||||||
|
|
||||||
// Marshal protocols to JSON
|
// Return protocol IDs along with definitions
|
||||||
protocolJSON, err := json.Marshal(queryRes.Protocols)
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusOK,
|
||||||
|
JSON: queryRes.Protocols,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ThirdPartyProxy proxies a third party lookup request to the handler
|
||||||
|
// application service
|
||||||
|
func ThirdPartyProxy(
|
||||||
|
req *http.Request,
|
||||||
|
asAPI appserviceAPI.AppServiceQueryAPI,
|
||||||
|
protocolID string,
|
||||||
|
) util.JSONResponse {
|
||||||
|
// Read the request body
|
||||||
|
body, err := ioutil.ReadAll(req.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return httputil.LogThenError(req, err)
|
return httputil.LogThenError(req, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return protocol IDs along with definitions
|
// Rewrite the path from a client URL to an application service URL
|
||||||
|
requestPath := strings.Replace(req.URL.String(), PathPrefixClient, appserviceRouting.PathPrefixAppUnstable, 1)
|
||||||
|
|
||||||
|
// Proxy the location lookup to the appservices component, which will send it
|
||||||
|
// off to an application service
|
||||||
|
queryReq := appserviceAPI.ThirdPartyProxyRequest{
|
||||||
|
ProtocolID: protocolID,
|
||||||
|
Path: requestPath,
|
||||||
|
Content: body,
|
||||||
|
}
|
||||||
|
var queryRes appserviceAPI.ThirdPartyProxyResponse
|
||||||
|
if err := asAPI.ThirdPartyProxy(req.Context(), &queryReq, &queryRes); err != nil {
|
||||||
|
return httputil.LogThenError(req, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return response to the client
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusOK,
|
Code: http.StatusOK,
|
||||||
JSON: protocolJSON,
|
JSON: queryRes.Content,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,8 +231,8 @@ func checkErrors(config *Dendrite) (err error) {
|
||||||
// Namespace-related checks
|
// Namespace-related checks
|
||||||
for key, namespaceSlice := range appservice.NamespaceMap {
|
for key, namespaceSlice := range appservice.NamespaceMap {
|
||||||
for _, namespace := range namespaceSlice {
|
for _, namespace := range namespaceSlice {
|
||||||
if err := validateNamespace(&appservice, key, &namespace, groupIDRegexp); err != nil {
|
if err = validateNamespace(&appservice, key, &namespace, groupIDRegexp); err != nil {
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,7 +240,7 @@ func checkErrors(config *Dendrite) (err error) {
|
||||||
// Check if the url has trailing /'s. If so, remove them
|
// Check if the url has trailing /'s. If so, remove them
|
||||||
appservice.URL = strings.TrimRight(appservice.URL, "/")
|
appservice.URL = strings.TrimRight(appservice.URL, "/")
|
||||||
if err = duplicationCheck(appservice, &idMap, &tokenMap, &protocolMap); err != nil {
|
if err = duplicationCheck(appservice, &idMap, &tokenMap, &protocolMap); err != nil {
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove once rate_limited is implemented
|
// TODO: Remove once rate_limited is implemented
|
||||||
|
|
|
@ -30,8 +30,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
pathPrefixV2Keys = "/_matrix/key/v2"
|
// PathPrefixKeys is the current Key API version
|
||||||
pathPrefixV1Federation = "/_matrix/federation/v1"
|
PathPrefixKeys = "/_matrix/key/v2"
|
||||||
|
// PathPrefixFederation is the current Federation API version
|
||||||
|
PathPrefixFederation = "/_matrix/federation/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Setup registers HTTP handlers with the given ServeMux.
|
// Setup registers HTTP handlers with the given ServeMux.
|
||||||
|
@ -47,8 +49,8 @@ func Setup(
|
||||||
accountDB *accounts.Database,
|
accountDB *accounts.Database,
|
||||||
deviceDB *devices.Database,
|
deviceDB *devices.Database,
|
||||||
) {
|
) {
|
||||||
v2keysmux := apiMux.PathPrefix(pathPrefixV2Keys).Subrouter()
|
v2keysmux := apiMux.PathPrefix(PathPrefixKeys).Subrouter()
|
||||||
v1fedmux := apiMux.PathPrefix(pathPrefixV1Federation).Subrouter()
|
v1fedmux := apiMux.PathPrefix(PathPrefixFederation).Subrouter()
|
||||||
|
|
||||||
localKeys := common.MakeExternalAPI("localkeys", func(req *http.Request) util.JSONResponse {
|
localKeys := common.MakeExternalAPI("localkeys", func(req *http.Request) util.JSONResponse {
|
||||||
return LocalKeys(cfg)
|
return LocalKeys(cfg)
|
||||||
|
|
|
@ -31,7 +31,10 @@ import (
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
const pathPrefixR0 = "/_matrix/media/v1"
|
const (
|
||||||
|
// PathPrefixMedia is the current Media API version
|
||||||
|
PathPrefixMedia = "/_matrix/media/v1"
|
||||||
|
)
|
||||||
|
|
||||||
// Setup registers the media API HTTP handlers
|
// Setup registers the media API HTTP handlers
|
||||||
func Setup(
|
func Setup(
|
||||||
|
@ -41,7 +44,7 @@ func Setup(
|
||||||
deviceDB *devices.Database,
|
deviceDB *devices.Database,
|
||||||
client *gomatrixserverlib.Client,
|
client *gomatrixserverlib.Client,
|
||||||
) {
|
) {
|
||||||
r0mux := apiMux.PathPrefix(pathPrefixR0).Subrouter()
|
r0mux := apiMux.PathPrefix(PathPrefixMedia).Subrouter()
|
||||||
|
|
||||||
activeThumbnailGeneration := &types.ActiveThumbnailGeneration{
|
activeThumbnailGeneration := &types.ActiveThumbnailGeneration{
|
||||||
PathToResult: map[string]*types.ThumbnailGenerationResult{},
|
PathToResult: map[string]*types.ThumbnailGenerationResult{},
|
||||||
|
|
|
@ -27,12 +27,14 @@ import (
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
const pathPrefixR0 = "/_matrix/client/r0"
|
const (
|
||||||
|
// PathPrefixClientPublicRooms is the current Client-Server Public Rooms API version
|
||||||
|
PathPrefixClientPublicRooms = "/_matrix/client/r0"
|
||||||
|
)
|
||||||
|
|
||||||
// Setup configures the given mux with publicroomsapi server listeners
|
// Setup configures the given mux with publicroomsapi server listeners
|
||||||
func Setup(apiMux *mux.Router, deviceDB *devices.Database, publicRoomsDB *storage.PublicRoomsServerDatabase) {
|
func Setup(apiMux *mux.Router, deviceDB *devices.Database, publicRoomsDB *storage.PublicRoomsServerDatabase) {
|
||||||
r0mux := apiMux.PathPrefix(pathPrefixR0).Subrouter()
|
r0mux := apiMux.PathPrefix(PathPrefixClientPublicRooms).Subrouter()
|
||||||
|
|
||||||
authData := auth.Data{nil, deviceDB, nil}
|
authData := auth.Data{nil, deviceDB, nil}
|
||||||
|
|
||||||
r0mux.Handle("/directory/list/room/{roomID}",
|
r0mux.Handle("/directory/list/room/{roomID}",
|
||||||
|
|
|
@ -27,11 +27,14 @@ import (
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
const pathPrefixR0 = "/_matrix/client/r0"
|
const (
|
||||||
|
// PathPrefixClientSync is the current Client-Server Sync API version
|
||||||
|
PathPrefixClientSync = "/_matrix/client/r0"
|
||||||
|
)
|
||||||
|
|
||||||
// Setup configures the given mux with sync-server listeners
|
// Setup configures the given mux with sync-server listeners
|
||||||
func Setup(apiMux *mux.Router, srp *sync.RequestPool, syncDB *storage.SyncServerDatabase, deviceDB *devices.Database) {
|
func Setup(apiMux *mux.Router, srp *sync.RequestPool, syncDB *storage.SyncServerDatabase, deviceDB *devices.Database) {
|
||||||
r0mux := apiMux.PathPrefix(pathPrefixR0).Subrouter()
|
r0mux := apiMux.PathPrefix(PathPrefixClientSync).Subrouter()
|
||||||
|
|
||||||
authData := auth.Data{nil, deviceDB, nil}
|
authData := auth.Data{nil, deviceDB, nil}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue