Browse Source

Docs about device ID & update mautrix version (#330)

* Remove unnecessary content ParseRaw calls

Signed-off-by: Nikos Filippakis <me@nfil.dev>

* Add details about getting the access token and device ID to readme

Signed-off-by: Nikos Filippakis <me@nfil.dev>

* Update mautrix to version 0.6.0

Signed-off-by: Nikos Filippakis <me@nfil.dev>
pull/337/head
Nikos Filippakis 5 years ago
committed by GitHub
parent
commit
86cbd3f899
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 17
      README.md
  2. 3
      clients/bot_client.go
  3. 18
      clients/clients.go
  4. 1
      clients/clients_test.go
  5. 14
      clients/state_store.go
  6. 2
      config.sample.yaml
  7. 2
      go.mod
  8. 2
      go.sum
  9. 19
      goneb_services_test.go

17
README.md

@ -26,13 +26,28 @@ go build github.com/matrix-org/go-neb
BIND_ADDRESS=:4050 DATABASE_TYPE=sqlite3 DATABASE_URL=go-neb.db?_busy_timeout=5000 BASE_URL=http://localhost:4050 ./go-neb BIND_ADDRESS=:4050 DATABASE_TYPE=sqlite3 DATABASE_URL=go-neb.db?_busy_timeout=5000 BASE_URL=http://localhost:4050 ./go-neb
``` ```
Get a Matrix user ID and access token and give it to Go-NEB:
Get a Matrix user ID and access token. You can do this, for example, with the following curl command by replacing the user ID, password and Synapse URL with your own.
```bash
curl -X POST --header 'Content-Type: application/json' -d '{
"identifier": { "type": "m.id.user", "user": "nebUsername" },
"password": "nebPassword",
"type": "m.login.password"
}' 'http://localhost:8008/_matrix/client/r0/login'
```
This is preferable to, for example, logging in via Riot and copying the access token and device ID from there, as then Riot will have uploaded its own device keys which Go-NEB won't have access to causing it to be unable to create encryption sessions.
The response of this command will be a JSON object with an access token and device ID.
Then, give the values to Go-NEB:
```bash ```bash
curl -X POST localhost:4050/admin/configureClient --data-binary '{ curl -X POST localhost:4050/admin/configureClient --data-binary '{
"UserID": "@goneb:localhost", "UserID": "@goneb:localhost",
"HomeserverURL": "http://localhost:8008", "HomeserverURL": "http://localhost:8008",
"AccessToken": "<access_token>", "AccessToken": "<access_token>",
"DeviceID": "<DEVICEID>",
"Sync": true, "Sync": true,
"AutoJoinRooms": true, "AutoJoinRooms": true,
"DisplayName": "My Bot" "DisplayName": "My Bot"

3
clients/bot_client.go

@ -32,7 +32,8 @@ func (botClient *BotClient) InitOlmMachine(client *mautrix.Client, nebStore *mat
if sdb, ok := database.GetServiceDB().(*database.ServiceDB); ok { if sdb, ok := database.GetServiceDB().(*database.ServiceDB); ok {
// Create an SQL crypto store based on the ServiceDB used // Create an SQL crypto store based on the ServiceDB used
db, dialect := sdb.GetSQLDb() db, dialect := sdb.GetSQLDb()
sqlCryptoStore := crypto.NewSQLCryptoStore(db, dialect, client.DeviceID, []byte(client.DeviceID.String()+"pickle"), cryptoLogger)
accountID := botClient.config.UserID.String() + "-" + client.DeviceID.String()
sqlCryptoStore := crypto.NewSQLCryptoStore(db, dialect, accountID, client.DeviceID, []byte(client.DeviceID.String()+"pickle"), cryptoLogger)
// Try to create the tables if they are missing // Try to create the tables if they are missing
if err = sqlCryptoStore.CreateTables(); err != nil { if err = sqlCryptoStore.CreateTables(); err != nil {
return return

18
clients/clients.go

@ -159,10 +159,6 @@ func (c *Clients) onMessageEvent(botClient *BotClient, event *mevt.Event) {
}).Warn("Error loading services") }).Warn("Error loading services")
} }
if err := event.Content.ParseRaw(mevt.EventMessage); err != nil {
return
}
message := event.Content.AsMessage() message := event.Content.AsMessage()
body := message.Body body := message.Body
@ -307,9 +303,6 @@ func (c *Clients) onBotOptionsEvent(client *mautrix.Client, event *mevt.Event) {
} }
func (c *Clients) onRoomMemberEvent(client *mautrix.Client, event *mevt.Event) { func (c *Clients) onRoomMemberEvent(client *mautrix.Client, event *mevt.Event) {
if err := event.Content.ParseRaw(mevt.StateMember); err != nil {
return
}
if event.StateKey == nil || *event.StateKey != client.UserID.String() { if event.StateKey == nil || *event.StateKey != client.UserID.String() {
return // not our member event return // not our member event
} }
@ -384,10 +377,6 @@ func (c *Clients) initClient(botClient *BotClient) error {
// When receiving an encrypted event, attempt to decrypt it using the BotClient's capabilities. // When receiving an encrypted event, attempt to decrypt it using the BotClient's capabilities.
// If successfully decrypted propagate the decrypted event to the clients. // If successfully decrypted propagate the decrypted event to the clients.
syncer.OnEventType(mevt.EventEncrypted, func(source mautrix.EventSource, evt *mevt.Event) { syncer.OnEventType(mevt.EventEncrypted, func(source mautrix.EventSource, evt *mevt.Event) {
if err := evt.Content.ParseRaw(mevt.EventEncrypted); err != nil {
log.WithError(err).Error("Failed to parse encrypted message")
return
}
encContent := evt.Content.AsEncrypted() encContent := evt.Content.AsEncrypted()
decrypted, err := botClient.DecryptMegolmEvent(evt) decrypted, err := botClient.DecryptMegolmEvent(evt)
if err != nil { if err != nil {
@ -399,12 +388,7 @@ func (c *Clients) initClient(botClient *BotClient) error {
}).WithError(err).Error("Failed to decrypt message") }).WithError(err).Error("Failed to decrypt message")
} else { } else {
if decrypted.Type == mevt.EventMessage { if decrypted.Type == mevt.EventMessage {
err = decrypted.Content.ParseRaw(mevt.EventMessage)
if err != nil {
log.WithError(err).Error("Could not parse decrypted message event")
} else {
c.onMessageEvent(botClient, decrypted)
}
c.onMessageEvent(botClient, decrypted)
} }
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"type": evt.Type, "type": evt.Type,

1
clients/clients_test.go

@ -89,6 +89,7 @@ func TestCommandParsing(t *testing.T) {
} else { } else {
content.VeryRaw = veryRaw content.VeryRaw = veryRaw
} }
content.ParseRaw(mevt.EventMessage)
event := mevt.Event{ event := mevt.Event{
Type: mevt.EventMessage, Type: mevt.EventMessage,
Sender: "@someone:somewhere", Sender: "@someone:somewhere",

14
clients/state_store.go

@ -15,6 +15,20 @@ type NebStateStore struct {
Storer *mautrix.InMemoryStore Storer *mautrix.InMemoryStore
} }
// GetEncryptionEvent returns the encryption event for a room.
func (ss *NebStateStore) GetEncryptionEvent(roomID id.RoomID) *event.EncryptionEventContent {
room := ss.Storer.LoadRoom(roomID)
if room == nil {
return nil
}
if evts, ok := room.State[event.StateEncryption]; ok {
if evt, ok := evts[""]; ok {
return evt.Content.AsEncryption()
}
}
return nil
}
// IsEncrypted returns whether a room has been encrypted. // IsEncrypted returns whether a room has been encrypted.
func (ss *NebStateStore) IsEncrypted(roomID id.RoomID) bool { func (ss *NebStateStore) IsEncrypted(roomID id.RoomID) bool {
room := ss.Storer.LoadRoom(roomID) room := ss.Storer.LoadRoom(roomID)

2
config.sample.yaml

@ -21,6 +21,7 @@
clients: clients:
- UserID: "@goneb:localhost" - UserID: "@goneb:localhost"
AccessToken: "MDASDASJDIASDJASDAFGFRGER" AccessToken: "MDASDASJDIASDJASDAFGFRGER"
DeviceID: "DEVICE1"
HomeserverURL: "http://localhost:8008" HomeserverURL: "http://localhost:8008"
Sync: true Sync: true
AutoJoinRooms: true AutoJoinRooms: true
@ -28,6 +29,7 @@ clients:
- UserID: "@another_goneb:localhost" - UserID: "@another_goneb:localhost"
AccessToken: "MDASDASJDIASDJASDAFGFRGER" AccessToken: "MDASDASJDIASDJASDAFGFRGER"
DeviceID: "DEVICE2"
HomeserverURL: "http://localhost:8008" HomeserverURL: "http://localhost:8008"
Sync: false Sync: false
AutoJoinRooms: false AutoJoinRooms: false

2
go.mod

@ -51,5 +51,5 @@ require (
gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v2 v2.3.0 gopkg.in/yaml.v2 v2.3.0
maunium.net/go/mautrix v0.5.5
maunium.net/go/mautrix v0.6.0
) )

2
go.sum

@ -270,5 +270,7 @@ maunium.net/go/mautrix v0.5.0-rc.1 h1:Ux2rwQfgf044lXjzCXmaY6VVJPcLioNzdN3okbOVIl
maunium.net/go/mautrix v0.5.0-rc.1/go.mod h1:LnkFnB1yjCbb8V+upoEHDGvI/F38NHSTWYCe2RRJgSY= maunium.net/go/mautrix v0.5.0-rc.1/go.mod h1:LnkFnB1yjCbb8V+upoEHDGvI/F38NHSTWYCe2RRJgSY=
maunium.net/go/mautrix v0.5.5 h1:e0Pql1FdxoNUudx2oXo1gZHMrqIh5MC72cdXEPIrYLA= maunium.net/go/mautrix v0.5.5 h1:e0Pql1FdxoNUudx2oXo1gZHMrqIh5MC72cdXEPIrYLA=
maunium.net/go/mautrix v0.5.5/go.mod h1:FLbMANzwqlsX2Fgm7SDe+E4I3wSa4UxJRKqS5wGkCwA= maunium.net/go/mautrix v0.5.5/go.mod h1:FLbMANzwqlsX2Fgm7SDe+E4I3wSa4UxJRKqS5wGkCwA=
maunium.net/go/mautrix v0.6.0 h1:V32l4aygKk2XcH3fi8Yd0pFeSyYZJNRIvr8vdA2GtC8=
maunium.net/go/mautrix v0.6.0/go.mod h1:Va/74MijqaS0DQ3aUqxmFO54/PMfr1LVsCOcGRHbYmo=
maunium.net/go/mauview v0.1.1/go.mod h1:3QBUiuLct9moP1LgDhCGIg0Ovxn38Bd2sGndnUOuj4o= maunium.net/go/mauview v0.1.1/go.mod h1:3QBUiuLct9moP1LgDhCGIg0Ovxn38Bd2sGndnUOuj4o=
maunium.net/go/tcell v0.2.0/go.mod h1:9Apcb3lNNS6C6lCqKT9UFp7BTRzHXfWE+/tgufsAMho= maunium.net/go/tcell v0.2.0/go.mod h1:9Apcb3lNNS6C6lCqKT9UFp7BTRzHXfWE+/tgufsAMho=

19
goneb_services_test.go

@ -14,6 +14,7 @@ import (
"maunium.net/go/mautrix/crypto" "maunium.net/go/mautrix/crypto"
"maunium.net/go/mautrix/crypto/olm" "maunium.net/go/mautrix/crypto/olm"
mevt "maunium.net/go/mautrix/event" mevt "maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
) )
func setupMockServer() (*http.ServeMux, *matrixTripper, *httptest.ResponseRecorder, chan string) { func setupMockServer() (*http.ServeMux, *matrixTripper, *httptest.ResponseRecorder, chan string) {
@ -164,13 +165,14 @@ func TestEncryptedRespondToEcho(t *testing.T) {
accountBot := olm.NewAccount() accountBot := olm.NewAccount()
signingKeyMock, identityKeyMock := accountMock.IdentityKeys() signingKeyMock, identityKeyMock := accountMock.IdentityKeys()
signingKeyBot, identityKeyBot := accountBot.IdentityKeys() signingKeyBot, identityKeyBot := accountBot.IdentityKeys()
ogsBot := crypto.NewOutboundGroupSession("!greatdekutree:hyrule")
// encryptionEvtContent := &mevt.EncryptionEventContent{Algorithm: "m.megolm.v1.aes-sha2"}
ogsBot := crypto.NewOutboundGroupSession("!greatdekutree:hyrule", nil)
ogsBot.Shared = true ogsBot.Shared = true
igsMock, err := crypto.NewInboundGroupSession(identityKeyBot, signingKeyBot, "!greatdekutree:hyrule", ogsBot.Internal.Key()) igsMock, err := crypto.NewInboundGroupSession(identityKeyBot, signingKeyBot, "!greatdekutree:hyrule", ogsBot.Internal.Key())
if err != nil { if err != nil {
t.Errorf("Error creating mock IGS: %v", err) t.Errorf("Error creating mock IGS: %v", err)
} }
ogsMock := crypto.NewOutboundGroupSession("!greatdekutree:hyrule")
ogsMock := crypto.NewOutboundGroupSession("!greatdekutree:hyrule", nil)
ogsMock.Shared = true ogsMock.Shared = true
igsBot, err := crypto.NewInboundGroupSession(identityKeyMock, signingKeyMock, "!greatdekutree:hyrule", ogsMock.Internal.Key()) igsBot, err := crypto.NewInboundGroupSession(identityKeyMock, signingKeyMock, "!greatdekutree:hyrule", ogsMock.Internal.Key())
if err != nil { if err != nil {
@ -279,7 +281,7 @@ func TestEncryptedRespondToEcho(t *testing.T) {
// DB is initialized, store the megolm sessions from before for the bot to be able to decrypt and encrypt // DB is initialized, store the megolm sessions from before for the bot to be able to decrypt and encrypt
sqlDB, dialect := database.GetServiceDB().(*database.ServiceDB).GetSQLDb() sqlDB, dialect := database.GetServiceDB().(*database.ServiceDB).GetSQLDb()
cryptoStore := crypto.NewSQLCryptoStore(sqlDB, dialect, "mastersword", []byte("masterswordpickle"), clients.CryptoMachineLogger{})
cryptoStore := crypto.NewSQLCryptoStore(sqlDB, dialect, "@link:hyrule-mastersword", "mastersword", []byte("masterswordpickle"), clients.CryptoMachineLogger{})
if err := cryptoStore.AddOutboundGroupSession(ogsBot); err != nil { if err := cryptoStore.AddOutboundGroupSession(ogsBot); err != nil {
t.Errorf("Error storing bot OGS: %v", err) t.Errorf("Error storing bot OGS: %v", err)
} }
@ -287,6 +289,14 @@ func TestEncryptedRespondToEcho(t *testing.T) {
if err := cryptoStore.PutGroupSession("!greatdekutree:hyrule", identityKeyMock, igsBot.ID(), igsBot); err != nil { if err := cryptoStore.PutGroupSession("!greatdekutree:hyrule", identityKeyMock, igsBot.ID(), igsBot); err != nil {
t.Errorf("Error storing bot IGS: %v", err) t.Errorf("Error storing bot IGS: %v", err)
} }
cryptoStore.PutDevices("@navi:hyrule", map[id.DeviceID]*crypto.DeviceIdentity{
"NAVI": {
UserID: "@navi:hyrule",
DeviceID: "NAVI",
IdentityKey: identityKeyMock,
SigningKey: signingKeyMock,
},
})
plaintext := `{"room_id":"!greatdekutree:hyrule","type":"m.room.message","content":{"body":"!echo save zelda","msgtype":"m.text"}}` plaintext := `{"room_id":"!greatdekutree:hyrule","type":"m.room.message","content":{"body":"!echo save zelda","msgtype":"m.text"}}`
ciphertext, err := ogsMock.Encrypt([]byte(plaintext)) ciphertext, err := ogsMock.Encrypt([]byte(plaintext))
@ -305,7 +315,8 @@ func TestEncryptedRespondToEcho(t *testing.T) {
"algorithm":"m.megolm.v1.aes-sha2", "algorithm":"m.megolm.v1.aes-sha2",
"sender_key":"%s", "sender_key":"%s",
"ciphertext":"%s", "ciphertext":"%s",
"session_id":"%s"
"session_id":"%s",
"device_id": "NAVI"
}, },
"origin_server_ts": 10000, "origin_server_ts": 10000,
"unsigned": {"age": 100}, "unsigned": {"age": 100},

Loading…
Cancel
Save