Move installations to status-go (#1499)
* Move installations to status-go This commit moves installations management/storage to status-go. We remove the native binding and provide RPC endpoints to set the metadata and return a list of our own installations.
This commit is contained in:
parent
0ade9a6cbb
commit
5335a2b4fd
|
@ -658,46 +658,6 @@ func (b *StatusBackend) SignGroupMembership(content string) (string, error) {
|
|||
return crypto.Sign(content, selectedChatAccount.AccountKey.PrivateKey)
|
||||
}
|
||||
|
||||
// EnableInstallation enables an installation for multi-device sync.
|
||||
func (b *StatusBackend) EnableInstallation(installationID string) error {
|
||||
selectedChatAccount, err := b.AccountManager().SelectedChatAccount()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
st, err := b.statusNode.ShhExtService()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := st.EnableInstallation(&selectedChatAccount.AccountKey.PrivateKey.PublicKey, installationID); err != nil {
|
||||
b.log.Error("error enabling installation", "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DisableInstallation disables an installation for multi-device sync.
|
||||
func (b *StatusBackend) DisableInstallation(installationID string) error {
|
||||
selectedChatAccount, err := b.AccountManager().SelectedChatAccount()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
st, err := b.statusNode.ShhExtService()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := st.DisableInstallation(&selectedChatAccount.AccountKey.PrivateKey.PublicKey, installationID); err != nil {
|
||||
b.log.Error("error disabling installation", "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateMailservers on ShhExtService.
|
||||
func (b *StatusBackend) UpdateMailservers(enodes []string) error {
|
||||
st, err := b.statusNode.ShhExtService()
|
||||
|
|
|
@ -93,42 +93,6 @@ func SignGroupMembership(content *C.char) *C.char {
|
|||
return C.CString(string(data))
|
||||
}
|
||||
|
||||
// EnableInstallation enables an installation for multi-device sync.
|
||||
//export EnableInstallation
|
||||
func EnableInstallation(installationID *C.char) *C.char {
|
||||
err := statusBackend.EnableInstallation(C.GoString(installationID))
|
||||
if err != nil {
|
||||
return makeJSONResponse(err)
|
||||
}
|
||||
|
||||
data, err := json.Marshal(struct {
|
||||
Response string `json:"response"`
|
||||
}{Response: "ok"})
|
||||
if err != nil {
|
||||
return makeJSONResponse(err)
|
||||
}
|
||||
|
||||
return C.CString(string(data))
|
||||
}
|
||||
|
||||
// DisableInstallation disables an installation for multi-device sync.
|
||||
//export DisableInstallation
|
||||
func DisableInstallation(installationID *C.char) *C.char {
|
||||
err := statusBackend.DisableInstallation(C.GoString(installationID))
|
||||
if err != nil {
|
||||
return makeJSONResponse(err)
|
||||
}
|
||||
|
||||
data, err := json.Marshal(struct {
|
||||
Response string `json:"response"`
|
||||
}{Response: "ok"})
|
||||
if err != nil {
|
||||
return makeJSONResponse(err)
|
||||
}
|
||||
|
||||
return C.CString(string(data))
|
||||
}
|
||||
|
||||
//ValidateNodeConfig validates config for status node
|
||||
//export ValidateNodeConfig
|
||||
func ValidateNodeConfig(configJSON *C.char) *C.char {
|
||||
|
|
|
@ -104,40 +104,6 @@ func SignGroupMembership(content string) string {
|
|||
return string(data)
|
||||
}
|
||||
|
||||
// EnableInstallation enables an installation for multi-device sync.
|
||||
func EnableInstallation(installationID string) string {
|
||||
err := statusBackend.EnableInstallation(installationID)
|
||||
if err != nil {
|
||||
return makeJSONResponse(err)
|
||||
}
|
||||
|
||||
data, err := json.Marshal(struct {
|
||||
Response string `json:"response"`
|
||||
}{Response: "ok"})
|
||||
if err != nil {
|
||||
return makeJSONResponse(err)
|
||||
}
|
||||
|
||||
return string(data)
|
||||
}
|
||||
|
||||
// DisableInstallation disables an installation for multi-device sync.
|
||||
func DisableInstallation(installationID string) string {
|
||||
err := statusBackend.DisableInstallation(installationID)
|
||||
if err != nil {
|
||||
return makeJSONResponse(err)
|
||||
}
|
||||
|
||||
data, err := json.Marshal(struct {
|
||||
Response string `json:"response"`
|
||||
}{Response: "ok"})
|
||||
if err != nil {
|
||||
return makeJSONResponse(err)
|
||||
}
|
||||
|
||||
return string(data)
|
||||
}
|
||||
|
||||
// ValidateNodeConfig validates config for the Status node.
|
||||
func ValidateNodeConfig(configJSON string) string {
|
||||
var resp APIDetailedResponse
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"github.com/status-im/status-go/db"
|
||||
"github.com/status-im/status-go/mailserver"
|
||||
"github.com/status-im/status-go/services/shhext/chat"
|
||||
"github.com/status-im/status-go/services/shhext/chat/multidevice"
|
||||
"github.com/status-im/status-go/services/shhext/dedup"
|
||||
"github.com/status-im/status-go/services/shhext/filter"
|
||||
"github.com/status-im/status-go/services/shhext/mailservers"
|
||||
|
@ -608,6 +609,26 @@ func (api *PublicAPI) RemoveFilters(parent context.Context, chats []*filter.Chat
|
|||
return api.service.RemoveFilters(chats)
|
||||
}
|
||||
|
||||
// EnableInstallation enables an installation for multi-device sync.
|
||||
func (api *PublicAPI) EnableInstallation(installationID string) error {
|
||||
return api.service.EnableInstallation(installationID)
|
||||
}
|
||||
|
||||
// DisableInstallation disables an installation for multi-device sync.
|
||||
func (api *PublicAPI) DisableInstallation(installationID string) error {
|
||||
return api.service.DisableInstallation(installationID)
|
||||
}
|
||||
|
||||
// GetOurInstallations returns all the installations available given an identity
|
||||
func (api *PublicAPI) GetOurInstallations() ([]*multidevice.Installation, error) {
|
||||
return api.service.GetOurInstallations()
|
||||
}
|
||||
|
||||
// SetInstallationMetadata sets the metadata for our own installation
|
||||
func (api *PublicAPI) SetInstallationMetadata(installationID string, data *multidevice.InstallationMetadata) error {
|
||||
return api.service.SetInstallationMetadata(installationID, data)
|
||||
}
|
||||
|
||||
// -----
|
||||
// HELPER
|
||||
// -----
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
// 1559627659_add_contact_code.up.sql
|
||||
// 1561059285_add_whisper_keys.down.sql
|
||||
// 1561059285_add_whisper_keys.up.sql
|
||||
// 1561368210_add_installation_metadata.down.sql
|
||||
// 1561368210_add_installation_metadata.up.sql
|
||||
// static.go
|
||||
// DO NOT EDIT!
|
||||
|
||||
|
@ -358,7 +360,7 @@ func _1561059285_add_whisper_keysDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561059285_add_whisper_keys.down.sql", size: 25, mode: os.FileMode(420), modTime: time.Unix(1561059394, 0)}
|
||||
info := bindataFileInfo{name: "1561059285_add_whisper_keys.down.sql", size: 25, mode: os.FileMode(420), modTime: time.Unix(1561361219, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -378,7 +380,47 @@ func _1561059285_add_whisper_keysUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561059285_add_whisper_keys.up.sql", size: 112, mode: os.FileMode(420), modTime: time.Unix(1561097945, 0)}
|
||||
info := bindataFileInfo{name: "1561059285_add_whisper_keys.up.sql", size: 112, mode: os.FileMode(420), modTime: time.Unix(1561361219, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var __1561368210_add_installation_metadataDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\x09\xf2\x0f\x50\x08\x71\x74\xf2\x71\x55\xc8\xcc\x2b\x2e\x49\xcc\xc9\x49\x2c\xc9\xcc\xcf\x2b\x8e\xcf\x4d\x2d\x49\x4c\x49\x2c\x49\xb4\xe6\x02\x04\x00\x00\xff\xff\x03\x72\x7f\x08\x23\x00\x00\x00")
|
||||
|
||||
func _1561368210_add_installation_metadataDownSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
__1561368210_add_installation_metadataDownSql,
|
||||
"1561368210_add_installation_metadata.down.sql",
|
||||
)
|
||||
}
|
||||
|
||||
func _1561368210_add_installation_metadataDownSql() (*asset, error) {
|
||||
bytes, err := _1561368210_add_installation_metadataDownSqlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561368210_add_installation_metadata.down.sql", size: 35, mode: os.FileMode(420), modTime: time.Unix(1561459323, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var __1561368210_add_installation_metadataUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\xce\xc1\x8a\x83\x30\x10\xc6\xf1\xbb\x4f\xf1\xdd\x54\xf0\x0d\xf6\x14\xb3\x23\x08\x21\xd9\x95\x04\x7a\x93\x60\x52\x08\xd5\x58\xe8\x50\xf0\xed\x8b\x87\x42\xed\xc1\xeb\xcc\xef\x83\xbf\x1c\x48\x58\x82\x15\xad\x22\xa4\xfc\x60\x3f\xcf\x9e\xd3\x9a\xc7\x25\xb2\x0f\x9e\x3d\x50\x15\x40\x0a\x31\x73\xe2\x0d\xad\x32\x2d\xb4\xb1\xd0\x4e\xa9\x66\xff\x7c\x8e\x52\x80\xa5\x8b\x3d\x80\xec\x97\x78\xbc\xe2\x97\x3a\xe1\x94\x45\x59\xee\x20\xc4\x67\x9a\xe2\xc8\xdb\xfd\xdc\x5d\xa7\x65\xe4\xf5\x16\xf3\xa9\x72\xba\xff\x77\x54\xbd\x83\x9b\xef\xc0\x1a\x46\x43\x1a\xdd\xa9\x5e\x5a\x0c\xf4\xa7\x84\xa4\xa2\xfe\x29\x5e\x01\x00\x00\xff\xff\x5d\x6f\xe6\xd3\x0b\x01\x00\x00")
|
||||
|
||||
func _1561368210_add_installation_metadataUpSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
__1561368210_add_installation_metadataUpSql,
|
||||
"1561368210_add_installation_metadata.up.sql",
|
||||
)
|
||||
}
|
||||
|
||||
func _1561368210_add_installation_metadataUpSql() (*asset, error) {
|
||||
bytes, err := _1561368210_add_installation_metadataUpSqlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561368210_add_installation_metadata.up.sql", size: 267, mode: os.FileMode(420), modTime: time.Unix(1561459769, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -470,6 +512,8 @@ var _bindata = map[string]func() (*asset, error){
|
|||
"1559627659_add_contact_code.up.sql": _1559627659_add_contact_codeUpSql,
|
||||
"1561059285_add_whisper_keys.down.sql": _1561059285_add_whisper_keysDownSql,
|
||||
"1561059285_add_whisper_keys.up.sql": _1561059285_add_whisper_keysUpSql,
|
||||
"1561368210_add_installation_metadata.down.sql": _1561368210_add_installation_metadataDownSql,
|
||||
"1561368210_add_installation_metadata.up.sql": _1561368210_add_installation_metadataUpSql,
|
||||
"static.go": staticGo,
|
||||
}
|
||||
|
||||
|
@ -528,6 +572,8 @@ var _bintree = &bintree{nil, map[string]*bintree{
|
|||
"1559627659_add_contact_code.up.sql": &bintree{_1559627659_add_contact_codeUpSql, map[string]*bintree{}},
|
||||
"1561059285_add_whisper_keys.down.sql": &bintree{_1561059285_add_whisper_keysDownSql, map[string]*bintree{}},
|
||||
"1561059285_add_whisper_keys.up.sql": &bintree{_1561059285_add_whisper_keysUpSql, map[string]*bintree{}},
|
||||
"1561368210_add_installation_metadata.down.sql": &bintree{_1561368210_add_installation_metadataDownSql, map[string]*bintree{}},
|
||||
"1561368210_add_installation_metadata.up.sql": &bintree{_1561368210_add_installation_metadataUpSql, map[string]*bintree{}},
|
||||
"static.go": &bintree{staticGo, map[string]*bintree{}},
|
||||
}}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"os"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/status-im/status-go/services/shhext/chat/multidevice"
|
||||
|
@ -69,7 +68,7 @@ func setupUser(user string, s *EncryptionServiceMultiDeviceSuite, n int) error {
|
|||
DefaultEncryptionServiceConfig(installationID)),
|
||||
sharedSecretService,
|
||||
multideviceService,
|
||||
func(s []*multidevice.IdentityAndID) {},
|
||||
func(s []*multidevice.Installation) {},
|
||||
func(s []*sharedsecret.Secret) {},
|
||||
)
|
||||
|
||||
|
@ -111,12 +110,20 @@ func (s *EncryptionServiceMultiDeviceSuite) TestProcessPublicBundle() {
|
|||
// Add alice2 bundle
|
||||
response, err := s.services[aliceUser].services[0].ProcessPublicBundle(aliceKey, alice2Bundle)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(multidevice.IdentityAndID{alice2Identity, "alice2"}, *response[0])
|
||||
s.Require().Equal(multidevice.Installation{
|
||||
Identity: alice2Identity,
|
||||
Version: 1,
|
||||
ID: "alice2",
|
||||
}, *response[0])
|
||||
|
||||
// Add alice3 bundle
|
||||
response, err = s.services[aliceUser].services[0].ProcessPublicBundle(aliceKey, alice3Bundle)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(multidevice.IdentityAndID{alice3Identity, "alice3"}, *response[0])
|
||||
s.Require().Equal(multidevice.Installation{
|
||||
Identity: alice3Identity,
|
||||
Version: 1,
|
||||
ID: "alice3",
|
||||
}, *response[0])
|
||||
|
||||
// No installation is enabled
|
||||
alice1MergedBundle1, err := s.services[aliceUser].services[0].GetBundle(aliceKey)
|
||||
|
@ -141,16 +148,6 @@ func (s *EncryptionServiceMultiDeviceSuite) TestProcessPublicBundle() {
|
|||
s.Require().NotNil(alice1MergedBundle2.GetSignedPreKeys()["alice2"])
|
||||
s.Require().NotNil(alice1MergedBundle2.GetSignedPreKeys()["alice3"])
|
||||
|
||||
response, err = s.services[aliceUser].services[0].ProcessPublicBundle(aliceKey, alice1MergedBundle2)
|
||||
s.Require().NoError(err)
|
||||
sort.Slice(response, func(i, j int) bool {
|
||||
return response[i].ID < response[j].ID
|
||||
})
|
||||
// We only get back installationIDs not equal to us
|
||||
s.Require().Equal(2, len(response))
|
||||
s.Require().Equal(multidevice.IdentityAndID{alice2Identity, "alice2"}, *response[0])
|
||||
s.Require().Equal(multidevice.IdentityAndID{alice2Identity, "alice3"}, *response[1])
|
||||
|
||||
// We disable the installations
|
||||
err = s.services[aliceUser].services[0].DisableInstallation(&aliceKey.PublicKey, "alice2")
|
||||
s.Require().NoError(err)
|
||||
|
|
|
@ -80,7 +80,7 @@ func (s *EncryptionServiceTestSuite) initDatabases(baseConfig *EncryptionService
|
|||
aliceEncryptionService,
|
||||
aliceSharedSecretService,
|
||||
aliceMultideviceService,
|
||||
func(s []*multidevice.IdentityAndID) {},
|
||||
func(s []*multidevice.Installation) {},
|
||||
func(s []*sharedsecret.Secret) {},
|
||||
)
|
||||
|
||||
|
@ -106,7 +106,7 @@ func (s *EncryptionServiceTestSuite) initDatabases(baseConfig *EncryptionService
|
|||
bobEncryptionService,
|
||||
bobSharedSecretService,
|
||||
bobMultideviceService,
|
||||
func(s []*multidevice.IdentityAndID) {},
|
||||
func(s []*multidevice.Installation) {},
|
||||
func(s []*sharedsecret.Secret) {},
|
||||
)
|
||||
|
||||
|
|
|
@ -8,5 +8,9 @@ type Persistence interface {
|
|||
// DisableInstallation disable the installation.
|
||||
DisableInstallation(identity []byte, installationID string) error
|
||||
// AddInstallations adds the installations for a given identity, maintaining the enabled flag
|
||||
AddInstallations(identity []byte, timestamp int64, installations []*Installation, defaultEnabled bool) error
|
||||
AddInstallations(identity []byte, timestamp int64, installations []*Installation, defaultEnabled bool) ([]*Installation, error)
|
||||
// GetInstallations returns all the installations for a given identity
|
||||
GetInstallations(identity []byte) ([]*Installation, error)
|
||||
// SetInstallationMetadata sets the metadata for a given installation
|
||||
SetInstallationMetadata(identity []byte, installationID string, data *InstallationMetadata) error
|
||||
}
|
||||
|
|
|
@ -7,11 +7,28 @@ import (
|
|||
"github.com/status-im/status-go/services/shhext/chat/protobuf"
|
||||
)
|
||||
|
||||
type InstallationMetadata struct {
|
||||
// The name of the device
|
||||
Name string `json:"name"`
|
||||
// The type of device
|
||||
DeviceType string `json:"deviceType"`
|
||||
// The FCMToken for mobile devices
|
||||
FCMToken string `json:"fcmToken"`
|
||||
}
|
||||
|
||||
type Installation struct {
|
||||
// Identity is the string identity of the owner
|
||||
Identity string `json:"identity"`
|
||||
// The installation-id of the device
|
||||
ID string
|
||||
ID string `json:"id"`
|
||||
// The last known protocol version of the device
|
||||
Version uint32
|
||||
Version uint32 `json:"version"`
|
||||
// Enabled is whether the installation is enabled
|
||||
Enabled bool `json:"enabled"`
|
||||
// Timestamp is the last time we saw this device
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
// InstallationMetadata
|
||||
InstallationMetadata *InstallationMetadata `json:"metadata"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
|
@ -32,11 +49,6 @@ type Service struct {
|
|||
config *Config
|
||||
}
|
||||
|
||||
type IdentityAndID struct {
|
||||
Identity string
|
||||
ID string
|
||||
}
|
||||
|
||||
func (s *Service) GetActiveInstallations(identity *ecdsa.PublicKey) ([]*Installation, error) {
|
||||
identityC := crypto.CompressPubkey(identity)
|
||||
return s.persistence.GetActiveInstallations(s.config.MaxInstallations, identityC)
|
||||
|
@ -57,6 +69,38 @@ func (s *Service) GetOurActiveInstallations(identity *ecdsa.PublicKey) ([]*Insta
|
|||
return installations, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetOurInstallations(identity *ecdsa.PublicKey) ([]*Installation, error) {
|
||||
var found bool
|
||||
identityC := crypto.CompressPubkey(identity)
|
||||
installations, err := s.persistence.GetInstallations(identityC)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, installation := range installations {
|
||||
if installation.ID == s.config.InstallationID {
|
||||
found = true
|
||||
installation.Enabled = true
|
||||
installation.Version = s.config.ProtocolVersion
|
||||
}
|
||||
|
||||
}
|
||||
if !found {
|
||||
installations = append(installations, &Installation{
|
||||
ID: s.config.InstallationID,
|
||||
Enabled: true,
|
||||
Version: s.config.ProtocolVersion,
|
||||
})
|
||||
}
|
||||
|
||||
return installations, nil
|
||||
}
|
||||
|
||||
func (s *Service) SetInstallationMetadata(identity *ecdsa.PublicKey, installationID string, metadata *InstallationMetadata) error {
|
||||
identityC := crypto.CompressPubkey(identity)
|
||||
return s.persistence.SetInstallationMetadata(identityC, installationID, metadata)
|
||||
}
|
||||
|
||||
func (s *Service) EnableInstallation(identity *ecdsa.PublicKey, installationID string) error {
|
||||
identityC := crypto.CompressPubkey(identity)
|
||||
return s.persistence.EnableInstallation(identityC, installationID)
|
||||
|
@ -68,9 +112,8 @@ func (s *Service) DisableInstallation(myIdentityKey *ecdsa.PublicKey, installati
|
|||
}
|
||||
|
||||
// ProcessPublicBundle persists a bundle and returns a list of tuples identity/installationID
|
||||
func (s *Service) ProcessPublicBundle(myIdentityKey *ecdsa.PrivateKey, theirIdentity *ecdsa.PublicKey, b *protobuf.Bundle) ([]*IdentityAndID, error) {
|
||||
func (s *Service) ProcessPublicBundle(myIdentityKey *ecdsa.PrivateKey, theirIdentity *ecdsa.PublicKey, b *protobuf.Bundle) ([]*Installation, error) {
|
||||
signedPreKeys := b.GetSignedPreKeys()
|
||||
var response []*IdentityAndID
|
||||
var installations []*Installation
|
||||
|
||||
myIdentityStr := fmt.Sprintf("0x%x", crypto.FromECDSAPub(&myIdentityKey.PublicKey))
|
||||
|
@ -83,16 +126,12 @@ func (s *Service) ProcessPublicBundle(myIdentityKey *ecdsa.PrivateKey, theirIden
|
|||
for installationID, signedPreKey := range signedPreKeys {
|
||||
if installationID != s.config.InstallationID {
|
||||
installations = append(installations, &Installation{
|
||||
Identity: theirIdentityStr,
|
||||
ID: installationID,
|
||||
Version: signedPreKey.GetProtocolVersion(),
|
||||
})
|
||||
response = append(response, &IdentityAndID{theirIdentityStr, installationID})
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.persistence.AddInstallations(b.GetIdentity(), b.GetTimestamp(), installations, fromOurIdentity); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
return s.persistence.AddInstallations(b.GetIdentity(), b.GetTimestamp(), installations, fromOurIdentity)
|
||||
}
|
||||
|
|
|
@ -32,8 +32,10 @@ func (s *SQLLitePersistence) GetActiveInstallations(maxInstallations int, identi
|
|||
}
|
||||
|
||||
for rows.Next() {
|
||||
var installationID string
|
||||
var version uint32
|
||||
var (
|
||||
installationID string
|
||||
version uint32
|
||||
)
|
||||
err = rows.Scan(
|
||||
&installationID,
|
||||
&version,
|
||||
|
@ -44,6 +46,7 @@ func (s *SQLLitePersistence) GetActiveInstallations(maxInstallations int, identi
|
|||
installations = append(installations, &Installation{
|
||||
ID: installationID,
|
||||
Version: version,
|
||||
Enabled: true,
|
||||
})
|
||||
|
||||
}
|
||||
|
@ -52,20 +55,116 @@ func (s *SQLLitePersistence) GetActiveInstallations(maxInstallations int, identi
|
|||
|
||||
}
|
||||
|
||||
// GetInstallations returns all the installations for a given identity
|
||||
// we both return the installations & the metadata
|
||||
// metadata is currently stored in a separate table, as in some cases we
|
||||
// might have metadata for a device, but no other information on the device
|
||||
func (s *SQLLitePersistence) GetInstallations(identity []byte) ([]*Installation, error) {
|
||||
installationMap := make(map[string]*Installation)
|
||||
var installations []*Installation
|
||||
|
||||
// We query both tables as sqlite does not support full outer joins
|
||||
installationsStmt, err := s.db.Prepare(`SELECT installation_id, version, enabled, timestamp FROM installations WHERE identity = ?`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer installationsStmt.Close()
|
||||
|
||||
installationRows, err := installationsStmt.Query(identity)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for installationRows.Next() {
|
||||
var (
|
||||
installationID string
|
||||
version uint32
|
||||
enabled bool
|
||||
timestamp int64
|
||||
)
|
||||
err = installationRows.Scan(
|
||||
&installationID,
|
||||
&version,
|
||||
&enabled,
|
||||
×tamp,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
installationMap[installationID] = &Installation{
|
||||
ID: installationID,
|
||||
Version: version,
|
||||
Enabled: enabled,
|
||||
Timestamp: timestamp,
|
||||
InstallationMetadata: &InstallationMetadata{},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
metadataStmt, err := s.db.Prepare(`SELECT installation_id, name, device_type, fcm_token FROM installation_metadata WHERE identity = ?`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer metadataStmt.Close()
|
||||
|
||||
metadataRows, err := metadataStmt.Query(identity)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for metadataRows.Next() {
|
||||
var (
|
||||
installationID string
|
||||
name sql.NullString
|
||||
deviceType sql.NullString
|
||||
fcmToken sql.NullString
|
||||
installation *Installation
|
||||
)
|
||||
err = metadataRows.Scan(
|
||||
&installationID,
|
||||
&name,
|
||||
&deviceType,
|
||||
&fcmToken,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := installationMap[installationID]; ok {
|
||||
installation = installationMap[installationID]
|
||||
} else {
|
||||
installation = &Installation{ID: installationID}
|
||||
}
|
||||
installation.InstallationMetadata = &InstallationMetadata{
|
||||
Name: name.String,
|
||||
DeviceType: deviceType.String,
|
||||
FCMToken: fcmToken.String,
|
||||
}
|
||||
installationMap[installationID] = installation
|
||||
}
|
||||
|
||||
for _, installation := range installationMap {
|
||||
installations = append(installations, installation)
|
||||
}
|
||||
|
||||
return installations, nil
|
||||
}
|
||||
|
||||
// AddInstallations adds the installations for a given identity, maintaining the enabled flag
|
||||
func (s *SQLLitePersistence) AddInstallations(identity []byte, timestamp int64, installations []*Installation, defaultEnabled bool) error {
|
||||
func (s *SQLLitePersistence) AddInstallations(identity []byte, timestamp int64, installations []*Installation, defaultEnabled bool) ([]*Installation, error) {
|
||||
tx, err := s.db.Begin()
|
||||
if err != nil {
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var insertedInstallations []*Installation
|
||||
|
||||
for _, installation := range installations {
|
||||
stmt, err := tx.Prepare(`SELECT enabled, version
|
||||
FROM installations
|
||||
WHERE identity = ? AND installation_id = ?
|
||||
LIMIT 1`)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
|
@ -76,14 +175,14 @@ func (s *SQLLitePersistence) AddInstallations(identity []byte, timestamp int64,
|
|||
|
||||
err = stmt.QueryRow(identity, installation.ID).Scan(&oldEnabled, &oldVersion)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
stmt, err = tx.Prepare(`INSERT INTO installations(identity, installation_id, timestamp, enabled, version)
|
||||
VALUES (?, ?, ?, ?, ?)`)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
|
@ -95,8 +194,9 @@ func (s *SQLLitePersistence) AddInstallations(identity []byte, timestamp int64,
|
|||
latestVersion,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
insertedInstallations = append(insertedInstallations, installation)
|
||||
} else {
|
||||
// We update timestamp if present without changing enabled, only if this is a new bundle
|
||||
// and we set the version to the latest we ever saw
|
||||
|
@ -110,7 +210,7 @@ func (s *SQLLitePersistence) AddInstallations(identity []byte, timestamp int64,
|
|||
AND installation_id = ?
|
||||
AND timestamp < ?`)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
|
@ -123,7 +223,7 @@ func (s *SQLLitePersistence) AddInstallations(identity []byte, timestamp int64,
|
|||
timestamp,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,10 +231,10 @@ func (s *SQLLitePersistence) AddInstallations(identity []byte, timestamp int64,
|
|||
|
||||
if err := tx.Commit(); err != nil {
|
||||
_ = tx.Rollback()
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil
|
||||
return insertedInstallations, nil
|
||||
|
||||
}
|
||||
|
||||
|
@ -165,3 +265,14 @@ func (s *SQLLitePersistence) DisableInstallation(identity []byte, installationID
|
|||
_, err = stmt.Exec(identity, installationID)
|
||||
return err
|
||||
}
|
||||
|
||||
// SetInstallationMetadata sets the metadata for a given installation
|
||||
func (s *SQLLitePersistence) SetInstallationMetadata(identity []byte, installationID string, metadata *InstallationMetadata) error {
|
||||
stmt, err := s.db.Prepare(`INSERT INTO installation_metadata(name, device_type, fcm_token, identity, installation_id) VALUES(?,?,?,?,?)`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = stmt.Exec(metadata.Name, metadata.DeviceType, metadata.FCMToken, identity, installationID)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -36,30 +36,30 @@ func (s *SQLLitePersistenceTestSuite) SetupTest() {
|
|||
func (s *SQLLitePersistenceTestSuite) TestAddInstallations() {
|
||||
identity := []byte("alice")
|
||||
installations := []*Installation{
|
||||
{ID: "alice-1", Version: 1},
|
||||
{ID: "alice-2", Version: 2},
|
||||
{ID: "alice-1", Version: 1, Enabled: true},
|
||||
{ID: "alice-2", Version: 2, Enabled: true},
|
||||
}
|
||||
err := s.service.AddInstallations(
|
||||
addedInstallations, err := s.service.AddInstallations(
|
||||
identity,
|
||||
1,
|
||||
installations,
|
||||
true,
|
||||
)
|
||||
|
||||
s.Require().NoError(err)
|
||||
|
||||
enabledInstallations, err := s.service.GetActiveInstallations(5, identity)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Equal(installations, enabledInstallations)
|
||||
s.Require().Equal(installations, addedInstallations)
|
||||
}
|
||||
|
||||
func (s *SQLLitePersistenceTestSuite) TestAddInstallationVersions() {
|
||||
identity := []byte("alice")
|
||||
installations := []*Installation{
|
||||
{ID: "alice-1", Version: 1},
|
||||
{ID: "alice-1", Version: 1, Enabled: true},
|
||||
}
|
||||
err := s.service.AddInstallations(
|
||||
_, err := s.service.AddInstallations(
|
||||
identity,
|
||||
1,
|
||||
installations,
|
||||
|
@ -77,7 +77,7 @@ func (s *SQLLitePersistenceTestSuite) TestAddInstallationVersions() {
|
|||
{ID: "alice-1", Version: 0},
|
||||
}
|
||||
|
||||
err = s.service.AddInstallations(
|
||||
_, err = s.service.AddInstallations(
|
||||
identity,
|
||||
3,
|
||||
installationsWithDowngradedVersion,
|
||||
|
@ -98,7 +98,7 @@ func (s *SQLLitePersistenceTestSuite) TestAddInstallationsLimit() {
|
|||
{ID: "alice-2", Version: 2},
|
||||
}
|
||||
|
||||
err := s.service.AddInstallations(
|
||||
_, err := s.service.AddInstallations(
|
||||
identity,
|
||||
1,
|
||||
installations,
|
||||
|
@ -111,7 +111,7 @@ func (s *SQLLitePersistenceTestSuite) TestAddInstallationsLimit() {
|
|||
{ID: "alice-3", Version: 3},
|
||||
}
|
||||
|
||||
err = s.service.AddInstallations(
|
||||
_, err = s.service.AddInstallations(
|
||||
identity,
|
||||
2,
|
||||
installations,
|
||||
|
@ -120,12 +120,12 @@ func (s *SQLLitePersistenceTestSuite) TestAddInstallationsLimit() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
installations = []*Installation{
|
||||
{ID: "alice-2", Version: 2},
|
||||
{ID: "alice-3", Version: 3},
|
||||
{ID: "alice-4", Version: 4},
|
||||
{ID: "alice-2", Version: 2, Enabled: true},
|
||||
{ID: "alice-3", Version: 3, Enabled: true},
|
||||
{ID: "alice-4", Version: 4, Enabled: true},
|
||||
}
|
||||
|
||||
err = s.service.AddInstallations(
|
||||
_, err = s.service.AddInstallations(
|
||||
identity,
|
||||
3,
|
||||
installations,
|
||||
|
@ -147,7 +147,7 @@ func (s *SQLLitePersistenceTestSuite) TestAddInstallationsDisabled() {
|
|||
{ID: "alice-2", Version: 2},
|
||||
}
|
||||
|
||||
err := s.service.AddInstallations(
|
||||
_, err := s.service.AddInstallations(
|
||||
identity,
|
||||
1,
|
||||
installations,
|
||||
|
@ -169,7 +169,7 @@ func (s *SQLLitePersistenceTestSuite) TestDisableInstallation() {
|
|||
{ID: "alice-2", Version: 2},
|
||||
}
|
||||
|
||||
err := s.service.AddInstallations(
|
||||
_, err := s.service.AddInstallations(
|
||||
identity,
|
||||
1,
|
||||
installations,
|
||||
|
@ -186,18 +186,19 @@ func (s *SQLLitePersistenceTestSuite) TestDisableInstallation() {
|
|||
{ID: "alice-2", Version: 2},
|
||||
}
|
||||
|
||||
err = s.service.AddInstallations(
|
||||
addedInstallations, err := s.service.AddInstallations(
|
||||
identity,
|
||||
1,
|
||||
installations,
|
||||
true,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(0, len(addedInstallations))
|
||||
|
||||
actualInstallations, err := s.service.GetActiveInstallations(3, identity)
|
||||
s.Require().NoError(err)
|
||||
|
||||
expected := []*Installation{{ID: "alice-2", Version: 2}}
|
||||
expected := []*Installation{{ID: "alice-2", Version: 2, Enabled: true}}
|
||||
s.Require().Equal(expected, actualInstallations)
|
||||
}
|
||||
|
||||
|
@ -209,7 +210,7 @@ func (s *SQLLitePersistenceTestSuite) TestEnableInstallation() {
|
|||
{ID: "alice-2", Version: 2},
|
||||
}
|
||||
|
||||
err := s.service.AddInstallations(
|
||||
_, err := s.service.AddInstallations(
|
||||
identity,
|
||||
1,
|
||||
installations,
|
||||
|
@ -223,7 +224,7 @@ func (s *SQLLitePersistenceTestSuite) TestEnableInstallation() {
|
|||
actualInstallations, err := s.service.GetActiveInstallations(3, identity)
|
||||
s.Require().NoError(err)
|
||||
|
||||
expected := []*Installation{{ID: "alice-2", Version: 2}}
|
||||
expected := []*Installation{{ID: "alice-2", Version: 2, Enabled: true}}
|
||||
s.Require().Equal(expected, actualInstallations)
|
||||
|
||||
err = s.service.EnableInstallation(identity, "alice-1")
|
||||
|
@ -233,9 +234,79 @@ func (s *SQLLitePersistenceTestSuite) TestEnableInstallation() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
expected = []*Installation{
|
||||
{ID: "alice-1", Version: 1, Enabled: true},
|
||||
{ID: "alice-2", Version: 2, Enabled: true},
|
||||
}
|
||||
s.Require().Equal(expected, actualInstallations)
|
||||
}
|
||||
|
||||
func (s *SQLLitePersistenceTestSuite) TestGetInstallations() {
|
||||
identity := []byte("alice")
|
||||
|
||||
installations := []*Installation{
|
||||
{ID: "alice-1", Version: 1},
|
||||
{ID: "alice-2", Version: 2},
|
||||
}
|
||||
s.Require().Equal(expected, actualInstallations)
|
||||
|
||||
_, err := s.service.AddInstallations(
|
||||
identity,
|
||||
1,
|
||||
installations,
|
||||
true,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = s.service.DisableInstallation(identity, "alice-1")
|
||||
s.Require().NoError(err)
|
||||
|
||||
actualInstallations, err := s.service.GetInstallations(identity)
|
||||
s.Require().NoError(err)
|
||||
|
||||
emptyMetadata := &InstallationMetadata{}
|
||||
|
||||
expected := []*Installation{
|
||||
{ID: "alice-1", Version: 1, Timestamp: 1, Enabled: false, InstallationMetadata: emptyMetadata},
|
||||
{ID: "alice-2", Version: 2, Timestamp: 1, Enabled: true, InstallationMetadata: emptyMetadata},
|
||||
}
|
||||
s.Require().Equal(2, len(actualInstallations))
|
||||
s.Require().ElementsMatch(expected, actualInstallations)
|
||||
}
|
||||
|
||||
func (s *SQLLitePersistenceTestSuite) TestSetMetadata() {
|
||||
identity := []byte("alice")
|
||||
|
||||
installations := []*Installation{
|
||||
{ID: "alice-1", Version: 1},
|
||||
{ID: "alice-2", Version: 2},
|
||||
}
|
||||
|
||||
_, err := s.service.AddInstallations(
|
||||
identity,
|
||||
1,
|
||||
installations,
|
||||
true,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = s.service.DisableInstallation(identity, "alice-1")
|
||||
s.Require().NoError(err)
|
||||
|
||||
emptyMetadata := &InstallationMetadata{}
|
||||
setMetadata := &InstallationMetadata{
|
||||
Name: "a",
|
||||
FCMToken: "b",
|
||||
DeviceType: "c",
|
||||
}
|
||||
|
||||
err = s.service.SetInstallationMetadata(identity, "alice-2", setMetadata)
|
||||
s.Require().NoError(err)
|
||||
|
||||
actualInstallations, err := s.service.GetInstallations(identity)
|
||||
s.Require().NoError(err)
|
||||
|
||||
expected := []*Installation{
|
||||
{ID: "alice-1", Version: 1, Timestamp: 1, Enabled: false, InstallationMetadata: emptyMetadata},
|
||||
{ID: "alice-2", Version: 2, Timestamp: 1, Enabled: true, InstallationMetadata: setMetadata},
|
||||
}
|
||||
s.Require().ElementsMatch(expected, actualInstallations)
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ type ProtocolService struct {
|
|||
encryption *EncryptionService
|
||||
secret *sharedsecret.Service
|
||||
multidevice *multidevice.Service
|
||||
addedBundlesHandler func([]*multidevice.IdentityAndID)
|
||||
addedBundlesHandler func([]*multidevice.Installation)
|
||||
onNewSharedSecretHandler func([]*sharedsecret.Secret)
|
||||
Enabled bool
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ type ProtocolService struct {
|
|||
var ErrNotProtocolMessage = errors.New("Not a protocol message")
|
||||
|
||||
// NewProtocolService creates a new ProtocolService instance
|
||||
func NewProtocolService(encryption *EncryptionService, secret *sharedsecret.Service, multidevice *multidevice.Service, addedBundlesHandler func([]*multidevice.IdentityAndID), onNewSharedSecretHandler func([]*sharedsecret.Secret)) *ProtocolService {
|
||||
func NewProtocolService(encryption *EncryptionService, secret *sharedsecret.Service, multidevice *multidevice.Service, addedBundlesHandler func([]*multidevice.Installation), onNewSharedSecretHandler func([]*sharedsecret.Secret)) *ProtocolService {
|
||||
return &ProtocolService{
|
||||
log: log.New("package", "status-go/services/sshext.chat"),
|
||||
encryption: encryption,
|
||||
|
@ -193,7 +193,7 @@ func (p *ProtocolService) BuildDHMessage(myIdentityKey *ecdsa.PrivateKey, destin
|
|||
}
|
||||
|
||||
// ProcessPublicBundle processes a received X3DH bundle.
|
||||
func (p *ProtocolService) ProcessPublicBundle(myIdentityKey *ecdsa.PrivateKey, bundle *protobuf.Bundle) ([]*multidevice.IdentityAndID, error) {
|
||||
func (p *ProtocolService) ProcessPublicBundle(myIdentityKey *ecdsa.PrivateKey, bundle *protobuf.Bundle) ([]*multidevice.Installation, error) {
|
||||
if err := p.encryption.ProcessPublicBundle(myIdentityKey, bundle); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -227,6 +227,16 @@ func (p *ProtocolService) DisableInstallation(myIdentityKey *ecdsa.PublicKey, in
|
|||
return p.multidevice.DisableInstallation(myIdentityKey, installationID)
|
||||
}
|
||||
|
||||
// GetOurInstallations returns all the installations available given an identity
|
||||
func (p *ProtocolService) GetOurInstallations(myIdentityKey *ecdsa.PublicKey) ([]*multidevice.Installation, error) {
|
||||
return p.multidevice.GetOurInstallations(myIdentityKey)
|
||||
}
|
||||
|
||||
// SetInstallationMetadata sets the metadata for our own installation
|
||||
func (p *ProtocolService) SetInstallationMetadata(myIdentityKey *ecdsa.PublicKey, installationID string, data *multidevice.InstallationMetadata) error {
|
||||
return p.multidevice.SetInstallationMetadata(myIdentityKey, installationID, data)
|
||||
}
|
||||
|
||||
// GetPublicBundle retrieves a public bundle given an identity
|
||||
func (p *ProtocolService) GetPublicBundle(theirIdentityKey *ecdsa.PublicKey) (*protobuf.Bundle, error) {
|
||||
installations, err := p.multidevice.GetActiveInstallations(theirIdentityKey)
|
||||
|
|
|
@ -39,7 +39,7 @@ func (s *ProtocolServiceTestSuite) SetupTest() {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
addedBundlesHandler := func(addedBundles []*multidevice.IdentityAndID) {}
|
||||
addedBundlesHandler := func(addedBundles []*multidevice.Installation) {}
|
||||
onNewSharedSecretHandler := func(secret []*sharedsecret.Secret) {}
|
||||
|
||||
aliceMultideviceConfig := &multidevice.Config{
|
||||
|
|
|
@ -37,6 +37,7 @@ var (
|
|||
// ErrPFSNotEnabled is returned when an endpoint PFS only is called but
|
||||
// PFS is disabled
|
||||
ErrPFSNotEnabled = errors.New("pfs not enabled")
|
||||
errNoKeySelected = errors.New("no key selected")
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
|
@ -134,7 +135,7 @@ func (s *Service) initProtocol(address, encKey, password string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
addedBundlesHandler := func(addedBundles []*multidevice.IdentityAndID) {
|
||||
addedBundlesHandler := func(addedBundles []*multidevice.Installation) {
|
||||
handler := SignalHandler{}
|
||||
for _, bundle := range addedBundles {
|
||||
handler.BundleAdded(bundle.Identity, bundle.ID)
|
||||
|
@ -142,7 +143,6 @@ func (s *Service) initProtocol(address, encKey, password string) error {
|
|||
}
|
||||
|
||||
// Initialize persistence
|
||||
|
||||
s.persistence = NewSQLLitePersistence(persistence.DB)
|
||||
|
||||
// Initialize sharedsecret
|
||||
|
@ -171,7 +171,7 @@ func (s *Service) initProtocol(address, encKey, password string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) ProcessPublicBundle(myIdentityKey *ecdsa.PrivateKey, bundle *protobuf.Bundle) ([]*multidevice.IdentityAndID, error) {
|
||||
func (s *Service) ProcessPublicBundle(myIdentityKey *ecdsa.PrivateKey, bundle *protobuf.Bundle) ([]*multidevice.Installation, error) {
|
||||
if s.protocol == nil {
|
||||
return nil, errProtocolNotInitialized
|
||||
}
|
||||
|
@ -188,12 +188,79 @@ func (s *Service) GetBundle(myIdentityKey *ecdsa.PrivateKey) (*protobuf.Bundle,
|
|||
}
|
||||
|
||||
// EnableInstallation enables an installation for multi-device sync.
|
||||
func (s *Service) EnableInstallation(myIdentityKey *ecdsa.PublicKey, installationID string) error {
|
||||
func (s *Service) EnableInstallation(installationID string) error {
|
||||
if s.protocol == nil {
|
||||
return errProtocolNotInitialized
|
||||
}
|
||||
|
||||
return s.protocol.EnableInstallation(myIdentityKey, installationID)
|
||||
privateKeyID := s.whisper.SelectedKeyPairID()
|
||||
if privateKeyID == "" {
|
||||
return errNoKeySelected
|
||||
}
|
||||
|
||||
privateKey, err := s.whisper.GetPrivateKey(privateKeyID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.protocol.EnableInstallation(&privateKey.PublicKey, installationID)
|
||||
}
|
||||
|
||||
// DisableInstallation disables an installation for multi-device sync.
|
||||
func (s *Service) DisableInstallation(installationID string) error {
|
||||
if s.protocol == nil {
|
||||
return errProtocolNotInitialized
|
||||
}
|
||||
|
||||
privateKeyID := s.whisper.SelectedKeyPairID()
|
||||
if privateKeyID == "" {
|
||||
return errNoKeySelected
|
||||
}
|
||||
|
||||
privateKey, err := s.whisper.GetPrivateKey(privateKeyID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.protocol.DisableInstallation(&privateKey.PublicKey, installationID)
|
||||
}
|
||||
|
||||
// GetOurInstallations returns all the installations available given an identity
|
||||
func (s *Service) GetOurInstallations() ([]*multidevice.Installation, error) {
|
||||
if s.protocol == nil {
|
||||
return nil, errProtocolNotInitialized
|
||||
}
|
||||
|
||||
privateKeyID := s.whisper.SelectedKeyPairID()
|
||||
if privateKeyID == "" {
|
||||
return nil, errNoKeySelected
|
||||
}
|
||||
|
||||
privateKey, err := s.whisper.GetPrivateKey(privateKeyID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.protocol.GetOurInstallations(&privateKey.PublicKey)
|
||||
}
|
||||
|
||||
// SetInstallationMetadata sets the metadata for our own installation
|
||||
func (s *Service) SetInstallationMetadata(installationID string, data *multidevice.InstallationMetadata) error {
|
||||
if s.protocol == nil {
|
||||
return errProtocolNotInitialized
|
||||
}
|
||||
|
||||
privateKeyID := s.whisper.SelectedKeyPairID()
|
||||
if privateKeyID == "" {
|
||||
return errNoKeySelected
|
||||
}
|
||||
|
||||
privateKey, err := s.whisper.GetPrivateKey(privateKeyID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.protocol.SetInstallationMetadata(&privateKey.PublicKey, installationID, data)
|
||||
}
|
||||
|
||||
func (s *Service) GetPublicBundle(identityKey *ecdsa.PublicKey) (*protobuf.Bundle, error) {
|
||||
|
@ -204,15 +271,6 @@ func (s *Service) GetPublicBundle(identityKey *ecdsa.PublicKey) (*protobuf.Bundl
|
|||
return s.protocol.GetPublicBundle(identityKey)
|
||||
}
|
||||
|
||||
// DisableInstallation disables an installation for multi-device sync.
|
||||
func (s *Service) DisableInstallation(myIdentityKey *ecdsa.PublicKey, installationID string) error {
|
||||
if s.protocol == nil {
|
||||
return errProtocolNotInitialized
|
||||
}
|
||||
|
||||
return s.protocol.DisableInstallation(myIdentityKey, installationID)
|
||||
}
|
||||
|
||||
func (s *Service) Start(online func() bool, startTicker bool) error {
|
||||
s.online = online
|
||||
if startTicker {
|
||||
|
@ -283,7 +341,7 @@ func (s *Service) ProcessMessage(dedupMessage dedup.DeduplicateMessage) error {
|
|||
|
||||
privateKeyID := s.whisper.SelectedKeyPairID()
|
||||
if privateKeyID == "" {
|
||||
return errors.New("no key selected")
|
||||
return errNoKeySelected
|
||||
}
|
||||
|
||||
privateKey, err := s.whisper.GetPrivateKey(privateKeyID)
|
||||
|
@ -425,7 +483,7 @@ func (s *Service) CreatePublicMessage(signature string, chatID string, payload [
|
|||
if wrap {
|
||||
privateKeyID := s.whisper.SelectedKeyPairID()
|
||||
if privateKeyID == "" {
|
||||
return nil, errors.New("no key selected")
|
||||
return nil, errNoKeySelected
|
||||
}
|
||||
|
||||
privateKey, err := s.whisper.GetPrivateKey(privateKeyID)
|
||||
|
@ -501,7 +559,7 @@ func (s *Service) sendContactCode() (*whisper.NewMessage, error) {
|
|||
|
||||
privateKeyID := s.whisper.SelectedKeyPairID()
|
||||
if privateKeyID == "" {
|
||||
return nil, errors.New("no key selected")
|
||||
return nil, errNoKeySelected
|
||||
}
|
||||
|
||||
privateKey, err := s.whisper.GetPrivateKey(privateKeyID)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
DROP TABLE installations_metadata;
|
|
@ -0,0 +1,8 @@
|
|||
CREATE TABLE installation_metadata (
|
||||
identity BLOB NOT NULL,
|
||||
installation_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL DEFAULT '',
|
||||
device_type TEXT NOT NULL DEFAULT '',
|
||||
fcm_token TEXT NOT NULL DEFAULT '',
|
||||
UNIQUE(identity, installation_id) ON CONFLICT REPLACE
|
||||
);
|
Loading…
Reference in New Issue