mirror of
https://github.com/balzack/databag.git
synced 2025-02-14 12:39:17 +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'
|
$ref: '#/components/schemas/Subject'
|
||||||
|
|
||||||
/content/channels/{channelId}:
|
/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:
|
delete:
|
||||||
tags:
|
tags:
|
||||||
- content
|
- content
|
||||||
@ -1919,37 +1948,6 @@ paths:
|
|||||||
description: account disabled
|
description: account disabled
|
||||||
'500':
|
'500':
|
||||||
description: internal server error
|
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}:
|
/content/channels/{channelId}/subject/{field}:
|
||||||
get:
|
get:
|
||||||
@ -2247,6 +2245,41 @@ paths:
|
|||||||
$ref: '#/components/schemas/Subject'
|
$ref: '#/components/schemas/Subject'
|
||||||
|
|
||||||
/content/channels/{channelId}/topics/{topicId}:
|
/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:
|
delete:
|
||||||
tags:
|
tags:
|
||||||
- content
|
- content
|
||||||
@ -2303,6 +2336,10 @@ paths:
|
|||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: success
|
description: success
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/TopicDetail'
|
||||||
'401':
|
'401':
|
||||||
description: invalid password
|
description: invalid password
|
||||||
'404':
|
'404':
|
||||||
@ -2312,12 +2349,12 @@ paths:
|
|||||||
'500':
|
'500':
|
||||||
description: internal server error
|
description: internal server error
|
||||||
|
|
||||||
/content/channels/{channelId}/topics/{topicId}/size:
|
/content/channels/{channelId}/topics/{topicId}/count:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
- content
|
- content
|
||||||
description: Get detail object of topic.
|
description: Get count of associated taghs.
|
||||||
operationId: get-channel-topic-size
|
operationId: get-channel-topic-count
|
||||||
security:
|
security:
|
||||||
- bearerAuth: []
|
- bearerAuth: []
|
||||||
parameters:
|
parameters:
|
||||||
@ -2336,6 +2373,10 @@ paths:
|
|||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: success
|
description: success
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/TagCount'
|
||||||
'401':
|
'401':
|
||||||
description: invalid password
|
description: invalid password
|
||||||
'404':
|
'404':
|
||||||
@ -3236,7 +3277,7 @@ components:
|
|||||||
topicDetail:
|
topicDetail:
|
||||||
$ref: '#/components/schemas/TopicDetail'
|
$ref: '#/components/schemas/TopicDetail'
|
||||||
topicTags::
|
topicTags::
|
||||||
$ref: '#/components/schemas/TopicTags'
|
$ref: '#/components/schemas/TagCount'
|
||||||
|
|
||||||
TopicDetail:
|
TopicDetail:
|
||||||
type: object
|
type: object
|
||||||
@ -3264,16 +3305,16 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
enum: [ unconfirmed, confirmed, complete, error ]
|
enum: [ unconfirmed, confirmed, complete, error ]
|
||||||
|
|
||||||
TopicTags:
|
TagCount:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- tagCount
|
- count
|
||||||
- tagUpdated
|
- updated
|
||||||
properties:
|
properties:
|
||||||
tagCount:
|
count:
|
||||||
type: integer
|
type: integer
|
||||||
format: int32
|
format: int32
|
||||||
tagUpdated:
|
updated:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
|
|
||||||
|
@ -1,81 +1,34 @@
|
|||||||
package databag
|
package databag
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"databag/internal/store"
|
"databag/internal/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
func AddChannelTopic(w http.ResponseWriter, r *http.Request) {
|
func AddChannelTopic(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
// scan parameters
|
|
||||||
params := mux.Vars(r)
|
|
||||||
channelId := params["channelId"]
|
|
||||||
|
|
||||||
var subject Subject
|
var subject Subject
|
||||||
if err := ParseRequest(r, w, &subject); err != nil {
|
if err := ParseRequest(r, w, &subject); err != nil {
|
||||||
ErrResponse(w, http.StatusBadRequest, err)
|
ErrResponse(w, http.StatusBadRequest, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var guid string
|
channelSlot, guid, err, code := getChannelSlot(r, false)
|
||||||
var act *store.Account
|
if err != nil {
|
||||||
tokenType := r.Header.Get("TokenType")
|
ErrResponse(w, code, err)
|
||||||
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"))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
act := &channelSlot.Account
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
topicSlot := &store.TopicSlot{}
|
topicSlot := &store.TopicSlot{}
|
||||||
err := store.DB.Transaction(func(tx *gorm.DB) error {
|
err = store.DB.Transaction(func(tx *gorm.DB) error {
|
||||||
|
|
||||||
// add new record
|
// add new record
|
||||||
topic := &store.Topic{}
|
topic := &store.Topic{}
|
||||||
topic.Data = subject.Data
|
topic.Data = subject.Data
|
||||||
topic.DataType = subject.DataType
|
topic.DataType = subject.DataType
|
||||||
topic.Channel = channelSlot.Channel
|
|
||||||
topic.TagCount = 0
|
topic.TagCount = 0
|
||||||
topic.Guid = guid
|
topic.Guid = guid
|
||||||
topic.DetailRevision = act.ChannelRevision + 1
|
topic.DetailRevision = act.ChannelRevision + 1
|
||||||
@ -86,6 +39,7 @@ func AddChannelTopic(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
topicSlot.TopicSlotId = uuid.New().String()
|
topicSlot.TopicSlotId = uuid.New().String()
|
||||||
topicSlot.AccountID = act.ID
|
topicSlot.AccountID = act.ID
|
||||||
|
topicSlot.ChannelID = channelSlot.Channel.ID
|
||||||
topicSlot.TopicID = topic.ID
|
topicSlot.TopicID = topic.ID
|
||||||
topicSlot.Revision = act.ChannelRevision + 1
|
topicSlot.Revision = act.ChannelRevision + 1
|
||||||
topicSlot.Topic = topic
|
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 {
|
if res := tx.Model(&channelSlot).Update("revision", act.ChannelRevision + 1).Error; res != nil {
|
||||||
return res
|
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 res
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -122,15 +76,7 @@ func AddChannelTopic(w http.ResponseWriter, r *http.Request) {
|
|||||||
for _, card := range cards {
|
for _, card := range cards {
|
||||||
SetContactChannelNotification(act, &card)
|
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)
|
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) {
|
func GetChannelTopicSubjectField(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||||
w.WriteHeader(http.StatusOK)
|
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 {
|
func getTopicRevisionModel(slot *store.TopicSlot, showData bool) *Topic {
|
||||||
|
|
||||||
if !showData || slot.Topic == nil {
|
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{
|
return &Topic{
|
||||||
Id: slot.TopicSlotId,
|
Id: slot.TopicSlotId,
|
||||||
Revision: slot.Revision,
|
Revision: slot.Revision,
|
||||||
@ -248,22 +274,11 @@ func getTopicModel(slot *store.TopicSlot, showData bool, showList bool) *Topic {
|
|||||||
Revision: slot.Revision,
|
Revision: slot.Revision,
|
||||||
Data: &TopicData {
|
Data: &TopicData {
|
||||||
DetailRevision: slot.Topic.DetailRevision,
|
DetailRevision: slot.Topic.DetailRevision,
|
||||||
TopicDetail: &TopicDetail{
|
TopicDetail: getTopicDetailModel(slot),
|
||||||
Guid: slot.Topic.Guid,
|
|
||||||
DataType: slot.Topic.DataType,
|
|
||||||
Data: slot.Topic.Data,
|
|
||||||
Created: slot.Topic.Created,
|
|
||||||
Updated: slot.Topic.Updated,
|
|
||||||
Status: slot.Topic.Status,
|
|
||||||
},
|
|
||||||
TagRevision: slot.Topic.TagRevision,
|
TagRevision: slot.Topic.TagRevision,
|
||||||
TopicTags: &TopicTags{
|
TopicTags: getTopicCountModel(slot),
|
||||||
TagCount: slot.Topic.TagCount,
|
|
||||||
TagUpdated: slot.Topic.TagUpdated,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -368,6 +368,13 @@ type Tag struct {
|
|||||||
Data *TagData `json:"data"`
|
Data *TagData `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TagCount struct {
|
||||||
|
|
||||||
|
Count int32 `json:"count"`
|
||||||
|
|
||||||
|
Updated int64 `json:"updated"`
|
||||||
|
}
|
||||||
|
|
||||||
type TagData struct {
|
type TagData struct {
|
||||||
|
|
||||||
Guid string `json:"guid"`
|
Guid string `json:"guid"`
|
||||||
@ -398,7 +405,7 @@ type TopicData struct {
|
|||||||
|
|
||||||
TopicDetail *TopicDetail `json:"topicDetail,omitempty"`
|
TopicDetail *TopicDetail `json:"topicDetail,omitempty"`
|
||||||
|
|
||||||
TopicTags *TopicTags `json:"topicTags:,omitempty"`
|
TopicTags *TagCount `json:"topicTags:,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type TopicDetail struct {
|
type TopicDetail struct {
|
||||||
|
@ -558,6 +558,13 @@ var routes = Routes{
|
|||||||
GetChannelSubjectField,
|
GetChannelSubjectField,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Route{
|
||||||
|
"GetChannelTopic",
|
||||||
|
strings.ToUpper("Get"),
|
||||||
|
"/content/channels/{channelId}/topics/{topicId}",
|
||||||
|
GetChannelTopic,
|
||||||
|
},
|
||||||
|
|
||||||
Route{
|
Route{
|
||||||
"GetChannelTopicDetail",
|
"GetChannelTopicDetail",
|
||||||
strings.ToUpper("Get"),
|
strings.ToUpper("Get"),
|
||||||
@ -566,10 +573,10 @@ var routes = Routes{
|
|||||||
},
|
},
|
||||||
|
|
||||||
Route{
|
Route{
|
||||||
"GetChannelTopicSize",
|
"GetChannelTopicCount",
|
||||||
strings.ToUpper("Get"),
|
strings.ToUpper("Get"),
|
||||||
"/content/channels/{channelId}/topics/{topicId}/size",
|
"/content/channels/{channelId}/topics/{topicId}/count",
|
||||||
GetChannelTopicSize,
|
GetChannelTopicCount,
|
||||||
},
|
},
|
||||||
|
|
||||||
Route{
|
Route{
|
||||||
|
@ -206,17 +206,18 @@ type Channel struct {
|
|||||||
|
|
||||||
type TopicSlot struct {
|
type TopicSlot struct {
|
||||||
ID uint
|
ID uint
|
||||||
TopicSlotId string `gorm:"not null;index:topicslot,unique"`
|
TopicSlotId string `gorm:"not null;index:topicaccount,unique;index:topicchannel,unique"`
|
||||||
AccountID uint `gorm:"not null;index:topicslot,unique"`
|
AccountID uint `gorm:"not null;index:topicaccount,unique"`
|
||||||
|
ChannelID uint `gorm:"not null;index:topicchannel,unique"`
|
||||||
Revision int64 `gorm:"not null"`
|
Revision int64 `gorm:"not null"`
|
||||||
TopicID uint `gorm:"not null;default:0"`
|
TopicID uint `gorm:"not null;default:0"`
|
||||||
Topic *Topic
|
Topic *Topic
|
||||||
|
Channel *Channel
|
||||||
Account Account
|
Account Account
|
||||||
}
|
}
|
||||||
|
|
||||||
type Topic struct {
|
type Topic struct {
|
||||||
ID uint `gorm:"primaryKey;not null;unique;autoIncrement"`
|
ID uint `gorm:"primaryKey;not null;unique;autoIncrement"`
|
||||||
ChannelID uint
|
|
||||||
DetailRevision int64 `gorm:"not null"`
|
DetailRevision int64 `gorm:"not null"`
|
||||||
Guid string
|
Guid string
|
||||||
DataType string `gorm:"index"`
|
DataType string `gorm:"index"`
|
||||||
@ -227,7 +228,6 @@ type Topic struct {
|
|||||||
TagCount int32 `gorm:"not null"`
|
TagCount int32 `gorm:"not null"`
|
||||||
TagUpdated int64 `gorm:"autoUpdateTime"`
|
TagUpdated int64 `gorm:"autoUpdateTime"`
|
||||||
TagRevision int64 `gorm:"not null"`
|
TagRevision int64 `gorm:"not null"`
|
||||||
Channel *Channel
|
|
||||||
Assets []Asset
|
Assets []Asset
|
||||||
Tags []Tag
|
Tags []Tag
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user