restructuring card with slots

This commit is contained in:
Roland Osborne 2022-02-02 22:13:46 -08:00
parent 84285194a7
commit 9d1f407653
14 changed files with 334 additions and 180 deletions

View File

@ -47,11 +47,11 @@ func AddArticle(w http.ResponseWriter, r *http.Request) {
Groups: groups, Groups: groups,
Labels: labels, Labels: labels,
}; };
if res := store.DB.Save(article).Error; res != nil { if res := tx.Save(article).Error; res != nil {
return res; return res;
} }
if res := store.DB.Where("article_id = 0 AND account_id = ?", account.ID).First(&slot).Error; res != nil { if res := tx.Where("article_id = 0 AND account_id = ?", account.ID).First(&slot).Error; res != nil {
if errors.Is(res, gorm.ErrRecordNotFound) { if errors.Is(res, gorm.ErrRecordNotFound) {
slot = &store.ArticleSlot{ slot = &store.ArticleSlot{
ArticleSlotId: uuid.New().String(), ArticleSlotId: uuid.New().String(),
@ -60,17 +60,17 @@ func AddArticle(w http.ResponseWriter, r *http.Request) {
ArticleID: article.ID, ArticleID: article.ID,
Article: article, Article: article,
} }
if ret := store.DB.Save(slot).Error; ret != nil { if ret := tx.Save(slot).Error; ret != nil {
return ret; return ret;
} }
} else { } else {
return res return res
} }
} }
if ret := store.DB.Model(slot).Update("article_id", article.ID).Error; ret != nil { if ret := tx.Model(slot).Update("article_id", article.ID).Error; ret != nil {
return ret; return ret;
} }
if ret := store.DB.Preload("Article.Labels.Groups").Where("id = ?", article.ID).First(slot).Error; ret != nil { if ret := tx.Preload("Article.Labels.Groups").Where("id = ?", article.ID).First(slot).Error; ret != nil {
return ret; return ret;
} }
if ret := tx.Model(&account).Update("content_revision", account.ContentRevision + 1).Error; ret != nil { if ret := tx.Model(&account).Update("content_revision", account.ContentRevision + 1).Error; ret != nil {

View File

@ -31,68 +31,134 @@ func AddCard(w http.ResponseWriter, r *http.Request) {
return return
} }
slot := &store.CardSlot{}
var card store.Card var card store.Card
if err := store.DB.Preload("Groups").Where("account_id = ? AND guid = ?", account.ID, guid).First(&card).Error; err != nil { if err := store.DB.Preload("Card.Groups").Where("account_id = ? AND guid = ?", account.ID, guid).First(&card).Error; err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) { if !errors.Is(err, gorm.ErrRecordNotFound) {
ErrResponse(w, http.StatusInternalServerError, err) ErrResponse(w, http.StatusInternalServerError, err)
return return
} }
// populate new record // create new card data
card.CardId = uuid.New().String()
card.AccountID = account.Guid
card.Guid = guid
card.Username = identity.Handle
card.Name = identity.Name
card.Description = identity.Description
card.Location = identity.Location
card.Image = identity.Image
card.Version = identity.Version
card.Node = identity.Node
card.ProfileRevision = identity.Revision
card.Status = APP_CARDCONFIRMED
card.ViewRevision = 0
data, res := securerandom.Bytes(APP_TOKENSIZE) data, res := securerandom.Bytes(APP_TOKENSIZE)
if res != nil { if res != nil {
ErrResponse(w, http.StatusInternalServerError, res) ErrResponse(w, http.StatusInternalServerError, err)
return return
} }
card.InToken = hex.EncodeToString(data) card := &store.Card{
Guid: guid,
Username: identity.Handle,
Name: identity.Name,
Description: identity.Description,
Location: identity.Location,
Image: identity.Image,
Version: identity.Version,
Node: identity.Node,
ProfileRevision: identity.Revision,
Status: APP_CARDCONFIRMED,
ViewRevision: 0,
InToken: hex.EncodeToString(data),
AccountID: account.Guid,
}
// create new card or update existing
if err = store.DB.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
}
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
}
} 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
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
}
}
} else { } else {
if identity.Revision <= card.ProfileRevision { if identity.Revision > card.ProfileRevision {
WriteResponse(w, getCardModel(&card))
return
}
// update record if revision changed // update card data
card.Username = identity.Handle card.Username = identity.Handle
card.Name = identity.Name card.Name = identity.Name
card.Description = identity.Description card.Description = identity.Description
card.Location = identity.Location card.Location = identity.Location
card.Image = identity.Image card.Image = identity.Image
card.Version = identity.Version card.Version = identity.Version
card.Node = identity.Node card.Node = identity.Node
card.ProfileRevision = identity.Revision card.ProfileRevision = identity.Revision
// save contact card
err = store.DB.Transaction(func(tx *gorm.DB) error {
if res := tx.Save(&card).Error; res != nil {
return res
}
if res := store.DB.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
}
if res := tx.Preload("Card").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
})
}
} }
// save contact card
err = store.DB.Transaction(func(tx *gorm.DB) error {
if res := tx.Save(&card).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 { if err != nil {
ErrResponse(w, http.StatusInternalServerError, err) ErrResponse(w, http.StatusInternalServerError, err)
return return
} }
SetStatus(account) SetStatus(account)
WriteResponse(w, getCardModel(&card)) WriteResponse(w, getCardModel(slot))
} }

View File

@ -17,8 +17,8 @@ func GetCard(w http.ResponseWriter, r *http.Request) {
} }
cardId := mux.Vars(r)["cardId"] cardId := mux.Vars(r)["cardId"]
var card store.Card var slot store.CardSlot
if err := store.DB.Preload("Groups").Where("account_id = ? AND card_id = ?", account.Guid, cardId).First(&card).Error; err != nil { if err := store.DB.Preload("Card.Groups").Where("account_id = ? AND card_slot_id = ?", account.ID, cardId).First(&slot).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
ErrResponse(w, http.StatusNotFound, err) ErrResponse(w, http.StatusNotFound, err)
} else { } else {
@ -27,6 +27,6 @@ func GetCard(w http.ResponseWriter, r *http.Request) {
return return
} }
WriteResponse(w, getCardModel(&card)) WriteResponse(w, getCardModel(&slot))
} }

View File

@ -13,11 +13,15 @@ func GetCards(w http.ResponseWriter, r *http.Request) {
return return
} }
var cards []store.Card var slots []store.CardSlot
if err := store.DB.Where("account_id = ?", account.Guid).Find(&cards).Error; err != nil { if err := store.DB.Preload("Card").Where("account_id = ?", account.ID).Find(&slots).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err) ErrResponse(w, http.StatusInternalServerError, err)
return return
} }
WriteResponse(w, &cards) var response []*Card
for _, slot := range slots {
response = append(response, getCardModel(&slot))
}
WriteResponse(w, response)
} }

View File

@ -18,8 +18,8 @@ func GetOpenMessage(w http.ResponseWriter, r *http.Request) {
detail := account.AccountDetail detail := account.AccountDetail
cardId := mux.Vars(r)["cardId"] cardId := mux.Vars(r)["cardId"]
var card store.Card var slot store.CardSlot
if err := store.DB.Where("account_id = ? AND card_id = ?", account.Guid, cardId).First(&card).Error; err != nil { if err := store.DB.Preload("Card").Where("account_id = ? AND card_slot_id = ?", account.ID, cardId).First(&slot).Error; err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) { if !errors.Is(err, gorm.ErrRecordNotFound) {
ErrResponse(w, http.StatusInternalServerError, err) ErrResponse(w, http.StatusInternalServerError, err)
} else { } else {
@ -27,16 +27,20 @@ func GetOpenMessage(w http.ResponseWriter, r *http.Request) {
} }
return return
} }
if slot.Card == nil {
ErrResponse(w, http.StatusNotFound, errors.New("card has been deleted"))
return
}
if card.Status != APP_CARDCONNECTING && card.Status != APP_CARDCONNECTED { if slot.Card.Status != APP_CARDCONNECTING && slot.Card.Status != APP_CARDCONNECTED {
ErrResponse(w, http.StatusMethodNotAllowed, errors.New("invalid card state")) ErrResponse(w, http.StatusMethodNotAllowed, errors.New("invalid card state"))
return return
} }
connect := &Connect{ connect := &Connect{
Contact: card.Guid, Contact: slot.Card.Guid,
Token: card.InToken, Token: slot.Card.InToken,
ContentRevision: account.ContentRevision + account.ViewRevision + card.ViewRevision, ContentRevision: account.ContentRevision + account.ViewRevision + slot.Card.ViewRevision,
ProfileRevision: account.ProfileRevision, ProfileRevision: account.ProfileRevision,
Handle: account.Username, Handle: account.Username,
Name: detail.Name, Name: detail.Name,

View File

@ -20,17 +20,20 @@ func SetCardGroup(w http.ResponseWriter, r *http.Request) {
cardId := params["cardId"] cardId := params["cardId"]
groupId := params["groupId"] groupId := params["groupId"]
// load referenced card // load referenced card
var card store.Card var slot store.CardSlot
if err := store.DB.Where("account_id = ? AND card_id = ?", account.Guid, cardId).First(&card).Error; err != nil { if err := store.DB.Preload("Card").Where("account_id = ? AND card_slot_id = ?", account.ID, cardId).First(&slot).Error; err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
ErrResponse(w, http.StatusInternalServerError, err)
} else {
ErrResponse(w, http.StatusNotFound, err) ErrResponse(w, http.StatusNotFound, err)
} else {
ErrResponse(w, http.StatusInternalServerError, err)
} }
return return
} }
if slot.Card == nil {
ErrResponse(w, http.StatusNotFound, errors.New("card has been deleted"))
return
}
// load referenced group // load referenced group
var group store.Group var group store.Group
@ -44,14 +47,17 @@ func SetCardGroup(w http.ResponseWriter, r *http.Request) {
} }
// save and update revision // save and update revision
card.Groups = append(card.Groups, group) slot.Card.Groups = append(slot.Card.Groups, group)
card.ViewRevision += 1 slot.Card.ViewRevision += 1
card.DataRevision += 1 slot.Revision = account.CardRevision + 1
err = store.DB.Transaction(func(tx *gorm.DB) error { err = store.DB.Transaction(func(tx *gorm.DB) error {
if res := tx.Model(&account).Update("card_revision", account.CardRevision + 1).Error; res != nil { if res := tx.Model(&account).Update("card_revision", account.CardRevision + 1).Error; res != nil {
return res return res
} }
if res := tx.Preload("Groups").Save(&card).Error; res != nil { if res := tx.Save(&slot.Card).Error; res != nil {
return res
}
if res := tx.Preload("CardData.Groups").Save(&slot).Error; res != nil {
return res return res
} }
return nil return nil
@ -61,18 +67,9 @@ func SetCardGroup(w http.ResponseWriter, r *http.Request) {
return return
} }
cardData := &CardData{ SetContactViewNotification(account, slot.Card)
Revision: card.DataRevision,
Status: card.Status,
Notes: card.Notes,
Token: card.OutToken,
}
for _, group := range card.Groups {
cardData.Groups = append(cardData.Groups, group.GroupId)
}
SetContactViewNotification(account, &card)
SetStatus(account) SetStatus(account)
WriteResponse(w, cardData) WriteResponse(w, getCardModel(&slot))
} }

View File

@ -38,8 +38,8 @@ func SetCardStatus(w http.ResponseWriter, r *http.Request) {
} }
// load referenced card // load referenced card
var card store.Card var slot store.CardSlot
if err := store.DB.Preload("Groups").Where("account_id = ? AND card_id = ?", account.Guid, cardId).First(&card).Error; err != nil { if err := store.DB.Preload("Card.Groups").Where("account_id = ? AND card_slot_id = ?", account.ID, cardId).First(&slot).Error; err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) { if !errors.Is(err, gorm.ErrRecordNotFound) {
ErrResponse(w, http.StatusInternalServerError, err) ErrResponse(w, http.StatusInternalServerError, err)
} else { } else {
@ -47,27 +47,34 @@ func SetCardStatus(w http.ResponseWriter, r *http.Request) {
} }
return return
} }
if slot.Card == nil {
ErrResponse(w, http.StatusNotFound, errors.New("card has been deleted"))
return
}
// update card // update card
card.DataRevision += 1 slot.Revision = account.CardRevision + 1
if token != "" { if token != "" {
card.OutToken = token slot.Card.OutToken = token
} }
if status == APP_CARDCONNECTING { if status == APP_CARDCONNECTING {
if card.Status != APP_CARDCONNECTING && card.Status != APP_CARDCONNECTED { if slot.Card.Status != APP_CARDCONNECTING && slot.Card.Status != APP_CARDCONNECTED {
data, err := securerandom.Bytes(APP_TOKENSIZE) data, err := securerandom.Bytes(APP_TOKENSIZE)
if err != nil { if err != nil {
ErrResponse(w, http.StatusInternalServerError, err) ErrResponse(w, http.StatusInternalServerError, err)
return return
} }
card.InToken = hex.EncodeToString(data) slot.Card.InToken = hex.EncodeToString(data)
} }
} }
card.Status = status slot.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 {
if res := tx.Save(&card).Error; res != nil { if res := tx.Save(&slot.Card).Error; res != nil {
return res
}
if res := tx.Preload("Card").Save(&slot).Error; res != nil {
return res return res
} }
if res := tx.Model(&account).Update("card_revision", account.CardRevision + 1).Error; res != nil { if res := tx.Model(&account).Update("card_revision", account.CardRevision + 1).Error; res != nil {
@ -81,6 +88,6 @@ func SetCardStatus(w http.ResponseWriter, r *http.Request) {
} }
SetStatus(account) SetStatus(account)
WriteResponse(w, getCardModel(&card)); WriteResponse(w, getCardModel(&slot));
} }

View File

@ -42,16 +42,20 @@ func SetOpenMessage(w http.ResponseWriter, r *http.Request) {
} }
// see if card exists // see if card exists
var card store.Card slot := &store.CardSlot{}
if err := store.DB.Where("account_id = ? AND guid = ?", account.Guid, guid).First(&card).Error; err != nil { card := &store.Card{}
if err := store.DB.Where("account_id = ? AND guid = ?", account.Guid, guid).First(card).Error; err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) { if !errors.Is(err, gorm.ErrRecordNotFound) {
ErrResponse(w, http.StatusInternalServerError, err) ErrResponse(w, http.StatusInternalServerError, err)
return return
} }
// populate new record // create new card
card.CardId = uuid.New().String() data, res := securerandom.Bytes(APP_TOKENSIZE)
card.AccountID = account.Guid if res != nil {
ErrResponse(w, http.StatusInternalServerError, res)
return
}
card.Guid = guid card.Guid = guid
card.Username = connect.Handle card.Username = connect.Handle
card.Name = connect.Name card.Name = connect.Name
@ -61,18 +65,61 @@ func SetOpenMessage(w http.ResponseWriter, r *http.Request) {
card.Version = connect.Version card.Version = connect.Version
card.Node = connect.Node card.Node = connect.Node
card.ProfileRevision = connect.ProfileRevision card.ProfileRevision = connect.ProfileRevision
card.Status = APP_CARDPENDING
card.NotifiedProfile = connect.ProfileRevision card.NotifiedProfile = connect.ProfileRevision
card.NotifiedContent = connect.ContentRevision card.NotifiedContent = connect.ContentRevision
card.NotifiedView = connect.ViewRevision card.NotifiedView = connect.ViewRevision
card.Status = APP_CARDPENDING
card.DataRevision = 1
card.OutToken = connect.Token card.OutToken = connect.Token
data, res := securerandom.Bytes(APP_TOKENSIZE)
if res != nil {
ErrResponse(w, http.StatusInternalServerError, res)
return
}
card.InToken = hex.EncodeToString(data) 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
}
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
}
} 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
}
}
} else { } else {
@ -105,26 +152,42 @@ func SetOpenMessage(w http.ResponseWriter, r *http.Request) {
card.DataRevision += 1 card.DataRevision += 1
card.OutToken = connect.Token card.OutToken = connect.Token
} // save contact card
err = store.DB.Transaction(func(tx *gorm.DB) error {
// save contact card if res := tx.Save(&card).Error; res != nil {
err = store.DB.Transaction(func(tx *gorm.DB) error { return res
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
}
if res := tx.Preload("Card").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
} }
status := &ContactStatus{ status := &ContactStatus{
Token: card.InToken, Token: slot.Card.InToken,
Status: card.Status, Status: slot.Card.Status,
} }
SetStatus(&account) SetStatus(&account)
WriteResponse(w, &status) WriteResponse(w, &status)

View File

@ -4,35 +4,40 @@ import (
"databag/internal/store" "databag/internal/store"
) )
func getCardModel(card *store.Card) *Card { func getCardModel(slot *store.CardSlot) *Card {
if slot.Card == nil {
return &Card{
CardId: slot.CardSlotId,
}
}
// populate group id list // populate group id list
var groups []string; var groups []string;
for _, group := range card.Groups { for _, group := range slot.Card.Groups {
groups = append(groups, group.GroupId) groups = append(groups, group.GroupId)
} }
return &Card{ return &Card{
CardId: card.CardId, CardId: slot.CardSlotId,
NotifiedProfile: card.NotifiedProfile, CardData: &CardData {
NotifiedContent: card.NotifiedContent, NotifiedProfile: slot.Card.NotifiedProfile,
NotifiedView: card.NotifiedView, NotifiedContent: slot.Card.NotifiedContent,
CardProfile: &CardProfile{ NotifiedView: slot.Card.NotifiedView,
Guid: card.Guid, CardProfile: &CardProfile{
Handle: card.Username, Guid: slot.Card.Guid,
Name: card.Name, Handle: slot.Card.Username,
Description: card.Description, Name: slot.Card.Name,
Location: card.Location, Description: slot.Card.Description,
Revision: card.ProfileRevision, Location: slot.Card.Location,
ImageSet: card.Image != "", Revision: slot.Card.ProfileRevision,
Version: card.Version, ImageSet: slot.Card.Image != "",
Node: card.Node, Version: slot.Card.Version,
}, Node: slot.Card.Node,
CardData: &CardData { },
Revision: card.DataRevision, Status: slot.Card.Status,
Status: card.Status, Notes: slot.Card.Notes,
Notes: card.Notes, Token: slot.Card.OutToken,
Token: card.OutToken,
Groups: groups, Groups: groups,
}, },
} }
@ -55,35 +60,34 @@ func getArticleModel(slot *store.ArticleSlot, contact bool, shared bool) *Articl
return &Article{ return &Article{
ArticleId: slot.ArticleSlotId, ArticleId: slot.ArticleSlotId,
} }
} else { }
var groups []string; var groups []string;
if !contact { if !contact {
for _, group := range slot.Article.Groups { for _, group := range slot.Article.Groups {
groups = append(groups, group.GroupId) groups = append(groups, group.GroupId)
}
} }
}
var labels []string; var labels []string;
for _, label := range slot.Article.Labels { for _, label := range slot.Article.Labels {
labels = append(labels, label.LabelId) labels = append(labels, label.LabelId)
} }
return &Article{ return &Article{
ArticleId: slot.ArticleSlotId, ArticleId: slot.ArticleSlotId,
ArticleData: &ArticleData{ ArticleData: &ArticleData{
DataType: slot.Article.DataType, DataType: slot.Article.DataType,
Data: slot.Article.Data, Data: slot.Article.Data,
Status: slot.Article.Status, Status: slot.Article.Status,
Labels: labels, Labels: labels,
Groups: groups, Groups: groups,
TagCount: slot.Article.TagCount, TagCount: slot.Article.TagCount,
Created: slot.Article.Created, Created: slot.Article.Created,
Updated: slot.Article.Updated, Updated: slot.Article.Updated,
TagUpdated: slot.Article.TagUpdated, TagUpdated: slot.Article.TagUpdated,
TagRevision: slot.Article.TagRevision, TagRevision: slot.Article.TagRevision,
}, },
}
} }
} }

View File

@ -83,15 +83,15 @@ type Asset struct {
type Card struct { type Card struct {
CardId string `json:"cardId"` CardId string `json:"cardId"`
CardData *CardData `json:"cardData"`
}
type CardData struct {
CardProfile *CardProfile `json:"cardProfile"` CardProfile *CardProfile `json:"cardProfile"`
CardData *CardData `json:"cardData"` CardData *CardData `json:"cardData"`
NotifiedProfile int64 `json:"notifiedProfile"` NotifiedProfile int64 `json:"notifiedProfile"`
NotifiedContent int64 `json:"notifiedContent"` NotifiedContent int64 `json:"notifiedContent"`
NotifiedView int64 `json:"notifiedView"` NotifiedView int64 `json:"notifiedView"`
}
type CardData struct {
Revision int64 `json:"revision,omitempty"`
Status string `json:"status"` Status string `json:"status"`
Notes string `json:"notes,omitempty"` Notes string `json:"notes,omitempty"`
Token string `json:"token,omitempty"` Token string `json:"token,omitempty"`

View File

@ -10,6 +10,7 @@ func AutoMigrate(db *gorm.DB) {
db.AutoMigrate(&AccountToken{}); db.AutoMigrate(&AccountToken{});
db.AutoMigrate(&Group{}); db.AutoMigrate(&Group{});
db.AutoMigrate(&Label{}); db.AutoMigrate(&Label{});
db.AutoMigrate(&CardSlot{});
db.AutoMigrate(&Card{}); db.AutoMigrate(&Card{});
db.AutoMigrate(&Asset{}); db.AutoMigrate(&Asset{});
db.AutoMigrate(&ArticleSlot{}); db.AutoMigrate(&ArticleSlot{});
@ -135,10 +136,19 @@ type LabelData struct {
Data string Data string
} }
type CardSlot struct {
ID uint `gorm:"primaryKey;not null;unique;autoIncrement"`
CardSlotId string `gorm:"not null;index:cardslot,unique"`
AccountID uint `gorm:"not null;index:cardslot,unique"`
Revision int64 `gorm:"not null"`
CardID uint `gorm:"not null;default:0"`
Card *Card
Account Account
}
type Card struct { type Card struct {
ID uint `gorm:"primaryKey;not null;unique;autoIncrement"` ID uint `gorm:"primaryKey;not null;unique;autoIncrement"`
CardId string `gorm:"not null;index:card,unique"` AccountID string `gorm:"not null;index:cardguid,unique"`
AccountID string `gorm:"not null;index:card,unique"`
Guid string `gorm:"not null;index:cardguid,unique"` Guid string `gorm:"not null;index:cardguid,unique"`
Username string Username string
Name string Name string

View File

@ -300,7 +300,7 @@ func GetCardToken(account string, cardId string) (token string, err error) {
err = errors.New("card not connected") err = errors.New("card not connected")
return return
} }
token = card.CardProfile.Guid + "." + card.CardData.Token token = card.CardData.CardProfile.Guid + "." + card.CardData.Token
return return
} }

View File

@ -15,7 +15,6 @@ func TestGroupContact(t *testing.T) {
var cardRevision int64 var cardRevision int64
var revision Revision var revision Revision
var vars map[string]string var vars map[string]string
var cardData CardData
var contactRevision int64 var contactRevision int64
var card Card var card Card
var contactViewRevision int64 var contactViewRevision int64
@ -62,18 +61,18 @@ func TestGroupContact(t *testing.T) {
SetBearerAuth(r, b) SetBearerAuth(r, b)
GetCard(w, r) GetCard(w, r)
assert.NoError(t, ReadResponse(w, &card)) assert.NoError(t, ReadResponse(w, &card))
contactViewRevision = card.NotifiedView contactViewRevision = card.CardData.NotifiedView
// set contact group // set contact group
r, w, _ = NewRequest("PUT", "/contact/cards/{cardId}/groups/{groupId}", nil) r, w, _ = NewRequest("PUT", "/contact/cards/{cardId}/groups/{groupId}", nil)
vars = make(map[string]string) vars = make(map[string]string)
vars["groupId"] = group.GroupId vars["groupId"] = group.GroupId
vars["cardId"] = aCard vars["cardId"] = aCard
r = mux.SetURLVars(r, vars) r = mux.SetURLVars(r, vars)
SetBearerAuth(r, a) SetBearerAuth(r, a)
SetCardGroup(w, r) SetCardGroup(w, r)
assert.NoError(t, ReadResponse(w, &cardData)) assert.NoError(t, ReadResponse(w, &card))
assert.Equal(t, 1, len(cardData.Groups)) assert.Equal(t, 1, len(card.CardData.Groups))
// get contact revision // get contact revision
r, w, _ = NewRequest("GET", "/contact/cards/{cardId}", nil) r, w, _ = NewRequest("GET", "/contact/cards/{cardId}", nil)
@ -102,8 +101,8 @@ func TestGroupContact(t *testing.T) {
SetBearerAuth(r, b) SetBearerAuth(r, b)
GetCard(w, r) GetCard(w, r)
assert.NoError(t, ReadResponse(w, &card)) assert.NoError(t, ReadResponse(w, &card))
assert.NotEqual(t, contactViewRevision, card.NotifiedView) assert.NotEqual(t, contactViewRevision, card.CardData.NotifiedView)
contactViewRevision = card.NotifiedView contactViewRevision = card.CardData.NotifiedView
// show group view // show group view
r, w, _ = NewRequest("GET", "/share/groups", nil) r, w, _ = NewRequest("GET", "/share/groups", nil)
@ -166,7 +165,7 @@ func TestGroupContact(t *testing.T) {
SetBearerAuth(r, b) SetBearerAuth(r, b)
GetCard(w, r) GetCard(w, r)
assert.NoError(t, ReadResponse(w, &card)) assert.NoError(t, ReadResponse(w, &card))
assert.NotEqual(t, contactViewRevision, card.NotifiedView) assert.NotEqual(t, contactViewRevision, card.CardData.NotifiedView)
// show group view // show group view
r, w, _ = NewRequest("GET", "/share/groups", nil) r, w, _ = NewRequest("GET", "/share/groups", nil)

View File

@ -26,7 +26,7 @@ func TestProfileNotification(t *testing.T) {
GetCards(w, r) GetCards(w, r)
assert.NoError(t, ReadResponse(w, &cards)) assert.NoError(t, ReadResponse(w, &cards))
assert.Equal(t, len(cards), 1) assert.Equal(t, len(cards), 1)
profileRevision := cards[0].NotifiedProfile profileRevision := cards[0].CardData.NotifiedProfile
// app connects websocket // app connects websocket
ws, err = StatusConnection(a, &revision); ws, err = StatusConnection(a, &revision);
@ -55,5 +55,5 @@ func TestProfileNotification(t *testing.T) {
GetCards(w, r) GetCards(w, r)
assert.NoError(t, ReadResponse(w, &cards)) assert.NoError(t, ReadResponse(w, &cards))
assert.Equal(t, len(cards), 1) assert.Equal(t, len(cards), 1)
assert.NotEqual(t, profileRevision, cards[0].NotifiedProfile) assert.NotEqual(t, profileRevision, cards[0].CardData.NotifiedProfile)
} }