diff --git a/net/server/internal/api_attribute.go b/net/server/internal/api_attribute.go index 5a06ae7a..4745ebd1 100644 --- a/net/server/internal/api_attribute.go +++ b/net/server/internal/api_attribute.go @@ -28,11 +28,6 @@ func GetArticleSubjectField(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) } -func GetArticles(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json; charset=UTF-8") - w.WriteHeader(http.StatusOK) -} - func RemoveArticle(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/api_getArticles.go b/net/server/internal/api_getArticles.go new file mode 100644 index 00000000..4059d824 --- /dev/null +++ b/net/server/internal/api_getArticles.go @@ -0,0 +1,108 @@ +package databag + +import ( + "errors" + "strconv" + "net/http" + "databag/internal/store" +) + +func GetArticles(w http.ResponseWriter, r *http.Request) { + var articleRevisionSet bool + var articleRevision int64 + var viewRevisionSet bool + var viewRevision int64 + + article := r.FormValue("articleRevision") + if article != "" { + var err error + articleRevisionSet = true + if articleRevision, err = strconv.ParseInt(article, 10, 64); err != nil { + ErrResponse(w, http.StatusBadRequest, err) + return + } + } + + view := r.FormValue("viewRevision") + if view != "" { + var err error + viewRevisionSet = true + if viewRevision, err = strconv.ParseInt(view, 10, 64); err != nil { + ErrResponse(w, http.StatusBadRequest, err) + return + } + } + + var response []*Article + tokenType := r.Header.Get("TokenType") + if tokenType == APP_TOKENAPP { + + account, code, err := BearerAppToken(r, false); + if err != nil { + ErrResponse(w, code, err) + return + } + + var slots []store.ArticleSlot + if articleRevisionSet { + if err := store.DB.Preload("Article.ArticleData").Where("account_id = ? AND revision > ?", account.ID, articleRevision).Find(&slots).Error; err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + } else { + if err := store.DB.Preload("Article.ArticleData").Where("account_id = ? AND article_id != 0", account.ID).Find(&slots).Error; err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + } + + for _, slot := range slots { + response = append(response, getArticleModel(&slot, true)) + } + + w.Header().Set("Article-Revision", strconv.FormatInt(account.ArticleRevision, 10)) + + } else if tokenType == APP_TOKENCONTACT { + + card, code, err := BearerContactToken(r, true) + if err != nil { + ErrResponse(w, code, err) + return + } + + if viewRevisionSet || articleRevisionSet { + if viewRevision != card.ViewRevision { + ErrResponse(w, http.StatusGone, errors.New("artivle view has changed")) + return + } + } + + account := &card.Account + var slots []store.ArticleSlot + if articleRevisionSet { + if err := store.DB.Preload("Article.ArticleData").Where("account_id = ? AND revision > ?", account.ID, articleRevision).Find(&slots).Error; err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + } else { + if err := store.DB.Preload("Article.ArticleData").Where("account_id = ? AND article_id != 0", account.ID).Find(&slots).Error; err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + } + + for _, slot := range slots { + response = append(response, getArticleModel(&slot, false)) + } + + w.Header().Set("Article-Revision", strconv.FormatInt(account.ArticleRevision, 10)) + w.Header().Set("View-Revision", strconv.FormatInt(card.ViewRevision, 10)) + + } else { + ErrResponse(w, http.StatusBadRequest, errors.New("invalid token type")) + return + } + + WriteResponse(w, response) +} + diff --git a/net/server/internal/modelUtil.go b/net/server/internal/modelUtil.go index a70e1924..866a2b09 100644 --- a/net/server/internal/modelUtil.go +++ b/net/server/internal/modelUtil.go @@ -115,4 +115,34 @@ func getGroupModel(slot *store.GroupSlot) *Group { } } +func getArticleModel(slot *store.ArticleSlot, showGroups bool) *Article { + if slot.Article == nil { + return &Article{ + Id: slot.ArticleSlotId, + Revision: slot.Revision, + } + } + + var articleGroups *ArticleGroups + if showGroups { + var groups []string; + for _, group := range slot.Article.Groups { + groups = append(groups, group.GroupSlot.GroupSlotId) + } + articleGroups = &ArticleGroups{ Groups: groups } + } + + return &Article{ + Id: slot.ArticleSlotId, + Revision: slot.Revision, + Data: &ArticleData { + DataType: slot.Article.DataType, + Data: slot.Article.Data, + Created: slot.Article.Created, + Updated: slot.Article.Updated, + Groups: articleGroups, + }, + } +} + diff --git a/net/server/internal/ucShareAttribute_test.go b/net/server/internal/ucShareAttribute_test.go new file mode 100644 index 00000000..94ecb26a --- /dev/null +++ b/net/server/internal/ucShareAttribute_test.go @@ -0,0 +1,20 @@ +package databag + +import ( + "testing" + "github.com/stretchr/testify/assert" +) + +func TestShareAttribute(t *testing.T) { + var articles []Article + + // setup testing group + set, err := AddTestGroup("shareattribute") + assert.NoError(t, err) + + assert.NoError(t, ApiTestMsg(GetArticles, "GET", "/attribute/articles", + nil, nil, APP_TOKENAPP, set.A.Token, &articles, nil)) + + PrintMsg(articles) +} +