2022-02-15 23:17:06 +00:00
|
|
|
package databag
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strings"
|
|
|
|
"errors"
|
|
|
|
"strconv"
|
|
|
|
"net/http"
|
2022-05-09 19:53:00 +00:00
|
|
|
"gorm.io/gorm"
|
2022-02-15 23:17:06 +00:00
|
|
|
"encoding/json"
|
|
|
|
"databag/internal/store"
|
|
|
|
)
|
|
|
|
|
|
|
|
func GetChannels(w http.ResponseWriter, r *http.Request) {
|
|
|
|
var channelRevisionSet bool
|
|
|
|
var channelRevision int64
|
|
|
|
var viewRevisionSet bool
|
|
|
|
var viewRevision int64
|
|
|
|
var typesSet bool
|
|
|
|
var types []string
|
|
|
|
|
|
|
|
channel := r.FormValue("channelRevision")
|
|
|
|
if channel != "" {
|
|
|
|
var err error
|
|
|
|
channelRevisionSet = true
|
|
|
|
if channelRevision, err = strconv.ParseInt(channel, 10, 64); err != nil {
|
|
|
|
ErrResponse(w, http.StatusBadRequest, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
view := r.FormValue("viewRevision")
|
|
|
|
if view != "" {
|
|
|
|
var err error
|
|
|
|
viewRevisionSet = true
|
|
|
|
if viewRevision, err = strconv.ParseInt(view, 10, 64); err != nil {
|
|
|
|
ErrResponse(w, http.StatusBadRequest, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
schemas := r.FormValue("types")
|
|
|
|
if schemas != "" {
|
|
|
|
var err error
|
|
|
|
typesSet = true
|
|
|
|
dec := json.NewDecoder(strings.NewReader(schemas))
|
|
|
|
if dec.Decode(&types) != nil {
|
|
|
|
ErrResponse(w, http.StatusBadRequest, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-07 22:41:29 +00:00
|
|
|
response := []*Channel{}
|
|
|
|
tokenType := ParamTokenType(r)
|
2022-03-20 21:09:40 +00:00
|
|
|
if tokenType == APP_TOKENAGENT {
|
2022-02-15 23:17:06 +00:00
|
|
|
|
2022-04-07 22:41:29 +00:00
|
|
|
account, code, err := ParamAgentToken(r, false);
|
2022-02-15 23:17:06 +00:00
|
|
|
if err != nil {
|
|
|
|
ErrResponse(w, code, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var slots []store.ChannelSlot
|
|
|
|
if channelRevisionSet {
|
2022-02-17 08:30:33 +00:00
|
|
|
if err := store.DB.Preload("Channel").Where("account_id = ? AND revision > ?", account.ID, channelRevision).Find(&slots).Error; err != nil {
|
2022-02-15 23:17:06 +00:00
|
|
|
ErrResponse(w, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
} else {
|
2022-05-09 21:08:54 +00:00
|
|
|
if err := store.DB.Preload("Channel.Topics", func(db *gorm.DB) *gorm.DB {
|
2022-05-09 22:17:05 +00:00
|
|
|
return store.DB.Order("topics.id DESC")
|
2022-05-09 21:08:54 +00:00
|
|
|
}).Preload("Channel.Cards.CardSlot").Preload("Channel.Groups.GroupSlot").Where("account_id = ? AND channel_id != 0", account.ID).Find(&slots).Error; err != nil {
|
2022-02-15 23:17:06 +00:00
|
|
|
ErrResponse(w, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, slot := range slots {
|
|
|
|
if !typesSet || hasChannelType(types, slot.Channel) {
|
2022-02-16 08:00:07 +00:00
|
|
|
if channelRevisionSet {
|
|
|
|
response = append(response, getChannelRevisionModel(&slot, true))
|
|
|
|
} else if slot.Channel != nil {
|
|
|
|
response = append(response, getChannelModel(&slot, true, true))
|
|
|
|
}
|
2022-02-15 23:17:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
w.Header().Set("Channel-Revision", strconv.FormatInt(account.ChannelRevision, 10))
|
|
|
|
|
|
|
|
} else if tokenType == APP_TOKENCONTACT {
|
|
|
|
|
2022-04-07 22:41:29 +00:00
|
|
|
card, code, err := ParamContactToken(r, true)
|
2022-02-15 23:17:06 +00:00
|
|
|
if err != nil {
|
|
|
|
ErrResponse(w, code, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if viewRevisionSet || channelRevisionSet {
|
|
|
|
if viewRevision != card.ViewRevision {
|
|
|
|
ErrResponse(w, http.StatusGone, errors.New("channel view has changed"))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
account := &card.Account
|
|
|
|
var slots []store.ChannelSlot
|
|
|
|
if channelRevisionSet {
|
2022-05-09 21:08:54 +00:00
|
|
|
if err := store.DB.Preload("Channel.Cards").Preload("Channel.Groups.Cards").Where("account_id = ? AND revision > ?", account.ID, channelRevision).Find(&slots).Error; err != nil {
|
2022-02-15 23:17:06 +00:00
|
|
|
ErrResponse(w, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
} else {
|
2022-05-09 21:08:54 +00:00
|
|
|
if err := store.DB.Preload("Channel.Topics", func(db *gorm.DB) *gorm.DB {
|
2022-05-09 22:17:05 +00:00
|
|
|
return store.DB.Order("topics.id DESC")
|
2022-05-09 21:08:54 +00:00
|
|
|
}).Preload("Channel.Cards").Preload("Channel.Groups.Cards").Where("account_id = ? AND channel_id != 0", account.ID).Find(&slots).Error; err != nil {
|
2022-02-15 23:17:06 +00:00
|
|
|
ErrResponse(w, http.StatusInternalServerError, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, slot := range slots {
|
|
|
|
if !typesSet || hasChannelType(types, slot.Channel) {
|
2022-02-23 06:11:56 +00:00
|
|
|
shared := isChannelShared(card.Guid, slot.Channel)
|
2022-02-16 08:00:07 +00:00
|
|
|
if channelRevisionSet {
|
|
|
|
response = append(response, getChannelRevisionModel(&slot, shared))
|
|
|
|
} else if shared {
|
|
|
|
response = append(response, getChannelModel(&slot, true, false))
|
|
|
|
}
|
2022-02-15 23:17:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
w.Header().Set("Channel-Revision", strconv.FormatInt(account.ChannelRevision, 10))
|
|
|
|
w.Header().Set("View-Revision", strconv.FormatInt(card.ViewRevision, 10))
|
|
|
|
|
|
|
|
} else {
|
|
|
|
ErrResponse(w, http.StatusBadRequest, errors.New("invalid token type"))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
WriteResponse(w, response)
|
|
|
|
}
|
|
|
|
|
|
|
|
func isChannelShared(guid string, channel *store.Channel) bool {
|
|
|
|
if channel == nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for _, card := range channel.Cards {
|
|
|
|
if guid == card.Guid {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, group := range channel.Groups {
|
|
|
|
for _, card := range group.Cards {
|
|
|
|
if guid == card.Guid {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func hasChannelType(types []string, channel *store.Channel) bool {
|
|
|
|
if channel == nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for _, schema := range types {
|
|
|
|
if schema == channel.DataType {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|