From 9d7220486f20d0c0e68ebabae2270bd3b00bc420 Mon Sep 17 00:00:00 2001 From: Roland Osborne Date: Tue, 5 Apr 2022 13:52:52 -0700 Subject: [PATCH] integrated connecting contacts --- net/server/internal/api_addCard.go | 4 + net/server/internal/api_getOpenMessage.go | 2 +- net/server/internal/api_setCardStatus.go | 2 +- net/server/internal/api_setOpenMessage.go | 86 ++++++--------------- net/server/internal/main_test.go | 4 +- net/server/internal/testUtil.go | 11 +-- net/web/src/Api/getCardOpenMessage.js | 8 ++ net/web/src/Api/setCardOpenMessage.js | 8 ++ net/web/src/Api/setCardStatus.js | 20 +++++ net/web/src/User/Contact/Contact.jsx | 10 ++- net/web/src/User/Contact/Contact.styled.js | 1 + net/web/src/User/Contact/useContact.hook.js | 38 ++++++++- net/web/src/User/SideBar/SideBar.styled.js | 4 +- 13 files changed, 118 insertions(+), 80 deletions(-) create mode 100644 net/web/src/Api/getCardOpenMessage.js create mode 100644 net/web/src/Api/setCardOpenMessage.js create mode 100644 net/web/src/Api/setCardStatus.js diff --git a/net/server/internal/api_addCard.go b/net/server/internal/api_addCard.go index 60616c32..36b14ee0 100644 --- a/net/server/internal/api_addCard.go +++ b/net/server/internal/api_addCard.go @@ -97,6 +97,10 @@ func AddCard(w http.ResponseWriter, r *http.Request) { card.Node = identity.Node card.ProfileRevision = identity.Revision } + if card.Status == APP_CARDPENDING { + card.Status = APP_CARDCONFIRMED + } + card.DetailRevision = account.CardRevision + 1 // save contact card err = store.DB.Transaction(func(tx *gorm.DB) error { diff --git a/net/server/internal/api_getOpenMessage.go b/net/server/internal/api_getOpenMessage.go index 3c344687..a53b56d4 100644 --- a/net/server/internal/api_getOpenMessage.go +++ b/net/server/internal/api_getOpenMessage.go @@ -10,7 +10,7 @@ import ( func GetOpenMessage(w http.ResponseWriter, r *http.Request) { - account, code, res := BearerAppToken(r, true); + account, code, res := ParamAgentToken(r, true); if res != nil { ErrResponse(w, code, res) return diff --git a/net/server/internal/api_setCardStatus.go b/net/server/internal/api_setCardStatus.go index 9b5fcc1b..1a37852a 100644 --- a/net/server/internal/api_setCardStatus.go +++ b/net/server/internal/api_setCardStatus.go @@ -14,7 +14,7 @@ import ( func SetCardStatus(w http.ResponseWriter, r *http.Request) { var res error - account, code, err := BearerAppToken(r, false); + account, code, err := ParamAgentToken(r, false); if err != nil { ErrResponse(w, code, err) return diff --git a/net/server/internal/api_setOpenMessage.go b/net/server/internal/api_setOpenMessage.go index 3c597f11..9c95d4e6 100644 --- a/net/server/internal/api_setOpenMessage.go +++ b/net/server/internal/api_setOpenMessage.go @@ -44,7 +44,7 @@ func SetOpenMessage(w http.ResponseWriter, r *http.Request) { // see if card exists slot := &store.CardSlot{} card := &store.Card{} - if err := store.DB.Where("account_id = ? AND guid = ?", account.Guid, guid).First(card).Error; err != nil { + if err := store.DB.Preload("CardSlot").Where("account_id = ? AND guid = ?", account.Guid, guid).First(card).Error; err != nil { if !errors.Is(err, gorm.ErrRecordNotFound) { ErrResponse(w, http.StatusInternalServerError, err) return @@ -74,54 +74,28 @@ func SetOpenMessage(w http.ResponseWriter, r *http.Request) { card.InToken = hex.EncodeToString(data) card.AccountID = account.Guid - // create new card or update existing - if err = store.DB.Preload("Card").Where("account_id = ? AND card_id = 0", account.ID).First(slot).Error; err != nil { - if !errors.Is(err, gorm.ErrRecordNotFound) { - ErrResponse(w, http.StatusInternalServerError, err) - return + // create slot + err = store.DB.Transaction(func(tx *gorm.DB) error { + if res := tx.Save(card).Error; res != nil { + return res } - err = store.DB.Transaction(func(tx *gorm.DB) error { - if res := tx.Save(card).Error; res != nil { - return res - } - slot.CardSlotId = uuid.New().String() - slot.AccountID = account.ID - slot.Revision = account.CardRevision + 1 - slot.CardID = card.ID - slot.Card = card - if res := tx.Save(slot).Error; res != nil { - return res - } - if res := tx.Model(&account).Update("card_revision", account.CardRevision + 1).Error; res != nil { - return res - } - return nil - }) - if err != nil { - ErrResponse(w, http.StatusInternalServerError, err) - return + slot.CardSlotId = uuid.New().String() + slot.AccountID = account.ID + slot.Revision = account.CardRevision + 1 + slot.CardID = card.ID + slot.Card = card + if res := tx.Save(slot).Error; res != nil { + return res } - } else { - err = store.DB.Transaction(func(tx *gorm.DB) error { - if res := tx.Save(card).Error; res != nil { - return res - } - slot.Revision = account.CardRevision + 1 - slot.CardID = card.ID - if res := tx.Save(slot).Error; res != nil { - return res - } - if res := tx.Model(&account).Update("card_revision", account.CardRevision + 1).Error; res != nil { - return res - } - return nil - }) - if err != nil { - ErrResponse(w, http.StatusInternalServerError, err) - return + if res := tx.Model(&account).Update("card_revision", account.CardRevision + 1).Error; res != nil { + return res } + return nil + }) + if err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return } - } else { // update profile if revision changed @@ -160,20 +134,8 @@ func SetOpenMessage(w http.ResponseWriter, r *http.Request) { if res := tx.Save(&card).Error; res != nil { return res } - if res := tx.Preload("Card").Where("account_id = ? AND card_id = ?", account.ID, card.ID).First(&slot).Error; res != nil { - if !errors.Is(res, gorm.ErrRecordNotFound) { - return nil - } - slot = &store.CardSlot{ - CardSlotId: uuid.New().String(), - AccountID: account.ID, - Revision: account.CardRevision + 1, - CardID: card.ID, - Card: card, - } - } else { - slot.Revision = account.CardRevision + 1 - } + slot = &card.CardSlot + slot.Revision = account.CardRevision + 1 if res := tx.Preload("Card").Save(slot).Error; res != nil { return res } @@ -189,9 +151,9 @@ func SetOpenMessage(w http.ResponseWriter, r *http.Request) { } status := &ContactStatus{ - Token: slot.Card.InToken, - Status: slot.Card.Status, - ViewRevision: slot.Card.ViewRevision, + Token: card.InToken, + Status: card.Status, + ViewRevision: card.ViewRevision, ChannelRevision: account.ChannelRevision, ProfileRevision: account.ProfileRevision, ArticleRevision: account.ArticleRevision, diff --git a/net/server/internal/main_test.go b/net/server/internal/main_test.go index 37b9ffb9..792a00d5 100644 --- a/net/server/internal/main_test.go +++ b/net/server/internal/main_test.go @@ -54,7 +54,7 @@ func TestMain(m *testing.M) { } // config server - config := NodeConfig{Domain: "example.com", AccountLimit: 1024, OpenAccess: true, AccountStorage: 4096} + config := NodeConfig{Domain: "databag.coredb.org", AccountLimit: 1024, OpenAccess: true, AccountStorage: 4096} r, w, _ = NewRequest("PUT", "/admin/config", &config) SetBasicAuth(r, "admin:pass") SetNodeConfig(w, r) @@ -70,7 +70,7 @@ func TestMain(m *testing.M) { if ReadResponse(w, &check) != nil { panic("failed to get node config") } - if check.Domain != "example.com" { + if check.Domain != "databag.coredb.org" { panic("failed to set config domain"); } if check.AccountLimit != 1024 { diff --git a/net/server/internal/testUtil.go b/net/server/internal/testUtil.go index 965b9ed5..1991a663 100644 --- a/net/server/internal/testUtil.go +++ b/net/server/internal/testUtil.go @@ -521,22 +521,20 @@ func OpenTestCard(account string, cardId string) (err error) { var contactStatus ContactStatus // set to connecting state - if r, w, err = NewRequest("PUT", "/contact/cards/{cardId}/status", APP_CARDCONNECTING); err != nil { + if r, w, err = NewRequest("PUT", "/contact/cards/{cardId}/status?agent=" + account, APP_CARDCONNECTING); err != nil { return } r = mux.SetURLVars(r, vars) - SetBearerAuth(r, account) SetCardStatus(w, r) if err = ReadResponse(w, &card); err != nil { return } // get open message - if r, w, err = NewRequest("GET", "/contact/cards/{cardId}/openMessage", nil); err != nil { + if r, w, err = NewRequest("GET", "/contact/cards/{cardId}/openMessage?agent=" + account, nil); err != nil { return } r = mux.SetURLVars(r, vars) - SetBearerAuth(r, account) GetOpenMessage(w, r) if err = ReadResponse(w, &msg); err != nil { return @@ -557,11 +555,10 @@ func OpenTestCard(account string, cardId string) (err error) { article := "articleRevision=" + strconv.FormatInt(contactStatus.ArticleRevision, 10) channel := "channelRevision=" + strconv.FormatInt(contactStatus.ChannelRevision, 10) profile := "profileRevision=" + strconv.FormatInt(contactStatus.ProfileRevision, 10) - if r, w, err = NewRequest("PUT", "/contact/cards/{cardId}/status?token=" + contactStatus.Token + "&" + view + "&" + article + "&" + channel + "&" + profile, APP_CARDCONNECTED); err != nil { + if r, w, err = NewRequest("PUT", "/contact/cards/{cardId}/status?agent=" + account + "&token=" + contactStatus.Token + "&" + view + "&" + article + "&" + channel + "&" + profile, APP_CARDCONNECTED); err != nil { return } r = mux.SetURLVars(r, vars) - SetBearerAuth(r, account) SetCardStatus(w, r) if err = ReadResponse(w, &card); err != nil { return @@ -605,7 +602,7 @@ func AddTestAccount(username string) (guid string, token string, err error) { app := AppData{ Name: "Appy", Description: "A test app", - Url: "http://app.example.com", + Url: "http://app.coredb.org", }; var claim Claim var msg DataMessage diff --git a/net/web/src/Api/getCardOpenMessage.js b/net/web/src/Api/getCardOpenMessage.js new file mode 100644 index 00000000..130a6d89 --- /dev/null +++ b/net/web/src/Api/getCardOpenMessage.js @@ -0,0 +1,8 @@ +import { checkResponse, fetchWithTimeout } from './fetchUtil'; + +export async function getCardOpenMessage(token, cardId) { + let message = await fetchWithTimeout(`/contact/cards/${cardId}/openMessage?agent=${token}`, { method: 'GET' }); + checkResponse(message); + return await message.json(); +} + diff --git a/net/web/src/Api/setCardOpenMessage.js b/net/web/src/Api/setCardOpenMessage.js new file mode 100644 index 00000000..b9e39884 --- /dev/null +++ b/net/web/src/Api/setCardOpenMessage.js @@ -0,0 +1,8 @@ +import { checkResponse, fetchWithTimeout } from './fetchUtil'; + +export async function setCardOpenMessage(server, message) { + let status = await fetchWithTimeout(`https://${server}/contact/openMessage`, { method: 'PUT', body: JSON.stringify(message) }); + checkResponse(status); + return await status.json(); +} + diff --git a/net/web/src/Api/setCardStatus.js b/net/web/src/Api/setCardStatus.js new file mode 100644 index 00000000..843bda2b --- /dev/null +++ b/net/web/src/Api/setCardStatus.js @@ -0,0 +1,20 @@ +import { checkResponse, fetchWithTimeout } from './fetchUtil'; + +export async function setCardConnecting(token, cardId) { + let card = await fetchWithTimeout(`/contact/cards/${cardId}/status?agent=${token}`, { method: 'PUT', body: JSON.stringify('connecting') } ); + checkResponse(card); + return await card.json(); +} + +export async function setCardConnected(token, cardId, access, view, article, channel, profile) { + let card = await fetchWithTimeout(`/contact/cards/${cardId}/status?agent=${token}&token=${access}&viewRevision=${view}&articleRevision=${article}&channelRevision=${channel}&profileRevision=${profile}`, { method: 'PUT', body: JSON.stringify('connected') } ); + checkResponse(card); + return await card.json(); +} + +export async function setCardConfirmed(token, cardId) { + let card = await fetchWithTimeout(`/contact/cards/${cardId}/status?agent=${token}`, { method: 'PUT', body: JSON.stringify('confirmed') } ); + checkResponse(card); + return await card.json(); +} + diff --git a/net/web/src/User/Contact/Contact.jsx b/net/web/src/User/Contact/Contact.jsx index 70e42f3f..087df8ef 100644 --- a/net/web/src/User/Contact/Contact.jsx +++ b/net/web/src/User/Contact/Contact.jsx @@ -74,6 +74,13 @@ export function Contact() { return <> } + const Confirm = () => { + if (state.showButtons.confirm) { + return actions.confirm()}>Save Contact + } + return <> + } + const SaveRequest = () => { if (state.showButtons.saveRequest) { return Save & Request @@ -83,7 +90,7 @@ export function Contact() { const Connect = () => { if (state.showButtons.connect) { - return Connect + return actions.connect()}>Connect } return <> } @@ -110,6 +117,7 @@ export function Contact() { + diff --git a/net/web/src/User/Contact/Contact.styled.js b/net/web/src/User/Contact/Contact.styled.js index 506a67d0..f849ff4b 100644 --- a/net/web/src/User/Contact/Contact.styled.js +++ b/net/web/src/User/Contact/Contact.styled.js @@ -64,6 +64,7 @@ export const ContactWrapper = styled.div` display: flex; flex-direction: row; margin-right: 32px; + align-items: center; } .profile { diff --git a/net/web/src/User/Contact/useContact.hook.js b/net/web/src/User/Contact/useContact.hook.js index bace5684..8e55d9a1 100644 --- a/net/web/src/User/Contact/useContact.hook.js +++ b/net/web/src/User/Contact/useContact.hook.js @@ -4,6 +4,9 @@ import { useNavigate, useLocation, useParams } from "react-router-dom"; import { getListingMessage } from '../../Api/getListingMessage'; import { addCard } from '../../Api/addCard'; import { removeCard } from '../../Api/removeCard'; +import { setCardConnecting, setCardConnected, setCardConfirmed } from '../../Api/setCardStatus'; +import { getCardOpenMessage } from '../../Api/getCardOpenMessage'; +import { setCardOpenMessage } from '../../Api/setCardOpenMessage'; export function useContact() { @@ -46,7 +49,34 @@ export function useContact() { updateState({ busy: false }); } }, - connect: () => { + confirm: async () => { + if (!state.busy) { + updateState({ busy: true }); + try { + await setCardConfirmed(app.state.token, state.cardId); + } + catch (err) { + window.alert(err); + } + updateState({ busy: false }); + } + }, + connect: async () => { + if (!state.busy) { + updateState({ busy: true }); + try { + await setCardConnecting(app.state.token, state.cardId); + let message = await getCardOpenMessage(app.state.token, state.cardId); + let contact = await setCardOpenMessage(state.node, message); + if (contact.status === 'connected') { + await setCardConnected(app.state.token, state.cardId, contact.token, contact.viewRevision, contact.articleRevision, contact.channelRevision, contact.profileRevision); + } + } + catch (err) { + window.alert(err); + } + updateState({ busy: false }); + } }, disconnect: () => { }, @@ -100,11 +130,11 @@ export function useContact() { updateState({ showButtons: { cancel: true, remove: true }}); } if (status === 'pending') { - updateState({ status: 'requested' }); - updateState({ showButtons: { ignore: true, save: true, saveAccept: true }}); + updateState({ status: 'pending' }); + updateState({ showButtons: { ignore: true, confirm: true, saveAccept: true }}); } if (status === 'confirmed') { - updateState({ status: 'disconnected' }); + updateState({ status: 'confirmed' }); updateState({ showButtons: { remove: true, connect: true }}); } if (status === 'requested') { diff --git a/net/web/src/User/SideBar/SideBar.styled.js b/net/web/src/User/SideBar/SideBar.styled.js index 0696630a..d4d8f788 100644 --- a/net/web/src/User/SideBar/SideBar.styled.js +++ b/net/web/src/User/SideBar/SideBar.styled.js @@ -1,10 +1,10 @@ import styled from 'styled-components'; export const SideBarWrapper = styled.div` - width: 30%; + width: 20%; height: 100%; max-width: 300px; - min-width: 200px; + min-width: 260px; border-right: 1px solid #8fbea7; background-color: #8fbea7; `;