mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
adding addArticle endpoint
This commit is contained in:
parent
4298bd5b31
commit
1dc2ddcf39
82
doc/api.oa3
82
doc/api.oa3
@ -1635,15 +1635,7 @@ paths:
|
|||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
$ref: '#/components/schemas/ArticleEntry'
|
||||||
properties:
|
|
||||||
blockId:
|
|
||||||
type: string
|
|
||||||
blockRevision:
|
|
||||||
type: integer
|
|
||||||
format: int64
|
|
||||||
article:
|
|
||||||
$ref: '#/components/schemas/Article'
|
|
||||||
'401':
|
'401':
|
||||||
description: permission denied
|
description: permission denied
|
||||||
'410':
|
'410':
|
||||||
@ -1654,19 +1646,7 @@ paths:
|
|||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
$ref: '#/components/schemas/ArticleAccess'
|
||||||
required:
|
|
||||||
- labels
|
|
||||||
- groups
|
|
||||||
properties:
|
|
||||||
labels:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
groups:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
/content/articles/{articleId}:
|
/content/articles/{articleId}:
|
||||||
get:
|
get:
|
||||||
@ -4025,6 +4005,36 @@ components:
|
|||||||
data:
|
data:
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
|
ArticleAccess:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- labels
|
||||||
|
- groups
|
||||||
|
properties:
|
||||||
|
labels:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
groups:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
ArticleEntry:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- blockId
|
||||||
|
- blockRevision
|
||||||
|
- article
|
||||||
|
properties:
|
||||||
|
blockId:
|
||||||
|
type: string
|
||||||
|
blockRevision:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
article:
|
||||||
|
$ref: '#/components/schemas/Article'
|
||||||
|
|
||||||
Account:
|
Account:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
@ -4251,19 +4261,6 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
enum: [ active, offsync, inactive, dismissed ]
|
enum: [ active, offsync, inactive, dismissed ]
|
||||||
|
|
||||||
Tunnel:
|
|
||||||
type: object
|
|
||||||
required:
|
|
||||||
- cardId
|
|
||||||
- type
|
|
||||||
properties:
|
|
||||||
cardId:
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
data:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
Topic:
|
Topic:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
@ -4310,11 +4307,11 @@ components:
|
|||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- articleId
|
- articleId
|
||||||
- articleRevision
|
- revision
|
||||||
- type
|
- dataType
|
||||||
- data
|
- data
|
||||||
- created
|
- created
|
||||||
- modified
|
- updated
|
||||||
- status
|
- status
|
||||||
- labels
|
- labels
|
||||||
- tagCount
|
- tagCount
|
||||||
@ -4323,22 +4320,22 @@ components:
|
|||||||
properties:
|
properties:
|
||||||
articleId:
|
articleId:
|
||||||
type: string
|
type: string
|
||||||
articleRevision:
|
revision:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
type:
|
dataType:
|
||||||
type: string
|
type: string
|
||||||
data:
|
data:
|
||||||
type: string
|
type: string
|
||||||
created:
|
created:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
modified:
|
updated:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
status:
|
status:
|
||||||
type: string
|
type: string
|
||||||
enum: [ unconfirmed, confirmed, complete, error ]
|
enum: [ unconfirmed, confirmed, incomplete, error ]
|
||||||
labels:
|
labels:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
@ -4555,3 +4552,4 @@ components:
|
|||||||
bearerAuth:
|
bearerAuth:
|
||||||
type: http
|
type: http
|
||||||
scheme: bearer
|
scheme: bearer
|
||||||
|
|
||||||
|
64
net/server/internal/api_addArticle.go
Normal file
64
net/server/internal/api_addArticle.go
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package databag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"databag/internal/store"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AddArticle(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
account, code, err := BearerAppToken(r, false)
|
||||||
|
if err != nil {
|
||||||
|
ErrResponse(w, code, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var articleAccess ArticleAccess
|
||||||
|
if err := ParseRequest(r, w, &articleAccess); err != nil {
|
||||||
|
ErrResponse(w, http.StatusBadRequest, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var groups []store.Group
|
||||||
|
if err := store.DB.Where("group_id IN ?", articleAccess.Groups).Find(&groups).Error; err != nil {
|
||||||
|
ErrResponse(w, http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var labels []store.Label
|
||||||
|
if err := store.DB.Where("label_id IN ?", articleAccess.Labels).Find(&labels).Error; err != nil {
|
||||||
|
ErrResponse(w, http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
article := &store.Article{
|
||||||
|
ArticleId: uuid.New().String(),
|
||||||
|
AccountID: account.ID,
|
||||||
|
Revision: 1,
|
||||||
|
Status: APP_ARTICLEUNCONFIRMED,
|
||||||
|
Expires: 0,
|
||||||
|
TagUpdated: 0,
|
||||||
|
TagRevision: 0,
|
||||||
|
Groups: groups,
|
||||||
|
Labels: labels,
|
||||||
|
}
|
||||||
|
err = store.DB.Transaction(func(tx *gorm.DB) error {
|
||||||
|
if res := store.DB.Save(article).Error; res != nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
if res := store.DB.Model(&account).Update("content_revision", account.ContentRevision + 1).Error; res != nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ErrResponse(w, http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
SetStatus(account)
|
||||||
|
SetContentNotification(account)
|
||||||
|
WriteResponse(w, getArticleModel(article, 0))
|
||||||
|
}
|
@ -13,11 +13,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func AddArticle(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddArticleAsset(w http.ResponseWriter, r *http.Request) {
|
func AddArticleAsset(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)
|
||||||
|
@ -25,6 +25,10 @@ const APP_MODULECONTENT = "content"
|
|||||||
const APP_TOKENAPP = "app"
|
const APP_TOKENAPP = "app"
|
||||||
const APP_TOKENCONTACT = "contact"
|
const APP_TOKENCONTACT = "contact"
|
||||||
const APP_NOTIFYBUFFER = 4096
|
const APP_NOTIFYBUFFER = 4096
|
||||||
|
const APP_ARTICLEUNCONFIRMED = "unconfirmed"
|
||||||
|
const APP_ARTICLECONFIRMED = "confirmed"
|
||||||
|
const APP_ARTICLEINCOMPLETE = "incomplete"
|
||||||
|
const APP_ARTICLEERROR = "error"
|
||||||
|
|
||||||
func AppCardStatus(status string) bool {
|
func AppCardStatus(status string) bool {
|
||||||
if status == APP_CARDPENDING {
|
if status == APP_CARDPENDING {
|
||||||
|
@ -47,3 +47,34 @@ func getGroupModel(group *store.Group) *Group {
|
|||||||
Updated: group.Updated,
|
Updated: group.Updated,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getArticleModel(article *store.Article, tagCount int32) *Article {
|
||||||
|
|
||||||
|
// populate group id list
|
||||||
|
var groups []string;
|
||||||
|
for _, group := range article.Groups {
|
||||||
|
groups = append(groups, group.GroupId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// populate label id list
|
||||||
|
var labels []string;
|
||||||
|
for _, label := range article.Labels {
|
||||||
|
labels = append(labels, label.LabelId)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Article{
|
||||||
|
ArticleId: article.ArticleId,
|
||||||
|
Revision: article.Revision,
|
||||||
|
DataType: article.DataType,
|
||||||
|
Data: article.Data,
|
||||||
|
Created: article.Created,
|
||||||
|
Updated: article.Updated,
|
||||||
|
Status: article.Status,
|
||||||
|
Labels: labels,
|
||||||
|
Groups: groups,
|
||||||
|
TagCount: tagCount,
|
||||||
|
TagUpdated: article.TagUpdated,
|
||||||
|
TagRevision: article.TagRevision,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,17 @@ type AppData struct {
|
|||||||
Image string `json:"image,omitempty"`
|
Image string `json:"image,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ArticleAccess struct {
|
||||||
|
Labels []string `json:"labels"`
|
||||||
|
Groups []string `json:"groups"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ArticleEntry struct {
|
||||||
|
BlockId string `json:"blockId"`
|
||||||
|
BlockRevision int64 `json:"blockRevision"`
|
||||||
|
Article *Article `json:"article"`
|
||||||
|
}
|
||||||
|
|
||||||
type Subject struct {
|
type Subject struct {
|
||||||
DataType string `json:"dataType"`
|
DataType string `json:"dataType"`
|
||||||
Data string `json:"data"`
|
Data string `json:"data"`
|
||||||
@ -45,16 +56,16 @@ type Subject struct {
|
|||||||
|
|
||||||
type Article struct {
|
type Article struct {
|
||||||
ArticleId string `json:"articleId"`
|
ArticleId string `json:"articleId"`
|
||||||
ArticleRevision int64 `json:"articleRevision"`
|
Revision int64 `json:"revision"`
|
||||||
Type_ string `json:"type"`
|
DataType string `json:"type"`
|
||||||
Data string `json:"data"`
|
Data string `json:"data"`
|
||||||
Created int64 `json:"created"`
|
Created int64 `json:"created"`
|
||||||
Modified int64 `json:"modified"`
|
Updated int64 `json:"updated"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
Labels []string `json:"labels"`
|
Labels []string `json:"labels"`
|
||||||
Groups []string `json:"groups,omitempty"`
|
Groups []string `json:"groups,omitempty"`
|
||||||
TagCount int32 `json:"tagCount"`
|
TagCount int32 `json:"tagCount"`
|
||||||
TagUpdate int64 `json:"tagUpdate,omitempty"`
|
TagUpdated int64 `json:"tagUpdated,omitempty"`
|
||||||
TagRevision int64 `json:"tagRevision"`
|
TagRevision int64 `json:"tagRevision"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ type Article struct {
|
|||||||
Created int64 `gorm:"autoCreateTime"`
|
Created int64 `gorm:"autoCreateTime"`
|
||||||
Updated int64 `gorm:"autoUpdateTime"`
|
Updated int64 `gorm:"autoUpdateTime"`
|
||||||
TagUpdated int64 `gorm:"not null"`
|
TagUpdated int64 `gorm:"not null"`
|
||||||
TagRevision uint64 `gorm:"not null"`
|
TagRevision int64 `gorm:"not null"`
|
||||||
Groups []Group `gorm:"many2many:article_groups;"`
|
Groups []Group `gorm:"many2many:article_groups;"`
|
||||||
Labels []Label `gorm:"many2many:article_labels;"`
|
Labels []Label `gorm:"many2many:article_labels;"`
|
||||||
Account Account
|
Account Account
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const TEST_READDEADLINE = 2
|
const TEST_READDEADLINE = 2
|
||||||
const TEST_REVISIONWAIT = 250
|
const TEST_REVISIONWAIT = 100
|
||||||
|
|
||||||
type TestCard struct {
|
type TestCard struct {
|
||||||
Guid string
|
Guid string
|
||||||
@ -91,11 +91,11 @@ func SendEndpointTest(
|
|||||||
// | \ /|
|
// | \ /|
|
||||||
// | requested,nogroup confirmed,group |
|
// | requested,nogroup confirmed,group |
|
||||||
// | |
|
// | |
|
||||||
// requested,group ,
|
// connected,group ,
|
||||||
// |
|
// |
|
||||||
// --x--
|
// --x--
|
||||||
// |
|
// |
|
||||||
// confirmed,group ,
|
// connected,group ,
|
||||||
// | |
|
// | |
|
||||||
// | confirmed,nogroup pending,nogroup |
|
// | confirmed,nogroup pending,nogroup |
|
||||||
// |/ \|
|
// |/ \|
|
||||||
@ -177,6 +177,9 @@ func AddTestGroup(prefix string) (*TestGroup, error) {
|
|||||||
if g.C.A.CardId, err = AddTestCard(g.C.Token, g.A.Token); err != nil {
|
if g.C.A.CardId, err = AddTestCard(g.C.Token, g.A.Token); err != nil {
|
||||||
return g, err
|
return g, err
|
||||||
}
|
}
|
||||||
|
if err = OpenTestCard(g.C.Token, g.C.A.CardId); err != nil {
|
||||||
|
return g, err
|
||||||
|
}
|
||||||
if g.C.A.GroupId, err = GroupTestCard(g.C.Token, g.C.A.CardId); err != nil {
|
if g.C.A.GroupId, err = GroupTestCard(g.C.Token, g.C.A.CardId); err != nil {
|
||||||
return g, err
|
return g, err
|
||||||
}
|
}
|
||||||
@ -202,6 +205,9 @@ func AddTestGroup(prefix string) (*TestGroup, error) {
|
|||||||
if g.B.A.Token, err = GetCardToken(g.B.Token, g.B.A.CardId); err != nil {
|
if g.B.A.Token, err = GetCardToken(g.B.Token, g.B.A.CardId); err != nil {
|
||||||
return g, err
|
return g, err
|
||||||
}
|
}
|
||||||
|
if g.C.A.Token, err = GetCardToken(g.C.Token, g.C.A.CardId); err != nil {
|
||||||
|
return g, err
|
||||||
|
}
|
||||||
if g.C.D.Token, err = GetCardToken(g.C.Token, g.C.D.CardId); err != nil {
|
if g.C.D.Token, err = GetCardToken(g.C.Token, g.C.D.CardId); err != nil {
|
||||||
return g, err
|
return g, err
|
||||||
}
|
}
|
||||||
@ -217,18 +223,21 @@ func AddTestGroup(prefix string) (*TestGroup, error) {
|
|||||||
g.A.Revisions = make(chan *Revision, 64)
|
g.A.Revisions = make(chan *Revision, 64)
|
||||||
g.A.Revisions <- rev
|
g.A.Revisions <- rev
|
||||||
go MonitorStatus(ws, &g.A);
|
go MonitorStatus(ws, &g.A);
|
||||||
|
rev = &Revision{}
|
||||||
if ws, err = StatusConnection(g.B.Token, rev); err != nil {
|
if ws, err = StatusConnection(g.B.Token, rev); err != nil {
|
||||||
return g, err
|
return g, err
|
||||||
}
|
}
|
||||||
g.B.Revisions = make(chan *Revision, 64)
|
g.B.Revisions = make(chan *Revision, 64)
|
||||||
g.B.Revisions <- rev
|
g.B.Revisions <- rev
|
||||||
go MonitorStatus(ws, &g.B);
|
go MonitorStatus(ws, &g.B);
|
||||||
|
rev = &Revision{}
|
||||||
if ws, err = StatusConnection(g.C.Token, rev); err != nil {
|
if ws, err = StatusConnection(g.C.Token, rev); err != nil {
|
||||||
return g, err
|
return g, err
|
||||||
}
|
}
|
||||||
g.C.Revisions = make(chan *Revision, 64)
|
g.C.Revisions = make(chan *Revision, 64)
|
||||||
g.C.Revisions <- rev
|
g.C.Revisions <- rev
|
||||||
go MonitorStatus(ws, &g.C);
|
go MonitorStatus(ws, &g.C);
|
||||||
|
rev = &Revision{}
|
||||||
if ws, err = StatusConnection(g.D.Token, rev); err != nil {
|
if ws, err = StatusConnection(g.D.Token, rev); err != nil {
|
||||||
return g, err
|
return g, err
|
||||||
}
|
}
|
||||||
|
@ -9,24 +9,26 @@ func TestAddArticle(t *testing.T) {
|
|||||||
var set *TestGroup
|
var set *TestGroup
|
||||||
var err error
|
var err error
|
||||||
var rev *Revision
|
var rev *Revision
|
||||||
|
var article Article
|
||||||
|
var contentRevision int64
|
||||||
|
|
||||||
// setup testing group
|
// setup testing group
|
||||||
set, err = AddTestGroup("addarticle1")
|
set, err = AddTestGroup("addarticle")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// initial revision
|
||||||
rev = GetTestRevision(set.A.Revisions)
|
rev = GetTestRevision(set.A.Revisions)
|
||||||
assert.NotNil(t, rev)
|
contentRevision = rev.Content
|
||||||
|
|
||||||
|
|
||||||
// EXAMPLE
|
|
||||||
subject := &Subject{
|
|
||||||
}
|
|
||||||
var group Group
|
|
||||||
assert.NoError(t, SendEndpointTest(AddGroup, nil, subject, set.A.Token, &group))
|
|
||||||
PrintMsg(group)
|
|
||||||
|
|
||||||
// create article
|
// create article
|
||||||
|
articleAccess := &ArticleAccess{ Groups: []string{set.A.B.GroupId} }
|
||||||
|
assert.NoError(t, SendEndpointTest(AddArticle, nil, articleAccess, set.A.Token, &article))
|
||||||
|
|
||||||
// check content revision
|
// check revisions
|
||||||
|
rev = GetTestRevision(set.A.Revisions)
|
||||||
|
assert.Greater(t, rev.Content, contentRevision)
|
||||||
|
|
||||||
// check contact revisions
|
// view article
|
||||||
|
|
||||||
|
PrintMsg(rev)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user