diff --git a/net/server/internal/api_addArticle.go b/net/server/internal/api_addArticle.go index 7ecf7831..79e99621 100644 --- a/net/server/internal/api_addArticle.go +++ b/net/server/internal/api_addArticle.go @@ -55,6 +55,7 @@ func AddArticle(w http.ResponseWriter, r *http.Request) { article := &store.Article{ ArticleId: uuid.New().String(), + ArticleBlockID: articleBlock.ID, AccountID: account.ID, Revision: 1, Status: APP_ARTICLEUNCONFIRMED, @@ -91,13 +92,13 @@ func AddArticle(w http.ResponseWriter, r *http.Request) { WriteResponse(w, articleEntry) } -func addArticleBlock(account *store.Account, articleBlock *store.ArticleBlock) error { +func addArticleBlock(account *store.Account, articleBlock *store.ArticleBlock) (err error) { articleBlock.ArticleBlockId = uuid.New().String() articleBlock.AccountID = account.ID articleBlock.Revision = account.ContentRevision - if err := store.DB.Save(articleBlock).Error; err != nil { - return err + if err = store.DB.Save(articleBlock).Error; err != nil { + return } - return nil + return } diff --git a/net/server/internal/api_getArticleBlocks.go b/net/server/internal/api_getArticleBlocks.go index 37ad0562..a89ec42a 100644 --- a/net/server/internal/api_getArticleBlocks.go +++ b/net/server/internal/api_getArticleBlocks.go @@ -1,11 +1,102 @@ package databag import ( + "strings" + "strconv" + "errors" "net/http" + "gorm.io/gorm" + "databag/internal/store" ) func GetArticleBlocks(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json; charset=UTF-8") - w.WriteHeader(http.StatusOK) + var err error + + var contentRevision int64 + if contentRevision, err = getArticleBlockRevision(r.FormValue("contentRevision")); err != nil { + ErrMsg(err) + } + + // extract token + tokenType := r.Header.Get("TokenType") + auth := r.Header.Get("Authorization") + token := strings.TrimSpace(strings.TrimPrefix(auth, "Bearer")) + target, access, err := ParseToken(token) + if err != nil { + ErrResponse(w, http.StatusBadRequest, errors.New("invalid bearer token")) + return + } + + // retrieve updated blocks + var blocks []store.ArticleBlock + if tokenType == APP_TOKENAPP { + var app store.App + if err := store.DB.Preload("Account").Where("account_id = ? AND token = ?", target, access).First(&app).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + ErrResponse(w, http.StatusNotFound, err) + } else { + ErrResponse(w, http.StatusInternalServerError, err) + } + return + } + + // retrieve block ids + if err = getAccountArticleBlocks(&app.Account, contentRevision, &blocks); err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + } else if tokenType == APP_TOKENCONTACT { + var card store.Card + if err := store.DB.Preload("Account").Where("account_id = ? AND InToken = ?", target, access).First(&card).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + ErrResponse(w, http.StatusNotFound, err) + } else { + ErrResponse(w, http.StatusInternalServerError, err) + } + return + } + + var viewRevision int64 + if viewRevision, err = getArticleBlockRevision(r.FormValue("viewRevision")); err != nil { + ErrMsg(err) + } + + // retrieve block ids + if err = getCardArticleBlocks(&card, viewRevision, contentRevision, &blocks); err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + } else { + ErrResponse(w, http.StatusBadRequest, errors.New("invalid token type")) + } + + var ids []string + for _, block := range blocks { + ids = append(ids, block.ArticleBlockId) + } + WriteResponse(w, ids) } +func getArticleBlockRevision(param string) (rev int64, err error) { + if param == "" { + return + } + rev, err = strconv.ParseInt(param, 10, 64) + return +} + +func getAccountArticleBlocks(act *store.Account, content int64, blocks *[]store.ArticleBlock) error { + return store.DB.Where("revision > ? AND account_id = ?", content, act.ID).Find(blocks).Error +} + +func getCardArticleBlocks(card *store.Card, view int64, content int64, blocks *[]store.ArticleBlock) error { + if view != card.ViewRevision + card.Account.ViewRevision { + return store.DB.Where("revision > ? && account_id = ?", content, card.Account.ID).Find(blocks).Error + } else { + return store.DB.Where("account_id = ?", card.Account.ID).Find(blocks).Error + } +} + + + + diff --git a/net/server/internal/api_setCardStatus.go b/net/server/internal/api_setCardStatus.go index 3079d1b2..804096a9 100644 --- a/net/server/internal/api_setCardStatus.go +++ b/net/server/internal/api_setCardStatus.go @@ -22,6 +22,7 @@ func SetCardStatus(w http.ResponseWriter, r *http.Request) { params := mux.Vars(r) cardId := params["cardId"] token := r.FormValue("token") + var status string if err := ParseRequest(r, w, &status); err != nil { ErrResponse(w, http.StatusBadRequest, err) diff --git a/net/server/internal/store/schema.go b/net/server/internal/store/schema.go index 3ac370ba..b04f2042 100644 --- a/net/server/internal/store/schema.go +++ b/net/server/internal/store/schema.go @@ -176,7 +176,7 @@ type Article struct { ID uint `gorm:"primaryKey;not null;unique;autoIncrement"` ArticleId string `gorm:"not null;index:article,unique"` AccountID uint `gorm:"not null;index:article,unique"` - ArticleBlockID uint `gorm:"not null;index:articleblock"` + ArticleBlockID uint `gorm:"not null;index:articleblockid"` Revision int64 `gorm:"not null"` DataType string `gorm:"index"` Data string @@ -189,6 +189,7 @@ type Article struct { Groups []Group `gorm:"many2many:article_groups;"` Labels []Label `gorm:"many2many:article_labels;"` Account Account + ArticleBlock ArticleBlock } type ArticleAsset struct { diff --git a/net/server/internal/testUtil.go b/net/server/internal/testUtil.go index a3881e63..9b1975d0 100644 --- a/net/server/internal/testUtil.go +++ b/net/server/internal/testUtil.go @@ -53,6 +53,8 @@ func GetTestRevision(status chan *Revision) (rev *Revision) { func SendEndpointTest( endpoint func(http.ResponseWriter, *http.Request), + requestType string, + name string, params *map[string]string, body interface{}, token string, @@ -62,13 +64,14 @@ func SendEndpointTest( var r *http.Request var w *httptest.ResponseRecorder - if r, w, err = NewRequest("REST", "/NAME", body); err != nil { + if r, w, err = NewRequest(requestType, name, body); err != nil { return } if params != nil { r = mux.SetURLVars(r, *params) } if token != "" { + r.Header.Add("TokenType", APP_TOKENAPP) SetBearerAuth(r, token) } endpoint(w, r) diff --git a/net/server/internal/ucAddArticle_test.go b/net/server/internal/ucAddArticle_test.go index 3a3c5322..46777f96 100644 --- a/net/server/internal/ucAddArticle_test.go +++ b/net/server/internal/ucAddArticle_test.go @@ -11,6 +11,7 @@ func TestAddArticle(t *testing.T) { var rev *Revision var articleEntry ArticleEntry var contentRevision int64 + var ids []string // setup testing group set, err = AddTestGroup("addarticle") @@ -22,12 +23,17 @@ func TestAddArticle(t *testing.T) { // create article articleAccess := &ArticleAccess{ Groups: []string{set.A.B.GroupId} } - assert.NoError(t, SendEndpointTest(AddArticle, nil, articleAccess, set.A.Token, &articleEntry)) + assert.NoError(t, SendEndpointTest(AddArticle, "POST", "/content/articles", nil, articleAccess, set.A.Token, &articleEntry)) + PrintMsg(articleEntry); // check revisions rev = GetTestRevision(set.A.Revisions) assert.Greater(t, rev.Content, contentRevision) + // view article blocks + assert.NoError(t, SendEndpointTest(GetArticleBlocks, "GET", "/content/articleBlocks", nil, nil, set.A.Token, &ids)) + PrintMsg(ids) + // view article PrintMsg(rev)