From 538094bf7f32d836b6628f747785f95a950669c7 Mon Sep 17 00:00:00 2001 From: Roland Osborne Date: Sat, 3 Dec 2022 16:57:22 -0800 Subject: [PATCH] adding backend distribution point for sealed channels --- doc/api.oa3 | 4 ++ net/server/internal/api_getAccountStatus.go | 8 +++- net/server/internal/api_setAccountSeal.go | 49 +++++++++++++++++++++ net/server/internal/authUtil.go | 25 +++++++++++ net/server/internal/modelUtil.go | 2 + net/server/internal/models.go | 19 ++++++++ net/server/internal/routers.go | 7 +++ net/server/internal/store/schema.go | 4 ++ 8 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 net/server/internal/api_setAccountSeal.go diff --git a/doc/api.oa3 b/doc/api.oa3 index 6898771c..d658fd4a 100644 --- a/doc/api.oa3 +++ b/doc/api.oa3 @@ -3762,6 +3762,8 @@ components: type: boolean disabled: type: boolean + seal: + type: string Profile: type: object @@ -3931,6 +3933,8 @@ components: type: string node: type: string + seal: + type: string revision: type: integer format: int64 diff --git a/net/server/internal/api_getAccountStatus.go b/net/server/internal/api_getAccountStatus.go index 7b6381a3..2a4501f4 100644 --- a/net/server/internal/api_getAccountStatus.go +++ b/net/server/internal/api_getAccountStatus.go @@ -8,7 +8,7 @@ import ( //GetAccountStatus retrieves account state values func GetAccountStatus(w http.ResponseWriter, r *http.Request) { - session, code, err := GetSession(r) + session, code, err := GetSessionDetail(r) if err != nil { ErrResponse(w, code, err) return @@ -22,6 +22,10 @@ func GetAccountStatus(w http.ResponseWriter, r *http.Request) { } // construct response + seal := &Seal{} + seal.Salt = account.AccountDetail.SealSalt + seal.PrivateKeyEncrypted = account.AccountDetail.SealPrivate + seal.PublicKey = account.AccountDetail.SealPublic status := &AccountStatus{} status.StorageAvailable = getNumConfigValue(CNFStorage, 0) for _, asset := range assets { @@ -31,6 +35,6 @@ func GetAccountStatus(w http.ResponseWriter, r *http.Request) { status.ForwardingAddress = account.Forward status.Searchable = account.Searchable status.PushEnabled = session.PushEnabled - + status.Seal = seal WriteResponse(w, status) } diff --git a/net/server/internal/api_setAccountSeal.go b/net/server/internal/api_setAccountSeal.go new file mode 100644 index 00000000..f7d298e9 --- /dev/null +++ b/net/server/internal/api_setAccountSeal.go @@ -0,0 +1,49 @@ +package databag + +import ( + "databag/internal/store" + "gorm.io/gorm" + "net/http" +) + +//SetAccountSeal sets sealing key for channels +func SetAccountSeal(w http.ResponseWriter, r *http.Request) { + + account, code, err := ParamAgentToken(r, true) + if err != nil { + ErrResponse(w, code, err) + return + } + + seal := Seal{} + if err := ParseRequest(r, w, &seal); err != nil { + ErrResponse(w, http.StatusBadRequest, err) + return + } + + // update record + account.AccountDetail.SealSalt = seal.Salt + account.AccountDetail.SealPrivate = seal.PrivateKeyEncrypted + account.AccountDetail.SealPublic = seal.PublicKey + + err = store.DB.Transaction(func(tx *gorm.DB) error { + if res := tx.Save(&account.AccountDetail).Error; res != nil { + return res + } + if res := tx.Model(&account).Update("profile_revision", account.ProfileRevision+1).Error; res != nil { + return res + } + if res := tx.Model(&account).Update("account_revision", account.AccountRevision+1).Error; res != nil { + return res + } + return nil + }) + if err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + + SetProfileNotification(account) + SetStatus(account) + WriteResponse(w, nil) +} diff --git a/net/server/internal/authUtil.go b/net/server/internal/authUtil.go index 281fb3f3..382af513 100644 --- a/net/server/internal/authUtil.go +++ b/net/server/internal/authUtil.go @@ -95,6 +95,31 @@ func ParamAdminToken(r *http.Request) (int, error) { return http.StatusOK, nil } +//GetSessionDetail retrieves account detail specified by agent query param +func GetSessionDetail(r *http.Request) (*store.Session, int, error) { + + // parse authentication token + target, access, err := ParseToken(r.FormValue("agent")) + if err != nil { + return nil, http.StatusBadRequest, err + } + + // find session record + var session store.Session; + if err := store.DB.Preload("Account.AccountDetail").Where("account_id = ? AND token = ?", target, access).Find(&session).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, http.StatusNotFound, err + } + return nil, http.StatusInternalServerError, err + } + + if session.Account.Disabled { + return nil, http.StatusGone, errors.New("account is inactive") + } + + return &session, http.StatusOK, nil +} + //GetSession retrieves account specified by agent query param func GetSession(r *http.Request) (*store.Session, int, error) { diff --git a/net/server/internal/modelUtil.go b/net/server/internal/modelUtil.go index 10c59de1..46a79478 100644 --- a/net/server/internal/modelUtil.go +++ b/net/server/internal/modelUtil.go @@ -16,6 +16,7 @@ func getProfileModel(account *store.Account) *Profile { Revision: account.ProfileRevision, Version: APPVersion, Node: getStrConfigValue(CNFDomain, ""), + Seal: account.AccountDetail.SealPublic, } } @@ -94,6 +95,7 @@ func getCardProfileModel(slot *store.CardSlot) *CardProfile { ImageSet: slot.Card.Image != "", Version: slot.Card.Version, Node: slot.Card.Node, + Seal: slot.Card.Seal, } } diff --git a/net/server/internal/models.go b/net/server/internal/models.go index 1b60113b..b51d3838 100644 --- a/net/server/internal/models.go +++ b/net/server/internal/models.go @@ -16,6 +16,8 @@ type AccountProfile struct { ImageSet bool `json:"imageSet,omitempty"` + Seal string `json:"seal,emitempty"` + Disabled bool `json:"disabled"` } @@ -32,6 +34,10 @@ type AccountStatus struct { Searchable bool `json:"searchable"` PushEnabled bool `json:"pushEnabled"` + + Sealable bool `json:"sealable"` + + Seal *Seal `json:"seal,omitempty"` } //Announce initial message sent on websocket @@ -134,6 +140,8 @@ type CardProfile struct { ImageSet bool `json:"imageSet"` + Seal string `json:"seal,omitempty"` + Version string `json:"version,omitempty"` Node string `json:"node"` @@ -363,6 +371,8 @@ type Profile struct { Image string `json:"image,omitempty"` + Seal string `json:"seal,omitempty"` + Revision int64 `json:"revision"` Version string `json:"version,omitempty"` @@ -394,6 +404,15 @@ type Revision struct { Card int64 `json:"card"` } +//Seal key for channel sealing +type Seal struct { + Salt string `json:"salt"` + + PrivateKeyEncrypted string `json:"privateKeyEncrypted,omitempty"` + + PublicKey string `json:"publicKey,omitempty"` +} + //SignedData object serialized in message type SignedData struct { GUID string `json:"guid"` diff --git a/net/server/internal/routers.go b/net/server/internal/routers.go index f83256c4..5017fa99 100644 --- a/net/server/internal/routers.go +++ b/net/server/internal/routers.go @@ -188,6 +188,13 @@ var endpoints = routes{ SetAccountNotification, }, + route{ + "SetAccountSeal", + strings.ToUpper("Put"), + "/account/seal", + SetAccountSeal, + }, + route{ "SetAccountSerchable", strings.ToUpper("Put"), diff --git a/net/server/internal/store/schema.go b/net/server/internal/store/schema.go index 4c7e857f..ca60096d 100644 --- a/net/server/internal/store/schema.go +++ b/net/server/internal/store/schema.go @@ -95,6 +95,9 @@ type AccountDetail struct { Description string Location string Image string + SealSalt string + SealPrivate string + SealPublic string } type Session struct { @@ -181,6 +184,7 @@ type Card struct { Description string Location string Image string + Seal string Version string `gorm:"not null"` Node string `gorm:"not null"` ProfileRevision int64 `gorm:"not null"`