mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
test channel sharing
This commit is contained in:
parent
ae2435e915
commit
c851320749
@ -48,11 +48,6 @@ func GetChannelAssets(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func GetChannelDetail(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func GetChannelSize(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
@ -113,11 +108,6 @@ func RemoveChannelTopicTag(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func SetChannelCard(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func SetChannelConfirmed(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
@ -19,6 +19,7 @@ func GetArticleSubjectField(w http.ResponseWriter, r *http.Request) {
|
||||
field := params["field"]
|
||||
elements := strings.Split(field, ".")
|
||||
|
||||
var guid string
|
||||
var act *store.Account
|
||||
tokenType := r.Header.Get("TokenType")
|
||||
if tokenType == APP_TOKENAPP {
|
||||
@ -35,6 +36,7 @@ func GetArticleSubjectField(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
act = &card.Account
|
||||
guid = card.Guid
|
||||
} else {
|
||||
ErrResponse(w, http.StatusBadRequest, errors.New("unknown token type"))
|
||||
return
|
||||
@ -42,7 +44,7 @@ func GetArticleSubjectField(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// load article
|
||||
var slot store.ArticleSlot
|
||||
if err := store.DB.Preload("Article").Where("account_id = ? AND article_slot_id = ?", act.ID, articleId).First(&slot).Error; err != nil {
|
||||
if err := store.DB.Preload("Article.Groups.Cards").Where("account_id = ? AND article_slot_id = ?", act.ID, articleId).First(&slot).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
ErrResponse(w, http.StatusNotFound, err)
|
||||
} else {
|
||||
@ -55,6 +57,12 @@ func GetArticleSubjectField(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// check if article is shared
|
||||
if tokenType == APP_TOKENCONTACT && !isArticleShared(guid, slot.Article) {
|
||||
ErrResponse(w, http.StatusNotFound, errors.New("referenced article not shared"))
|
||||
return
|
||||
}
|
||||
|
||||
// decode data
|
||||
strData := fastjson.GetString([]byte(slot.Article.Data), elements...)
|
||||
binData, err := base64.StdEncoding.DecodeString(strData)
|
||||
|
66
net/server/internal/api_getChannel.go
Normal file
66
net/server/internal/api_getChannel.go
Normal file
@ -0,0 +1,66 @@
|
||||
package databag
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"gorm.io/gorm"
|
||||
"github.com/gorilla/mux"
|
||||
"databag/internal/store"
|
||||
)
|
||||
|
||||
func GetChannel(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// scan parameters
|
||||
params := mux.Vars(r)
|
||||
channelId := params["channelId"]
|
||||
|
||||
var guid string
|
||||
var act *store.Account
|
||||
tokenType := r.Header.Get("TokenType")
|
||||
if tokenType == APP_TOKENAPP {
|
||||
account, code, err := BearerAppToken(r, false);
|
||||
if err != nil {
|
||||
ErrResponse(w, code, err)
|
||||
return
|
||||
}
|
||||
act = account
|
||||
} else if tokenType == APP_TOKENCONTACT {
|
||||
card, code, err := BearerContactToken(r, true)
|
||||
if err != nil {
|
||||
ErrResponse(w, code, err)
|
||||
return
|
||||
}
|
||||
act = &card.Account
|
||||
guid = card.Guid
|
||||
} else {
|
||||
ErrResponse(w, http.StatusBadRequest, errors.New("unknown token type"))
|
||||
return
|
||||
}
|
||||
|
||||
// load channel
|
||||
var slot store.ChannelSlot
|
||||
if err := store.DB.Preload("Channel.Cards.CardSlot").Preload("Channel.Groups.Cards").Preload("Channel.Groups.GroupSlot").Where("account_id = ? AND channel_slot_id = ?", act.ID, channelId).First(&slot).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
ErrResponse(w, http.StatusNotFound, err)
|
||||
} else {
|
||||
ErrResponse(w, http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if slot.Channel == nil {
|
||||
ErrResponse(w, http.StatusNotFound, errors.New("referenced channel missing"))
|
||||
return
|
||||
}
|
||||
|
||||
// return model data
|
||||
if guid != "" {
|
||||
if isChannelShared(guid, slot.Channel) {
|
||||
WriteResponse(w, getChannelModel(&slot, true, false))
|
||||
} else {
|
||||
WriteResponse(w, getChannelModel(&slot, false, false))
|
||||
}
|
||||
} else {
|
||||
WriteResponse(w, getChannelModel(&slot, true, true))
|
||||
}
|
||||
}
|
||||
|
@ -60,12 +60,12 @@ func GetChannels(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var slots []store.ChannelSlot
|
||||
if channelRevisionSet {
|
||||
if err := store.DB.Preload("Channel").Where("account_id = ? AND revision > ?", account.ID, channelRevision).Find(&slots).Error; err != nil {
|
||||
if err := store.DB.Preload("Channel.Cards").Preload("Channel.Groups").Where("account_id = ? AND revision > ?", account.ID, channelRevision).Find(&slots).Error; err != nil {
|
||||
ErrResponse(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if err := store.DB.Preload("Channel").Where("account_id = ? AND channel_id != 0", account.ID).Find(&slots).Error; err != nil {
|
||||
if err := store.DB.Preload("Channel.Cards").Preload("Channel.Groups").Where("account_id = ? AND channel_id != 0", account.ID).Find(&slots).Error; err != nil {
|
||||
ErrResponse(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
@ -73,9 +73,13 @@ func GetChannels(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
for _, slot := range slots {
|
||||
if !typesSet || hasChannelType(types, slot.Channel) {
|
||||
if channelRevisionSet {
|
||||
response = append(response, getChannelRevisionModel(&slot, true))
|
||||
} else if slot.Channel != nil {
|
||||
response = append(response, getChannelModel(&slot, true, true))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
w.Header().Set("Channel-Revision", strconv.FormatInt(account.ChannelRevision, 10))
|
||||
|
||||
@ -97,12 +101,12 @@ func GetChannels(w http.ResponseWriter, r *http.Request) {
|
||||
account := &card.Account
|
||||
var slots []store.ChannelSlot
|
||||
if channelRevisionSet {
|
||||
if err := store.DB.Preload("Channel.Groups.Cards").Where("account_id = ? AND revision > ?", account.ID, channelRevision).Find(&slots).Error; err != nil {
|
||||
if err := store.DB.Preload("Channel.Cards").Preload("Channel.Groups.Cards").Where("account_id = ? AND revision > ?", account.ID, channelRevision).Find(&slots).Error; err != nil {
|
||||
ErrResponse(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if err := store.DB.Preload("Channel.Groups.Cards").Where("account_id = ? AND channel_id != 0", account.ID).Find(&slots).Error; err != nil {
|
||||
if err := store.DB.Preload("Channel.Cards").Preload("Channel.Groups.Cards").Where("account_id = ? AND channel_id != 0", account.ID).Find(&slots).Error; err != nil {
|
||||
ErrResponse(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
@ -111,7 +115,11 @@ func GetChannels(w http.ResponseWriter, r *http.Request) {
|
||||
for _, slot := range slots {
|
||||
shared := isChannelShared(card.Guid, slot.Channel)
|
||||
if !typesSet || hasChannelType(types, slot.Channel) {
|
||||
response = append(response, getChannelModel(&slot, shared, false))
|
||||
if channelRevisionSet {
|
||||
response = append(response, getChannelRevisionModel(&slot, shared))
|
||||
} else if shared {
|
||||
response = append(response, getChannelModel(&slot, true, false))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
83
net/server/internal/api_setChannelCard.go
Normal file
83
net/server/internal/api_setChannelCard.go
Normal file
@ -0,0 +1,83 @@
|
||||
package databag
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"gorm.io/gorm"
|
||||
"github.com/gorilla/mux"
|
||||
"databag/internal/store"
|
||||
)
|
||||
|
||||
func SetChannelCard(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
account, code, err := BearerAppToken(r, false);
|
||||
if err != nil {
|
||||
ErrResponse(w, code, err)
|
||||
return
|
||||
}
|
||||
|
||||
// scan parameters
|
||||
params := mux.Vars(r)
|
||||
channelId := params["channelId"]
|
||||
cardId := params["cardId"]
|
||||
|
||||
// load referenced channel
|
||||
var channelSlot store.ChannelSlot
|
||||
if err := store.DB.Preload("Channel").Where("account_id = ? AND channel_slot_id = ?", account.ID, channelId).First(&channelSlot).Error; err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
ErrResponse(w, http.StatusInternalServerError, err)
|
||||
} else {
|
||||
ErrResponse(w, http.StatusNotFound, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if channelSlot.Channel == nil {
|
||||
ErrResponse(w, http.StatusNotFound, errors.New("channel has been deleted"))
|
||||
return
|
||||
}
|
||||
|
||||
// load referenced card
|
||||
var cardSlot store.CardSlot
|
||||
if err := store.DB.Preload("Card.CardSlot").Where("account_id = ? AND card_slot_id = ?", account.ID, cardId).First(&cardSlot).Error; err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
ErrResponse(w, http.StatusInternalServerError, err)
|
||||
} else {
|
||||
ErrResponse(w, http.StatusNotFound, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if cardSlot.Card == nil {
|
||||
ErrResponse(w, http.StatusNotFound, errors.New("card has been deleted"))
|
||||
return
|
||||
}
|
||||
|
||||
// save and update contact revision
|
||||
err = store.DB.Transaction(func(tx *gorm.DB) error {
|
||||
if res := tx.Model(&channelSlot.Channel).Association("Cards").Append(cardSlot.Card); res != nil {
|
||||
return res
|
||||
}
|
||||
if res := tx.Model(&channelSlot.Channel).Update("detail_revision", account.ChannelRevision + 1).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
if res := tx.Model(&channelSlot).Update("revision", account.ChannelRevision + 1).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
if res := tx.Model(&account).Update("channel_revision", account.ChannelRevision + 1).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
ErrResponse(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
// notify contacts of content change
|
||||
SetStatus(account)
|
||||
for _, card := range channelSlot.Channel.Cards {
|
||||
SetContactChannelNotification(account, &card)
|
||||
}
|
||||
|
||||
WriteResponse(w, getChannelModel(&channelSlot, true, true));
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ func getGroupModel(slot *store.GroupSlot) *Group {
|
||||
}
|
||||
}
|
||||
|
||||
func getArticleModel(slot *store.ArticleSlot, showData bool, showGroups bool) *Article {
|
||||
func getArticleModel(slot *store.ArticleSlot, showData bool, showList bool) *Article {
|
||||
if !showData || slot.Article == nil {
|
||||
return &Article{
|
||||
Id: slot.ArticleSlotId,
|
||||
@ -123,13 +123,13 @@ func getArticleModel(slot *store.ArticleSlot, showData bool, showGroups bool) *A
|
||||
}
|
||||
}
|
||||
|
||||
var articleGroups *ArticleGroups
|
||||
if showGroups {
|
||||
var articleGroups *IdList
|
||||
if showList {
|
||||
var groups []string;
|
||||
for _, group := range slot.Article.Groups {
|
||||
groups = append(groups, group.GroupSlot.GroupSlotId)
|
||||
}
|
||||
articleGroups = &ArticleGroups{ Groups: groups }
|
||||
articleGroups = &IdList{ Ids: groups }
|
||||
}
|
||||
|
||||
return &Article{
|
||||
@ -145,7 +145,7 @@ func getArticleModel(slot *store.ArticleSlot, showData bool, showGroups bool) *A
|
||||
}
|
||||
}
|
||||
|
||||
func getChannelRevisionModel(slot *store.ChannelSlot, showData bool, showGroups bool) *Channel {
|
||||
func getChannelRevisionModel(slot *store.ChannelSlot, showData bool) *Channel {
|
||||
|
||||
if !showData || slot.Channel == nil {
|
||||
return &Channel{
|
||||
@ -163,7 +163,7 @@ func getChannelRevisionModel(slot *store.ChannelSlot, showData bool, showGroups
|
||||
}
|
||||
}
|
||||
|
||||
func getChannelModel(slot *store.ChannelSlot, showData bool, showGroups bool) *Channel {
|
||||
func getChannelModel(slot *store.ChannelSlot, showData bool, showList bool) *Channel {
|
||||
|
||||
if !showData || slot.Channel == nil {
|
||||
return &Channel{
|
||||
@ -172,19 +172,28 @@ func getChannelModel(slot *store.ChannelSlot, showData bool, showGroups bool) *C
|
||||
}
|
||||
}
|
||||
|
||||
var channelGroups *ChannelGroups
|
||||
if showGroups {
|
||||
var channelGroups *IdList
|
||||
if showList {
|
||||
var groups []string;
|
||||
for _, group := range slot.Channel.Groups {
|
||||
groups = append(groups, group.GroupSlot.GroupSlotId)
|
||||
}
|
||||
channelGroups = &ChannelGroups{ Groups: groups }
|
||||
channelGroups = &IdList{ Ids: groups }
|
||||
}
|
||||
|
||||
var cards []string
|
||||
var channelCards *IdList
|
||||
if showList {
|
||||
var cards []string;
|
||||
for _, card := range slot.Channel.Cards {
|
||||
cards = append(cards, card.CardSlot.CardSlotId)
|
||||
}
|
||||
channelCards = &IdList{ Ids: cards }
|
||||
}
|
||||
|
||||
members := []string{}
|
||||
for _, card := range slot.Channel.Cards {
|
||||
members = append(members, card.Guid)
|
||||
}
|
||||
|
||||
return &Channel{
|
||||
Id: slot.ChannelSlotId,
|
||||
@ -197,7 +206,8 @@ func getChannelModel(slot *store.ChannelSlot, showData bool, showGroups bool) *C
|
||||
Created: slot.Channel.Created,
|
||||
Updated: slot.Channel.Updated,
|
||||
Groups: channelGroups,
|
||||
Cards: cards,
|
||||
Cards: channelCards,
|
||||
Members: members,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ type ArticleData struct {
|
||||
|
||||
Updated int64 `json:"updated"`
|
||||
|
||||
Groups *ArticleGroups `json:"groups,omitempty"`
|
||||
Groups *IdList `json:"groups,omitempty"`
|
||||
}
|
||||
|
||||
type ArticleGroups struct {
|
||||
@ -171,14 +171,11 @@ type ChannelDetail struct {
|
||||
|
||||
Updated int64 `json:"updated"`
|
||||
|
||||
Groups *ChannelGroups `json:"groups,omitempty"`
|
||||
Groups *IdList `json:"groups,omitempty"`
|
||||
|
||||
Cards []string `json:"cards"`
|
||||
}
|
||||
Cards *IdList `json:"groups,omitempty"`
|
||||
|
||||
type ChannelGroups struct {
|
||||
|
||||
Groups []string `json:"groups"`
|
||||
Members []string `json:"cards"`
|
||||
}
|
||||
|
||||
type Claim struct {
|
||||
@ -287,6 +284,11 @@ type Identity struct {
|
||||
Node string `json:"node"`
|
||||
}
|
||||
|
||||
type IdList struct {
|
||||
|
||||
Ids []string `json:"ids"`
|
||||
}
|
||||
|
||||
type NodeConfig struct {
|
||||
|
||||
Domain string `json:"domain"`
|
||||
|
@ -545,10 +545,10 @@ var routes = Routes{
|
||||
},
|
||||
|
||||
Route{
|
||||
"GetChannelDetail",
|
||||
"GetChannel",
|
||||
strings.ToUpper("Get"),
|
||||
"/content/channels/{channelId}/detail",
|
||||
GetChannelDetail,
|
||||
"/content/channels/{channelId}",
|
||||
GetChannel,
|
||||
},
|
||||
|
||||
Route{
|
||||
|
@ -6,9 +6,76 @@ import (
|
||||
)
|
||||
|
||||
func TestTopicShare(t *testing.T) {
|
||||
var subject *Subject
|
||||
var channel *Channel
|
||||
var channels *[]Channel
|
||||
aRevision := make(map[string][]string)
|
||||
bRevision := make(map[string][]string)
|
||||
cRevision := make(map[string][]string)
|
||||
var revision string
|
||||
params := make(map[string]string)
|
||||
var detailRevision int64
|
||||
|
||||
// setup testing group
|
||||
set, err := AddTestGroup("topicshare")
|
||||
assert.NoError(t, err)
|
||||
PrintMsg(set)
|
||||
|
||||
// add new channel
|
||||
channel = &Channel{}
|
||||
subject = &Subject{ Data: "channeldata", DataType: "channeldatatype" }
|
||||
assert.NoError(t, ApiTestMsg(AddChannel, "POST", "/content/channels",
|
||||
nil, subject, APP_TOKENAPP, set.A.Token, channel, nil))
|
||||
|
||||
// retrieve channels
|
||||
channels = &[]Channel{}
|
||||
assert.NoError(t, ApiTestMsg(GetChannels, "GET", "/content/channels",
|
||||
nil, nil, APP_TOKENAPP, set.A.Token, channels, &aRevision))
|
||||
assert.Equal(t, 1, len(*channels))
|
||||
assert.NotNil(t, (*channels)[0].Data)
|
||||
detailRevision = (*channels)[0].Data.DetailRevision
|
||||
channels = &[]Channel{}
|
||||
assert.NoError(t, ApiTestMsg(GetChannels, "GET", "/content/channels",
|
||||
nil, nil, APP_TOKENCONTACT, set.B.A.Token, channels, &bRevision))
|
||||
assert.Equal(t, 0, len(*channels))
|
||||
channels = &[]Channel{}
|
||||
assert.NoError(t, ApiTestMsg(GetChannels, "GET", "/content/channels",
|
||||
nil, nil, APP_TOKENCONTACT, set.C.A.Token, channels, &cRevision))
|
||||
assert.Equal(t, 0, len(*channels))
|
||||
|
||||
// assign channel to B
|
||||
params["channelId"] = channel.Id
|
||||
params["cardId"] = set.A.B.CardId
|
||||
assert.NoError(t, ApiTestMsg(SetChannelCard, "PUT", "/content/channels/{channelId}/cards/{cardId}",
|
||||
¶ms, nil, APP_TOKENAPP, set.A.Token, nil, nil))
|
||||
|
||||
// check shared channel
|
||||
channels = &[]Channel{}
|
||||
revision = "?channelRevision=" + aRevision["Channel-Revision"][0]
|
||||
assert.NoError(t, ApiTestMsg(GetChannels, "GET", "/content/channels" + revision,
|
||||
nil, nil, APP_TOKENAPP, set.A.Token, channels, &aRevision))
|
||||
assert.Equal(t, 1, len(*channels))
|
||||
assert.NotNil(t, (*channels)[0].Data)
|
||||
assert.NotEqual(t, detailRevision, (*channels)[0].Data.DetailRevision)
|
||||
channels = &[]Channel{}
|
||||
revision = "?channelRevision=" + bRevision["Channel-Revision"][0] + "&viewRevision=" + bRevision["View-Revision"][0]
|
||||
assert.NoError(t, ApiTestMsg(GetChannels, "GET", "/content/channels" + revision,
|
||||
nil, nil, APP_TOKENCONTACT, set.B.A.Token, channels, &bRevision))
|
||||
assert.Equal(t, 1, len(*channels))
|
||||
assert.NotNil(t, (*channels)[0].Data)
|
||||
channels = &[]Channel{}
|
||||
revision = "?channelRevision=" + cRevision["Channel-Revision"][0] + "&viewRevision=" + cRevision["View-Revision"][0]
|
||||
assert.NoError(t, ApiTestMsg(GetChannels, "GET", "/content/channels" + revision,
|
||||
nil, nil, APP_TOKENCONTACT, set.C.A.Token, channels, &cRevision))
|
||||
assert.Equal(t, 1, len(*channels))
|
||||
assert.Nil(t, (*channels)[0].Data)
|
||||
|
||||
// get discovered channel
|
||||
channel = &Channel{}
|
||||
assert.NoError(t, ApiTestMsg(GetChannel, "GET", "/content/channels/{channelId}",
|
||||
¶ms, nil, APP_TOKENCONTACT, set.B.A.Token, channel, nil))
|
||||
assert.Equal(t, "channeldatatype", channel.Data.ChannelDetail.DataType)
|
||||
assert.Equal(t, 1, len(channel.Data.ChannelDetail.Members))
|
||||
assert.Equal(t, set.B.Guid, channel.Data.ChannelDetail.Members[0])
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user