diff --git a/doc/api.oa3 b/doc/api.oa3 index 7a02d9df..4974b0f4 100644 --- a/doc/api.oa3 +++ b/doc/api.oa3 @@ -1635,15 +1635,7 @@ paths: content: application/json: schema: - type: object - properties: - blockId: - type: string - blockRevision: - type: integer - format: int64 - article: - $ref: '#/components/schemas/Article' + $ref: '#/components/schemas/ArticleEntry' '401': description: permission denied '410': @@ -1654,19 +1646,7 @@ paths: content: application/json: schema: - type: object - required: - - labels - - groups - properties: - labels: - type: array - items: - type: string - groups: - type: array - items: - type: string + $ref: '#/components/schemas/ArticleAccess' /content/articles/{articleId}: get: @@ -4025,6 +4005,36 @@ components: data: 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: type: object required: @@ -4251,19 +4261,6 @@ components: type: string enum: [ active, offsync, inactive, dismissed ] - Tunnel: - type: object - required: - - cardId - - type - properties: - cardId: - type: string - type: - type: string - data: - type: string - Topic: type: object required: @@ -4310,11 +4307,11 @@ components: type: object required: - articleId - - articleRevision - - type + - revision + - dataType - data - created - - modified + - updated - status - labels - tagCount @@ -4323,22 +4320,22 @@ components: properties: articleId: type: string - articleRevision: + revision: type: integer format: int64 - type: + dataType: type: string data: type: string created: type: integer format: int64 - modified: + updated: type: integer format: int64 status: type: string - enum: [ unconfirmed, confirmed, complete, error ] + enum: [ unconfirmed, confirmed, incomplete, error ] labels: type: array items: @@ -4555,3 +4552,4 @@ components: bearerAuth: type: http scheme: bearer + diff --git a/net/server/internal/api_addArticle.go b/net/server/internal/api_addArticle.go new file mode 100644 index 00000000..73970352 --- /dev/null +++ b/net/server/internal/api_addArticle.go @@ -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)) +} diff --git a/net/server/internal/api_content.go b/net/server/internal/api_content.go index 1df22e91..b0b4c17a 100644 --- a/net/server/internal/api_content.go +++ b/net/server/internal/api_content.go @@ -13,11 +13,6 @@ import ( "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) { w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.WriteHeader(http.StatusOK) diff --git a/net/server/internal/appValues.go b/net/server/internal/appValues.go index a12ef381..0bed51fd 100644 --- a/net/server/internal/appValues.go +++ b/net/server/internal/appValues.go @@ -25,6 +25,10 @@ const APP_MODULECONTENT = "content" const APP_TOKENAPP = "app" const APP_TOKENCONTACT = "contact" 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 { if status == APP_CARDPENDING { diff --git a/net/server/internal/modelUtil.go b/net/server/internal/modelUtil.go index dea81c77..b779af5b 100644 --- a/net/server/internal/modelUtil.go +++ b/net/server/internal/modelUtil.go @@ -47,3 +47,34 @@ func getGroupModel(group *store.Group) *Group { 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, + } +} + diff --git a/net/server/internal/models.go b/net/server/internal/models.go index bb95249a..43c67a57 100644 --- a/net/server/internal/models.go +++ b/net/server/internal/models.go @@ -38,6 +38,17 @@ type AppData struct { 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 { DataType string `json:"dataType"` Data string `json:"data"` @@ -45,16 +56,16 @@ type Subject struct { type Article struct { ArticleId string `json:"articleId"` - ArticleRevision int64 `json:"articleRevision"` - Type_ string `json:"type"` + Revision int64 `json:"revision"` + DataType string `json:"type"` Data string `json:"data"` Created int64 `json:"created"` - Modified int64 `json:"modified"` + Updated int64 `json:"updated"` Status string `json:"status"` Labels []string `json:"labels"` Groups []string `json:"groups,omitempty"` TagCount int32 `json:"tagCount"` - TagUpdate int64 `json:"tagUpdate,omitempty"` + TagUpdated int64 `json:"tagUpdated,omitempty"` TagRevision int64 `json:"tagRevision"` } diff --git a/net/server/internal/store/schema.go b/net/server/internal/store/schema.go index 772ad249..6fd3a202 100644 --- a/net/server/internal/store/schema.go +++ b/net/server/internal/store/schema.go @@ -174,7 +174,7 @@ type Article struct { Created int64 `gorm:"autoCreateTime"` Updated int64 `gorm:"autoUpdateTime"` TagUpdated int64 `gorm:"not null"` - TagRevision uint64 `gorm:"not null"` + TagRevision int64 `gorm:"not null"` Groups []Group `gorm:"many2many:article_groups;"` Labels []Label `gorm:"many2many:article_labels;"` Account Account diff --git a/net/server/internal/testUtil.go b/net/server/internal/testUtil.go index 19d7243f..a3881e63 100644 --- a/net/server/internal/testUtil.go +++ b/net/server/internal/testUtil.go @@ -13,7 +13,7 @@ import ( ) const TEST_READDEADLINE = 2 -const TEST_REVISIONWAIT = 250 +const TEST_REVISIONWAIT = 100 type TestCard struct { Guid string @@ -91,11 +91,11 @@ func SendEndpointTest( // | \ /| // | requested,nogroup confirmed,group | // | | -// requested,group , +// connected,group , // | // --x-- // | -// confirmed,group , +// connected,group , // | | // | 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 { 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 { 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 { 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 { return g, err } @@ -217,18 +223,21 @@ func AddTestGroup(prefix string) (*TestGroup, error) { g.A.Revisions = make(chan *Revision, 64) g.A.Revisions <- rev go MonitorStatus(ws, &g.A); + rev = &Revision{} if ws, err = StatusConnection(g.B.Token, rev); err != nil { return g, err } g.B.Revisions = make(chan *Revision, 64) g.B.Revisions <- rev go MonitorStatus(ws, &g.B); + rev = &Revision{} if ws, err = StatusConnection(g.C.Token, rev); err != nil { return g, err } g.C.Revisions = make(chan *Revision, 64) g.C.Revisions <- rev go MonitorStatus(ws, &g.C); + rev = &Revision{} if ws, err = StatusConnection(g.D.Token, rev); err != nil { return g, err } diff --git a/net/server/internal/ucAddArticle_test.go b/net/server/internal/ucAddArticle_test.go index 5baabec0..17678a62 100644 --- a/net/server/internal/ucAddArticle_test.go +++ b/net/server/internal/ucAddArticle_test.go @@ -9,24 +9,26 @@ func TestAddArticle(t *testing.T) { var set *TestGroup var err error var rev *Revision + var article Article + var contentRevision int64 // setup testing group - set, err = AddTestGroup("addarticle1") + set, err = AddTestGroup("addarticle") assert.NoError(t, err) + + // initial revision rev = GetTestRevision(set.A.Revisions) - assert.NotNil(t, rev) - - - // EXAMPLE - subject := &Subject{ - } - var group Group - assert.NoError(t, SendEndpointTest(AddGroup, nil, subject, set.A.Token, &group)) - PrintMsg(group) + contentRevision = rev.Content // 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) }