aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2020-02-29 10:51:09 +0100
committerAlex Auvolat <alex@adnab.me>2020-02-29 10:51:09 +0100
commit2649e41c85283c680b9e1aa3294868b985aecc22 (patch)
tree67a37cd6044f217e9be5fe217efaf86d040f06bc
parent38a3f1bdb18159cc4808fa86280da55f0599dcc8 (diff)
downloadeasybridge-2649e41c85283c680b9e1aa3294868b985aecc22.tar.gz
easybridge-2649e41c85283c680b9e1aa3294868b985aecc22.zip
Allow _ezbr_ to be put in suffix of usernames/room aliases instead of prefix
-rw-r--r--README.md19
-rw-r--r--db.go23
-rw-r--r--main.go26
-rw-r--r--mxlib/client.go20
-rw-r--r--server.go2
-rw-r--r--util.go29
6 files changed, 92 insertions, 27 deletions
diff --git a/README.md b/README.md
index 3540e48..c2bd29d 100644
--- a/README.md
+++ b/README.md
@@ -48,11 +48,22 @@ Easybridge is configured using a single JSON configuration file, which contains
a dictionnary whose keys are the following:
- `log_level`: what log level Easybridge runs with (trace, debug, info, warn, error, fatal, panic). **Warning:** in `trace` level, the content of all calls to the Matrix API and some other information will be dumped, exposing user's credentials and messages. In `debug` level, room join/leave information will be exposed. The `info` level (default) does not expose any user's private information.
+- `easybridge_avatar`: path to the image that Easybridge uses as an avatar on Matrix
+
+### Matrix configuration
+
+- `registration`: path to the YAML appservice registration file
- `appservice_bind_addr`: on what IP/port to bind as a Matrix app service (HTTP only, no HTTPS)
+- `homeserver_url`: HTTP address of the Matrix homeserver
+- `matrix_domain`: the domain name of the Matrix homeserver (i.e. the domain used in user identifiers, room identifiers, etc)
+- `name_format`: the format of identifiers that are created on Matrix for users and room aliases. `{}` is replaced by the concatenation of user/room identifier and protocol. Typically you want either `_ezbr_{}` or `{}_ezbr`, the latter having the advantage that the briged user's names are then used as prefixes for the created identifiers.
+
+### Web interface configuration
+
- `web_bind_addr`: on what IP/port to bind for the web interface that allows adding and configuring accounts (HTTP only, no HTTPS, use a reverse proxy for that)
- `web_url`: the outside HTTP/HTTPS address at which the web interface is made available. If set, a widget will be added in the Easybridge room so that users can configure the bridge without leaving the Riot client.
-- `registration`: path to the YAML appservice registration file
-- `homeserver_url`: HTTP address of the Matrix homeserver
-- `matrix_domain`: the dmoain name of the Matrix homeserver (i.e. the domain used in user identifiers, room identifiers, etc)
-- `db_type` and `db_path`: the database backend and path to use (see the [Gorm documentation](http://gorm.io/docs/connecting_to_the_database.html))
- `session_key`: a key with which session cookies are encrypted for the web interface
+
+### Storage configuration
+
+- `db_type` and `db_path`: the database backend and path to use (see the [Gorm documentation](http://gorm.io/docs/connecting_to_the_database.html))
diff --git a/db.go b/db.go
index cdbdca1..42c9aee 100644
--- a/db.go
+++ b/db.go
@@ -213,18 +213,21 @@ func dbGetMxRoom(protocol string, roomId connector.RoomID) (string, error) {
if must_create {
alias := roomAlias(protocol, roomId)
- // Lookup alias
- mx_room_id, err := mx.DirectoryRoom(fmt.Sprintf("#%s:%s", alias, config.MatrixDomain))
- // If no alias found, create room
- if err != nil {
- name := fmt.Sprintf("%s (%s)", roomId, protocol)
+ // Delete previous alias if it existed
+ prev_full_alias := fmt.Sprintf("#%s:%s", alias, config.MatrixDomain)
+ mx_room_id, err := mx.DirectoryRoom(prev_full_alias)
+ if err == nil {
+ mx.DirectoryDeleteRoom(prev_full_alias)
+ }
- mx_room_id, err = mx.CreateRoom(name, alias, []string{})
- if err != nil {
- log.Warnf("Could not create room for %s: %s", name, err)
- return "", err
- }
+ // Create room
+ name := fmt.Sprintf("%s (%s)", roomId, protocol)
+
+ mx_room_id, err = mx.CreateRoom(name, alias, []string{})
+ if err != nil {
+ log.Warnf("Could not create room for %s: %s", name, err)
+ return "", err
}
room = DbRoomMap{
diff --git a/main.go b/main.go
index d25a3d6..514bd4c 100644
--- a/main.go
+++ b/main.go
@@ -15,17 +15,22 @@ import (
)
type ConfigFile struct {
- LogLevel string `json:"log_level"`
- ASBindAddr string `json:"appservice_bind_addr"`
- WebBindAddr string `json:"web_bind_addr"`
- WebURL string `json:"web_url"`
+ LogLevel string `json:"log_level"`
+
Registration string `json:"registration"`
+ ASBindAddr string `json:"appservice_bind_addr"`
Server string `json:"homeserver_url"`
- DbType string `json:"db_type"`
- DbPath string `json:"db_path"`
MatrixDomain string `json:"matrix_domain"`
- SessionKey string `json:"web_session_key"`
- AvatarFile string `json:"easybridge_avatar"`
+ NameFormat string `json:"name_format"`
+
+ WebBindAddr string `json:"web_bind_addr"`
+ WebURL string `json:"web_url"`
+ SessionKey string `json:"web_session_key"`
+
+ DbType string `json:"db_type"`
+ DbPath string `json:"db_path"`
+
+ AvatarFile string `json:"easybridge_avatar"`
}
var configFlag = flag.String("config", "./config.json", "Configuration file path")
@@ -43,6 +48,7 @@ func readConfig() ConfigFile {
WebBindAddr: "0.0.0.0:8281",
Registration: "./registration.yaml",
Server: "http://localhost:8008",
+ NameFormat: "{}_ezbr_",
DbType: "sqlite3",
DbPath: "easybridge.db",
AvatarFile: "./easybridge.jpg",
@@ -102,13 +108,13 @@ func readRegistration(file string) mxlib.Registration {
Users: []mxlib.RegistrationNamespace{
mxlib.RegistrationNamespace{
Exclusive: true,
- Regex: "@_ezbr_.*",
+ Regex: "@.*_ezbr_",
},
},
Aliases: []mxlib.RegistrationNamespace{
mxlib.RegistrationNamespace{
Exclusive: true,
- Regex: "#_ezbr_.*",
+ Regex: "#.*_ezbr_",
},
},
Rooms: []mxlib.RegistrationNamespace{},
diff --git a/mxlib/client.go b/mxlib/client.go
index 71bba3f..c111360 100644
--- a/mxlib/client.go
+++ b/mxlib/client.go
@@ -78,6 +78,17 @@ func (mx *Client) PostApiCall(endpoint string, data interface{}, response interf
return mx.DoAndParse(req, response)
}
+func (mx *Client) DeleteApiCall(endpoint string, response interface{}) error {
+ log.Debugf("Matrix DELETE request: %s\n", endpoint)
+
+ req, err := http.NewRequest("DELETE", mx.Server+endpoint, nil)
+ if err != nil {
+ return err
+ }
+
+ return mx.DoAndParse(req, response)
+}
+
func (mx *Client) DoAndParse(req *http.Request, response interface{}) error {
if mx.Token != "" {
req.Header.Add("Authorization", "Bearer "+mx.Token)
@@ -181,6 +192,15 @@ func (mx *Client) DirectoryRoom(alias string) (string, error) {
return rep.RoomId, nil
}
+func (mx *Client) DirectoryDeleteRoom(alias string) error {
+ var rep struct{}
+ err := mx.DeleteApiCall("/_matrix/client/r0/directory/room/"+url.QueryEscape(alias), &rep)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
func (mx *Client) CreateRoom(name string, alias string, invite []string) (string, error) {
rq := CreateRoomRequest{
Preset: "private_chat",
diff --git a/server.go b/server.go
index dc04006..028e7b8 100644
--- a/server.go
+++ b/server.go
@@ -102,7 +102,7 @@ func handleTxn(w http.ResponseWriter, r *http.Request) {
for i := range txn.Events {
ev := &txn.Events[i]
- if strings.HasPrefix(ev.Sender, "@"+registration.SenderLocalpart) {
+ if isBridgedIdentifier(ev.Sender) {
// Don't do anything with ezbr events that come back to us
continue
}
diff --git a/util.go b/util.go
index 5d86b8a..4e23bb1 100644
--- a/util.go
+++ b/util.go
@@ -5,6 +5,7 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
+ "strings"
"unicode"
log "github.com/sirupsen/logrus"
@@ -58,11 +59,13 @@ func ezbrSystemSendf(user_mx_id string, format string, args ...interface{}) {
// ----
func roomAlias(protocol string, id RoomID) string {
- return fmt.Sprintf("%s_%s__%s", registration.SenderLocalpart, safeStringForId(string(id)), protocol)
+ what := fmt.Sprintf("%s_%s", safeStringForId(string(id)), protocol)
+ return strings.Replace(config.NameFormat, "{}", what, 1)
}
func userMxId(protocol string, id UserID) string {
- return fmt.Sprintf("%s_%s__%s", registration.SenderLocalpart, safeStringForId(string(id)), protocol)
+ what := fmt.Sprintf("%s_%s", safeStringForId(string(id)), protocol)
+ return strings.Replace(config.NameFormat, "{}", what, 1)
}
func safeStringForId(in string) string {
@@ -79,6 +82,28 @@ func safeStringForId(in string) string {
return id2
}
+func isBridgedIdentifier(mxid string) bool {
+ if mxid[0] == '@' || mxid[0] == '#' {
+ return isBridgedIdentifier(mxid[1:])
+ }
+
+ if strings.Contains(mxid, ":") {
+ sp := strings.Split(mxid, ":")
+ return (sp[1] == config.MatrixDomain) && isBridgedIdentifier(sp[0])
+ }
+
+ nameformat_fixed_part := strings.Replace(config.NameFormat, "{}", "", 1)
+ if strings.HasPrefix(config.NameFormat, "{}") {
+ return strings.HasSuffix(mxid, nameformat_fixed_part)
+ } else if strings.HasSuffix(config.NameFormat, "{}") {
+ return strings.HasPrefix(mxid, nameformat_fixed_part)
+ } else {
+ // This is not supported
+ log.Fatal("Invalid name format %s, please put {} at the beginning or at the end", config.NameFormat)
+ return false
+ }
+}
+
// ---- Encoding and encryption of account config
func encryptAccountConfig(config map[string]string, key *[32]byte) string {