added revision filter for groups and cards

This commit is contained in:
Roland Osborne 2022-02-03 00:30:43 -08:00
parent 5932f177aa
commit 67ffe43c8c
9 changed files with 232 additions and 55 deletions

View File

@ -835,6 +835,13 @@ paths:
operationId: get-groups operationId: get-groups
security: security:
- bearerAuth: [] - bearerAuth: []
parameters:
- name: groupRevision
in: query
description: only return updated groups since specified revision
required: false
schema:
type: string
responses: responses:
'200': '200':
description: successful operation description: successful operation
@ -1524,6 +1531,30 @@ paths:
type: integer type: integer
format: int64 format: int64
/contact/label/revision:
put:
tags:
- contact
description: Set label revision for contact. This is intend to be invoked automatically anytime a contact updates their label or sharing. Access granted to contact tokens.
operationId: set-label-revision
security:
- bearerAuth: []
responses:
'200':
description: revision set
'401':
description: not authorized
'410':
description: account disabled
'500':
description: internal server error
requestBody:
content:
application/json:
schema:
type: integer
format: int64
/contact/view/revision: /contact/view/revision:
put: put:
tags: tags:
@ -2404,6 +2435,19 @@ paths:
operationId: get-labels operationId: get-labels
security: security:
- bearerAuth: [] - bearerAuth: []
parameters:
- name: viewRevision
in: query
description: only return updated if view matches
required: false
schema:
type: string
- name: labelRevision
in: query
description: only return updated if view matches
required: false
schema:
type: string
responses: responses:
'200': '200':
description: successful operation description: successful operation
@ -4068,30 +4112,21 @@ components:
node: node:
type: string type: string
CardData:
type: object
required:
- status
properties:
revision:
type: integer
format: int64
status:
type: string
enum: [ pending, confirmed, requested, connecting, connected ]
notes:
type: string
token:
type: string
groups:
type: array
items:
type: string
Card: Card:
type: object type: object
required: required:
- cardId - cardId
- cardData
properties:
cardId:
type: string
cardData:
$ref: '#/components/schemas/CardData'
CardData:
type: object
required:
- status
- cardProfile - cardProfile
- cardData - cardData
- notifiedProfile - notifiedProfile
@ -4110,9 +4145,23 @@ components:
notifiedContent: notifiedContent:
type: integer type: integer
format: int64 format: int64
notifiedLabel:
type: integer
format: int64
notifiedView: notifiedView:
type: integer type: integer
format: int64 format: int64
status:
type: string
enum: [ pending, confirmed, requested, connecting, connected ]
notes:
type: string
token:
type: string
groups:
type: array
items:
type: string
Asset: Asset:
type: object type: object
@ -4326,37 +4375,25 @@ components:
type: integer type: integer
format: int64 format: int64
ArticleView:
type: object
required:
- articleId
- revision
- tagRevision
properties:
articleId:
type: string
revision:
type: integer
format: int64
tagRevision:
type: integer
format: int64
Group: Group:
type: object type: object
required: required:
- groupId - groupId
- revision - groupData
properties:
groupId:
type: string
groupData:
$ref: '#/components/schemas/GroupData'
GroupData:
type: object
required:
- dataType - dataType
- data - data
- created - created
- updated - updated
properties: properties:
groupId:
type: string
revision:
type: integer
format: int64
dataType: dataType:
type: string type: string
data: data:
@ -4372,18 +4409,22 @@ components:
type: object type: object
required: required:
- labelId - labelId
- labelRevision - labelData
- type properties:
labelId:
type: string
labelData:
$ref: '#/components/schemas/LabelData'
LabelData:
type: object
required:
- dataType
- data - data
- created - created
- modified - modified
properties: properties:
labelId: dataType:
type: string
labelRevision:
type: integer
format: int64
type:
type: string type: string
data: data:
type: string type: string
@ -4544,4 +4585,3 @@ components:
scheme: bearer scheme: bearer

View File

@ -1,11 +1,22 @@
package databag package databag
import ( import (
"strconv"
"net/http" "net/http"
"databag/internal/store" "databag/internal/store"
) )
func GetCards(w http.ResponseWriter, r *http.Request) { func GetCards(w http.ResponseWriter, r *http.Request) {
var res error
var cardRevision int64
card := r.FormValue("cardRevision")
if card != "" {
if cardRevision, res = strconv.ParseInt(card, 10, 64); res != nil {
ErrResponse(w, http.StatusBadRequest, res)
return
}
}
account, code, err := BearerAppToken(r, false); account, code, err := BearerAppToken(r, false);
if err != nil { if err != nil {
@ -14,7 +25,7 @@ func GetCards(w http.ResponseWriter, r *http.Request) {
} }
var slots []store.CardSlot var slots []store.CardSlot
if err := store.DB.Preload("Card.Groups.GroupSlot").Where("account_id = ?", account.ID).Find(&slots).Error; err != nil { if err := store.DB.Preload("Card.Groups.GroupSlot").Where("account_id = ? AND revision > ?", account.ID, cardRevision).Find(&slots).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err) ErrResponse(w, http.StatusInternalServerError, err)
return return
} }

View File

@ -1,11 +1,22 @@
package databag package databag
import ( import (
"strconv"
"net/http" "net/http"
"databag/internal/store" "databag/internal/store"
) )
func GetGroups(w http.ResponseWriter, r *http.Request) { func GetGroups(w http.ResponseWriter, r *http.Request) {
var res error
var groupRevision int64
group := r.FormValue("groupRevision")
if group != "" {
if groupRevision, res = strconv.ParseInt(group, 10, 64); res != nil {
ErrResponse(w, http.StatusBadRequest, res)
return
}
}
account, code, err := BearerAppToken(r, false) account, code, err := BearerAppToken(r, false)
if err != nil { if err != nil {
@ -14,7 +25,7 @@ func GetGroups(w http.ResponseWriter, r *http.Request) {
} }
var slots []store.GroupSlot var slots []store.GroupSlot
if err := store.DB.Where("account_id = ?", account.ID).Find(&slots).Error; err != nil { if err := store.DB.Preload("Group").Where("account_id = ? AND revision > ?", account.ID, groupRevision).Find(&slots).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err) ErrResponse(w, http.StatusInternalServerError, err)
return return
} }

View File

@ -0,0 +1,49 @@
package databag
import (
"net/http"
"gorm.io/gorm"
"databag/internal/store"
)
func SetLabelRevision(w http.ResponseWriter, r *http.Request) {
card, code, err := BearerContactToken(r)
if err != nil {
ErrResponse(w, code, err)
return
}
var revision int64
if err := ParseRequest(r, w, &revision); err != nil {
ErrResponse(w, http.StatusBadRequest, err)
return
}
if err := NotifyProfileRevision(card, revision); err != nil {
ErrResponse(w, http.StatusInternalServerError, err)
return
}
WriteResponse(w, nil)
}
func NotifyLabelRevision(card *store.Card, revision int64) error {
act := &card.Account
err := store.DB.Transaction(func(tx *gorm.DB) error {
if res := tx.Model(card).Where("id = ?", card.ID).Update("notified_label", revision).Error; res != nil {
return res
}
if res := tx.Model(act).Where("id = ?", act.ID).Update("card_revision", act.CardRevision + 1).Error; res != nil {
return res
}
return nil
})
if err != nil {
return err
}
SetStatus(act)
return nil
}

View File

@ -22,6 +22,7 @@ const APP_CARDCONNECTING = "connecting"
const APP_CARDCONNECTED = "connected" const APP_CARDCONNECTED = "connected"
const APP_NOTIFYPROFILE = "profile" const APP_NOTIFYPROFILE = "profile"
const APP_NOTIFYCONTENT = "content" const APP_NOTIFYCONTENT = "content"
const APP_NOTIFYLABEL = "label"
const APP_NOTIFYVIEW = "view" const APP_NOTIFYVIEW = "view"
const APP_TOKENAPP = "app" const APP_TOKENAPP = "app"
const APP_TOKENCONTACT = "contact" const APP_TOKENCONTACT = "contact"

View File

@ -64,6 +64,10 @@ func SendLocalNotification(notification *store.Notification) {
if err := NotifyContentRevision(&card, notification.Revision); err != nil { if err := NotifyContentRevision(&card, notification.Revision); err != nil {
ErrMsg(err) ErrMsg(err)
} }
} else if notification.Module == APP_NOTIFYLABEL {
if err := NotifyLabelRevision(&card, notification.Revision); err != nil {
ErrMsg(err)
}
} else if notification.Module == APP_NOTIFYVIEW { } else if notification.Module == APP_NOTIFYVIEW {
if err := NotifyViewRevision(&card, notification.Revision); err != nil { if err := NotifyViewRevision(&card, notification.Revision); err != nil {
ErrMsg(err) ErrMsg(err)
@ -220,4 +224,59 @@ func SetContactViewNotification(account *store.Account, card *store.Card) {
} }
// notify all cards of label change
// account.Label incremented by adding, updating, removing a label & setting or clearning group from article
func SetLabelNotification(account *store.Account) {
// select all connected cards
var cards []store.Card
if err := store.DB.Where("account_id = ? AND status = ?", account.Guid, APP_CARDCONNECTED).Find(&cards).Error; err != nil {
ErrMsg(err)
return
}
// add new notification for each card
err := store.DB.Transaction(func(tx *gorm.DB) error {
for _, card := range cards {
notification := &store.Notification{
Node: card.Node,
Module: APP_NOTIFYLABEL,
Token: card.OutToken,
Revision: account.LabelRevision,
}
if err := tx.Save(notification).Error; err != nil {
return err
}
notify <- notification
}
return nil
})
if err != nil {
ErrMsg(err)
}
}
// notify single card of label change
// card.Label incremented by adding or removing group from label
func SetContactLabelNotification(account *store.Account, card *store.Card) {
if card.Status != APP_CARDCONNECTED {
return
}
// add new notification for card
notification := &store.Notification{
Node: card.Node,
Module: APP_NOTIFYLABEL,
Token: card.OutToken,
Revision: account.LabelRevision,
}
if res := store.DB.Save(notification).Error; res != nil {
ErrMsg(res)
} else {
notify <- notification
}
}

View File

@ -390,6 +390,13 @@ var routes = Routes{
SetContentRevision, SetContentRevision,
}, },
Route{
"SetLabelRevision",
strings.ToUpper("Put"),
"/contact/label/revision",
SetLabelRevision,
},
Route{ Route{
"SetOpenMessage", "SetOpenMessage",
strings.ToUpper("Put"), strings.ToUpper("Put"),

View File

@ -185,6 +185,7 @@ type Card struct {
ViewRevision int64 `gorm:"not null"` ViewRevision int64 `gorm:"not null"`
NotifiedView int64 NotifiedView int64
NotifiedContent int64 NotifiedContent int64
NotifiedLabel int64
NotifiedProfile int64 NotifiedProfile int64
Account Account `gorm:"references:Guid"` Account Account `gorm:"references:Guid"`
Groups []Group `gorm:"many2many:card_groups"` Groups []Group `gorm:"many2many:card_groups"`

View File

@ -17,8 +17,6 @@ func TestAddArticle(t *testing.T) {
set, err = AddTestGroup("addarticle") set, err = AddTestGroup("addarticle")
assert.NoError(t, err) assert.NoError(t, err)
PrintMsg(set)
// initial revision // initial revision
rev = GetTestRevision(set.B.Revisions) rev = GetTestRevision(set.B.Revisions)