Filter Roomserver Events Based on Application Service (#467)

* Compile room and alias namespace regexs

We'll be needing these for event filtering in the appservice component.

Signed-off-by: Andrew Morgan <andrewm@matrix.org>

* App service filters roomserver events

Doing so based on namespace regexes that each app service has defined.

To get the aliases for a roomID a new aliasAPI endpoint was defined,
GetAliasesFromRoomID, which does exactly what it says on the tin.

Next step is to queue events to be sent off to each homeserver.

* Additionally filter state events for app services

* Fixed context, logging, derps, config handling

* Prevented user from creating more than one regex per namespace type

Got caught out by realizing I had an extra '-' in the config file. This
prevents anyone from making the same mistake :)

* Removed exclusive RoomID namespace regex, as we won't need to check
upon room creation if the ID is reserved exclusively by an AS (as this
is silly and horribly inefficient).

* Fixed all else mentioned
This commit is contained in:
Andrew Morgan 2018-05-30 13:43:13 +01:00 committed by GitHub
parent 60e77959ee
commit 04551becb4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 229 additions and 76 deletions

View file

@ -36,10 +36,10 @@ func SetupAppServiceAPIComponent(
transactionsCache *transactions.Cache, transactionsCache *transactions.Cache,
) { ) {
consumer := consumers.NewOutputRoomEventConsumer( consumer := consumers.NewOutputRoomEventConsumer(
base.Cfg, base.KafkaConsumer, accountsDB, queryAPI, base.Cfg, base.KafkaConsumer, accountsDB, queryAPI, aliasAPI,
) )
if err := consumer.Start(); err != nil { if err := consumer.Start(); err != nil {
logrus.WithError(err).Panicf("failed to start app service's room server consumer") logrus.WithError(err).Panicf("failed to start app service roomserver consumer")
} }
// Set up HTTP Endpoints // Set up HTTP Endpoints

View file

@ -17,6 +17,7 @@ package consumers
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"github.com/matrix-org/dendrite/clientapi/auth/storage/accounts" "github.com/matrix-org/dendrite/clientapi/auth/storage/accounts"
"github.com/matrix-org/dendrite/common" "github.com/matrix-org/dendrite/common"
@ -28,11 +29,16 @@ import (
sarama "gopkg.in/Shopify/sarama.v1" sarama "gopkg.in/Shopify/sarama.v1"
) )
var (
appServices []config.ApplicationService
)
// OutputRoomEventConsumer consumes events that originated in the room server. // OutputRoomEventConsumer consumes events that originated in the room server.
type OutputRoomEventConsumer struct { type OutputRoomEventConsumer struct {
roomServerConsumer *common.ContinualConsumer roomServerConsumer *common.ContinualConsumer
db *accounts.Database db *accounts.Database
query api.RoomserverQueryAPI query api.RoomserverQueryAPI
alias api.RoomserverAliasAPI
serverName string serverName string
} }
@ -42,7 +48,9 @@ func NewOutputRoomEventConsumer(
kafkaConsumer sarama.Consumer, kafkaConsumer sarama.Consumer,
store *accounts.Database, store *accounts.Database,
queryAPI api.RoomserverQueryAPI, queryAPI api.RoomserverQueryAPI,
aliasAPI api.RoomserverAliasAPI,
) *OutputRoomEventConsumer { ) *OutputRoomEventConsumer {
appServices = cfg.Derived.ApplicationServices
consumer := common.ContinualConsumer{ consumer := common.ContinualConsumer{
Topic: string(cfg.Kafka.Topics.OutputRoomEvent), Topic: string(cfg.Kafka.Topics.OutputRoomEvent),
@ -53,6 +61,7 @@ func NewOutputRoomEventConsumer(
roomServerConsumer: &consumer, roomServerConsumer: &consumer,
db: store, db: store,
query: queryAPI, query: queryAPI,
alias: aliasAPI,
serverName: string(cfg.Matrix.ServerName), serverName: string(cfg.Matrix.ServerName),
} }
consumer.ProcessMessage = s.onMessage consumer.ProcessMessage = s.onMessage
@ -96,7 +105,15 @@ func (s *OutputRoomEventConsumer) onMessage(msg *sarama.ConsumerMessage) error {
return err return err
} }
return s.db.UpdateMemberships(context.TODO(), events, output.NewRoomEvent.RemovesStateEventIDs) // Create a context to thread through the whole filtering process
ctx := context.TODO()
if err = s.db.UpdateMemberships(ctx, events, output.NewRoomEvent.RemovesStateEventIDs); err != nil {
return err
}
// Check if any events need to passed on to external application services
return s.filterRoomserverEvents(ctx, append(events, ev))
} }
// lookupStateEvents looks up the state events that are added by a new event. // lookupStateEvents looks up the state events that are added by a new event.
@ -142,3 +159,59 @@ func (s *OutputRoomEventConsumer) lookupStateEvents(
return result, nil return result, nil
} }
// filterRoomserverEvents takes in events and decides whether any of them need
// to be passed on to an external application service. It does this by checking
// each namespace of each registered application service, and if there is a
// match, adds the event to the queue for events to be sent to a particular
// application service.
func (s *OutputRoomEventConsumer) filterRoomserverEvents(ctx context.Context, events []gomatrixserverlib.Event) error {
for _, event := range events {
for _, appservice := range appServices {
// Check if this event is interesting to this application service
if s.appserviceIsInterestedInEvent(ctx, event, appservice) {
// TODO: Queue this event to be sent off to the application service
fmt.Println(appservice.ID, "was interested in", event.Sender(), event.Type(), event.RoomID())
}
}
}
return nil
}
// appserviceIsInterestedInEvent returns a boolean depending on whether a given
// event falls within one of a given application service's namespaces.
func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Context, event gomatrixserverlib.Event, appservice config.ApplicationService) bool {
// Check sender of the event
for _, userNamespace := range appservice.NamespaceMap["users"] {
if userNamespace.RegexpObject.MatchString(event.Sender()) {
return true
}
}
// Check room id of the event
for _, roomNamespace := range appservice.NamespaceMap["rooms"] {
if roomNamespace.RegexpObject.MatchString(event.RoomID()) {
return true
}
}
// Check all known room aliases of the room the event came from
queryReq := api.GetAliasesForRoomIDRequest{RoomID: event.RoomID()}
var queryRes api.GetAliasesForRoomIDResponse
if err := s.alias.GetAliasesForRoomID(ctx, &queryReq, &queryRes); err == nil {
for _, alias := range queryRes.Aliases {
for _, aliasNamespace := range appservice.NamespaceMap["aliases"] {
if aliasNamespace.RegexpObject.MatchString(alias) {
return true
}
}
}
} else {
log.WithFields(log.Fields{
"room_id": event.RoomID(),
}).WithError(err).Errorf("Unable to get aliases for room")
}
return false
}

View file

@ -46,9 +46,9 @@ func DirectoryRoom(
var resp gomatrixserverlib.RespDirectory var resp gomatrixserverlib.RespDirectory
if domain == cfg.Matrix.ServerName { if domain == cfg.Matrix.ServerName {
queryReq := api.GetAliasRoomIDRequest{Alias: roomAlias} queryReq := api.GetRoomIDForAliasRequest{Alias: roomAlias}
var queryRes api.GetAliasRoomIDResponse var queryRes api.GetRoomIDForAliasResponse
if err = aliasAPI.GetAliasRoomID(req.Context(), &queryReq, &queryRes); err != nil { if err = aliasAPI.GetRoomIDForAlias(req.Context(), &queryReq, &queryRes); err != nil {
return httputil.LogThenError(req, err) return httputil.LogThenError(req, err)
} }

View file

@ -145,9 +145,9 @@ func (r joinRoomReq) joinRoomByAlias(roomAlias string) util.JSONResponse {
} }
} }
if domain == r.cfg.Matrix.ServerName { if domain == r.cfg.Matrix.ServerName {
queryReq := api.GetAliasRoomIDRequest{Alias: roomAlias} queryReq := api.GetRoomIDForAliasRequest{Alias: roomAlias}
var queryRes api.GetAliasRoomIDResponse var queryRes api.GetRoomIDForAliasResponse
if err = r.aliasAPI.GetAliasRoomID(r.req.Context(), &queryReq, &queryRes); err != nil { if err = r.aliasAPI.GetRoomIDForAlias(r.req.Context(), &queryReq, &queryRes); err != nil {
return httputil.LogThenError(r.req, err) return httputil.LogThenError(r.req, err)
} }

View file

@ -21,7 +21,7 @@ import (
"regexp" "regexp"
"strings" "strings"
"gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
) )
// ApplicationServiceNamespace is the namespace that a specific application // ApplicationServiceNamespace is the namespace that a specific application
@ -48,7 +48,8 @@ type ApplicationService struct {
HSToken string `yaml:"hs_token"` HSToken string `yaml:"hs_token"`
// Localpart of application service user // Localpart of application service user
SenderLocalpart string `yaml:"sender_localpart"` SenderLocalpart string `yaml:"sender_localpart"`
// Information about an application service's namespaces // Information about an application service's namespaces. Key is either
// "users", "aliases" or "rooms"
NamespaceMap map[string][]ApplicationServiceNamespace `yaml:"namespaces"` NamespaceMap map[string][]ApplicationServiceNamespace `yaml:"namespaces"`
} }
@ -78,7 +79,8 @@ func loadAppservices(config *Dendrite) error {
// Append the parsed application service to the global config // Append the parsed application service to the global config
config.Derived.ApplicationServices = append( config.Derived.ApplicationServices = append(
config.Derived.ApplicationServices, appservice) config.Derived.ApplicationServices, appservice,
)
} }
// Check for any errors in the loaded application services // Check for any errors in the loaded application services
@ -88,12 +90,13 @@ func loadAppservices(config *Dendrite) error {
// setupRegexps will create regex objects for exclusive and non-exclusive // setupRegexps will create regex objects for exclusive and non-exclusive
// usernames, aliases and rooms of all application services, so that other // usernames, aliases and rooms of all application services, so that other
// methods can quickly check if a particular string matches any of them. // methods can quickly check if a particular string matches any of them.
func setupRegexps(cfg *Dendrite) { func setupRegexps(cfg *Dendrite) (err error) {
// Combine all exclusive namespaces for later string checking // Combine all exclusive namespaces for later string checking
var exclusiveUsernameStrings, exclusiveAliasStrings, exclusiveRoomStrings []string var exclusiveUsernameStrings, exclusiveAliasStrings []string
// If an application service's regex is marked as exclusive, add // If an application service's regex is marked as exclusive, add
// it's contents to the overall exlusive regex string // its contents to the overall exlusive regex string. Room regex
// not necessary as we aren't denying exclusive room ID creation
for _, appservice := range cfg.Derived.ApplicationServices { for _, appservice := range cfg.Derived.ApplicationServices {
for key, namespaceSlice := range appservice.NamespaceMap { for key, namespaceSlice := range appservice.NamespaceMap {
switch key { switch key {
@ -101,38 +104,46 @@ func setupRegexps(cfg *Dendrite) {
appendExclusiveNamespaceRegexs(&exclusiveUsernameStrings, namespaceSlice) appendExclusiveNamespaceRegexs(&exclusiveUsernameStrings, namespaceSlice)
case "aliases": case "aliases":
appendExclusiveNamespaceRegexs(&exclusiveAliasStrings, namespaceSlice) appendExclusiveNamespaceRegexs(&exclusiveAliasStrings, namespaceSlice)
case "rooms":
appendExclusiveNamespaceRegexs(&exclusiveRoomStrings, namespaceSlice)
} }
} }
} }
fmt.Println(exclusiveUsernameStrings, exclusiveAliasStrings)
// Join the regexes together into one big regex. // Join the regexes together into one big regex.
// i.e. "app1.*", "app2.*" -> "(app1.*)|(app2.*)" // i.e. "app1.*", "app2.*" -> "(app1.*)|(app2.*)"
// Later we can check if a username or some other string matches any exclusive // Later we can check if a username or alias matches any exclusive regex and
// regex and deny access if it isn't from an application service // deny access if it isn't from an application service
exclusiveUsernames := strings.Join(exclusiveUsernameStrings, "|") exclusiveUsernames := strings.Join(exclusiveUsernameStrings, "|")
exclusiveAliases := strings.Join(exclusiveAliasStrings, "|")
// If there are no exclusive username regexes, compile string so that it // If there are no exclusive regexes, compile string so that it will not match
// will not match any valid usernames // any valid usernames/aliases/roomIDs
if exclusiveUsernames == "" { if exclusiveUsernames == "" {
exclusiveUsernames = "^$" exclusiveUsernames = "^$"
} }
if exclusiveAliases == "" {
exclusiveAliases = "^$"
}
// TODO: Aliases and rooms. Needed? // Store compiled Regex
//exclusiveAliases := strings.Join(exclusiveAliasStrings, "|") if cfg.Derived.ExclusiveApplicationServicesUsernameRegexp, err = regexp.Compile(exclusiveUsernames); err != nil {
//exclusiveRooms := strings.Join(exclusiveRoomStrings, "|") return err
}
if cfg.Derived.ExclusiveApplicationServicesAliasRegexp, err = regexp.Compile(exclusiveAliases); err != nil {
return err
}
cfg.Derived.ExclusiveApplicationServicesUsernameRegexp, _ = regexp.Compile(exclusiveUsernames) return nil
} }
// concatenateExclusiveNamespaces takes a slice of strings and a slice of // appendExclusiveNamespaceRegexs takes a slice of strings and a slice of
// namespaces and will append the regexes of only the exclusive namespaces // namespaces and will append the regexes of only the exclusive namespaces
// into the string slice // into the string slice
func appendExclusiveNamespaceRegexs( func appendExclusiveNamespaceRegexs(
exclusiveStrings *[]string, namespaces []ApplicationServiceNamespace, exclusiveStrings *[]string, namespaces []ApplicationServiceNamespace,
) { ) {
for _, namespace := range namespaces { for index, namespace := range namespaces {
if namespace.Exclusive { if namespace.Exclusive {
// We append parenthesis to later separate each regex when we compile // We append parenthesis to later separate each regex when we compile
// i.e. "app1.*", "app2.*" -> "(app1.*)|(app2.*)" // i.e. "app1.*", "app2.*" -> "(app1.*)|(app2.*)"
@ -140,24 +151,26 @@ func appendExclusiveNamespaceRegexs(
} }
// Compile this regex into a Regexp object for later use // Compile this regex into a Regexp object for later use
namespace.RegexpObject, _ = regexp.Compile(namespace.Regex) namespaces[index].RegexpObject, _ = regexp.Compile(namespace.Regex)
} }
} }
// checkErrors checks for any configuration errors amongst the loaded // checkErrors checks for any configuration errors amongst the loaded
// application services according to the application service spec. // application services according to the application service spec.
func checkErrors(config *Dendrite) error { func checkErrors(config *Dendrite) (err error) {
var idMap = make(map[string]bool) var idMap = make(map[string]bool)
var tokenMap = make(map[string]bool) var tokenMap = make(map[string]bool)
// Check that no two application services have the same as_token or id // Check each application service for any config errors
for _, appservice := range config.Derived.ApplicationServices { for _, appservice := range config.Derived.ApplicationServices {
// Check if we've already seen this ID // Check if we've already seen this ID. No two application services
// can have the same ID or token.
if idMap[appservice.ID] { if idMap[appservice.ID] {
return configErrors([]string{fmt.Sprintf( return configErrors([]string{fmt.Sprintf(
"Application Service ID %s must be unique", appservice.ID, "Application Service ID %s must be unique", appservice.ID,
)}) )})
} }
// Check if we've already seen this token
if tokenMap[appservice.ASToken] { if tokenMap[appservice.ASToken] {
return configErrors([]string{fmt.Sprintf( return configErrors([]string{fmt.Sprintf(
"Application Service Token %s must be unique", appservice.ASToken, "Application Service Token %s must be unique", appservice.ASToken,
@ -168,6 +181,18 @@ func checkErrors(config *Dendrite) error {
// seen them. // seen them.
idMap[appservice.ID] = true idMap[appservice.ID] = true
tokenMap[appservice.ID] = true tokenMap[appservice.ID] = true
// Check if more than one regex exists per namespace
for _, namespace := range appservice.NamespaceMap {
if len(namespace) > 1 {
// It's quite easy to accidentally make multiple regex objects per
// namespace, which often ends up in an application service receiving events
// it doesn't want, as an empty regex will match all events.
return configErrors([]string{fmt.Sprintf(
"Application Service namespace can only contain a single regex tuple. Check your YAML.",
)})
}
}
} }
// Check that namespace(s) are valid regex // Check that namespace(s) are valid regex
@ -182,9 +207,8 @@ func checkErrors(config *Dendrite) error {
} }
} }
} }
setupRegexps(config)
return nil return setupRegexps(config)
} }
// IsValidRegex returns true or false based on whether the // IsValidRegex returns true or false based on whether the

View file

@ -30,7 +30,7 @@ import (
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/crypto/ed25519" "golang.org/x/crypto/ed25519"
"gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
jaegerconfig "github.com/uber/jaeger-client-go/config" jaegerconfig "github.com/uber/jaeger-client-go/config"
jaegermetrics "github.com/uber/jaeger-lib/metrics" jaegermetrics "github.com/uber/jaeger-lib/metrics"
@ -235,12 +235,17 @@ type Dendrite struct {
// The paths of which were given above in the main config file // The paths of which were given above in the main config file
ApplicationServices []ApplicationService ApplicationServices []ApplicationService
// A meta-regex compiled from all exclusive Application Service // Meta-regexes compiled from all exclusive Application Service
// Regexes. When a user registers, we check that their username // Regexes.
// does not match any exclusive Application Service namespaces //
// When a user registers, we check that their username does not match any
// exclusive Application Service namespaces
ExclusiveApplicationServicesUsernameRegexp *regexp.Regexp ExclusiveApplicationServicesUsernameRegexp *regexp.Regexp
// When a user creates a room alias, we check that it isn't already
// TODO: Exclusive alias, room regexp's // reserved by an application service
ExclusiveApplicationServicesAliasRegexp *regexp.Regexp
// Note: An Exclusive Regex for room ID isn't necessary as we aren't blocking
// servers from creating RoomIDs in exclusive application service namespaces
} `yaml:"-"` } `yaml:"-"`
} }

View file

@ -52,9 +52,9 @@ func RoomAliasToID(
var resp gomatrixserverlib.RespDirectory var resp gomatrixserverlib.RespDirectory
if domain == cfg.Matrix.ServerName { if domain == cfg.Matrix.ServerName {
queryReq := api.GetAliasRoomIDRequest{Alias: roomAlias} queryReq := api.GetRoomIDForAliasRequest{Alias: roomAlias}
var queryRes api.GetAliasRoomIDResponse var queryRes api.GetRoomIDForAliasResponse
if err = aliasAPI.GetAliasRoomID(httpReq.Context(), &queryReq, &queryRes); err != nil { if err = aliasAPI.GetRoomIDForAlias(httpReq.Context(), &queryReq, &queryRes); err != nil {
return httputil.LogThenError(httpReq, err) return httputil.LogThenError(httpReq, err)
} }

View file

@ -35,10 +35,10 @@ type RoomserverAliasAPIDatabase interface {
SetRoomAlias(ctx context.Context, alias string, roomID string) error SetRoomAlias(ctx context.Context, alias string, roomID string) error
// Look up the room ID a given alias refers to. // Look up the room ID a given alias refers to.
// Returns an error if there was a problem talking to the database. // Returns an error if there was a problem talking to the database.
GetRoomIDFromAlias(ctx context.Context, alias string) (string, error) GetRoomIDForAlias(ctx context.Context, alias string) (string, error)
// Look up all aliases referring to a given room ID. // Look up all aliases referring to a given room ID.
// Returns an error if there was a problem talking to the database. // Returns an error if there was a problem talking to the database.
GetAliasesFromRoomID(ctx context.Context, roomID string) ([]string, error) GetAliasesForRoomID(ctx context.Context, roomID string) ([]string, error)
// Remove a given room alias. // Remove a given room alias.
// Returns an error if there was a problem talking to the database. // Returns an error if there was a problem talking to the database.
RemoveRoomAlias(ctx context.Context, alias string) error RemoveRoomAlias(ctx context.Context, alias string) error
@ -59,7 +59,7 @@ func (r *RoomserverAliasAPI) SetRoomAlias(
response *api.SetRoomAliasResponse, response *api.SetRoomAliasResponse,
) error { ) error {
// Check if the alias isn't already referring to a room // Check if the alias isn't already referring to a room
roomID, err := r.DB.GetRoomIDFromAlias(ctx, request.Alias) roomID, err := r.DB.GetRoomIDForAlias(ctx, request.Alias)
if err != nil { if err != nil {
return err return err
} }
@ -82,14 +82,14 @@ func (r *RoomserverAliasAPI) SetRoomAlias(
return r.sendUpdatedAliasesEvent(context.TODO(), request.UserID, request.RoomID) return r.sendUpdatedAliasesEvent(context.TODO(), request.UserID, request.RoomID)
} }
// GetAliasRoomID implements api.RoomserverAliasAPI // GetRoomIDForAlias implements api.RoomserverAliasAPI
func (r *RoomserverAliasAPI) GetAliasRoomID( func (r *RoomserverAliasAPI) GetRoomIDForAlias(
ctx context.Context, ctx context.Context,
request *api.GetAliasRoomIDRequest, request *api.GetRoomIDForAliasRequest,
response *api.GetAliasRoomIDResponse, response *api.GetRoomIDForAliasResponse,
) error { ) error {
// Look up the room ID in the database // Look up the room ID in the database
roomID, err := r.DB.GetRoomIDFromAlias(ctx, request.Alias) roomID, err := r.DB.GetRoomIDForAlias(ctx, request.Alias)
if err != nil { if err != nil {
return err return err
} }
@ -98,6 +98,22 @@ func (r *RoomserverAliasAPI) GetAliasRoomID(
return nil return nil
} }
// GetAliasesForRoomID implements api.RoomserverAliasAPI
func (r *RoomserverAliasAPI) GetAliasesForRoomID(
ctx context.Context,
request *api.GetAliasesForRoomIDRequest,
response *api.GetAliasesForRoomIDResponse,
) error {
// Look up the aliases in the database for the given RoomID
aliases, err := r.DB.GetAliasesForRoomID(ctx, request.RoomID)
if err != nil {
return err
}
response.Aliases = aliases
return nil
}
// RemoveRoomAlias implements api.RoomserverAliasAPI // RemoveRoomAlias implements api.RoomserverAliasAPI
func (r *RoomserverAliasAPI) RemoveRoomAlias( func (r *RoomserverAliasAPI) RemoveRoomAlias(
ctx context.Context, ctx context.Context,
@ -105,7 +121,7 @@ func (r *RoomserverAliasAPI) RemoveRoomAlias(
response *api.RemoveRoomAliasResponse, response *api.RemoveRoomAliasResponse,
) error { ) error {
// Look up the room ID in the database // Look up the room ID in the database
roomID, err := r.DB.GetRoomIDFromAlias(ctx, request.Alias) roomID, err := r.DB.GetRoomIDForAlias(ctx, request.Alias)
if err != nil { if err != nil {
return err return err
} }
@ -142,7 +158,7 @@ func (r *RoomserverAliasAPI) sendUpdatedAliasesEvent(
// Retrieve the updated list of aliases, marhal it and set it as the // Retrieve the updated list of aliases, marhal it and set it as the
// event's content // event's content
aliases, err := r.DB.GetAliasesFromRoomID(ctx, roomID) aliases, err := r.DB.GetAliasesForRoomID(ctx, roomID)
if err != nil { if err != nil {
return err return err
} }
@ -229,14 +245,14 @@ func (r *RoomserverAliasAPI) SetupHTTP(servMux *http.ServeMux) {
}), }),
) )
servMux.Handle( servMux.Handle(
api.RoomserverGetAliasRoomIDPath, api.RoomserverGetRoomIDForAliasPath,
common.MakeInternalAPI("getAliasRoomID", func(req *http.Request) util.JSONResponse { common.MakeInternalAPI("GetRoomIDForAlias", func(req *http.Request) util.JSONResponse {
var request api.GetAliasRoomIDRequest var request api.GetRoomIDForAliasRequest
var response api.GetAliasRoomIDResponse var response api.GetRoomIDForAliasResponse
if err := json.NewDecoder(req.Body).Decode(&request); err != nil { if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
return util.ErrorResponse(err) return util.ErrorResponse(err)
} }
if err := r.GetAliasRoomID(req.Context(), &request, &response); err != nil { if err := r.GetRoomIDForAlias(req.Context(), &request, &response); err != nil {
return util.ErrorResponse(err) return util.ErrorResponse(err)
} }
return util.JSONResponse{Code: http.StatusOK, JSON: &response} return util.JSONResponse{Code: http.StatusOK, JSON: &response}

View file

@ -37,18 +37,30 @@ type SetRoomAliasResponse struct {
AliasExists bool `json:"alias_exists"` AliasExists bool `json:"alias_exists"`
} }
// GetAliasRoomIDRequest is a request to GetAliasRoomID // GetRoomIDForAliasRequest is a request to GetRoomIDForAlias
type GetAliasRoomIDRequest struct { type GetRoomIDForAliasRequest struct {
// Alias we want to lookup // Alias we want to lookup
Alias string `json:"alias"` Alias string `json:"alias"`
} }
// GetAliasRoomIDResponse is a response to GetAliasRoomID // GetRoomIDForAliasResponse is a response to GetRoomIDForAlias
type GetAliasRoomIDResponse struct { type GetRoomIDForAliasResponse struct {
// The room ID the alias refers to // The room ID the alias refers to
RoomID string `json:"room_id"` RoomID string `json:"room_id"`
} }
// GetAliasesForRoomIDRequest is a request to GetAliasesForRoomID
type GetAliasesForRoomIDRequest struct {
// The room ID we want to find aliases for
RoomID string `json:"room_id"`
}
// GetAliasesForRoomIDResponse is a response to GetAliasesForRoomID
type GetAliasesForRoomIDResponse struct {
// The aliases the alias refers to
Aliases []string `json:"aliases"`
}
// RemoveRoomAliasRequest is a request to RemoveRoomAlias // RemoveRoomAliasRequest is a request to RemoveRoomAlias
type RemoveRoomAliasRequest struct { type RemoveRoomAliasRequest struct {
// ID of the user removing the alias // ID of the user removing the alias
@ -70,10 +82,17 @@ type RoomserverAliasAPI interface {
) error ) error
// Get the room ID for an alias // Get the room ID for an alias
GetAliasRoomID( GetRoomIDForAlias(
ctx context.Context, ctx context.Context,
req *GetAliasRoomIDRequest, req *GetRoomIDForAliasRequest,
response *GetAliasRoomIDResponse, response *GetRoomIDForAliasResponse,
) error
// Get all known aliases for a room ID
GetAliasesForRoomID(
ctx context.Context,
req *GetAliasesForRoomIDRequest,
response *GetAliasesForRoomIDResponse,
) error ) error
// Remove a room alias // Remove a room alias
@ -87,8 +106,11 @@ type RoomserverAliasAPI interface {
// RoomserverSetRoomAliasPath is the HTTP path for the SetRoomAlias API. // RoomserverSetRoomAliasPath is the HTTP path for the SetRoomAlias API.
const RoomserverSetRoomAliasPath = "/api/roomserver/setRoomAlias" const RoomserverSetRoomAliasPath = "/api/roomserver/setRoomAlias"
// RoomserverGetAliasRoomIDPath is the HTTP path for the GetAliasRoomID API. // RoomserverGetRoomIDForAliasPath is the HTTP path for the GetRoomIDForAlias API.
const RoomserverGetAliasRoomIDPath = "/api/roomserver/getAliasRoomID" const RoomserverGetRoomIDForAliasPath = "/api/roomserver/GetRoomIDForAlias"
// RoomserverGetAliasesForRoomIDPath is the HTTP path for the GetAliasesForRoomID API.
const RoomserverGetAliasesForRoomIDPath = "/api/roomserver/GetAliasesForRoomID"
// RoomserverRemoveRoomAliasPath is the HTTP path for the RemoveRoomAlias API. // RoomserverRemoveRoomAliasPath is the HTTP path for the RemoveRoomAlias API.
const RoomserverRemoveRoomAliasPath = "/api/roomserver/removeRoomAlias" const RoomserverRemoveRoomAliasPath = "/api/roomserver/removeRoomAlias"
@ -120,16 +142,29 @@ func (h *httpRoomserverAliasAPI) SetRoomAlias(
return postJSON(ctx, span, h.httpClient, apiURL, request, response) return postJSON(ctx, span, h.httpClient, apiURL, request, response)
} }
// GetAliasRoomID implements RoomserverAliasAPI // GetRoomIDForAlias implements RoomserverAliasAPI
func (h *httpRoomserverAliasAPI) GetAliasRoomID( func (h *httpRoomserverAliasAPI) GetRoomIDForAlias(
ctx context.Context, ctx context.Context,
request *GetAliasRoomIDRequest, request *GetRoomIDForAliasRequest,
response *GetAliasRoomIDResponse, response *GetRoomIDForAliasResponse,
) error { ) error {
span, ctx := opentracing.StartSpanFromContext(ctx, "GetAliasRoomID") span, ctx := opentracing.StartSpanFromContext(ctx, "GetRoomIDForAlias")
defer span.Finish() defer span.Finish()
apiURL := h.roomserverURL + RoomserverGetAliasRoomIDPath apiURL := h.roomserverURL + RoomserverGetRoomIDForAliasPath
return postJSON(ctx, span, h.httpClient, apiURL, request, response)
}
// GetAliasesForRoomID implements RoomserverAliasAPI
func (h *httpRoomserverAliasAPI) GetAliasesForRoomID(
ctx context.Context,
request *GetAliasesForRoomIDRequest,
response *GetAliasesForRoomIDResponse,
) error {
span, ctx := opentracing.StartSpanFromContext(ctx, "GetAliasesForRoomID")
defer span.Finish()
apiURL := h.roomserverURL + RoomserverGetAliasesForRoomIDPath
return postJSON(ctx, span, h.httpClient, apiURL, request, response) return postJSON(ctx, span, h.httpClient, apiURL, request, response)
} }

View file

@ -445,13 +445,13 @@ func (d *Database) SetRoomAlias(ctx context.Context, alias string, roomID string
return d.statements.insertRoomAlias(ctx, alias, roomID) return d.statements.insertRoomAlias(ctx, alias, roomID)
} }
// GetRoomIDFromAlias implements alias.RoomserverAliasAPIDB // GetRoomIDForAlias implements alias.RoomserverAliasAPIDB
func (d *Database) GetRoomIDFromAlias(ctx context.Context, alias string) (string, error) { func (d *Database) GetRoomIDForAlias(ctx context.Context, alias string) (string, error) {
return d.statements.selectRoomIDFromAlias(ctx, alias) return d.statements.selectRoomIDFromAlias(ctx, alias)
} }
// GetAliasesFromRoomID implements alias.RoomserverAliasAPIDB // GetAliasesForRoomID implements alias.RoomserverAliasAPIDB
func (d *Database) GetAliasesFromRoomID(ctx context.Context, roomID string) ([]string, error) { func (d *Database) GetAliasesForRoomID(ctx context.Context, roomID string) ([]string, error) {
return d.statements.selectAliasesFromRoomID(ctx, roomID) return d.statements.selectAliasesFromRoomID(ctx, roomID)
} }