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 (
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.5.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/primitives v0.0.3-0.20230214180039-9a25e2d3969c
gitlab.com/xx_network/crypto v0.0.5-0.20230214003943-8a09396e95dd
......@@ -27,12 +27,10 @@ require (
github.com/cloudflare/circl v1.2.0 // indirect
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // 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/golang-collections/collections v0.0.0-20130729185459-604e922904d3 // indirect
github.com/golang/protobuf v1.5.2 // 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/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
......@@ -40,27 +38,18 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.15.9 // 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-sqlite3 v1.14.15 // 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/oasisprotocol/curve25519-voi v0.0.0-20221003100820-41fad3beba17 // 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/rs/cors v1.8.2 // indirect
github.com/sethvargo/go-diceware v0.3.0 // indirect
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // 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/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/libphonenumber v1.2.1 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
......@@ -81,9 +70,6 @@ require (
google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc // indirect
google.golang.org/grpc v1.49.0 // 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/gorm v1.24.3 // indirect
nhooyr.io/websocket v1.8.7 // indirect
......
This diff is collapsed.
......@@ -42,6 +42,11 @@ func (m *manager) registerCallbacks() {
m.mh.RegisterCallback(wDm.ReceiveReplyTag, m.receiveReplyCB)
m.mh.RegisterCallback(wDm.ReceiveReactionTag, m.receiveReactionCB)
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
......@@ -278,3 +283,31 @@ func (m *manager) updateSentStatusCB(data []byte) ([]byte, error) {
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) {
}
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 {
// Get is a generic helper for getting values from the given [idb.ObjectStore].
// Only usable by primary key.
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
txn, err := db.Transaction(idb.TransactionReadOnly, objectStoreName)
......@@ -82,17 +82,56 @@ func Get(db *idb.Database, objectStoreName string, key js.Value) (js.Value, erro
}
// Process result into string
jww.DEBUG.Printf("Got from %s/%s: %s",
objectStoreName, key, utils.JsToJson(resultObj))
jww.DEBUG.Printf("Got from %s: %s",
objectStoreName, utils.JsToJson(resultObj))
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
// [idb.ObjectStore] using the given [idb.Index].
func GetIndex(db *idb.Database, objectStoreName,
indexName string, key js.Value) (js.Value, error) {
parentErr := errors.Errorf("failed to GetIndex %s/%s/%s",
objectStoreName, indexName, key)
parentErr := errors.Errorf("failed to GetIndex %s/%s",
objectStoreName, indexName)
// Prepare the Transaction
txn, err := db.Transaction(idb.TransactionReadOnly, objectStoreName)
......@@ -131,8 +170,8 @@ func GetIndex(db *idb.Database, objectStoreName,
}
// Process result into string
jww.DEBUG.Printf("Got from %s/%s/%s: %s",
objectStoreName, indexName, key, utils.JsToJson(resultObj))
jww.DEBUG.Printf("Got from %s/%s: %s",
objectStoreName, indexName, utils.JsToJson(resultObj))
return resultObj, nil
}
......@@ -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
// [idb.ObjectStore]. Only usable by primary key.
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
txn, err := db.Transaction(idb.TransactionReadWrite, objectStoreName)
......
......@@ -249,3 +249,57 @@ func (w *wasmModel) UpdateSentStatus(uuid uint64, messageID message.ID,
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 (
ReceiveTag worker.Tag = "Receive"
ReceiveTextTag worker.Tag = "ReceiveText"
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
import (
"crypto/ed25519"
"encoding/json"
"gitlab.com/elixxir/client/v4/dm"
"syscall/js"
indexDB "gitlab.com/elixxir/xxdk-wasm/indexedDb/worker/dm"
......@@ -59,21 +61,21 @@ func newDMClientJS(api *bindings.DMClient) map[string]any {
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.
//
// Returns:
// - Tracker ID (int).
func (ch *DMClient) GetID(js.Value, []js.Value) any {
return ch.api.GetID()
func (dmc *DMClient) GetID(js.Value, []js.Value) any {
return dmc.api.GetID()
}
func (ch *DMClient) GetPublicKey(js.Value, []js.Value) any {
return ch.api.GetPublicKey()
func (dmc *DMClient) GetPublicKey(js.Value, []js.Value) any {
return dmc.api.GetPublicKey()
}
func (ch *DMClient) GetToken(js.Value, []js.Value) any {
return ch.api.GetToken()
func (dmc *DMClient) GetToken(js.Value, []js.Value) any {
return dmc.api.GetToken()
}
// dmReceiverBuilder adheres to the [bindings.DMReceiverBuilder] interface.
......@@ -238,7 +240,7 @@ func newDMClientWithIndexedDb(cmixID int, wasmJsPath string,
// 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
// 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
......@@ -262,7 +264,7 @@ func newDMClientWithIndexedDb(cmixID int, wasmJsPath string,
// Returns a promise:
// - Resolves to the JSON of [bindings.ChannelSendReport] (Uint8Array).
// - 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()
partnerPubKeyBytes := utils.CopyBytesToGo(args[1])
partnerToken := args[2].Int()
......@@ -271,7 +273,7 @@ func (ch *DMClient) Send(_ js.Value, args []js.Value) any {
cmixParamsJSON := utils.CopyBytesToGo(args[5])
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,
cmixParamsJSON)
if err != nil {
......@@ -284,7 +286,7 @@ func (ch *DMClient) Send(_ js.Value, args []js.Value) any {
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
// the largest payload that can be sent, but it will always be possible to send
// a payload of 798 bytes at minimum.
......@@ -306,7 +308,7 @@ func (ch *DMClient) Send(_ js.Value, args []js.Value) any {
// Returns a promise:
// - Resolves to the JSON of [bindings.ChannelSendReport] (Uint8Array).
// - 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])
partnerToken := args[1].Int()
message := args[2].String()
......@@ -314,7 +316,7 @@ func (ch *DMClient) SendText(_ js.Value, args []js.Value) any {
cmixParamsJSON := utils.CopyBytesToGo(args[4])
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,
cmixParamsJSON)
if err != nil {
......@@ -358,7 +360,7 @@ func (ch *DMClient) SendText(_ js.Value, args []js.Value) any {
// Returns a promise:
// - Resolves to the JSON of [bindings.ChannelSendReport] (Uint8Array).
// - 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])
partnerToken := args[1].Int()
replyID := utils.CopyBytesToGo(args[2])
......@@ -367,7 +369,7 @@ func (ch *DMClient) SendReply(_ js.Value, args []js.Value) any {
cmixParamsJSON := utils.CopyBytesToGo(args[5])
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,
cmixParamsJSON)
if err != nil {
......@@ -400,7 +402,7 @@ func (ch *DMClient) SendReply(_ js.Value, args []js.Value) any {
// Returns a promise:
// - Resolves to the JSON of [bindings.ChannelSendReport] (Uint8Array).
// - 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])
partnerToken := args[1].Int()
replyID := utils.CopyBytesToGo(args[2])
......@@ -408,7 +410,7 @@ func (ch *DMClient) SendReaction(_ js.Value, args []js.Value) any {
cmixParamsJSON := utils.CopyBytesToGo(args[4])
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,
cmixParamsJSON)
if err != nil {
......@@ -427,8 +429,8 @@ func (ch *DMClient) SendReaction(_ js.Value, args []js.Value) any {
// Returns:
// - JSON of the [channel.Identity] (Uint8Array).
// - Throws TypeError if marshalling the identity fails.
func (ch *DMClient) GetIdentity(js.Value, []js.Value) any {
i := ch.api.GetIdentity()
func (dmc *DMClient) GetIdentity(js.Value, []js.Value) any {
i := dmc.api.GetIdentity()
return utils.CopyBytesToJS(i)
}
......@@ -442,8 +444,8 @@ func (ch *DMClient) GetIdentity(js.Value, []js.Value) any {
// Returns:
// - JSON of the encrypted private identity (Uint8Array).
// - Throws TypeError if exporting the identity fails.
func (ch *DMClient) ExportPrivateIdentity(_ js.Value, args []js.Value) any {
i, err := ch.api.ExportPrivateIdentity(args[0].String())
func (dmc *DMClient) ExportPrivateIdentity(_ js.Value, args []js.Value) any {
i, err := dmc.api.ExportPrivateIdentity(args[0].String())
if err != nil {
utils.Throw(utils.TypeError, err)
return nil
......@@ -462,8 +464,8 @@ func (ch *DMClient) ExportPrivateIdentity(_ js.Value, args []js.Value) any {
// Returns:
// - Throws TypeError if unmarshalling the ID fails or the nickname is
// invalid.
func (ch *DMClient) SetNickname(_ js.Value, args []js.Value) any {
ch.api.SetNickname(args[0].String())
func (dmc *DMClient) SetNickname(_ js.Value, args []js.Value) any {
dmc.api.SetNickname(args[0].String())
return nil
}
......@@ -473,8 +475,8 @@ func (ch *DMClient) SetNickname(_ js.Value, args []js.Value) any {
// Returns:
// - The nickname (string).
// - Throws TypeError if the channel has no nickname set.
func (ch *DMClient) GetNickname(_ js.Value, args []js.Value) any {
nickname, err := ch.api.GetNickname()
func (dmc *DMClient) GetNickname(_ js.Value, _ []js.Value) any {
nickname, err := dmc.api.GetNickname()
if err != nil {
utils.Throw(utils.TypeError, err)
return nil
......@@ -490,9 +492,9 @@ func (ch *DMClient) GetNickname(_ js.Value, args []js.Value) any {
//
// Returns:
// - The storage tag (string).
func (dmc *DMClient) GetDatabaseName(_ js.Value, args []js.Value) any {
return (base64.RawStdEncoding.EncodeToString(dmc.api.GetPublicKey()) +
"_speakeasy_dm")
func (dmc *DMClient) GetDatabaseName(_ js.Value, _ []js.Value) any {
return base64.RawStdEncoding.EncodeToString(dmc.api.GetPublicKey()) +
"_speakeasy_dm"
}
////////////////////////////////////////////////////////////////////////////////
......@@ -536,9 +538,13 @@ type dmReceiver struct {
receiveReply func(args ...any) js.Value
receiveReaction 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
// user of the API to filter such called by message ID.
//
......@@ -730,6 +736,61 @@ func (em *dmReceiver) UpdateSentStatus(uuid int64, messageID []byte,
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 //
////////////////////////////////////////////////////////////////////////////////
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment