mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
added filtering of articles
This commit is contained in:
parent
b1e0a17506
commit
a6ea2a7be1
@ -45,13 +45,14 @@ func AddArticle(w http.ResponseWriter, r *http.Request) {
|
||||
Status: APP_ARTICLEUNCONFIRMED,
|
||||
TagUpdated: time.Now().Unix(),
|
||||
TagRevision: 1,
|
||||
TagCount: 0,
|
||||
Labels: append(groups, labels...),
|
||||
};
|
||||
if res := store.DB.Save(articleData).Error; res != nil {
|
||||
return res;
|
||||
}
|
||||
|
||||
if res := store.DB.Where("article_data_id is null AND account_id = ?", account.ID).First(&article).Error; res != nil {
|
||||
if res := store.DB.Where("article_data_id = 0 AND account_id = ?", account.ID).First(&article).Error; res != nil {
|
||||
if errors.Is(res, gorm.ErrRecordNotFound) {
|
||||
article = &store.Article{
|
||||
ArticleId: uuid.New().String(),
|
||||
@ -73,6 +74,9 @@ func AddArticle(w http.ResponseWriter, r *http.Request) {
|
||||
if ret := store.DB.Preload("ArticleData.Labels.Groups").Where("id = ?", article.ID).First(article).Error; ret != nil {
|
||||
return ret;
|
||||
}
|
||||
if ret := tx.Model(&account).Update("content_revision", account.ContentRevision + 1).Error; ret != nil {
|
||||
return ret
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
@ -82,7 +86,7 @@ func AddArticle(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
SetContentNotification(account)
|
||||
SetStatus(account)
|
||||
WriteResponse(w, getArticleModel(article, 0))
|
||||
WriteResponse(w, getArticleModel(article, false, true))
|
||||
}
|
||||
|
||||
|
||||
|
@ -51,11 +51,6 @@ func AddGroup(w http.ResponseWriter, r *http.Request) {
|
||||
return res
|
||||
}
|
||||
|
||||
PrintMsg("ADDED")
|
||||
PrintMsg(group.GroupId)
|
||||
PrintMsg(label.LabelId)
|
||||
PrintMsg("***")
|
||||
|
||||
if res := tx.Model(&account).Update("group_revision", account.GroupRevision + 1).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
|
@ -88,21 +88,11 @@ func GetArticleTags(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 GetLabels(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)
|
||||
}
|
||||
|
||||
func RemoveArticleAsset(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
104
net/server/internal/api_getArticles.go
Normal file
104
net/server/internal/api_getArticles.go
Normal file
@ -0,0 +1,104 @@
|
||||
package databag
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"net/http"
|
||||
"databag/internal/store"
|
||||
)
|
||||
|
||||
func GetArticles(w http.ResponseWriter, r *http.Request) {
|
||||
var res error
|
||||
var viewRevision int64
|
||||
var contentRevision int64
|
||||
|
||||
view := r.FormValue("viewRevision")
|
||||
if view != "" {
|
||||
if viewRevision, res = strconv.ParseInt(view, 10, 64); res != nil {
|
||||
ErrResponse(w, http.StatusBadRequest, res)
|
||||
return
|
||||
}
|
||||
}
|
||||
content := r.FormValue("contentRevision")
|
||||
if content != "" {
|
||||
if contentRevision, res = strconv.ParseInt(content, 10, 64); res != nil {
|
||||
ErrResponse(w, http.StatusBadRequest, res)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
tokenType := r.Header.Get("TokenType")
|
||||
var response []*Article
|
||||
if tokenType == APP_TOKENAPP {
|
||||
|
||||
account, code, err := BearerAppToken(r, false)
|
||||
if err != nil {
|
||||
ErrResponse(w, code, err)
|
||||
return
|
||||
}
|
||||
|
||||
var articles []store.Article
|
||||
if err := getAccountArticles(account, contentRevision, &articles); err != nil {
|
||||
ErrResponse(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, article := range articles {
|
||||
response = append(response, getArticleModel(&article, false, true))
|
||||
}
|
||||
} else if tokenType == APP_TOKENCONTACT {
|
||||
|
||||
card, code, err := BearerContactToken(r)
|
||||
if err != nil {
|
||||
ErrResponse(w, code, err)
|
||||
return
|
||||
}
|
||||
|
||||
if viewRevision != card.ViewRevision + card.Account.ViewRevision {
|
||||
contentRevision = 0
|
||||
}
|
||||
|
||||
var articles []store.Article
|
||||
if err := getContactArticles(card, contentRevision, &articles); err != nil {
|
||||
ErrResponse(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, article := range articles {
|
||||
response = append(response, getArticleModel(&article, true, isShared(&article, card.Guid)))
|
||||
}
|
||||
} else {
|
||||
ErrResponse(w, http.StatusBadRequest, errors.New("invalid token type"))
|
||||
}
|
||||
|
||||
WriteResponse(w, response)
|
||||
}
|
||||
|
||||
// better if this filtering was done in gorm or sql
|
||||
func isShared(article *store.Article, guid string) bool {
|
||||
if article.ArticleData == nil {
|
||||
return false
|
||||
}
|
||||
for _, label := range article.ArticleData.Labels {
|
||||
for _, group := range label.Groups {
|
||||
for _, card := range group.Cards {
|
||||
if card.Guid == guid {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getAccountArticles(account *store.Account, revision int64, articles *[]store.Article) error {
|
||||
return store.DB.Preload("ArticleData.Labels.Groups").Where("account_id = ? AND revision > ?", account.ID, revision).Find(articles).Error
|
||||
}
|
||||
|
||||
func getContactArticles(card *store.Card, revision int64, articles *[]store.Article) error {
|
||||
return store.DB.Preload("ArticleData.Labels.Groups.Cards").Where("account_id = ? AND revision > ?", card.Account.ID, revision).Find(articles).Error
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
56
net/server/internal/api_removeArticle.go
Normal file
56
net/server/internal/api_removeArticle.go
Normal file
@ -0,0 +1,56 @@
|
||||
package databag
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"gorm.io/gorm"
|
||||
"github.com/gorilla/mux"
|
||||
"databag/internal/store"
|
||||
)
|
||||
|
||||
func RemoveArticle(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
account, code, err := BearerAppToken(r, false)
|
||||
if err != nil {
|
||||
ErrResponse(w, code, err)
|
||||
return
|
||||
}
|
||||
|
||||
params := mux.Vars(r)
|
||||
articleId := params["articleId"]
|
||||
|
||||
err = store.DB.Transaction(func(tx *gorm.DB) error {
|
||||
var article store.Article
|
||||
if res := store.DB.Preload("ArticleData").Where("account_id = ? AND article_id = ?", account.ID, articleId).First(&article).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
if article.ArticleData == nil {
|
||||
return nil
|
||||
}
|
||||
if res := tx.Delete(article.ArticleData).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
article.ArticleDataID = 0
|
||||
article.ArticleData = nil
|
||||
if res := tx.Save(&article).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
if res := tx.Model(&account).Update("content_revision", account.ContentRevision).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
ErrResponse(w, http.StatusNotFound, err)
|
||||
} else {
|
||||
ErrResponse(w, http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
SetContentNotification(account)
|
||||
SetStatus(account)
|
||||
WriteResponse(w, nil)
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ func BearerContactToken(r *http.Request) (*store.Card, int, error) {
|
||||
|
||||
// find token record
|
||||
var card store.Card
|
||||
if err := store.DB.Preload("Account").Where("account_id = ? AND InToken = ?", target, access).First(&card).Error; err != nil {
|
||||
if err := store.DB.Preload("Account").Where("account_id = ? AND in_token = ?", target, access).First(&card).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, http.StatusNotFound, err
|
||||
} else {
|
||||
|
@ -49,9 +49,9 @@ func getGroupModel(group *store.Group) *Group {
|
||||
}
|
||||
}
|
||||
|
||||
func getArticleModel(article *store.Article, tagCount int32) *Article {
|
||||
func getArticleModel(article *store.Article, contact bool, shared bool) *Article {
|
||||
|
||||
if article.ArticleData == nil {
|
||||
if !shared || article.ArticleData == nil {
|
||||
return &Article{
|
||||
ArticleId: article.ArticleId,
|
||||
Revision: article.Revision,
|
||||
@ -62,8 +62,10 @@ func getArticleModel(article *store.Article, tagCount int32) *Article {
|
||||
var groups []string;
|
||||
var labels []string;
|
||||
for _, label := range article.ArticleData.Labels {
|
||||
if label.Direct && len(label.Groups) > 0 {
|
||||
groups = append(groups, label.Groups[0].GroupId)
|
||||
if label.Direct {
|
||||
if !contact && len(label.Groups) > 0 {
|
||||
groups = append(groups, label.Groups[0].GroupId)
|
||||
}
|
||||
} else {
|
||||
labels = append(labels, label.LabelId)
|
||||
}
|
||||
@ -78,7 +80,7 @@ func getArticleModel(article *store.Article, tagCount int32) *Article {
|
||||
Status: article.ArticleData.Status,
|
||||
Labels: labels,
|
||||
Groups: groups,
|
||||
TagCount: tagCount,
|
||||
TagCount: article.ArticleData.TagCount,
|
||||
Created: article.ArticleData.Created,
|
||||
Updated: article.ArticleData.Updated,
|
||||
TagUpdated: article.ArticleData.TagUpdated,
|
||||
|
@ -106,6 +106,7 @@ type Group struct {
|
||||
Data string
|
||||
Created int64 `gorm:"autoCreateTime"`
|
||||
Updated int64 `gorm:"autoUpdateTime"`
|
||||
Cards []Card `gorm:"many2many:card_groups"`
|
||||
Label Label //reference to label for direct assignment to articles
|
||||
Account Account
|
||||
}
|
||||
@ -148,8 +149,8 @@ type Card struct {
|
||||
NotifiedView int64
|
||||
NotifiedContent int64
|
||||
NotifiedProfile int64
|
||||
Groups []Group `gorm:"many2many:card_groups;"`
|
||||
Account Account `gorm:"references:Guid"`
|
||||
Groups []Group `gorm:"many2many:card_groups"`
|
||||
}
|
||||
|
||||
type Asset struct {
|
||||
@ -172,7 +173,7 @@ type Article struct {
|
||||
ArticleId string `gorm:"not null;index:article,unique"`
|
||||
AccountID uint `gorm:"not null;index:article,unique"`
|
||||
Revision int64 `gorm:"not null"`
|
||||
ArticleDataID uint
|
||||
ArticleDataID uint `gorm:"not null;default:0"`
|
||||
ArticleData *ArticleData
|
||||
Account Account
|
||||
}
|
||||
@ -187,6 +188,7 @@ type ArticleData struct {
|
||||
Created int64 `gorm:"autoCreateTime"`
|
||||
Updated int64 `gorm:"autoUpdateTime"`
|
||||
TagUpdated int64 `gorm:"not null"`
|
||||
TagCount int32 `gorm:"not null"`
|
||||
TagRevision int64 `gorm:"not null"`
|
||||
Labels []Label `gorm:"many2many:article_labels;"`
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ func SendEndpointTest(
|
||||
name string,
|
||||
params *map[string]string,
|
||||
body interface{},
|
||||
tokenType string,
|
||||
token string,
|
||||
response interface{},
|
||||
) (err error) {
|
||||
@ -71,7 +72,7 @@ func SendEndpointTest(
|
||||
r = mux.SetURLVars(r, *params)
|
||||
}
|
||||
if token != "" {
|
||||
r.Header.Add("TokenType", APP_TOKENAPP)
|
||||
r.Header.Add("TokenType", tokenType)
|
||||
SetBearerAuth(r, token)
|
||||
}
|
||||
endpoint(w, r)
|
||||
@ -205,6 +206,7 @@ func AddTestGroup(prefix string) (*TestGroup, error) {
|
||||
if g.A.B.Token, err = GetCardToken(g.A.Token, g.A.B.CardId); err != nil {
|
||||
return g, err
|
||||
}
|
||||
|
||||
if g.B.A.Token, err = GetCardToken(g.B.Token, g.B.A.CardId); err != nil {
|
||||
return g, err
|
||||
}
|
||||
|
@ -10,24 +10,42 @@ func TestAddArticle(t *testing.T) {
|
||||
var err error
|
||||
var rev *Revision
|
||||
var article Article
|
||||
var articles *[]Article
|
||||
var articleAccess *ArticleAccess
|
||||
|
||||
// setup testing group
|
||||
set, err = AddTestGroup("addarticle")
|
||||
assert.NoError(t, err)
|
||||
|
||||
// initial revision
|
||||
rev = GetTestRevision(set.A.Revisions)
|
||||
rev = GetTestRevision(set.B.Revisions)
|
||||
|
||||
// create article
|
||||
articleAccess := &ArticleAccess{ Groups: []string{set.A.B.GroupId} }
|
||||
assert.NoError(t, SendEndpointTest(AddArticle, "POST", "/content/articles", nil, articleAccess, set.A.Token, &article))
|
||||
PrintMsg(article);
|
||||
articleAccess = &ArticleAccess{ Groups: []string{set.A.B.GroupId} }
|
||||
assert.NoError(t, SendEndpointTest(AddArticle, "POST", "/content/articles", nil, articleAccess, APP_TOKENAPP, set.A.Token, &article))
|
||||
|
||||
// check revisions
|
||||
rev = GetTestRevision(set.A.Revisions)
|
||||
assert.NoError(t, SendEndpointTest(AddArticle, "POST", "/content/articles", nil, articleAccess, APP_TOKENAPP, set.A.Token, &article))
|
||||
|
||||
assert.NoError(t, SendEndpointTest(RemoveArticle, "DELETE", "/content/articls/" + article.ArticleId, &map[string]string{"articleId": article.ArticleId }, nil, APP_TOKENAPP, set.A.Token, nil))
|
||||
|
||||
articles = &[]Article{}
|
||||
assert.NoError(t, SendEndpointTest(GetArticles, "GET", "/content/articles", nil, nil, APP_TOKENAPP, set.A.Token, articles))
|
||||
assert.Equal(t, 2, len(*articles))
|
||||
assert.True(t, (*articles)[0].ArticleData != nil || (*articles)[1].ArticleData != nil)
|
||||
assert.True(t, (*articles)[0].ArticleData == nil || (*articles)[1].ArticleData == nil)
|
||||
|
||||
articles = &[]Article{}
|
||||
assert.NoError(t, SendEndpointTest(GetArticles, "GET", "/content/articles", nil, nil, APP_TOKENCONTACT, set.B.A.Token, articles))
|
||||
assert.Equal(t, 2, len(*articles))
|
||||
assert.True(t, (*articles)[0].ArticleData != nil || (*articles)[1].ArticleData != nil)
|
||||
assert.True(t, (*articles)[0].ArticleData == nil || (*articles)[1].ArticleData == nil)
|
||||
|
||||
articles = &[]Article{}
|
||||
assert.NoError(t, SendEndpointTest(GetArticles, "GET", "/content/articles", nil, nil, APP_TOKENCONTACT, set.C.A.Token, articles))
|
||||
assert.Equal(t, 2, len(*articles))
|
||||
assert.True(t, (*articles)[0].ArticleData == nil && (*articles)[1].ArticleData == nil)
|
||||
|
||||
// view article
|
||||
assert.NotEqual(t, GetTestRevision(set.B.Revisions).Card, rev)
|
||||
|
||||
PrintMsg(rev)
|
||||
}
|
||||
|
@ -138,8 +138,6 @@ func TestGroupContact(t *testing.T) {
|
||||
vars["groupId"] = group.GroupId
|
||||
r = mux.SetURLVars(r, vars)
|
||||
SetBearerAuth(r, a)
|
||||
PrintMsg(group.GroupId)
|
||||
PrintMsg("REMOVED")
|
||||
RemoveGroup(w, r)
|
||||
assert.NoError(t, ReadResponse(w, &group))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user