mirror of
https://github.com/balzack/databag.git
synced 2025-03-13 00:50:03 +00:00
test removal of channel topic assets
This commit is contained in:
parent
b53115fb52
commit
b77e869fd5
@ -40,7 +40,6 @@ func AddChannelTopic(w http.ResponseWriter, r *http.Request) {
|
||||
} else {
|
||||
topic.Status = APP_TOPICUNCONFIRMED
|
||||
}
|
||||
topic.Transform = APP_TRANSFORMCOMPLETE
|
||||
if res := tx.Save(topic).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
|
@ -64,6 +64,10 @@ func AddChannelTopicAsset(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// avoid async cleanup of file before record is created
|
||||
garbageSync.Lock()
|
||||
defer garbageSync.Unlock()
|
||||
|
||||
// save new file
|
||||
id := uuid.New().String()
|
||||
path := getStrConfigValue(CONFIG_ASSETPATH, ".") + "/" + channelSlot.Account.Guid + "/" + id
|
||||
@ -120,13 +124,8 @@ func AddChannelTopicAsset(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
assets = append(assets, Asset{ AssetId: asset.AssetId, Transform: transform, Status: APP_ASSETWAITING})
|
||||
}
|
||||
if len(transforms) > 0 {
|
||||
if res := tx.Model(&topicSlot.Topic).Update("transform", APP_TRANSFORMINCOMPLETE).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
if res := tx.Model(&topicSlot.Topic).Update("detail_revision", act.ChannelRevision + 1).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
if res := tx.Model(&topicSlot.Topic).Update("detail_revision", act.ChannelRevision + 1).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
if res := tx.Model(&topicSlot).Update("revision", act.ChannelRevision + 1).Error; res != nil {
|
||||
return res
|
||||
|
@ -18,16 +18,6 @@ func AddChannelTopicTag(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func GetChannelAssets(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func GetChannelTopicSubjectField(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func GetChannelTopicTagSubjectField(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
@ -43,11 +33,6 @@ func RemoveChannel(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func RemoveChannelAsset(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func RemoveChannelTopic(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
@ -3,13 +3,10 @@ package databag
|
||||
import (
|
||||
"time"
|
||||
"bytes"
|
||||
"errors"
|
||||
"strings"
|
||||
"net/http"
|
||||
"gorm.io/gorm"
|
||||
"encoding/base64"
|
||||
"github.com/gorilla/mux"
|
||||
"databag/internal/store"
|
||||
"github.com/valyala/fastjson"
|
||||
)
|
||||
|
||||
@ -17,56 +14,18 @@ func GetChannelSubjectField(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// scan parameters
|
||||
params := mux.Vars(r)
|
||||
channelId := params["channelId"]
|
||||
field := params["field"]
|
||||
elements := strings.Split(field, ".")
|
||||
|
||||
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.Groups.Cards").Preload("Channel.Cards").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
|
||||
}
|
||||
|
||||
// check if channel is shared
|
||||
if tokenType == APP_TOKENCONTACT && !isChannelShared(guid, slot.Channel) {
|
||||
ErrResponse(w, http.StatusNotFound, errors.New("referenced channel not shared"))
|
||||
// get channel stlot
|
||||
channelSlot, _, err, code := getChannelSlot(r, false)
|
||||
if err != nil {
|
||||
ErrResponse(w, code, err)
|
||||
return
|
||||
}
|
||||
|
||||
// decode data
|
||||
strData := fastjson.GetString([]byte(slot.Channel.Data), elements...)
|
||||
strData := fastjson.GetString([]byte(channelSlot.Channel.Data), elements...)
|
||||
binData, err := base64.StdEncoding.DecodeString(strData)
|
||||
if err != nil {
|
||||
ErrResponse(w, http.StatusNotFound, err)
|
||||
@ -74,6 +33,6 @@ func GetChannelSubjectField(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// response with content
|
||||
http.ServeContent(w, r, field, time.Unix(slot.Channel.Updated, 0), bytes.NewReader(binData))
|
||||
http.ServeContent(w, r, field, time.Unix(channelSlot.Channel.Updated, 0), bytes.NewReader(binData))
|
||||
}
|
||||
|
||||
|
@ -14,12 +14,6 @@ func GetChannelTopic(w http.ResponseWriter, r *http.Request) {
|
||||
params := mux.Vars(r)
|
||||
topicId := params["topicId"]
|
||||
|
||||
var subject Subject
|
||||
if err := ParseRequest(r, w, &subject); err != nil {
|
||||
ErrResponse(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
channelSlot, _, err, code := getChannelSlot(r, false)
|
||||
if err != nil {
|
||||
ErrResponse(w, code, err)
|
||||
|
50
net/server/internal/api_getChannelTopicAssets.go
Normal file
50
net/server/internal/api_getChannelTopicAssets.go
Normal file
@ -0,0 +1,50 @@
|
||||
package databag
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"github.com/gorilla/mux"
|
||||
"gorm.io/gorm"
|
||||
"databag/internal/store"
|
||||
)
|
||||
|
||||
func GetChannelTopicAssets(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// scan parameters
|
||||
params := mux.Vars(r)
|
||||
topicId := params["topicId"]
|
||||
|
||||
channelSlot, guid, err, code := getChannelSlot(r, true)
|
||||
if err != nil {
|
||||
ErrResponse(w, code, err)
|
||||
return
|
||||
}
|
||||
|
||||
// load topic
|
||||
var topicSlot store.TopicSlot
|
||||
if err = store.DB.Preload("Topic.Assets").Where("channel_id = ? AND topic_slot_id = ?", channelSlot.Channel.ID, topicId).First(&topicSlot).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
ErrResponse(w, http.StatusNotFound, err)
|
||||
} else {
|
||||
ErrResponse(w, http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if topicSlot.Topic == nil {
|
||||
ErrResponse(w, http.StatusNotFound, errors.New("referenced empty topic"))
|
||||
return
|
||||
}
|
||||
|
||||
// only creator can list assets
|
||||
if topicSlot.Topic.Guid != guid {
|
||||
ErrResponse(w, http.StatusUnauthorized, errors.New("permission denied to asset list"))
|
||||
return
|
||||
}
|
||||
|
||||
// return list of assets
|
||||
assets := []Asset{}
|
||||
for _, asset := range topicSlot.Topic.Assets {
|
||||
assets = append(assets, Asset{ AssetId: asset.AssetId, Status: asset.Status })
|
||||
}
|
||||
WriteResponse(w, &assets)
|
||||
}
|
55
net/server/internal/api_getChannelTopicSubjectField.go
Normal file
55
net/server/internal/api_getChannelTopicSubjectField.go
Normal file
@ -0,0 +1,55 @@
|
||||
package databag
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
"bytes"
|
||||
"errors"
|
||||
"net/http"
|
||||
"gorm.io/gorm"
|
||||
"github.com/gorilla/mux"
|
||||
"databag/internal/store"
|
||||
"encoding/base64"
|
||||
"github.com/valyala/fastjson"
|
||||
)
|
||||
|
||||
func GetChannelTopicSubjectField(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// scan parameters
|
||||
params := mux.Vars(r)
|
||||
topicId := params["topicId"]
|
||||
field := params["field"]
|
||||
elements := strings.Split(field, ".")
|
||||
|
||||
channelSlot, _, err, code := getChannelSlot(r, false)
|
||||
if err != nil {
|
||||
ErrResponse(w, code, err)
|
||||
return
|
||||
}
|
||||
|
||||
// load topic
|
||||
var topicSlot store.TopicSlot
|
||||
if err = store.DB.Where("channel_id = ? AND topic_slot_id = ?", channelSlot.Channel.ID, topicId).First(&topicSlot).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
code = http.StatusNotFound
|
||||
} else {
|
||||
code = http.StatusInternalServerError
|
||||
}
|
||||
return
|
||||
}
|
||||
if topicSlot.Topic == nil {
|
||||
ErrResponse(w, http.StatusNotFound, errors.New("referenced missing topic"))
|
||||
return
|
||||
}
|
||||
|
||||
// decode data
|
||||
strData := fastjson.GetString([]byte(topicSlot.Topic.Data), elements...)
|
||||
binData, err := base64.StdEncoding.DecodeString(strData)
|
||||
if err != nil {
|
||||
ErrResponse(w, http.StatusNotFound, err)
|
||||
return
|
||||
}
|
||||
|
||||
// response with content
|
||||
http.ServeContent(w, r, field, time.Unix(topicSlot.Topic.Updated, 0), bytes.NewReader(binData))
|
||||
}
|
92
net/server/internal/api_removeChannelTopicAsset.go
Normal file
92
net/server/internal/api_removeChannelTopicAsset.go
Normal file
@ -0,0 +1,92 @@
|
||||
package databag
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/gorilla/mux"
|
||||
"gorm.io/gorm"
|
||||
"databag/internal/store"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func RemoveChannelTopicAsset(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// scan parameters
|
||||
params := mux.Vars(r)
|
||||
topicId := params["topicId"]
|
||||
assetId := params["assetId"]
|
||||
|
||||
channelSlot, guid, err, code := getChannelSlot(r, true)
|
||||
if err != nil {
|
||||
ErrResponse(w, code, err)
|
||||
return
|
||||
}
|
||||
act := &channelSlot.Account
|
||||
|
||||
// load asset
|
||||
var asset store.Asset
|
||||
if err = store.DB.Preload("Topic.TopicSlot").Where("channel_id = ? AND asset_id = ?", channelSlot.Channel.ID, assetId).First(&asset).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
ErrResponse(w, http.StatusNotFound, err)
|
||||
} else {
|
||||
ErrResponse(w, http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if asset.Topic.TopicSlot.TopicSlotId != topicId {
|
||||
ErrResponse(w, http.StatusNotFound, errors.New("invalid topic"))
|
||||
return
|
||||
}
|
||||
|
||||
// can only update topic if creator
|
||||
if asset.Topic.Guid != guid {
|
||||
ErrResponse(w, http.StatusUnauthorized, errors.New("topic not created by you"))
|
||||
return
|
||||
}
|
||||
|
||||
// delete asset record
|
||||
err = store.DB.Transaction(func(tx *gorm.DB) error {
|
||||
if res := tx.Delete(&asset).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
if res := tx.Model(&asset.Topic).Update("detail_revision", act.ChannelRevision + 1).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
if res := tx.Model(&asset.Topic.TopicSlot).Update("revision", act.ChannelRevision + 1).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
if res := tx.Model(&channelSlot).Update("revision", act.ChannelRevision + 1).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
if res := tx.Model(act).Update("channel_revision", act.ChannelRevision + 1).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
ErrResponse(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
// cleanup files from deleted record
|
||||
go garbageCollect(act)
|
||||
|
||||
// determine affected contact list
|
||||
cards := make(map[string]store.Card)
|
||||
for _, card := range channelSlot.Channel.Cards {
|
||||
cards[card.Guid] = card
|
||||
}
|
||||
for _, group := range channelSlot.Channel.Groups {
|
||||
for _, card := range group.Cards {
|
||||
cards[card.Guid] = card
|
||||
}
|
||||
}
|
||||
|
||||
// notify
|
||||
SetStatus(act)
|
||||
for _, card := range cards {
|
||||
SetContactChannelNotification(act, &card)
|
||||
}
|
||||
|
||||
WriteResponse(w, nil)
|
||||
}
|
||||
|
51
net/server/internal/garbageUtil.go
Normal file
51
net/server/internal/garbageUtil.go
Normal file
@ -0,0 +1,51 @@
|
||||
package databag
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"os"
|
||||
"databag/internal/store"
|
||||
)
|
||||
|
||||
var garbageSync sync.Mutex
|
||||
|
||||
func garbageCollect(act *store.Account) {
|
||||
garbageSync.Lock()
|
||||
defer garbageSync.Unlock()
|
||||
|
||||
// get all asset files
|
||||
dir := getStrConfigValue(CONFIG_ASSETPATH, ".") + "/" + act.Guid
|
||||
files, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
ErrMsg(err)
|
||||
return
|
||||
}
|
||||
|
||||
// create map of all files
|
||||
list := make(map[string]bool)
|
||||
for _, file := range files {
|
||||
list[file.Name()] = false
|
||||
}
|
||||
|
||||
// get all asset records
|
||||
var assets []store.Asset
|
||||
if err := store.DB.Where("account_id = ?", act.ID).Find(&assets).Error; err != nil {
|
||||
ErrMsg(err)
|
||||
return
|
||||
}
|
||||
|
||||
// mark all referenced files
|
||||
for _, asset := range assets {
|
||||
list[asset.AssetId] = true
|
||||
}
|
||||
|
||||
// delete any unreferenced file
|
||||
for id, set := range list {
|
||||
if !set {
|
||||
LogMsg("removing file asset " + act.Guid + "/" + id)
|
||||
if err := os.Remove(dir + "/" + id); err != nil {
|
||||
ErrMsg(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -238,6 +238,15 @@ func getTopicDetailModel(slot *store.TopicSlot) *TopicDetail {
|
||||
return nil
|
||||
}
|
||||
|
||||
transform := APP_TRANSFORMCOMPLETE
|
||||
for _, asset := range slot.Topic.Assets {
|
||||
if asset.Status == APP_ASSETERROR {
|
||||
transform = APP_TRANSFORMERROR
|
||||
} else if asset.Status == APP_ASSETWAITING && transform == APP_TRANSFORMCOMPLETE {
|
||||
transform = APP_TRANSFORMINCOMPLETE
|
||||
}
|
||||
}
|
||||
|
||||
return &TopicDetail{
|
||||
Guid: slot.Topic.Guid,
|
||||
DataType: slot.Topic.DataType,
|
||||
@ -245,7 +254,7 @@ func getTopicDetailModel(slot *store.TopicSlot) *TopicDetail {
|
||||
Created: slot.Topic.Created,
|
||||
Updated: slot.Topic.Updated,
|
||||
Status: slot.Topic.Status,
|
||||
Transform: slot.Topic.Transform,
|
||||
Transform: transform,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -538,10 +538,10 @@ var routes = Routes{
|
||||
},
|
||||
|
||||
Route{
|
||||
"GetChannelAssets",
|
||||
"GetChannelTopicAssets",
|
||||
strings.ToUpper("Get"),
|
||||
"/content/channels/{channelId}/topics/{topicId}/assets",
|
||||
GetChannelAssets,
|
||||
GetChannelTopicAssets,
|
||||
},
|
||||
|
||||
Route{
|
||||
@ -622,10 +622,10 @@ var routes = Routes{
|
||||
},
|
||||
|
||||
Route{
|
||||
"RemoveChannelAsset",
|
||||
"RemoveChannelTopicAsset",
|
||||
strings.ToUpper("Delete"),
|
||||
"/content/channels/{channelId}/topics/{topicId}/assets/{assetId}",
|
||||
RemoveChannelAsset,
|
||||
RemoveChannelTopicAsset,
|
||||
},
|
||||
|
||||
Route{
|
||||
|
@ -224,7 +224,6 @@ type Topic struct {
|
||||
DataType string `gorm:"index"`
|
||||
Data string
|
||||
Status string `gorm:"not null;index"`
|
||||
Transform string
|
||||
Created int64 `gorm:"autoCreateTime"`
|
||||
Updated int64 `gorm:"autoUpdateTime"`
|
||||
TagCount int32 `gorm:"not null"`
|
||||
|
@ -120,6 +120,7 @@ func transcodeAsset(asset *store.Asset) {
|
||||
LogMsg(stderr.String())
|
||||
}
|
||||
crc, size, err := ScanAsset(output)
|
||||
|
||||
if err != nil {
|
||||
ErrMsg(err)
|
||||
if err := UpdateAsset(asset, APP_ASSETERROR, 0, 0); err != nil {
|
||||
@ -132,20 +133,6 @@ func transcodeAsset(asset *store.Asset) {
|
||||
}
|
||||
}
|
||||
|
||||
func isComplete(id uint) (complete bool, err error) {
|
||||
var assets []store.Asset
|
||||
if err = store.DB.Where("topic_id = ?", id).Find(&assets).Error; err != nil {
|
||||
return
|
||||
}
|
||||
for _, asset := range assets {
|
||||
if id != asset.ID && asset.Status != APP_ASSETREADY {
|
||||
return
|
||||
}
|
||||
}
|
||||
complete = true
|
||||
return
|
||||
}
|
||||
|
||||
func UpdateAsset(asset *store.Asset, status string, crc uint32, size int64) (err error) {
|
||||
|
||||
act := asset.Account
|
||||
@ -153,24 +140,9 @@ func UpdateAsset(asset *store.Asset, status string, crc uint32, size int64) (err
|
||||
asset.Crc = crc
|
||||
asset.Size = size
|
||||
asset.Status = status
|
||||
if res := tx.Save(asset).Error; res != nil {
|
||||
if res := tx.Model(store.Asset{}).Where("id = ?", asset.ID).Updates(asset).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
if status == APP_ASSETERROR {
|
||||
if res := tx.Model(&asset.Topic).Update("transform", APP_TRANSFORMERROR).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
} else if status == APP_ASSETREADY {
|
||||
complete, ret := isComplete(asset.ID)
|
||||
if ret != nil {
|
||||
return ret
|
||||
}
|
||||
if complete {
|
||||
if res := tx.Model(&asset.Topic).Update("transform", APP_TRANSFORMCOMPLETE).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
}
|
||||
}
|
||||
if res := tx.Model(&asset.Topic).Update("detail_revision", act.ChannelRevision + 1).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestTopicShare(t *testing.T) {
|
||||
@ -90,27 +89,35 @@ func TestTopicShare(t *testing.T) {
|
||||
¶ms, subject, APP_TOKENCONTACT, set.C.A.Token, topic, nil))
|
||||
|
||||
// add asset to topic
|
||||
assets := &[]Asset{}
|
||||
assets := []Asset{}
|
||||
params["topicId"] = topic.Id
|
||||
transforms, err := json.Marshal([]string{ "copy;photo" })
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, ApiTestUpload(AddChannelTopicAsset, "POST", "/content/channels/{channelId}/topics/{topicId}/assets?transforms=" + url.QueryEscape(string(transforms)),
|
||||
¶ms, img, APP_TOKENCONTACT, set.C.A.Token, assets, nil))
|
||||
¶ms, img, APP_TOKENCONTACT, set.C.A.Token, &assets, nil))
|
||||
|
||||
// view topics
|
||||
topics := &[]Topic{}
|
||||
assert.NoError(t, ApiTestMsg(GetChannelTopics, "GET", "/content/channels/{channelId}/topics",
|
||||
¶ms, nil, APP_TOKENAPP, set.A.Token, topics, nil))
|
||||
|
||||
time.Sleep(time.Second)
|
||||
// get list of assets
|
||||
assets = []Asset{}
|
||||
assert.NoError(t, ApiTestMsg(GetChannelTopicAssets, "GET", "/content/channels/{channelId}/topics/{topicId}",
|
||||
¶ms, nil, APP_TOKENCONTACT, set.C.A.Token, &assets, nil))
|
||||
assert.Equal(t, 2, len(assets))
|
||||
|
||||
// download file
|
||||
params["assetId"] = (*assets)[1].AssetId
|
||||
data, header, err = ApiTestData(GetChannelTopicAsset, "GET", "/content/channels/{channelId}/topics/{topicId}/assets/{assetId}",
|
||||
¶ms, nil, APP_TOKENAPP, set.A.Token, 1, 2)
|
||||
// delete each asset
|
||||
for _, asset := range assets {
|
||||
params["assetId"] = asset.AssetId
|
||||
assert.NoError(t, ApiTestMsg(RemoveChannelTopicAsset, "DELETE", "/content/channels/{channelId}/topics/{topicId}/assets/{assetId}",
|
||||
¶ms, nil, APP_TOKENCONTACT, set.C.A.Token, nil, nil))
|
||||
}
|
||||
|
||||
PrintMsg(header)
|
||||
PrintMsg(err)
|
||||
PrintMsg(len(data))
|
||||
// get list of assets
|
||||
assets = []Asset{}
|
||||
assert.NoError(t, ApiTestMsg(GetChannelTopicAssets, "GET", "/content/channels/{channelId}/topics/{topicId}",
|
||||
¶ms, nil, APP_TOKENCONTACT, set.C.A.Token, &assets, nil))
|
||||
assert.Equal(t, 0, len(assets))
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user