mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
added profile notification
This commit is contained in:
parent
a2354704fc
commit
bc0921c721
@ -48,12 +48,12 @@ func SetCardStatus(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update card
|
// update card
|
||||||
card.Status = status
|
|
||||||
card.DataRevision += 1
|
card.DataRevision += 1
|
||||||
if token != "" {
|
if token != "" {
|
||||||
card.OutToken = token
|
card.OutToken = token
|
||||||
}
|
}
|
||||||
if status == APP_CARDCONNECTING {
|
if status == APP_CARDCONNECTING {
|
||||||
|
if card.Status != APP_CARDCONNECTING && card.Status != APP_CARDCONNECTED {
|
||||||
data, err := securerandom.Bytes(32)
|
data, err := securerandom.Bytes(32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ErrResponse(w, http.StatusInternalServerError, err)
|
ErrResponse(w, http.StatusInternalServerError, err)
|
||||||
@ -61,6 +61,8 @@ func SetCardStatus(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
card.InToken = hex.EncodeToString(data)
|
card.InToken = hex.EncodeToString(data)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
card.Status = status
|
||||||
|
|
||||||
// save and update contact revision
|
// save and update contact revision
|
||||||
err = store.DB.Transaction(func(tx *gorm.DB) error {
|
err = store.DB.Transaction(func(tx *gorm.DB) error {
|
||||||
|
@ -2,13 +2,48 @@ package databag
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"databag/internal/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetContentRevision(w http.ResponseWriter, r *http.Request) {
|
func SetContentRevision(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
card, code, err := BearerContactToken(r)
|
||||||
|
if err != nil {
|
||||||
|
ErrResponse(w, code, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var revision int64
|
||||||
|
if err := ParseRequest(r, w, &revision); err != nil {
|
||||||
|
ErrResponse(w, http.StatusBadRequest, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := NotifyProfileRevision(card, revision); err != nil {
|
||||||
|
ErrResponse(w, http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteResponse(w, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NotifyContentRevision(token string, revision int64) error {
|
func NotifyContentRevision(card *store.Card, revision int64) error {
|
||||||
|
|
||||||
|
act := &card.Account
|
||||||
|
err := store.DB.Transaction(func(tx *gorm.DB) error {
|
||||||
|
if res := tx.Model(card).Where("id = ?", card.ID).Update("remote_content", revision).Error; res != nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
if res := tx.Model(act).Where("id = ?", act.ID).Update("card_revision", act.CardRevision+1).Error; res != nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
SetStatus(act)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,14 +2,49 @@ package databag
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"databag/internal/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetProfileRevision(w http.ResponseWriter, r *http.Request) {
|
func SetProfileRevision(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
card, code, err := BearerContactToken(r)
|
||||||
|
if err != nil {
|
||||||
|
ErrResponse(w, code, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var revision int64
|
||||||
|
if err := ParseRequest(r, w, &revision); err != nil {
|
||||||
|
ErrResponse(w, http.StatusBadRequest, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := NotifyProfileRevision(card, revision); err != nil {
|
||||||
|
ErrResponse(w, http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteResponse(w, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NotifyProfileRevision(token string, revision int64) error {
|
func NotifyProfileRevision(card *store.Card, revision int64) error {
|
||||||
|
|
||||||
|
card.RemoteProfile = revision
|
||||||
|
act := &card.Account
|
||||||
|
err := store.DB.Transaction(func(tx *gorm.DB) error {
|
||||||
|
if res := tx.Model(card).Where("id = ?", card.ID).Update("remote_profile", revision).Error; res != nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
if res := tx.Model(act).Where("id = ?", act.ID).Update("card_revision", act.CardRevision+1).Error; res != nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
SetStatus(act)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,6 +114,28 @@ func BearerAppToken(r *http.Request, detail bool) (*store.Account, int, error) {
|
|||||||
return &app.Account, http.StatusOK, nil
|
return &app.Account, http.StatusOK, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BearerContactToken(r *http.Request) (*store.Card, int, error) {
|
||||||
|
|
||||||
|
// parse bearer authentication
|
||||||
|
auth := r.Header.Get("Authorization")
|
||||||
|
token := strings.TrimSpace(strings.TrimPrefix(auth, "Bearer"))
|
||||||
|
|
||||||
|
// find token record
|
||||||
|
var card store.Card
|
||||||
|
if err := store.DB.Preload("Account").Where("InToken = ?", token).First(&card).Error; err != nil {
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return nil, http.StatusNotFound, err
|
||||||
|
} else {
|
||||||
|
return nil, http.StatusInternalServerError, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if card.Account.Disabled {
|
||||||
|
return nil, http.StatusGone, errors.New("account is inactive")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &card, http.StatusOK, nil
|
||||||
|
}
|
||||||
|
|
||||||
func BasicCredentials(r *http.Request) (string, []byte, error) {
|
func BasicCredentials(r *http.Request) (string, []byte, error) {
|
||||||
|
|
||||||
var username string
|
var username string
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package databag
|
package databag
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"databag/internal/store"
|
"databag/internal/store"
|
||||||
)
|
)
|
||||||
@ -43,12 +44,24 @@ func SendNotifications() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SendLocalNotification(notification *store.Notification) {
|
func SendLocalNotification(notification *store.Notification) {
|
||||||
|
|
||||||
|
// pull reference account
|
||||||
|
var card store.Card
|
||||||
|
if err := store.DB.Preload("Account").Where("in_token = ?", notification.Token).First(&card).Error; err != nil {
|
||||||
|
ErrMsg(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if card.Account.Disabled {
|
||||||
|
ErrMsg(errors.New("account is inactive"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if notification.Module == APP_MODULEPROFILE {
|
if notification.Module == APP_MODULEPROFILE {
|
||||||
if err := NotifyProfileRevision(notification.Token, notification.Revision); err != nil {
|
if err := NotifyProfileRevision(&card, notification.Revision); err != nil {
|
||||||
ErrMsg(err)
|
ErrMsg(err)
|
||||||
}
|
}
|
||||||
} else if notification.Module == APP_MODULECONTENT {
|
} else if notification.Module == APP_MODULECONTENT {
|
||||||
if err := NotifyContentRevision(notification.Token, notification.Revision); err != nil {
|
if err := NotifyContentRevision(&card, notification.Revision); err != nil {
|
||||||
ErrMsg(err)
|
ErrMsg(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2,30 +2,65 @@ package databag
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestProfileNotification(t *testing.T) {
|
func TestProfileNotification(t *testing.T) {
|
||||||
|
var views []CardView
|
||||||
|
var revision Revision
|
||||||
|
var data []byte
|
||||||
|
|
||||||
// start notifcation thread
|
// start notifcation thread
|
||||||
go SendNotifications()
|
go SendNotifications()
|
||||||
|
|
||||||
|
// connect contacts
|
||||||
access := AddTestContacts(t, "profilenotification", 2);
|
access := AddTestContacts(t, "profilenotification", 2);
|
||||||
contact := ConnectTestContacts(t, access[0], access[1])
|
ConnectTestContacts(t, access[0], access[1])
|
||||||
|
|
||||||
PrintMsg(access)
|
// get views list of cards
|
||||||
PrintMsg(contact)
|
r, w, _ := NewRequest("GET", "/contact/cards/view", nil)
|
||||||
|
SetBearerAuth(r, access[0])
|
||||||
|
GetCardView(w, r)
|
||||||
|
assert.NoError(t, ReadResponse(w, &views))
|
||||||
|
assert.Equal(t, len(views), 1)
|
||||||
|
profileRevision := views[0].RemoteProfile
|
||||||
|
|
||||||
// connect revision websocket for A
|
// app connects websocket
|
||||||
|
ws := getTestWebsocket()
|
||||||
|
announce := Announce{ AppToken: access[0] }
|
||||||
|
data, _ = json.Marshal(&announce)
|
||||||
|
ws.WriteMessage(websocket.TextMessage, data)
|
||||||
|
|
||||||
// get profile revision of B
|
// receive revision
|
||||||
|
_, data, _ = ws.ReadMessage()
|
||||||
|
assert.NoError(t, json.Unmarshal(data, &revision))
|
||||||
|
cardRevision := revision.Card
|
||||||
|
|
||||||
// update profile of B
|
// update B profile
|
||||||
|
profileData := ProfileData{
|
||||||
|
Name: "Namer",
|
||||||
|
Location: "San Francisco",
|
||||||
|
Description: "databaggerr",
|
||||||
|
};
|
||||||
|
r, w, _ = NewRequest("PUT", "/profile/data", &profileData)
|
||||||
|
SetBearerAuth(r, access[1])
|
||||||
|
SetProfile(w, r)
|
||||||
|
assert.NoError(t, ReadResponse(w, nil))
|
||||||
|
|
||||||
// read revision message
|
// receive revision
|
||||||
|
_, data, _ = ws.ReadMessage()
|
||||||
|
assert.NoError(t, json.Unmarshal(data, &revision))
|
||||||
|
assert.NotEqual(t, cardRevision, revision.Card)
|
||||||
|
|
||||||
// check card increment
|
// get views list of cards
|
||||||
|
r, w, _ = NewRequest("GET", "/contact/cards/view", nil)
|
||||||
// check B profile incremented
|
SetBearerAuth(r, access[0])
|
||||||
|
GetCardView(w, r)
|
||||||
|
assert.NoError(t, ReadResponse(w, &views))
|
||||||
|
assert.Equal(t, len(views), 1)
|
||||||
|
assert.NotEqual(t, profileRevision, views[0].RemoteProfile)
|
||||||
|
|
||||||
// stop notification thread
|
// stop notification thread
|
||||||
ExitNotifications()
|
ExitNotifications()
|
||||||
|
Loading…
Reference in New Issue
Block a user