From a06984aeec86b745cb0f5a966e1f97afad42dbeb Mon Sep 17 00:00:00 2001 From: Samuel Hawksby-Robinson Date: Thu, 18 May 2023 10:35:18 +0100 Subject: [PATCH] Ensured time was a value and implemented explicit RekeyCommunity() --- protocol/communities/community.go | 5 ++++ protocol/communities/manager.go | 13 +++++++++ protocol/communities/persistence.go | 11 ++++--- protocol/messenger_communities.go | 45 ++++++++++++++++++++++------- 4 files changed, 57 insertions(+), 17 deletions(-) diff --git a/protocol/communities/community.go b/protocol/communities/community.go index 8ddb2dc01..4afd8afc9 100644 --- a/protocol/communities/community.go +++ b/protocol/communities/community.go @@ -1967,6 +1967,11 @@ func (o *Community) SetActiveMembersCount(activeMembersCount uint64) (updated bo return true, nil } +// RekeyedAt returns the RekeyedAt value from the underlying Community.config +func (o *Community) RekeyedAt() time.Time { + return o.config.RekeyedAt +} + type sortSlice []sorterHelperIdx type sorterHelperIdx struct { pos int32 diff --git a/protocol/communities/manager.go b/protocol/communities/manager.go index e6375f59e..81b3d097e 100644 --- a/protocol/communities/manager.go +++ b/protocol/communities/manager.go @@ -84,6 +84,7 @@ type Manager struct { torrentTasks map[string]metainfo.Hash historyArchiveDownloadTasks map[string]*HistoryArchiveDownloadTask stopped bool + RekeyInterval *time.Duration } type HistoryArchiveDownloadTask struct { @@ -4028,3 +4029,15 @@ func (m *Manager) saveAndPublish(community *Community) error { return nil } + +// GetRekeyedAtClock returns the rekeyed_at time of a given community +// exposes persistence level functionality to exported Manager APIs +func (m *Manager) GetRekeyedAtClock(id []byte) (time.Time, error) { + return m.persistence.GetRekeyedAtClock(id) +} + +// SetRekeyedAtClock sets the rekeyed_at time value of a given community +// exposes persistence level functionality to exported Manager APIs +func (m *Manager) SetRekeyedAtClock(id []byte, time time.Time) error { + return m.persistence.SetRekeyedAtClock(id, time) +} diff --git a/protocol/communities/persistence.go b/protocol/communities/persistence.go index 7aeac6bb6..6759d30b8 100644 --- a/protocol/communities/persistence.go +++ b/protocol/communities/persistence.go @@ -1273,17 +1273,16 @@ func decodeEventsData(eventsBytes []byte, eventsDescriptionBytes []byte) (*Event } // GetRekeyedAtClock returns the rekeyed_at time of a given community -func (p *Persistence) GetRekeyedAtClock(id []byte) (*time.Time, error) { - rekeyedAt := time.Time{} - err := p.db.QueryRow(`SELECT rekeyed_at FROM communities_communities WHERE id = ?`, id).Scan(&rekeyedAt) +func (p *Persistence) GetRekeyedAtClock(id []byte) (rekeyedAt time.Time, err error) { + err = p.db.QueryRow(`SELECT rekeyed_at FROM communities_communities WHERE id = ?`, id).Scan(&rekeyedAt) if err != nil { - return nil, err + return rekeyedAt, err } - return &rekeyedAt, nil + return rekeyedAt, nil } // SetRekeyedAtClock sets the rekeyed_at time value of a given community -func (p *Persistence) SetRekeyedAtClock(id []byte, time *time.Time) error { +func (p *Persistence) SetRekeyedAtClock(id []byte, time time.Time) error { _, err := p.db.Exec(`UPDATE communities_communities SET rekeyed_at = ? WHERE id = ? AND rekeyed_at < ?`, time, id, time) return err } diff --git a/protocol/messenger_communities.go b/protocol/messenger_communities.go index e4f11ee2f..26e7c6771 100644 --- a/protocol/messenger_communities.go +++ b/protocol/messenger_communities.go @@ -2032,6 +2032,25 @@ func (m *Messenger) SendKeyExchangeMessage(communityID []byte, pubkeys []*ecdsa. return nil } +// RekeyCommunity takes a communities.Community and triggers a force rekey event, +// after rekeying has be triggered updates the communities.Community rekeyed_at value to now +func (m *Messenger) RekeyCommunity(cID types.HexBytes) error { + // Get the community as the member list could have changed + c, err := m.GetCommunityByID(cID) + if err != nil { + return err + } + + // RekeyCommunity + err = m.SendKeyExchangeMessage(c.ID(), c.GetMemberPubkeys(), common.KeyExMsgRekey) + if err != nil { + return err + } + + // update rekey timestamp + return m.communitiesManager.SetRekeyedAtClock(c.ID(), time.Now()) +} + func (m *Messenger) UnbanUserFromCommunity(request *requests.UnbanUserFromCommunity) (*MessengerResponse, error) { community, err := m.communitiesManager.UnbanUserFromCommunity(request) if err != nil { @@ -4210,9 +4229,13 @@ func chunkAttachmentsByByteSize(slice []*protobuf.DiscordMessageAttachment, maxF func (m *Messenger) startCommunityRekeyLoop() error { logger := m.logger.Named("CommunityRekeyLoop") - rekeyInterval := time.Hour - - ticker := time.NewTicker(rekeyInterval) + var rki time.Duration + if m.communitiesManager.RekeyInterval == nil { + rki = time.Hour + } else { + rki = *m.communitiesManager.RekeyInterval + } + ticker := time.NewTicker(rki) cs, err := m.Communities() if err != nil { @@ -4221,24 +4244,24 @@ func (m *Messenger) startCommunityRekeyLoop() error { for _, c := range cs { if c.IsAdmin() && c.Encrypted() { - // get last rekey timestamp - c.config.RekeyedAt.Before(time.Now().Add(rekeyInterval)) - - // if rekey time period exceeded perform a rekey and set new last rekey timestamp to now + // if rekey time period exceeded, perform a rekey + if c.RekeyedAt().Add(rki).Before(time.Now()) { + err = m.RekeyCommunity(c.ID()) + if err != nil { + return err + } + } go func() { logger.Debug("CommunityRekeyLoop started", zap.Binary("community ID", c.ID())) for { select { case <-ticker.C: - // Rekey - err = m.SendKeyExchangeMessage(c.ID(), c.GetMemberPubkeys(), common.KeyExMsgRekey) + err = m.RekeyCommunity(c.ID()) if err != nil { logger.Error("error sending rekey message", zap.Error(err), zap.Binary("community ID", c.ID())) } - // update rekey timestamp - case <-m.quit: ticker.Stop() logger.Debug("CommunityRekeyLoop stopped", zap.Binary("community ID", c.ID()))