mirror of https://github.com/matrix-org/go-neb.git
Browse Source
Move some of the client and crypto logic to a new BotClient type
Move some of the client and crypto logic to a new BotClient type
Signed-off-by: Nikos Filippakis <me@nfil.dev>pull/324/head
No known key found for this signature in database
GPG Key ID: 7110E4356101F017
6 changed files with 255 additions and 106 deletions
-
103clients/bot_client.go
-
167clients/clients.go
-
3clients/clients_test.go
-
28clients/crypto_logger.go
-
54clients/state_store.go
-
2services/jira/jira.go
@ -0,0 +1,103 @@ |
|||||
|
package clients |
||||
|
|
||||
|
import ( |
||||
|
"github.com/matrix-org/go-neb/api" |
||||
|
"github.com/matrix-org/go-neb/matrix" |
||||
|
log "github.com/sirupsen/logrus" |
||||
|
"maunium.net/go/mautrix" |
||||
|
"maunium.net/go/mautrix/crypto" |
||||
|
mevt "maunium.net/go/mautrix/event" |
||||
|
"maunium.net/go/mautrix/id" |
||||
|
) |
||||
|
|
||||
|
// BotClient represents one of the bot's sessions, with a specific User and Device ID.
|
||||
|
// It can be used for sending messages and retrieving information about the rooms that
|
||||
|
// the client has joined.
|
||||
|
type BotClient struct { |
||||
|
config api.ClientConfig |
||||
|
client *mautrix.Client |
||||
|
olmMachine *crypto.OlmMachine |
||||
|
stateStore *NebStateStore |
||||
|
} |
||||
|
|
||||
|
// InitOlmMachine initializes a BotClient's internal OlmMachine given a client object and a Neb store,
|
||||
|
// which will be used to store room information.
|
||||
|
func (botClient *BotClient) InitOlmMachine(client *mautrix.Client, nebStore *matrix.NEBStore) error { |
||||
|
gobStore, err := crypto.NewGobStore("crypto.gob") |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
|
||||
|
botClient.stateStore = &NebStateStore{&nebStore.InMemoryStore} |
||||
|
olmMachine := crypto.NewOlmMachine(client, CryptoMachineLogger{}, gobStore, botClient.stateStore) |
||||
|
if err = olmMachine.Load(); err != nil { |
||||
|
return nil |
||||
|
} |
||||
|
botClient.olmMachine = olmMachine |
||||
|
|
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
// Register registers a BotClient's Sync and StateMember event callbacks to update its internal state
|
||||
|
// when new events arrive.
|
||||
|
func (botClient *BotClient) Register(syncer mautrix.ExtensibleSyncer) { |
||||
|
syncer.OnEventType(mevt.StateMember, func(_ mautrix.EventSource, evt *mevt.Event) { |
||||
|
botClient.olmMachine.HandleMemberEvent(evt) |
||||
|
}) |
||||
|
syncer.OnSync(botClient.syncCallback) |
||||
|
} |
||||
|
|
||||
|
func (botClient *BotClient) syncCallback(resp *mautrix.RespSync, since string) bool { |
||||
|
botClient.stateStore.UpdateStateStore(resp) |
||||
|
botClient.olmMachine.ProcessSyncResponse(resp, since) |
||||
|
if err := botClient.olmMachine.CryptoStore.Flush(); err != nil { |
||||
|
log.WithError(err).Error("Could not flush crypto store") |
||||
|
} |
||||
|
return true |
||||
|
} |
||||
|
|
||||
|
// DecryptMegolmEvent attempts to decrypt an incoming m.room.encrypted message using the session information
|
||||
|
// already present in the OlmMachine. The corresponding decrypted event is then returned.
|
||||
|
// If it fails, usually because the session is not known, an error is returned.
|
||||
|
func (botClient *BotClient) DecryptMegolmEvent(evt *mevt.Event) (*mevt.Event, error) { |
||||
|
return botClient.olmMachine.DecryptMegolmEvent(evt) |
||||
|
} |
||||
|
|
||||
|
// SendMessageEvent sends the given content to the given room ID using this BotClient as a message event.
|
||||
|
// If the target room has enabled encryption, a megolm session is created if one doesn't already exist
|
||||
|
// and the message is sent after being encrypted.
|
||||
|
func (botClient *BotClient) SendMessageEvent(content interface{}, roomID id.RoomID) error { |
||||
|
evtType := mevt.EventMessage |
||||
|
olmMachine := botClient.olmMachine |
||||
|
if olmMachine.StateStore.IsEncrypted(roomID) { |
||||
|
// Check if there is already a megolm session
|
||||
|
if sess, err := olmMachine.CryptoStore.GetOutboundGroupSession(roomID); err != nil { |
||||
|
return err |
||||
|
} else if sess == nil || sess.Expired() || !sess.Shared { |
||||
|
// No error but valid, shared session does not exist
|
||||
|
membs, err := botClient.client.JoinedMembers(roomID) |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
memberIDs := make([]id.UserID, 0, len(membs.Joined)) |
||||
|
for member := range membs.Joined { |
||||
|
memberIDs = append(memberIDs, member) |
||||
|
} |
||||
|
// Share group session with room members
|
||||
|
if err = olmMachine.ShareGroupSession(roomID, memberIDs); err != nil { |
||||
|
return err |
||||
|
} |
||||
|
} |
||||
|
msgContent := mevt.Content{Parsed: content} |
||||
|
enc, err := olmMachine.EncryptMegolmEvent(roomID, mevt.EventMessage, msgContent) |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
content = enc |
||||
|
evtType = mevt.EventEncrypted |
||||
|
} |
||||
|
if _, err := botClient.client.SendMessageEvent(roomID, evtType, content); err != nil { |
||||
|
return err |
||||
|
} |
||||
|
return nil |
||||
|
} |
@ -0,0 +1,28 @@ |
|||||
|
package clients |
||||
|
|
||||
|
import ( |
||||
|
log "github.com/sirupsen/logrus" |
||||
|
) |
||||
|
|
||||
|
// CryptoMachineLogger wraps around the usual logger, implementing the Logger interface needed by OlmMachine.
|
||||
|
type CryptoMachineLogger struct{} |
||||
|
|
||||
|
// Error formats and logs an error message.
|
||||
|
func (CryptoMachineLogger) Error(message string, args ...interface{}) { |
||||
|
log.Errorf(message, args...) |
||||
|
} |
||||
|
|
||||
|
// Warn formats and logs a warning message.
|
||||
|
func (CryptoMachineLogger) Warn(message string, args ...interface{}) { |
||||
|
log.Warnf(message, args...) |
||||
|
} |
||||
|
|
||||
|
// Debug formats and logs a debug message.
|
||||
|
func (CryptoMachineLogger) Debug(message string, args ...interface{}) { |
||||
|
log.Debugf(message, args...) |
||||
|
} |
||||
|
|
||||
|
// Trace formats and logs a trace message.
|
||||
|
func (CryptoMachineLogger) Trace(message string, args ...interface{}) { |
||||
|
log.Tracef(message, args...) |
||||
|
} |
@ -0,0 +1,54 @@ |
|||||
|
package clients |
||||
|
|
||||
|
import ( |
||||
|
"maunium.net/go/mautrix" |
||||
|
"maunium.net/go/mautrix/event" |
||||
|
"maunium.net/go/mautrix/id" |
||||
|
) |
||||
|
|
||||
|
// NebStateStore implements the StateStore interface for OlmMachine.
|
||||
|
// It is used to determine which rooms are encrypted and which rooms are shared with a user.
|
||||
|
// The state is updated by /sync responses.
|
||||
|
type NebStateStore struct { |
||||
|
Storer *mautrix.InMemoryStore |
||||
|
} |
||||
|
|
||||
|
// IsEncrypted returns whether a room has been encrypted.
|
||||
|
func (ss *NebStateStore) IsEncrypted(roomID id.RoomID) bool { |
||||
|
room := ss.Storer.LoadRoom(roomID) |
||||
|
if room == nil { |
||||
|
return false |
||||
|
} |
||||
|
_, ok := room.State[event.StateEncryption] |
||||
|
return ok |
||||
|
} |
||||
|
|
||||
|
// FindSharedRooms returns a list of room IDs that the given user ID is also a member of.
|
||||
|
func (ss *NebStateStore) FindSharedRooms(userID id.UserID) []id.RoomID { |
||||
|
sharedRooms := make([]id.RoomID, 0) |
||||
|
for roomID, room := range ss.Storer.Rooms { |
||||
|
if room.GetMembershipState(userID) != event.MembershipLeave { |
||||
|
sharedRooms = append(sharedRooms, roomID) |
||||
|
} |
||||
|
} |
||||
|
return sharedRooms |
||||
|
} |
||||
|
|
||||
|
// UpdateStateStore updates the internal state of NebStateStore from a /sync response.
|
||||
|
func (ss *NebStateStore) UpdateStateStore(resp *mautrix.RespSync) { |
||||
|
for roomID, evts := range resp.Rooms.Join { |
||||
|
room := ss.Storer.LoadRoom(roomID) |
||||
|
if room == nil { |
||||
|
room = mautrix.NewRoom(roomID) |
||||
|
ss.Storer.SaveRoom(room) |
||||
|
} |
||||
|
for _, i := range evts.State.Events { |
||||
|
room.UpdateState(i) |
||||
|
} |
||||
|
for _, i := range evts.Timeline.Events { |
||||
|
if i.Type.IsState() { |
||||
|
room.UpdateState(i) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue