Skip to content
Snippets Groups Projects
Commit 594ea0fd authored by Jake Taylor's avatar Jake Taylor :lips:
Browse files

Merge branch 'XX-4512/DisableUsersImpl' into 'release'

added first implementation for disabling users in DM indexedDb package

See merge request !76
parents 1e4d215e 186dc687
No related branches found
No related tags found
2 merge requests!76added first implementation for disabling users in DM indexedDb package,!67fix for latest client release
...@@ -10,7 +10,7 @@ require ( ...@@ -10,7 +10,7 @@ require (
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.5.0 github.com/spf13/cobra v1.5.0
github.com/spf13/jwalterweatherman v1.1.0 github.com/spf13/jwalterweatherman v1.1.0
gitlab.com/elixxir/client/v4 v4.3.12-0.20230302190347-650340742d3b gitlab.com/elixxir/client/v4 v4.3.12-0.20230302181743-042f9c941d2d
gitlab.com/elixxir/crypto v0.0.7-0.20230214180106-72841fd1e426 gitlab.com/elixxir/crypto v0.0.7-0.20230214180106-72841fd1e426
gitlab.com/elixxir/primitives v0.0.3-0.20230214180039-9a25e2d3969c gitlab.com/elixxir/primitives v0.0.3-0.20230214180039-9a25e2d3969c
gitlab.com/xx_network/crypto v0.0.5-0.20230214003943-8a09396e95dd gitlab.com/xx_network/crypto v0.0.5-0.20230214003943-8a09396e95dd
...@@ -27,12 +27,10 @@ require ( ...@@ -27,12 +27,10 @@ require (
github.com/cloudflare/circl v1.2.0 // indirect github.com/cloudflare/circl v1.2.0 // indirect
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
github.com/elliotchance/orderedmap v1.4.0 // indirect github.com/elliotchance/orderedmap v1.4.0 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/gobwas/ws v1.1.0 // indirect github.com/gobwas/ws v1.1.0 // indirect
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 // indirect github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 // indirect
github.com/golang/protobuf v1.5.2 // indirect github.com/golang/protobuf v1.5.2 // indirect
github.com/gorilla/websocket v1.5.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/improbable-eng/grpc-web v0.15.0 // indirect github.com/improbable-eng/grpc-web v0.15.0 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
...@@ -40,27 +38,18 @@ require ( ...@@ -40,27 +38,18 @@ require (
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.15.9 // indirect github.com/klauspost/compress v1.15.9 // indirect
github.com/klauspost/cpuid/v2 v2.1.0 // indirect github.com/klauspost/cpuid/v2 v2.1.0 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-sqlite3 v1.14.15 // indirect github.com/mattn/go-sqlite3 v1.14.15 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/oasisprotocol/curve25519-voi v0.0.0-20221003100820-41fad3beba17 // indirect github.com/oasisprotocol/curve25519-voi v0.0.0-20221003100820-41fad3beba17 // indirect
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.2 // indirect
github.com/pkg/profile v1.6.0 // indirect
github.com/rivo/uniseg v0.4.3 // indirect github.com/rivo/uniseg v0.4.3 // indirect
github.com/rs/cors v1.8.2 // indirect github.com/rs/cors v1.8.2 // indirect
github.com/sethvargo/go-diceware v0.3.0 // indirect github.com/sethvargo/go-diceware v0.3.0 // indirect
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
github.com/soheilhy/cmux v0.1.5 // indirect github.com/soheilhy/cmux v0.1.5 // indirect
github.com/spf13/afero v1.9.2 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.12.0 // indirect
github.com/subosito/gotenv v1.4.0 // indirect
github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 // indirect github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 // indirect
github.com/ttacon/libphonenumber v1.2.1 // indirect github.com/ttacon/libphonenumber v1.2.1 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect
...@@ -81,9 +70,6 @@ require ( ...@@ -81,9 +70,6 @@ require (
google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc // indirect google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc // indirect
google.golang.org/grpc v1.49.0 // indirect google.golang.org/grpc v1.49.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/ini.v1 v1.66.6 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/driver/sqlite v1.4.4 // indirect gorm.io/driver/sqlite v1.4.4 // indirect
gorm.io/gorm v1.24.3 // indirect gorm.io/gorm v1.24.3 // indirect
nhooyr.io/websocket v1.8.7 // indirect nhooyr.io/websocket v1.8.7 // indirect
......
This diff is collapsed.
...@@ -42,6 +42,11 @@ func (m *manager) registerCallbacks() { ...@@ -42,6 +42,11 @@ func (m *manager) registerCallbacks() {
m.mh.RegisterCallback(wDm.ReceiveReplyTag, m.receiveReplyCB) m.mh.RegisterCallback(wDm.ReceiveReplyTag, m.receiveReplyCB)
m.mh.RegisterCallback(wDm.ReceiveReactionTag, m.receiveReactionCB) m.mh.RegisterCallback(wDm.ReceiveReactionTag, m.receiveReactionCB)
m.mh.RegisterCallback(wDm.UpdateSentStatusTag, m.updateSentStatusCB) m.mh.RegisterCallback(wDm.UpdateSentStatusTag, m.updateSentStatusCB)
m.mh.RegisterCallback(wDm.BlockSenderTag, m.blockSenderCB)
m.mh.RegisterCallback(wDm.UnblockSenderTag, m.unblockSenderCB)
m.mh.RegisterCallback(wDm.GetConversationTag, m.getConversationCB)
m.mh.RegisterCallback(wDm.GetConversationsTag, m.getConversationsCB)
} }
// newWASMEventModelCB is the callback for NewWASMEventModel. Returns an empty // newWASMEventModelCB is the callback for NewWASMEventModel. Returns an empty
...@@ -278,3 +283,31 @@ func (m *manager) updateSentStatusCB(data []byte) ([]byte, error) { ...@@ -278,3 +283,31 @@ func (m *manager) updateSentStatusCB(data []byte) ([]byte, error) {
return nil, nil return nil, nil
} }
// blockSenderCB is the callback for wasmModel.BlockSender. Always
// returns nil; meaning, no response is supplied (or expected).
func (m *manager) blockSenderCB(data []byte) ([]byte, error) {
m.model.BlockSender(data)
return nil, nil
}
// unblockSenderCB is the callback for wasmModel.UnblockSender. Always
// returns nil; meaning, no response is supplied (or expected).
func (m *manager) unblockSenderCB(data []byte) ([]byte, error) {
m.model.UnblockSender(data)
return nil, nil
}
// getConversationCB is the callback for wasmModel.GetConversation.
// Returns nil on error or the JSON marshalled Conversation on success.
func (m *manager) getConversationCB(data []byte) ([]byte, error) {
result := m.model.GetConversation(data)
return json.Marshal(result)
}
// getConversationsCB is the callback for wasmModel.GetConversations.
// Returns nil on error or the JSON marshalled list of Conversation on success.
func (m *manager) getConversationsCB(_ []byte) ([]byte, error) {
result := m.model.GetConversations()
return json.Marshal(result)
}
...@@ -329,3 +329,109 @@ func (w *wasmModel) msgIDLookup(messageID message.ID) (uint64, error) { ...@@ -329,3 +329,109 @@ func (w *wasmModel) msgIDLookup(messageID message.ID) (uint64, error) {
} }
return uuid, nil return uuid, nil
} }
// BlockSender silences messages sent by the indicated sender
// public key.
func (w *wasmModel) BlockSender(senderPubKey ed25519.PublicKey) {
parentErr := "failed to BlockSender"
err := w.setBlocked(senderPubKey, true)
if err != nil {
jww.ERROR.Printf("%+v", errors.WithMessage(err, parentErr))
}
}
// UnblockSender allows messages sent by the indicated sender
// public key.
func (w *wasmModel) UnblockSender(senderPubKey ed25519.PublicKey) {
parentErr := "failed to UnblockSender"
err := w.setBlocked(senderPubKey, false)
if err != nil {
jww.ERROR.Printf("%+v", errors.WithMessage(err, parentErr))
}
}
// setBlocked is a helper for blocking/unblocking a given Conversation.
func (w *wasmModel) setBlocked(senderPubKey ed25519.PublicKey, isBlocked bool) error {
// Get current Conversation and set blocked
resultConvo, err := w.getConversation(senderPubKey)
if err != nil {
return err
}
resultConvo.Blocked = isBlocked
// Convert back to js.Value
newMessageJson, err := json.Marshal(resultConvo)
if err != nil {
return err
}
convoObj, err := utils.JsonToJS(newMessageJson)
if err != nil {
return err
}
// Insert into storage
_, err = impl.Put(w.db, conversationStoreName, convoObj)
return err
}
// GetConversation returns the conversation held by the model (receiver).
func (w *wasmModel) GetConversation(senderPubKey ed25519.PublicKey) *dm.ModelConversation {
parentErr := "failed to GetConversation"
resultConvo, err := w.getConversation(senderPubKey)
if err != nil {
jww.ERROR.Printf("%+v", errors.WithMessage(err, parentErr))
return nil
}
return &dm.ModelConversation{
Pubkey: resultConvo.Pubkey,
Nickname: resultConvo.Nickname,
Token: resultConvo.Token,
CodesetVersion: resultConvo.CodesetVersion,
Blocked: resultConvo.Blocked,
}
}
// getConversation is a helper that returns the Conversation with the given senderPubKey.
func (w *wasmModel) getConversation(senderPubKey ed25519.PublicKey) (*Conversation, error) {
resultObj, err := impl.Get(w.db, conversationStoreName, impl.EncodeBytes(senderPubKey))
if err != nil {
return nil, err
}
resultConvo := &Conversation{}
err = json.Unmarshal([]byte(utils.JsToJson(resultObj)), resultConvo)
if err != nil {
return nil, err
}
return resultConvo, nil
}
// GetConversations returns any conversations held by the model (receiver).
func (w *wasmModel) GetConversations() []dm.ModelConversation {
parentErr := "failed to GetConversations"
results, err := impl.GetAll(w.db, conversationStoreName)
if err != nil {
jww.ERROR.Printf("%+v", errors.WithMessage(err, parentErr))
return nil
}
conversations := make([]dm.ModelConversation, len(results))
for i := range results {
resultConvo := &Conversation{}
err = json.Unmarshal([]byte(utils.JsToJson(results[i])), resultConvo)
if err != nil {
jww.ERROR.Printf("%+v", errors.WithMessage(err, parentErr))
return nil
}
conversations[i] = dm.ModelConversation{
Pubkey: resultConvo.Pubkey,
Nickname: resultConvo.Nickname,
Token: resultConvo.Token,
CodesetVersion: resultConvo.CodesetVersion,
Blocked: resultConvo.Blocked,
}
}
return conversations
}
////////////////////////////////////////////////////////////////////////////////
// Copyright © 2022 xx foundation //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file. //
////////////////////////////////////////////////////////////////////////////////
//go:build js && wasm
package main
import (
"crypto/ed25519"
jww "github.com/spf13/jwalterweatherman"
"os"
"testing"
)
func dummyReceivedMessageCB(uint64, ed25519.PublicKey, bool) {}
func dummyStoreDatabaseName(string) error { return nil }
func dummyStoreEncryptionStatus(_ string, encryptionStatus bool) (bool, error) {
return encryptionStatus, nil
}
func TestMain(m *testing.M) {
jww.SetStdoutThreshold(jww.LevelDebug)
os.Exit(m.Run())
}
// Test happy path toggling between blocked/unblocked in a Conversation.
func TestWasmModel_BlockSender(t *testing.T) {
m, err := newWASMModel("test", nil,
dummyReceivedMessageCB, dummyStoreDatabaseName, dummyStoreEncryptionStatus)
if err != nil {
t.Fatal(err.Error())
}
// Insert a test convo
testPubKey := ed25519.PublicKey{}
err = m.joinConversation("test", testPubKey, 0, 0)
if err != nil {
t.Fatal(err.Error())
}
// Default to unblocked
result := m.GetConversation(testPubKey)
if result.Blocked {
t.Fatal("Expected blocked to be false")
}
// Now toggle blocked
m.BlockSender(testPubKey)
result = m.GetConversation(testPubKey)
if !result.Blocked {
t.Fatal("Expected blocked to be true")
}
// Now toggle blocked again
m.UnblockSender(testPubKey)
result = m.GetConversation(testPubKey)
if result.Blocked {
t.Fatal("Expected blocked to be false")
}
}
...@@ -48,7 +48,7 @@ func EncodeBytes(input []byte) js.Value { ...@@ -48,7 +48,7 @@ func EncodeBytes(input []byte) js.Value {
// Get is a generic helper for getting values from the given [idb.ObjectStore]. // Get is a generic helper for getting values from the given [idb.ObjectStore].
// Only usable by primary key. // Only usable by primary key.
func Get(db *idb.Database, objectStoreName string, key js.Value) (js.Value, error) { func Get(db *idb.Database, objectStoreName string, key js.Value) (js.Value, error) {
parentErr := errors.Errorf("failed to Get %s/%s", objectStoreName, key) parentErr := errors.Errorf("failed to Get %s", objectStoreName)
// Prepare the Transaction // Prepare the Transaction
txn, err := db.Transaction(idb.TransactionReadOnly, objectStoreName) txn, err := db.Transaction(idb.TransactionReadOnly, objectStoreName)
...@@ -82,17 +82,56 @@ func Get(db *idb.Database, objectStoreName string, key js.Value) (js.Value, erro ...@@ -82,17 +82,56 @@ func Get(db *idb.Database, objectStoreName string, key js.Value) (js.Value, erro
} }
// Process result into string // Process result into string
jww.DEBUG.Printf("Got from %s/%s: %s", jww.DEBUG.Printf("Got from %s: %s",
objectStoreName, key, utils.JsToJson(resultObj)) objectStoreName, utils.JsToJson(resultObj))
return resultObj, nil return resultObj, nil
} }
// GetAll is a generic helper for getting all values from the given [idb.ObjectStore].
func GetAll(db *idb.Database, objectStoreName string) ([]js.Value, error) {
parentErr := errors.Errorf("failed to GetAll %s", objectStoreName)
// Prepare the Transaction
txn, err := db.Transaction(idb.TransactionReadWrite, objectStoreName)
if err != nil {
return nil, errors.WithMessagef(parentErr,
"Unable to create Transaction: %+v", err)
}
store, err := txn.ObjectStore(objectStoreName)
if err != nil {
return nil, errors.WithMessagef(parentErr,
"Unable to get ObjectStore: %+v", err)
}
// Perform the operation
result := make([]js.Value, 0)
cursorRequest, err := store.OpenCursor(idb.CursorNext)
if err != nil {
return nil, errors.WithMessagef(parentErr, "Unable to open Cursor: %+v", err)
}
ctx, cancel := NewContext()
err = cursorRequest.Iter(ctx,
func(cursor *idb.CursorWithValue) error {
row, err := cursor.Value()
if err != nil {
return err
}
result = append(result, row)
return nil
})
cancel()
if err != nil {
return nil, errors.WithMessagef(parentErr, err.Error())
}
return result, nil
}
// GetIndex is a generic helper for getting values from the given // GetIndex is a generic helper for getting values from the given
// [idb.ObjectStore] using the given [idb.Index]. // [idb.ObjectStore] using the given [idb.Index].
func GetIndex(db *idb.Database, objectStoreName, func GetIndex(db *idb.Database, objectStoreName,
indexName string, key js.Value) (js.Value, error) { indexName string, key js.Value) (js.Value, error) {
parentErr := errors.Errorf("failed to GetIndex %s/%s/%s", parentErr := errors.Errorf("failed to GetIndex %s/%s",
objectStoreName, indexName, key) objectStoreName, indexName)
// Prepare the Transaction // Prepare the Transaction
txn, err := db.Transaction(idb.TransactionReadOnly, objectStoreName) txn, err := db.Transaction(idb.TransactionReadOnly, objectStoreName)
...@@ -131,8 +170,8 @@ func GetIndex(db *idb.Database, objectStoreName, ...@@ -131,8 +170,8 @@ func GetIndex(db *idb.Database, objectStoreName,
} }
// Process result into string // Process result into string
jww.DEBUG.Printf("Got from %s/%s/%s: %s", jww.DEBUG.Printf("Got from %s/%s: %s",
objectStoreName, indexName, key, utils.JsToJson(resultObj)) objectStoreName, indexName, utils.JsToJson(resultObj))
return resultObj, nil return resultObj, nil
} }
...@@ -170,7 +209,7 @@ func Put(db *idb.Database, objectStoreName string, value js.Value) (js.Value, er ...@@ -170,7 +209,7 @@ func Put(db *idb.Database, objectStoreName string, value js.Value) (js.Value, er
// Delete is a generic helper for removing values from the given // Delete is a generic helper for removing values from the given
// [idb.ObjectStore]. Only usable by primary key. // [idb.ObjectStore]. Only usable by primary key.
func Delete(db *idb.Database, objectStoreName string, key js.Value) error { func Delete(db *idb.Database, objectStoreName string, key js.Value) error {
parentErr := errors.Errorf("failed to Delete %s/%s", objectStoreName, key) parentErr := errors.Errorf("failed to Delete %s", objectStoreName)
// Prepare the Transaction // Prepare the Transaction
txn, err := db.Transaction(idb.TransactionReadWrite, objectStoreName) txn, err := db.Transaction(idb.TransactionReadWrite, objectStoreName)
......
...@@ -249,3 +249,57 @@ func (w *wasmModel) UpdateSentStatus(uuid uint64, messageID message.ID, ...@@ -249,3 +249,57 @@ func (w *wasmModel) UpdateSentStatus(uuid uint64, messageID message.ID,
w.wh.SendMessage(UpdateSentStatusTag, data, nil) w.wh.SendMessage(UpdateSentStatusTag, data, nil)
} }
func (w *wasmModel) BlockSender(senderPubKey ed25519.PublicKey) {
w.wh.SendMessage(BlockSenderTag, senderPubKey, nil)
}
func (w *wasmModel) UnblockSender(senderPubKey ed25519.PublicKey) {
w.wh.SendMessage(UnblockSenderTag, senderPubKey, nil)
}
func (w *wasmModel) GetConversation(senderPubKey ed25519.PublicKey) *dm.ModelConversation {
resultChan := make(chan *dm.ModelConversation)
w.wh.SendMessage(GetConversationTag, senderPubKey,
func(data []byte) {
var result *dm.ModelConversation
err := json.Unmarshal(data, &result)
if err != nil {
jww.ERROR.Printf("Could not JSON unmarshal response to "+
"GetConversation: %+v", err)
}
resultChan <- result
})
select {
case result := <-resultChan:
return result
case <-time.After(worker.ResponseTimeout):
jww.ERROR.Printf("Timed out after %s waiting for response from the "+
"worker about GetConversation", worker.ResponseTimeout)
return nil
}
}
func (w *wasmModel) GetConversations() []dm.ModelConversation {
resultChan := make(chan []dm.ModelConversation)
w.wh.SendMessage(GetConversationTag, nil,
func(data []byte) {
var result []dm.ModelConversation
err := json.Unmarshal(data, &result)
if err != nil {
jww.ERROR.Printf("Could not JSON unmarshal response to "+
"GetConversations: %+v", err)
}
resultChan <- result
})
select {
case result := <-resultChan:
return result
case <-time.After(worker.ResponseTimeout):
jww.ERROR.Printf("Timed out after %s waiting for response from the "+
"worker about GetConversations", worker.ResponseTimeout)
return nil
}
}
...@@ -24,4 +24,9 @@ const ( ...@@ -24,4 +24,9 @@ const (
ReceiveTag worker.Tag = "Receive" ReceiveTag worker.Tag = "Receive"
ReceiveTextTag worker.Tag = "ReceiveText" ReceiveTextTag worker.Tag = "ReceiveText"
UpdateSentStatusTag worker.Tag = "UpdateSentStatusTag" UpdateSentStatusTag worker.Tag = "UpdateSentStatusTag"
BlockSenderTag worker.Tag = "BlockSender"
UnblockSenderTag worker.Tag = "UnblockSender"
GetConversationTag worker.Tag = "GetConversation"
GetConversationsTag worker.Tag = "GetConversations"
) )
...@@ -11,6 +11,8 @@ package wasm ...@@ -11,6 +11,8 @@ package wasm
import ( import (
"crypto/ed25519" "crypto/ed25519"
"encoding/json"
"gitlab.com/elixxir/client/v4/dm"
"syscall/js" "syscall/js"
indexDB "gitlab.com/elixxir/xxdk-wasm/indexedDb/worker/dm" indexDB "gitlab.com/elixxir/xxdk-wasm/indexedDb/worker/dm"
...@@ -59,21 +61,21 @@ func newDMClientJS(api *bindings.DMClient) map[string]any { ...@@ -59,21 +61,21 @@ func newDMClientJS(api *bindings.DMClient) map[string]any {
return dmClientMap return dmClientMap
} }
// GetPublicKey returns the ecdh Public Key for this [DMClient] in the // GetID returns the ecdh Public Key for this [DMClient] in the
// [DMClient] tracker. // [DMClient] tracker.
// //
// Returns: // Returns:
// - Tracker ID (int). // - Tracker ID (int).
func (ch *DMClient) GetID(js.Value, []js.Value) any { func (dmc *DMClient) GetID(js.Value, []js.Value) any {
return ch.api.GetID() return dmc.api.GetID()
} }
func (ch *DMClient) GetPublicKey(js.Value, []js.Value) any { func (dmc *DMClient) GetPublicKey(js.Value, []js.Value) any {
return ch.api.GetPublicKey() return dmc.api.GetPublicKey()
} }
func (ch *DMClient) GetToken(js.Value, []js.Value) any { func (dmc *DMClient) GetToken(js.Value, []js.Value) any {
return ch.api.GetToken() return dmc.api.GetToken()
} }
// dmReceiverBuilder adheres to the [bindings.DMReceiverBuilder] interface. // dmReceiverBuilder adheres to the [bindings.DMReceiverBuilder] interface.
...@@ -238,7 +240,7 @@ func newDMClientWithIndexedDb(cmixID int, wasmJsPath string, ...@@ -238,7 +240,7 @@ func newDMClientWithIndexedDb(cmixID int, wasmJsPath string,
// Channel Sending Methods and Reports // // Channel Sending Methods and Reports //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// SendGeneric is used to send a raw message over a channel. In general, it // Send is used to send a raw message over a channel. In general, it
// should be wrapped in a function which defines the wire protocol. If the final // should be wrapped in a function which defines the wire protocol. If the final
// message, before being sent over the wire, is too long, this will return an // message, before being sent over the wire, is too long, this will return an
// error. Due to the underlying encoding using compression, it isn't possible to // error. Due to the underlying encoding using compression, it isn't possible to
...@@ -262,7 +264,7 @@ func newDMClientWithIndexedDb(cmixID int, wasmJsPath string, ...@@ -262,7 +264,7 @@ func newDMClientWithIndexedDb(cmixID int, wasmJsPath string,
// Returns a promise: // Returns a promise:
// - Resolves to the JSON of [bindings.ChannelSendReport] (Uint8Array). // - Resolves to the JSON of [bindings.ChannelSendReport] (Uint8Array).
// - Rejected with an error if sending fails. // - Rejected with an error if sending fails.
func (ch *DMClient) Send(_ js.Value, args []js.Value) any { func (dmc *DMClient) Send(_ js.Value, args []js.Value) any {
messageType := args[0].Int() messageType := args[0].Int()
partnerPubKeyBytes := utils.CopyBytesToGo(args[1]) partnerPubKeyBytes := utils.CopyBytesToGo(args[1])
partnerToken := args[2].Int() partnerToken := args[2].Int()
...@@ -271,7 +273,7 @@ func (ch *DMClient) Send(_ js.Value, args []js.Value) any { ...@@ -271,7 +273,7 @@ func (ch *DMClient) Send(_ js.Value, args []js.Value) any {
cmixParamsJSON := utils.CopyBytesToGo(args[5]) cmixParamsJSON := utils.CopyBytesToGo(args[5])
promiseFn := func(resolve, reject func(args ...any) js.Value) { promiseFn := func(resolve, reject func(args ...any) js.Value) {
sendReport, err := ch.api.Send(messageType, partnerPubKeyBytes, sendReport, err := dmc.api.Send(messageType, partnerPubKeyBytes,
uint32(partnerToken), message, leaseTimeMS, uint32(partnerToken), message, leaseTimeMS,
cmixParamsJSON) cmixParamsJSON)
if err != nil { if err != nil {
...@@ -284,7 +286,7 @@ func (ch *DMClient) Send(_ js.Value, args []js.Value) any { ...@@ -284,7 +286,7 @@ func (ch *DMClient) Send(_ js.Value, args []js.Value) any {
return utils.CreatePromise(promiseFn) return utils.CreatePromise(promiseFn)
} }
// SendMessage is used to send a formatted message over a channel. // SendText is used to send a formatted message over a channel.
// Due to the underlying encoding using compression, it isn't possible to define // Due to the underlying encoding using compression, it isn't possible to define
// the largest payload that can be sent, but it will always be possible to send // the largest payload that can be sent, but it will always be possible to send
// a payload of 798 bytes at minimum. // a payload of 798 bytes at minimum.
...@@ -306,7 +308,7 @@ func (ch *DMClient) Send(_ js.Value, args []js.Value) any { ...@@ -306,7 +308,7 @@ func (ch *DMClient) Send(_ js.Value, args []js.Value) any {
// Returns a promise: // Returns a promise:
// - Resolves to the JSON of [bindings.ChannelSendReport] (Uint8Array). // - Resolves to the JSON of [bindings.ChannelSendReport] (Uint8Array).
// - Rejected with an error if sending fails. // - Rejected with an error if sending fails.
func (ch *DMClient) SendText(_ js.Value, args []js.Value) any { func (dmc *DMClient) SendText(_ js.Value, args []js.Value) any {
partnerPubKeyBytes := utils.CopyBytesToGo(args[0]) partnerPubKeyBytes := utils.CopyBytesToGo(args[0])
partnerToken := args[1].Int() partnerToken := args[1].Int()
message := args[2].String() message := args[2].String()
...@@ -314,7 +316,7 @@ func (ch *DMClient) SendText(_ js.Value, args []js.Value) any { ...@@ -314,7 +316,7 @@ func (ch *DMClient) SendText(_ js.Value, args []js.Value) any {
cmixParamsJSON := utils.CopyBytesToGo(args[4]) cmixParamsJSON := utils.CopyBytesToGo(args[4])
promiseFn := func(resolve, reject func(args ...any) js.Value) { promiseFn := func(resolve, reject func(args ...any) js.Value) {
sendReport, err := ch.api.SendText(partnerPubKeyBytes, sendReport, err := dmc.api.SendText(partnerPubKeyBytes,
uint32(partnerToken), message, leaseTimeMS, uint32(partnerToken), message, leaseTimeMS,
cmixParamsJSON) cmixParamsJSON)
if err != nil { if err != nil {
...@@ -358,7 +360,7 @@ func (ch *DMClient) SendText(_ js.Value, args []js.Value) any { ...@@ -358,7 +360,7 @@ func (ch *DMClient) SendText(_ js.Value, args []js.Value) any {
// Returns a promise: // Returns a promise:
// - Resolves to the JSON of [bindings.ChannelSendReport] (Uint8Array). // - Resolves to the JSON of [bindings.ChannelSendReport] (Uint8Array).
// - Rejected with an error if sending fails. // - Rejected with an error if sending fails.
func (ch *DMClient) SendReply(_ js.Value, args []js.Value) any { func (dmc *DMClient) SendReply(_ js.Value, args []js.Value) any {
partnerPubKeyBytes := utils.CopyBytesToGo(args[0]) partnerPubKeyBytes := utils.CopyBytesToGo(args[0])
partnerToken := args[1].Int() partnerToken := args[1].Int()
replyID := utils.CopyBytesToGo(args[2]) replyID := utils.CopyBytesToGo(args[2])
...@@ -367,7 +369,7 @@ func (ch *DMClient) SendReply(_ js.Value, args []js.Value) any { ...@@ -367,7 +369,7 @@ func (ch *DMClient) SendReply(_ js.Value, args []js.Value) any {
cmixParamsJSON := utils.CopyBytesToGo(args[5]) cmixParamsJSON := utils.CopyBytesToGo(args[5])
promiseFn := func(resolve, reject func(args ...any) js.Value) { promiseFn := func(resolve, reject func(args ...any) js.Value) {
sendReport, err := ch.api.SendReply(partnerPubKeyBytes, sendReport, err := dmc.api.SendReply(partnerPubKeyBytes,
uint32(partnerToken), message, replyID, leaseTimeMS, uint32(partnerToken), message, replyID, leaseTimeMS,
cmixParamsJSON) cmixParamsJSON)
if err != nil { if err != nil {
...@@ -400,7 +402,7 @@ func (ch *DMClient) SendReply(_ js.Value, args []js.Value) any { ...@@ -400,7 +402,7 @@ func (ch *DMClient) SendReply(_ js.Value, args []js.Value) any {
// Returns a promise: // Returns a promise:
// - Resolves to the JSON of [bindings.ChannelSendReport] (Uint8Array). // - Resolves to the JSON of [bindings.ChannelSendReport] (Uint8Array).
// - Rejected with an error if sending fails. // - Rejected with an error if sending fails.
func (ch *DMClient) SendReaction(_ js.Value, args []js.Value) any { func (dmc *DMClient) SendReaction(_ js.Value, args []js.Value) any {
partnerPubKeyBytes := utils.CopyBytesToGo(args[0]) partnerPubKeyBytes := utils.CopyBytesToGo(args[0])
partnerToken := args[1].Int() partnerToken := args[1].Int()
replyID := utils.CopyBytesToGo(args[2]) replyID := utils.CopyBytesToGo(args[2])
...@@ -408,7 +410,7 @@ func (ch *DMClient) SendReaction(_ js.Value, args []js.Value) any { ...@@ -408,7 +410,7 @@ func (ch *DMClient) SendReaction(_ js.Value, args []js.Value) any {
cmixParamsJSON := utils.CopyBytesToGo(args[4]) cmixParamsJSON := utils.CopyBytesToGo(args[4])
promiseFn := func(resolve, reject func(args ...any) js.Value) { promiseFn := func(resolve, reject func(args ...any) js.Value) {
sendReport, err := ch.api.SendReaction(partnerPubKeyBytes, sendReport, err := dmc.api.SendReaction(partnerPubKeyBytes,
uint32(partnerToken), message, replyID, uint32(partnerToken), message, replyID,
cmixParamsJSON) cmixParamsJSON)
if err != nil { if err != nil {
...@@ -427,8 +429,8 @@ func (ch *DMClient) SendReaction(_ js.Value, args []js.Value) any { ...@@ -427,8 +429,8 @@ func (ch *DMClient) SendReaction(_ js.Value, args []js.Value) any {
// Returns: // Returns:
// - JSON of the [channel.Identity] (Uint8Array). // - JSON of the [channel.Identity] (Uint8Array).
// - Throws TypeError if marshalling the identity fails. // - Throws TypeError if marshalling the identity fails.
func (ch *DMClient) GetIdentity(js.Value, []js.Value) any { func (dmc *DMClient) GetIdentity(js.Value, []js.Value) any {
i := ch.api.GetIdentity() i := dmc.api.GetIdentity()
return utils.CopyBytesToJS(i) return utils.CopyBytesToJS(i)
} }
...@@ -442,8 +444,8 @@ func (ch *DMClient) GetIdentity(js.Value, []js.Value) any { ...@@ -442,8 +444,8 @@ func (ch *DMClient) GetIdentity(js.Value, []js.Value) any {
// Returns: // Returns:
// - JSON of the encrypted private identity (Uint8Array). // - JSON of the encrypted private identity (Uint8Array).
// - Throws TypeError if exporting the identity fails. // - Throws TypeError if exporting the identity fails.
func (ch *DMClient) ExportPrivateIdentity(_ js.Value, args []js.Value) any { func (dmc *DMClient) ExportPrivateIdentity(_ js.Value, args []js.Value) any {
i, err := ch.api.ExportPrivateIdentity(args[0].String()) i, err := dmc.api.ExportPrivateIdentity(args[0].String())
if err != nil { if err != nil {
utils.Throw(utils.TypeError, err) utils.Throw(utils.TypeError, err)
return nil return nil
...@@ -462,8 +464,8 @@ func (ch *DMClient) ExportPrivateIdentity(_ js.Value, args []js.Value) any { ...@@ -462,8 +464,8 @@ func (ch *DMClient) ExportPrivateIdentity(_ js.Value, args []js.Value) any {
// Returns: // Returns:
// - Throws TypeError if unmarshalling the ID fails or the nickname is // - Throws TypeError if unmarshalling the ID fails or the nickname is
// invalid. // invalid.
func (ch *DMClient) SetNickname(_ js.Value, args []js.Value) any { func (dmc *DMClient) SetNickname(_ js.Value, args []js.Value) any {
ch.api.SetNickname(args[0].String()) dmc.api.SetNickname(args[0].String())
return nil return nil
} }
...@@ -473,8 +475,8 @@ func (ch *DMClient) SetNickname(_ js.Value, args []js.Value) any { ...@@ -473,8 +475,8 @@ func (ch *DMClient) SetNickname(_ js.Value, args []js.Value) any {
// Returns: // Returns:
// - The nickname (string). // - The nickname (string).
// - Throws TypeError if the channel has no nickname set. // - Throws TypeError if the channel has no nickname set.
func (ch *DMClient) GetNickname(_ js.Value, args []js.Value) any { func (dmc *DMClient) GetNickname(_ js.Value, _ []js.Value) any {
nickname, err := ch.api.GetNickname() nickname, err := dmc.api.GetNickname()
if err != nil { if err != nil {
utils.Throw(utils.TypeError, err) utils.Throw(utils.TypeError, err)
return nil return nil
...@@ -490,9 +492,9 @@ func (ch *DMClient) GetNickname(_ js.Value, args []js.Value) any { ...@@ -490,9 +492,9 @@ func (ch *DMClient) GetNickname(_ js.Value, args []js.Value) any {
// //
// Returns: // Returns:
// - The storage tag (string). // - The storage tag (string).
func (dmc *DMClient) GetDatabaseName(_ js.Value, args []js.Value) any { func (dmc *DMClient) GetDatabaseName(_ js.Value, _ []js.Value) any {
return (base64.RawStdEncoding.EncodeToString(dmc.api.GetPublicKey()) + return base64.RawStdEncoding.EncodeToString(dmc.api.GetPublicKey()) +
"_speakeasy_dm") "_speakeasy_dm"
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
...@@ -536,9 +538,13 @@ type dmReceiver struct { ...@@ -536,9 +538,13 @@ type dmReceiver struct {
receiveReply func(args ...any) js.Value receiveReply func(args ...any) js.Value
receiveReaction func(args ...any) js.Value receiveReaction func(args ...any) js.Value
updateSentStatus func(args ...any) js.Value updateSentStatus func(args ...any) js.Value
blockSender func(args ...any) js.Value
unblockSender func(args ...any) js.Value
getConversation func(args ...any) js.Value
getConversations func(args ...any) js.Value
} }
// ReceiveMessage is called whenever a message is received on a given channel. // Receive is called whenever a message is received on a given channel.
// It may be called multiple times on the same message. It is incumbent on the // It may be called multiple times on the same message. It is incumbent on the
// user of the API to filter such called by message ID. // user of the API to filter such called by message ID.
// //
...@@ -730,6 +736,61 @@ func (em *dmReceiver) UpdateSentStatus(uuid int64, messageID []byte, ...@@ -730,6 +736,61 @@ func (em *dmReceiver) UpdateSentStatus(uuid int64, messageID []byte,
timestamp, roundID, status) timestamp, roundID, status)
} }
// BlockSender silences messages sent by the indicated sender
// public key.
//
// Parameters:
// - senderPubKey - The unique public key for the conversation.
func (em *dmReceiver) BlockSender(senderPubKey []byte) {
em.blockSender(senderPubKey)
}
// UnblockSender silences messages sent by the indicated sender
// public key.
//
// Parameters:
// - senderPubKey - The unique public key for the conversation.
func (em *dmReceiver) UnblockSender(senderPubKey []byte) {
em.unblockSender(senderPubKey)
}
// GetConversation returns the conversation held by the model (receiver).
//
// Parameters:
// - senderPubKey - The unique public key for the conversation.
//
// Returns:
// - JSON of [dm.ModelConversation] (Uint8Array).
func (em *dmReceiver) GetConversation(senderPubKey []byte) []byte {
result := utils.CopyBytesToGo(em.getConversation(senderPubKey))
var conversation dm.ModelConversation
err := json.Unmarshal(result, &conversation)
if err != nil {
return nil
}
conversationsBytes, _ := json.Marshal(conversation)
return conversationsBytes
}
// GetConversations returns all conversations held by the model (receiver).
//
// Returns:
// - JSON of [][dm.ModelConversation] (Uint8Array).
func (em *dmReceiver) GetConversations() []byte {
result := utils.CopyBytesToGo(em.getConversations())
var conversations []dm.ModelConversation
err := json.Unmarshal(result, &conversations)
if err != nil {
return nil
}
conversationsBytes, _ := json.Marshal(conversations)
return conversationsBytes
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// DM DB Cipher // // DM DB Cipher //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment