mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
testing get channel topics
This commit is contained in:
parent
898ad9f4ac
commit
73bedbccdc
121
doc/api.oa3
121
doc/api.oa3
@ -1894,6 +1894,35 @@ paths:
|
||||
$ref: '#/components/schemas/Subject'
|
||||
|
||||
/content/channels/{channelId}:
|
||||
get:
|
||||
tags:
|
||||
- content
|
||||
description: Get details of channel.
|
||||
operationId: get-channel
|
||||
security:
|
||||
- bearerAuth: []
|
||||
parameters:
|
||||
- name: channelId
|
||||
in: path
|
||||
description: specified channel id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Channel'
|
||||
'401':
|
||||
description: invalid password
|
||||
'404':
|
||||
description: channel not found
|
||||
'410':
|
||||
description: account disabled
|
||||
'500':
|
||||
description: internal server error
|
||||
delete:
|
||||
tags:
|
||||
- content
|
||||
@ -1919,37 +1948,6 @@ paths:
|
||||
description: account disabled
|
||||
'500':
|
||||
description: internal server error
|
||||
|
||||
/content/channels/{channelId}/detail:
|
||||
get:
|
||||
tags:
|
||||
- content
|
||||
description: Get detail object of channel.
|
||||
operationId: get-channel-detail
|
||||
security:
|
||||
- bearerAuth: []
|
||||
parameters:
|
||||
- name: channelId
|
||||
in: path
|
||||
description: specified channel id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ChannelDetail'
|
||||
'401':
|
||||
description: invalid password
|
||||
'404':
|
||||
description: channel not found
|
||||
'410':
|
||||
description: account disabled
|
||||
'500':
|
||||
description: internal server error
|
||||
|
||||
/content/channels/{channelId}/subject/{field}:
|
||||
get:
|
||||
@ -2247,6 +2245,41 @@ paths:
|
||||
$ref: '#/components/schemas/Subject'
|
||||
|
||||
/content/channels/{channelId}/topics/{topicId}:
|
||||
get:
|
||||
tags:
|
||||
- content
|
||||
description: Get full object of topic.
|
||||
operationId: get-channel-topic
|
||||
security:
|
||||
- bearerAuth: []
|
||||
parameters:
|
||||
- name: channelId
|
||||
in: path
|
||||
description: specified channel id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- name: topicId
|
||||
in: path
|
||||
description: specified topic id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Topic'
|
||||
'401':
|
||||
description: invalid password
|
||||
'404':
|
||||
description: channel not found
|
||||
'410':
|
||||
description: account disabled
|
||||
'500':
|
||||
description: internal server error
|
||||
delete:
|
||||
tags:
|
||||
- content
|
||||
@ -2303,6 +2336,10 @@ paths:
|
||||
responses:
|
||||
'200':
|
||||
description: success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/TopicDetail'
|
||||
'401':
|
||||
description: invalid password
|
||||
'404':
|
||||
@ -2312,12 +2349,12 @@ paths:
|
||||
'500':
|
||||
description: internal server error
|
||||
|
||||
/content/channels/{channelId}/topics/{topicId}/size:
|
||||
/content/channels/{channelId}/topics/{topicId}/count:
|
||||
get:
|
||||
tags:
|
||||
- content
|
||||
description: Get detail object of topic.
|
||||
operationId: get-channel-topic-size
|
||||
description: Get count of associated taghs.
|
||||
operationId: get-channel-topic-count
|
||||
security:
|
||||
- bearerAuth: []
|
||||
parameters:
|
||||
@ -2336,6 +2373,10 @@ paths:
|
||||
responses:
|
||||
'200':
|
||||
description: success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/TagCount'
|
||||
'401':
|
||||
description: invalid password
|
||||
'404':
|
||||
@ -3236,7 +3277,7 @@ components:
|
||||
topicDetail:
|
||||
$ref: '#/components/schemas/TopicDetail'
|
||||
topicTags::
|
||||
$ref: '#/components/schemas/TopicTags'
|
||||
$ref: '#/components/schemas/TagCount'
|
||||
|
||||
TopicDetail:
|
||||
type: object
|
||||
@ -3264,16 +3305,16 @@ components:
|
||||
type: string
|
||||
enum: [ unconfirmed, confirmed, complete, error ]
|
||||
|
||||
TopicTags:
|
||||
TagCount:
|
||||
type: object
|
||||
required:
|
||||
- tagCount
|
||||
- tagUpdated
|
||||
- count
|
||||
- updated
|
||||
properties:
|
||||
tagCount:
|
||||
count:
|
||||
type: integer
|
||||
format: int32
|
||||
tagUpdated:
|
||||
updated:
|
||||
type: integer
|
||||
format: int64
|
||||
|
||||
|
@ -1,81 +1,34 @@
|
||||
package databag
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"gorm.io/gorm"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/google/uuid"
|
||||
"databag/internal/store"
|
||||
)
|
||||
|
||||
func AddChannelTopic(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// scan parameters
|
||||
params := mux.Vars(r)
|
||||
channelId := params["channelId"]
|
||||
|
||||
var subject Subject
|
||||
if err := ParseRequest(r, w, &subject); err != nil {
|
||||
ErrResponse(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
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
|
||||
guid = account.Guid
|
||||
} 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"))
|
||||
channelSlot, guid, err, code := getChannelSlot(r, false)
|
||||
if err != nil {
|
||||
ErrResponse(w, code, err)
|
||||
return
|
||||
}
|
||||
|
||||
// load channel
|
||||
var channelSlot store.ChannelSlot
|
||||
if err := store.DB.Preload("Channel.Cards").Preload("Channel.Groups.Cards").Where("account_id = ? AND channel_slot_id = ?", act.ID, channelId).First(&channelSlot).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
ErrResponse(w, http.StatusNotFound, err)
|
||||
} else {
|
||||
ErrResponse(w, http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if channelSlot.Channel == nil {
|
||||
ErrResponse(w, http.StatusNotFound, errors.New("referenced empty channel"))
|
||||
return
|
||||
}
|
||||
|
||||
// check if a member
|
||||
if tokenType == APP_TOKENCONTACT {
|
||||
if !isMember(guid, channelSlot.Channel.Cards) {
|
||||
ErrResponse(w, http.StatusUnauthorized, errors.New("not a member of channel"))
|
||||
return
|
||||
}
|
||||
}
|
||||
act := &channelSlot.Account
|
||||
|
||||
topicSlot := &store.TopicSlot{}
|
||||
err := store.DB.Transaction(func(tx *gorm.DB) error {
|
||||
err = store.DB.Transaction(func(tx *gorm.DB) error {
|
||||
|
||||
// add new record
|
||||
topic := &store.Topic{}
|
||||
topic.Data = subject.Data
|
||||
topic.DataType = subject.DataType
|
||||
topic.Channel = channelSlot.Channel
|
||||
topic.TagCount = 0
|
||||
topic.Guid = guid
|
||||
topic.DetailRevision = act.ChannelRevision + 1
|
||||
@ -86,6 +39,7 @@ func AddChannelTopic(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
topicSlot.TopicSlotId = uuid.New().String()
|
||||
topicSlot.AccountID = act.ID
|
||||
topicSlot.ChannelID = channelSlot.Channel.ID
|
||||
topicSlot.TopicID = topic.ID
|
||||
topicSlot.Revision = act.ChannelRevision + 1
|
||||
topicSlot.Topic = topic
|
||||
@ -97,7 +51,7 @@ func AddChannelTopic(w http.ResponseWriter, r *http.Request) {
|
||||
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 {
|
||||
if res := tx.Model(act).Update("channel_revision", act.ChannelRevision + 1).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
return nil
|
||||
@ -122,15 +76,7 @@ func AddChannelTopic(w http.ResponseWriter, r *http.Request) {
|
||||
for _, card := range cards {
|
||||
SetContactChannelNotification(act, &card)
|
||||
}
|
||||
WriteResponse(w, getTopicModel(topicSlot, true, true))
|
||||
WriteResponse(w, getTopicModel(topicSlot))
|
||||
}
|
||||
|
||||
func isMember(guid string, cards []store.Card) bool {
|
||||
for _, card := range cards {
|
||||
if guid == card.Guid {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -33,21 +33,6 @@ func GetChannelAssets(w http.ResponseWriter, r *http.Request) {
|
||||
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)
|
||||
}
|
||||
|
||||
func GetChannelTopicDetail(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func GetChannelTopicSize(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)
|
||||
|
122
net/server/internal/api_getChannelTopic.go
Normal file
122
net/server/internal/api_getChannelTopic.go
Normal file
@ -0,0 +1,122 @@
|
||||
package databag
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"gorm.io/gorm"
|
||||
"github.com/gorilla/mux"
|
||||
"databag/internal/store"
|
||||
)
|
||||
|
||||
func GetChannelTopic(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// scan parameters
|
||||
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)
|
||||
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
|
||||
}
|
||||
|
||||
WriteResponse(w, getTopicModel(&topicSlot))
|
||||
}
|
||||
|
||||
func isMember(guid string, cards []store.Card) bool {
|
||||
for _, card := range cards {
|
||||
if guid == card.Guid {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isViewer(guid string, groups []store.Group) bool {
|
||||
for _, group := range groups {
|
||||
for _, card := range group.Cards {
|
||||
if guid == card.Guid {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getChannelSlot(r *http.Request, member bool) (slot store.ChannelSlot, guid string, err error, code int) {
|
||||
|
||||
// scan parameters
|
||||
params := mux.Vars(r)
|
||||
channelId := params["channelId"]
|
||||
|
||||
// validate contact access
|
||||
var account *store.Account
|
||||
tokenType := r.Header.Get("TokenType")
|
||||
if tokenType == APP_TOKENAPP {
|
||||
account, code, err = BearerAppToken(r, false);
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
guid = account.Guid
|
||||
} else if tokenType == APP_TOKENCONTACT {
|
||||
var card *store.Card
|
||||
card, code, err = BearerContactToken(r, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
account = &card.Account
|
||||
guid = card.Guid
|
||||
} else {
|
||||
err = errors.New("unknown token type")
|
||||
code = http.StatusBadRequest
|
||||
return
|
||||
}
|
||||
|
||||
// load channel
|
||||
if err = store.DB.Preload("Account").Preload("Channel.Cards").Preload("Channel.Groups.Cards").Where("account_id = ? AND channel_slot_id = ?", account.ID, channelId).First(&slot).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
code = http.StatusNotFound
|
||||
} else {
|
||||
code = http.StatusInternalServerError
|
||||
}
|
||||
return
|
||||
}
|
||||
if slot.Channel == nil {
|
||||
err = errors.New("referenced empty channel")
|
||||
code = http.StatusNotFound
|
||||
return
|
||||
}
|
||||
|
||||
// validate access to channel
|
||||
if tokenType == APP_TOKENCONTACT {
|
||||
if member && !isMember(guid, slot.Channel.Cards) {
|
||||
err = errors.New("contact is not a channel member")
|
||||
code = http.StatusUnauthorized
|
||||
return
|
||||
} else if !isViewer(guid, slot.Channel.Groups) && !isMember(guid, slot.Channel.Cards) {
|
||||
err = errors.New("contact is not a channel viewer")
|
||||
code = http.StatusUnauthorized
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
42
net/server/internal/api_getChannelTopicCount.go
Normal file
42
net/server/internal/api_getChannelTopicCount.go
Normal file
@ -0,0 +1,42 @@
|
||||
package databag
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"gorm.io/gorm"
|
||||
"github.com/gorilla/mux"
|
||||
"databag/internal/store"
|
||||
)
|
||||
|
||||
func GetChannelTopicCount(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// scan parameters
|
||||
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)
|
||||
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
|
||||
}
|
||||
|
||||
WriteResponse(w, getTopicCountModel(&topicSlot))
|
||||
}
|
||||
|
42
net/server/internal/api_getChannelTopicDetail.go
Normal file
42
net/server/internal/api_getChannelTopicDetail.go
Normal file
@ -0,0 +1,42 @@
|
||||
package databag
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"gorm.io/gorm"
|
||||
"github.com/gorilla/mux"
|
||||
"databag/internal/store"
|
||||
)
|
||||
|
||||
func GetChannelTopicDetail(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// scan parameters
|
||||
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)
|
||||
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
|
||||
}
|
||||
|
||||
WriteResponse(w, getTopicDetailModel(&topicSlot))
|
||||
}
|
||||
|
@ -213,8 +213,6 @@ func getChannelModel(slot *store.ChannelSlot, showData bool, showList bool) *Cha
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func getTopicRevisionModel(slot *store.TopicSlot, showData bool) *Topic {
|
||||
|
||||
if !showData || slot.Topic == nil {
|
||||
@ -234,9 +232,37 @@ func getTopicRevisionModel(slot *store.TopicSlot, showData bool) *Topic {
|
||||
}
|
||||
}
|
||||
|
||||
func getTopicModel(slot *store.TopicSlot, showData bool, showList bool) *Topic {
|
||||
func getTopicDetailModel(slot *store.TopicSlot) *TopicDetail {
|
||||
|
||||
if !showData || slot.Topic == nil {
|
||||
if slot.Topic == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &TopicDetail{
|
||||
Guid: slot.Topic.Guid,
|
||||
DataType: slot.Topic.DataType,
|
||||
Data: slot.Topic.Data,
|
||||
Created: slot.Topic.Created,
|
||||
Updated: slot.Topic.Updated,
|
||||
Status: slot.Topic.Status,
|
||||
}
|
||||
}
|
||||
|
||||
func getTopicCountModel(slot *store.TopicSlot) *TagCount {
|
||||
|
||||
if slot.Topic == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &TagCount{
|
||||
Count: slot.Topic.TagCount,
|
||||
Updated: slot.Topic.TagUpdated,
|
||||
}
|
||||
}
|
||||
|
||||
func getTopicModel(slot *store.TopicSlot) *Topic {
|
||||
|
||||
if slot.Topic == nil {
|
||||
return &Topic{
|
||||
Id: slot.TopicSlotId,
|
||||
Revision: slot.Revision,
|
||||
@ -248,22 +274,11 @@ func getTopicModel(slot *store.TopicSlot, showData bool, showList bool) *Topic {
|
||||
Revision: slot.Revision,
|
||||
Data: &TopicData {
|
||||
DetailRevision: slot.Topic.DetailRevision,
|
||||
TopicDetail: &TopicDetail{
|
||||
Guid: slot.Topic.Guid,
|
||||
DataType: slot.Topic.DataType,
|
||||
Data: slot.Topic.Data,
|
||||
Created: slot.Topic.Created,
|
||||
Updated: slot.Topic.Updated,
|
||||
Status: slot.Topic.Status,
|
||||
},
|
||||
TopicDetail: getTopicDetailModel(slot),
|
||||
TagRevision: slot.Topic.TagRevision,
|
||||
TopicTags: &TopicTags{
|
||||
TagCount: slot.Topic.TagCount,
|
||||
TagUpdated: slot.Topic.TagUpdated,
|
||||
},
|
||||
TopicTags: getTopicCountModel(slot),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -368,6 +368,13 @@ type Tag struct {
|
||||
Data *TagData `json:"data"`
|
||||
}
|
||||
|
||||
type TagCount struct {
|
||||
|
||||
Count int32 `json:"count"`
|
||||
|
||||
Updated int64 `json:"updated"`
|
||||
}
|
||||
|
||||
type TagData struct {
|
||||
|
||||
Guid string `json:"guid"`
|
||||
@ -398,7 +405,7 @@ type TopicData struct {
|
||||
|
||||
TopicDetail *TopicDetail `json:"topicDetail,omitempty"`
|
||||
|
||||
TopicTags *TopicTags `json:"topicTags:,omitempty"`
|
||||
TopicTags *TagCount `json:"topicTags:,omitempty"`
|
||||
}
|
||||
|
||||
type TopicDetail struct {
|
||||
|
@ -558,6 +558,13 @@ var routes = Routes{
|
||||
GetChannelSubjectField,
|
||||
},
|
||||
|
||||
Route{
|
||||
"GetChannelTopic",
|
||||
strings.ToUpper("Get"),
|
||||
"/content/channels/{channelId}/topics/{topicId}",
|
||||
GetChannelTopic,
|
||||
},
|
||||
|
||||
Route{
|
||||
"GetChannelTopicDetail",
|
||||
strings.ToUpper("Get"),
|
||||
@ -566,10 +573,10 @@ var routes = Routes{
|
||||
},
|
||||
|
||||
Route{
|
||||
"GetChannelTopicSize",
|
||||
"GetChannelTopicCount",
|
||||
strings.ToUpper("Get"),
|
||||
"/content/channels/{channelId}/topics/{topicId}/size",
|
||||
GetChannelTopicSize,
|
||||
"/content/channels/{channelId}/topics/{topicId}/count",
|
||||
GetChannelTopicCount,
|
||||
},
|
||||
|
||||
Route{
|
||||
|
@ -206,17 +206,18 @@ type Channel struct {
|
||||
|
||||
type TopicSlot struct {
|
||||
ID uint
|
||||
TopicSlotId string `gorm:"not null;index:topicslot,unique"`
|
||||
AccountID uint `gorm:"not null;index:topicslot,unique"`
|
||||
TopicSlotId string `gorm:"not null;index:topicaccount,unique;index:topicchannel,unique"`
|
||||
AccountID uint `gorm:"not null;index:topicaccount,unique"`
|
||||
ChannelID uint `gorm:"not null;index:topicchannel,unique"`
|
||||
Revision int64 `gorm:"not null"`
|
||||
TopicID uint `gorm:"not null;default:0"`
|
||||
Topic *Topic
|
||||
Channel *Channel
|
||||
Account Account
|
||||
}
|
||||
|
||||
type Topic struct {
|
||||
ID uint `gorm:"primaryKey;not null;unique;autoIncrement"`
|
||||
ChannelID uint
|
||||
DetailRevision int64 `gorm:"not null"`
|
||||
Guid string
|
||||
DataType string `gorm:"index"`
|
||||
@ -227,7 +228,6 @@ type Topic struct {
|
||||
TagCount int32 `gorm:"not null"`
|
||||
TagUpdated int64 `gorm:"autoUpdateTime"`
|
||||
TagRevision int64 `gorm:"not null"`
|
||||
Channel *Channel
|
||||
Assets []Asset
|
||||
Tags []Tag
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user