mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
added revision filter for groups and cards
This commit is contained in:
parent
5932f177aa
commit
67ffe43c8c
142
doc/api.oa3
142
doc/api.oa3
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
49
net/server/internal/api_setLabelRevision.go
Normal file
49
net/server/internal/api_setLabelRevision.go
Normal 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
|
||||||
|
}
|
||||||
|
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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"),
|
||||||
|
@ -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"`
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user