mirror of
https://github.com/matrix-org/dendrite
synced 2024-11-18 07:40:53 +01:00
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:
parent
60e77959ee
commit
04551becb4
10 changed files with 229 additions and 76 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue