adding addArticle endpoint

This commit is contained in:
Roland Osborne 2022-01-27 23:01:17 -08:00
parent 4298bd5b31
commit 1dc2ddcf39
9 changed files with 181 additions and 67 deletions

View File

@ -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

View 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))
}

View File

@ -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)

View File

@ -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 {

View File

@ -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,
}
}

View File

@ -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"`
} }

View File

@ -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

View File

@ -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
} }

View File

@ -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)
} }