matrix: end-to-end encryption by default

Existing chats will remain unencrypted but new ones will be.
This commit is contained in:
Harvey Tindall 2021-07-13 19:02:16 +01:00
parent 30198fab87
commit 833d02b032
Signed by: hrfee
GPG Key ID: BBC65952848FB1A2
10 changed files with 221 additions and 53 deletions

View File

@ -1,3 +1,5 @@
---jfa-go---
MIT License
Copyright (c) 2021 Harvey Tindall
@ -19,3 +21,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

12
api.go
View File

@ -2571,18 +2571,20 @@ func (app *appContext) MatrixConnect(gc *gin.Context) {
if app.storage.matrix == nil {
app.storage.matrix = map[string]MatrixUser{}
}
roomID, err := app.matrix.CreateRoom(req.UserID)
roomID, encrypted, err := app.matrix.CreateRoom(req.UserID)
if err != nil {
app.err.Printf("Matrix: Failed to create room: %v", err)
respondBool(500, false, gc)
return
}
app.storage.matrix[req.JellyfinID] = MatrixUser{
UserID: req.UserID,
RoomID: string(roomID),
Lang: "en-us",
Contact: true,
UserID: req.UserID,
RoomID: string(roomID),
Lang: "en-us",
Contact: true,
Encrypted: encrypted,
}
app.matrix.isEncrypted[roomID] = encrypted
if err := app.storage.storeMatrixUsers(); err != nil {
app.err.Printf("Failed to store Matrix users: %v", err)
respondBool(500, false, gc)

View File

@ -47,6 +47,9 @@ func (app *appContext) loadConfig() error {
for _, key := range []string{"user_configuration", "user_displayprefs", "user_profiles", "ombi_template", "invites", "emails", "user_template", "custom_emails", "users", "telegram_users", "discord_users", "matrix_users", "announcements"} {
app.config.Section("files").Key(key).SetValue(app.config.Section("files").Key(key).MustString(filepath.Join(app.dataPath, (key + ".json"))))
}
for _, key := range []string{"matrix_sql"} {
app.config.Section("files").Key(key).SetValue(app.config.Section("files").Key(key).MustString(filepath.Join(app.dataPath, (key + ".db"))))
}
app.URLBase = strings.TrimSuffix(app.config.Section("ui").Key("url_base").MustString(""), "/")
app.config.Section("email").Key("no_username").SetValue(strconv.FormatBool(app.config.Section("email").Key("no_username").MustBool(false)))

View File

@ -1324,6 +1324,14 @@
"value": "",
"description": "Stores matrix user IDs and language preferences."
},
"matrix_sql": {
"name": "Matrix encryption DB",
"required": false,
"requires_restart": false,
"type": "text",
"value": "",
"description": "Stores cryptographic material for Matrix end-to-end encryption."
},
"discord_users": {
"name": "Discord users",
"required": false,

View File

@ -819,7 +819,7 @@ func (app *appContext) sendByID(email *Message, ID ...string) error {
}
}
if mxChat, ok := app.storage.matrix[id]; ok && mxChat.Contact && matrixEnabled {
err = app.matrix.Send(email, mxChat.RoomID)
err = app.matrix.Send(email, mxChat)
if err != nil {
return err
}

1
go.mod
View File

@ -56,4 +56,5 @@ require (
google.golang.org/protobuf v1.25.0 // indirect
gopkg.in/ini.v1 v1.62.0
maunium.net/go/mautrix v0.9.14
modernc.org/sqlite v1.11.2
)

48
go.sum
View File

@ -33,6 +33,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/emersion/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:M88ob4TyDnEqNuL3PgsE/p3bDujfspnulR+0dQWNYZs=
github.com/emersion/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:buzQsO8HHkZX2Q45fdfGH1xejPjuDQaXH8btcYMFzPM=
@ -141,8 +143,9 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
@ -173,6 +176,8 @@ github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@ -183,6 +188,7 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8=
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lithammer/shortuuid/v3 v3.0.4 h1:uj4xhotfY92Y1Oa6n6HUiFn87CdoEHYUlTy0+IgbLrs=
github.com/lithammer/shortuuid/v3 v3.0.4/go.mod h1:RviRjexKqIzx/7r1peoAITm6m7gnif/h+0zmolKJjzw=
@ -202,6 +208,7 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
@ -223,6 +230,8 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@ -252,9 +261,13 @@ github.com/swaggo/swag v1.7.0 h1:5bCA/MTLQoIqDXXyHfOpMeDvL9j68OY/udlK4pQoo4E=
github.com/swaggo/swag v1.7.0/go.mod h1:BdPIL73gvS9NBsdi7M1JOxLvlbfvNRaBP8m6WT6Aajo=
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
github.com/tidwall/gjson v1.6.8 h1:CTmXMClGYPAmln7652e69B7OLXfTi5ABcPPwjIWUv7w=
github.com/tidwall/gjson v1.6.8/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI=
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU=
github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/sjson v1.1.5 h1:wsUceI/XDyZk3J1FUvuuYlK62zJv2HO2Pzb8A5EWdUE=
github.com/tidwall/sjson v1.1.5/go.mod h1:VuJzsZnTowhSxWdOgsAnb886i4AjEyTkk7tNtsL7EYE=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go v1.1.5-pre/go.mod h1:FwP/aQVg39TXzItUBMwnWp9T9gPQnXw4Poh4/oBQZ/0=
@ -338,6 +351,8 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210319071255-635bc2c9138d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -365,6 +380,7 @@ golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.3 h1:L69ShwSZEyCsLKoAxDKeMvLDZkumEe8gXUZAjab0tX8=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -413,6 +429,36 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclp
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU=
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
maunium.net/go/maulogger/v2 v2.2.4/go.mod h1:TYWy7wKwz/tIXTpsx8G3mZseIRiC5DoMxSZazOHy68A=
maunium.net/go/mautrix v0.9.14 h1:2MMJ630VM+xfa4Q5AooMAhPG1+wQnQybSr/z8PlRZ8A=
maunium.net/go/mautrix v0.9.14/go.mod h1:7IzKfWvpQtN+W2Lzxc0rLvIxFM3ryKX6Ys3S/ZoWbg8=
modernc.org/cc/v3 v3.33.6 h1:r63dgSzVzRxUpAJFPQWHy1QeZeY1ydNENUDaBx1GqYc=
modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/ccgo/v3 v3.9.5 h1:dEuUSf8WN51rDkprFuAqjfchKEzN0WttP/Py3enBwjk=
modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60=
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v1.7.13-0.20210308123627-12f642a52bb8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
modernc.org/libc v1.9.11 h1:QUxZMs48Ahg2F7SN41aERvMfGLY2HU/ADnB9DC4Yts8=
modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q=
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.0 h1:GCjoRaBew8ECCKINQA2nYjzvufFW9YiEuuB+rQ9bn2E=
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.0.4 h1:utMBrFcpnQDdNsmM6asmyH/FM9TqLPS7XF7otpJmrwM=
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sqlite v1.11.2 h1:ShWQpeD3ag/bmx6TqidBlIWonWmQaSQKls3aenCbt+w=
modernc.org/sqlite v1.11.2/go.mod h1:+mhs/P1ONd+6G7hcAs6irwDi/bjTQ7nLW6LHRBsEa3A=
modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs=
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
modernc.org/tcl v1.5.5 h1:N03RwthgTR/l/eQvz3UjfYnvVVj1G2sZqzFGfoD4HE4=
modernc.org/tcl v1.5.5/go.mod h1:ADkaTUuwukkrlhqwERyq0SM8OvyXo7+TjFz7yAF56EI=
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.0.1 h1:WyIDpEpAIx4Hel6q/Pcgj/VhaQV5XPJ2I6ryIYbjnpc=
modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=

View File

@ -652,7 +652,8 @@ func main() {
Exit(r)
}
}()
defer logOutput()()
f := logOutput()
defer f()
printVersion()
SOCK = filepath.Join(temp, SOCK)
fmt.Println("Socket:", SOCK)

160
matrix.go
View File

@ -4,10 +4,15 @@ import (
"fmt"
"strings"
"database/sql"
"github.com/gomarkdown/markdown"
gomatrix "maunium.net/go/mautrix"
"maunium.net/go/mautrix/crypto"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
_ "modernc.org/sqlite"
)
type MatrixDaemon struct {
@ -17,6 +22,10 @@ type MatrixDaemon struct {
userID id.UserID
tokens map[string]UnverifiedUser // Map of tokens to users
languages map[id.RoomID]string // Map of roomIDs to language codes
isEncrypted map[id.RoomID]bool
cryptoStore *crypto.SQLCryptoStore
olm *crypto.OlmMachine
db *sql.DB
app *appContext
}
@ -26,18 +35,47 @@ type UnverifiedUser struct {
}
type MatrixUser struct {
RoomID string
UserID string
Lang string
Contact bool
RoomID string
Encrypted bool
UserID string
Lang string
Contact bool
}
type MatrixIdentifier struct {
User string `json:"user"`
IdentType string `json:"type"`
func (m *MatrixDaemon) IsEncrypted(roomID id.RoomID) bool {
return m.isEncrypted[roomID]
}
func (m MatrixIdentifier) Type() string { return m.IdentType }
func (m *MatrixDaemon) GetEncryptionEvent(roomID id.RoomID) *event.EncryptionEventContent {
return &event.EncryptionEventContent{
Algorithm: id.AlgorithmMegolmV1,
RotationPeriodMillis: 7 * 24 * 60 * 60 * 1000,
RotationPeriodMessages: 100,
}
}
// Users are assumed to only have one common channel with the bot, so we can stub this out.
func (m *MatrixDaemon) FindSharedRooms(userID id.UserID) []id.RoomID { return []id.RoomID{} }
type olmLogger struct {
app *appContext
}
func (o olmLogger) Error(message string, args ...interface{}) {
o.app.err.Printf("OLM: "+message+"\n", args)
}
func (o olmLogger) Warn(message string, args ...interface{}) {
o.app.info.Printf("OLM: "+message+"\n", args)
}
func (o olmLogger) Debug(message string, args ...interface{}) {
o.app.debug.Printf("OLM: "+message+"\n", args)
}
func (o olmLogger) Trace(message string, args ...interface{}) {
o.app.debug.Printf("OLM [TRACE]: "+message+"\n", args)
}
var matrixFilter = gomatrix.Filter{
Room: gomatrix.RoomFilter{
@ -68,6 +106,7 @@ func newMatrixDaemon(app *appContext) (d *MatrixDaemon, err error) {
userID: id.UserID(matrix.Key("user_id").String()),
tokens: map[string]UnverifiedUser{},
languages: map[id.RoomID]string{},
isEncrypted: map[id.RoomID]bool{},
app: app,
}
d.bot, err = gomatrix.NewClient(homeserver, d.userID, token)
@ -80,6 +119,19 @@ func newMatrixDaemon(app *appContext) (d *MatrixDaemon, err error) {
if user.Lang != "" {
d.languages[id.RoomID(user.RoomID)] = user.Lang
}
d.isEncrypted[id.RoomID(user.RoomID)] = user.Encrypted
}
d.db, err = sql.Open("sqlite", app.config.Section("files").Key("matrix_sql").String())
olmLog := &olmLogger{app}
d.cryptoStore = crypto.NewSQLCryptoStore(d.db, "sqlite3", "jfa-go", "jfa-go", []byte("jfa-go"), olmLog)
err = d.cryptoStore.CreateTables()
if err != nil {
return
}
d.olm = crypto.NewOlmMachine(d.bot, olmLog, d.cryptoStore, crypto.StateStore(d))
err = d.olm.Load()
if err != nil {
return
}
return
}
@ -108,7 +160,20 @@ func (d *MatrixDaemon) generateAccessToken(homeserver, username, password string
func (d *MatrixDaemon) run() {
d.app.info.Println("Starting Matrix bot daemon")
syncer := d.bot.Syncer.(*gomatrix.DefaultSyncer)
syncer.OnEventType(event.NewEventType("m.room.message"), d.handleMessage)
syncer.OnEventType(event.EventMessage, d.handleMessage)
syncer.OnEventType(event.EventEncrypted, func(source gomatrix.EventSource, evt *event.Event) {
decrypted, err := d.olm.DecryptMegolmEvent(evt)
if err != nil {
d.app.err.Printf("Failed to decrypt Matrix message: %v", err)
return
}
d.handleMessage(source, decrypted)
})
syncer.OnSync(d.olm.ProcessSyncResponse)
syncer.OnEventType(event.StateMember, func(source gomatrix.EventSource, evt *event.Event) {
d.olm.HandleMemberEvent(evt)
})
// syncer.OnEventType("m.room.member", d.handleMembership)
if err := d.bot.Sync(); err != nil {
d.app.err.Printf("Matrix sync failed: %v", err)
@ -117,6 +182,7 @@ func (d *MatrixDaemon) run() {
func (d *MatrixDaemon) Shutdown() {
d.bot.StopSync()
d.db.Close()
d.Stopped = true
close(d.ShutdownChannel)
}
@ -170,20 +236,32 @@ func (d *MatrixDaemon) commandLang(evt *event.Event, code, lang string) {
}
}
func (d *MatrixDaemon) CreateRoom(userID string) (id.RoomID, error) {
room, err := d.bot.CreateRoom(&gomatrix.ReqCreateRoom{
func (d *MatrixDaemon) CreateRoom(userID string) (roomID id.RoomID, encrypted bool, err error) {
var room *gomatrix.RespCreateRoom
room, err = d.bot.CreateRoom(&gomatrix.ReqCreateRoom{
Visibility: "private",
Invite: []id.UserID{id.UserID(userID)},
Topic: d.app.config.Section("matrix").Key("topic").String(),
})
if err != nil {
return "", err
return
}
return room.RoomID, nil
_, err = d.bot.SendStateEvent(room.RoomID, event.StateEncryption, "", &event.EncryptionEventContent{
Algorithm: id.AlgorithmMegolmV1,
RotationPeriodMillis: 7 * 24 * 60 * 60 * 1000,
RotationPeriodMessages: 100,
})
if err == nil {
encrypted = true
} else {
d.app.debug.Printf("Matrix: Failed to enable encryption in room: %v", err)
}
roomID = room.RoomID
return
}
func (d *MatrixDaemon) SendStart(userID string) (ok bool) {
roomID, err := d.CreateRoom(userID)
roomID, encrypted, err := d.CreateRoom(userID)
if err != nil {
d.app.err.Printf("Failed to create room for user \"%s\": %v", userID, err)
return
@ -193,11 +271,13 @@ func (d *MatrixDaemon) SendStart(userID string) (ok bool) {
d.tokens[pin] = UnverifiedUser{
false,
&MatrixUser{
RoomID: string(roomID),
UserID: userID,
Lang: lang,
RoomID: string(roomID),
UserID: userID,
Lang: lang,
Encrypted: encrypted,
},
}
d.isEncrypted[roomID] = encrypted
_, err = d.bot.SendText(
roomID,
d.app.storage.lang.Telegram[lang].Strings.get("matrixStartMessage")+"\n\n"+pin+"\n\n"+
@ -211,23 +291,25 @@ func (d *MatrixDaemon) SendStart(userID string) (ok bool) {
return
}
func (d *MatrixDaemon) Send(message *Message, roomID ...string) (err error) {
func (d *MatrixDaemon) Send(message *Message, users ...MatrixUser) (err error) {
md := ""
if message.Markdown != "" {
// Convert images to links
md = string(markdown.ToHTML([]byte(strings.ReplaceAll(message.Markdown, "![", "[")), nil, renderer))
}
for _, ident := range roomID {
if md != "" {
_, err = d.bot.SendMessageEvent(id.RoomID(ident), event.NewEventType("m.room.message"), map[string]interface{}{
"msgtype": "m.text",
"body": message.Text,
"formatted_body": md,
"format": "org.matrix.custom.html",
}, gomatrix.ReqSendEvent{})
content := event.MessageEventContent{
MsgType: "m.text",
Body: message.Text,
}
if md != "" {
content.FormattedBody = md
content.Format = "org.matrix.custom.html"
}
for _, user := range users {
if user.Encrypted {
err = d.SendEncrypted(&content, user)
} else {
_, err = d.bot.SendText(id.RoomID(ident), message.Text)
_, err = d.bot.SendMessageEvent(id.RoomID(user.RoomID), event.NewEventType("m.room.message"), content, gomatrix.ReqSendEvent{})
}
if err != nil {
return
@ -236,6 +318,28 @@ func (d *MatrixDaemon) Send(message *Message, roomID ...string) (err error) {
return
}
func (d *MatrixDaemon) SendEncrypted(content *event.MessageEventContent, users ...MatrixUser) (err error) {
for _, user := range users {
var encrypted *event.EncryptedEventContent
encrypted, err = d.olm.EncryptMegolmEvent(id.RoomID(user.RoomID), event.EventMessage, content)
if err == crypto.SessionExpired || err == crypto.SessionNotShared || err == crypto.NoGroupSession {
err = d.olm.ShareGroupSession(id.RoomID(user.RoomID), []id.UserID{id.UserID(user.UserID)})
if err != nil {
return
}
encrypted, err = d.olm.EncryptMegolmEvent(id.RoomID(user.RoomID), event.EventMessage, content)
}
if err != nil {
return
}
_, err = d.bot.SendMessageEvent(id.RoomID(user.RoomID), event.EventEncrypted, encrypted)
if err != nil {
return
}
}
return
}
// User enters ID on sign-up, a PIN is sent to them. They enter it on sign-up.
// Message the user first, to avoid E2EE by default

View File

@ -15,23 +15,23 @@ import (
)
type Storage struct {
timePattern string
invite_path, emails_path, policy_path, configuration_path, displayprefs_path, ombi_path, profiles_path, customEmails_path, users_path, telegram_path, discord_path, matrix_path, announcements_path string
users map[string]time.Time
invites Invites
profiles map[string]Profile
defaultProfile string
displayprefs, ombi_template map[string]interface{}
emails map[string]EmailAddress
telegram map[string]TelegramUser // Map of Jellyfin User IDs to telegram users.
discord map[string]DiscordUser // Map of Jellyfin user IDs to discord users.
matrix map[string]MatrixUser // Map of Jellyfin user IDs to Matrix users.
customEmails customEmails
policy mediabrowser.Policy
configuration mediabrowser.Configuration
lang Lang
announcements map[string]announcementTemplate
invitesLock, usersLock sync.Mutex
timePattern string
invite_path, emails_path, policy_path, configuration_path, displayprefs_path, ombi_path, profiles_path, customEmails_path, users_path, telegram_path, discord_path, matrix_path, announcements_path, matrix_sql_path string
users map[string]time.Time
invites Invites
profiles map[string]Profile
defaultProfile string
displayprefs, ombi_template map[string]interface{}
emails map[string]EmailAddress
telegram map[string]TelegramUser // Map of Jellyfin User IDs to telegram users.
discord map[string]DiscordUser // Map of Jellyfin user IDs to discord users.
matrix map[string]MatrixUser // Map of Jellyfin user IDs to Matrix users.
customEmails customEmails
policy mediabrowser.Policy
configuration mediabrowser.Configuration
lang Lang
announcements map[string]announcementTemplate
invitesLock, usersLock sync.Mutex
}
type TelegramUser struct {