restoring profile update test

This commit is contained in:
Roland Osborne 2022-02-08 23:54:09 -08:00
parent 873e35a292
commit 0beabeb713
8 changed files with 285 additions and 100 deletions

View File

@ -43,12 +43,12 @@ paths:
'200':
description: Awaiting announce
/admin/status:
/admin/available:
get:
tags:
- admin
description: Check if portal params have been set
operationId: get-node-status
operationId: get-node-available
responses:
'200':
description: success
@ -58,11 +58,13 @@ paths:
type: boolean
'500':
description: internal server error
put:
/admin/claim:
post:
tags:
- admin
description: Set admin password and node domain
operationId: set-node-status
operationId: set-node-claim
security:
- basicCredentials: []
parameters:
@ -267,12 +269,12 @@ paths:
type: string
format: binary
/account/public/status:
/account/public/available:
get:
tags:
- account
description: Check if a public account can be created.
operationId: get-public-status
operationId: get-public-available
responses:
'200':
description: success
@ -981,7 +983,7 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/DataMessage'
$ref: '#/components/schemas/Card'
'400':
description: invalid data message
'401':
@ -990,8 +992,42 @@ paths:
description: account disabled
'500':
description: internal server error
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/DataMessage'
/contact/cards/{cardId}:
get:
tags:
- contact
description: get card entry. Access granted to app tokens of account holder.
operationId: get-card
security:
- bearerAuth: []
parameters:
- name: cardId
in: path
description: specified card id
required: true
schema:
type: string
responses:
'200':
description: success
content:
application/json:
schema:
$ref: '#/components/schemas/Card'
'401':
description: permission denied
'404':
description: card not found
'410':
description: account disabled
'500':
description: internal server error
delete:
tags:
- contact
@ -1039,30 +1075,6 @@ paths:
required: false # required for connected
schema:
type: string
- name: profileRevision
in: query
description: profile revision of contact
required: false # required for connected
schema:
type: string
- name: articleRevision
in: query
description: article revision of contact
required: false # required for connected
schema:
type: string
- name: channelRevision
in: query
description: channel revision of contact
required: false # required for connected
schema:
type: string
- name: viewRevision
in: query
description: view revision of contact
required: false # required for connected
schema:
type: string
responses:
'200':
description: success
@ -1181,6 +1193,18 @@ paths:
responses:
'200':
description: successful operation
content:
application/json:
schema:
type: object
required:
- status
properties:
token:
type: string
status:
type: string
enum: [ pending, confirmed, requested, connecting, connected ]
'400':
description: invalid data message
'410':
@ -1484,36 +1508,12 @@ paths:
type: integer
format: int64
/contact/article/revision:
/contact/content/revision:
put:
tags:
- contact
description: Set artcile revision for contact. This is intend to be invoked automatically anytime a contact updates their content or sharing. Access granted to contact tokens.
operationId: set-article-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/channel/revision:
put:
tags:
- contact
description: Set channel revision for contact. This is intend to be invoked automatically anytime a contact updates their content or sharing. Access granted to contact tokens.
operationId: set-channel-revision
description: Set content revision for contact. This is intend to be invoked automatically anytime a contact updates their content or sharing. Access granted to contact tokens.
operationId: set-content-revision
security:
- bearerAuth: []
responses:
@ -1726,7 +1726,15 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/Subject'
type: object
required:
- type
- data
properties:
type:
type: string
data:
type: string
/attribute/articles/{articleId}/groups/{groupId}:
put:
@ -2367,7 +2375,15 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/Subject'
type: object
required:
- type
- data
properties:
type:
type: string
data:
type: string
/content/channels/{channelId}/topics/{topicId}/assets:
get:
@ -2822,7 +2838,7 @@ components:
type: object
required:
- profile
- article
- attribute
- group
- channel
- card
@ -2973,7 +2989,7 @@ components:
id:
type: string
revision:
type: integer
type: number
format: int64
data:
$ref: '#/components/schemas/CardData'
@ -2984,7 +3000,7 @@ components:
- detailRevision
- profileRevision
- notifiedProfile
- notifiedArticle
- notifiedContent
- notifiedChannel
- notifiedView
properties:
@ -2997,7 +3013,7 @@ components:
notifiedProfile:
type: integer
format: int64
notifiedArticle:
notifiedContent:
type: integer
format: int64
notifiedChannel:
@ -3056,7 +3072,7 @@ components:
required:
- id
- revision
- data
- ata
properties:
id:
type: string
@ -3180,8 +3196,7 @@ components:
id:
type: string
revision:
type: integer
format: int64
type: string
data:
$ref: '#/components/schemas/TopicData'
@ -3251,8 +3266,7 @@ components:
id:
type: string
revision:
type: integer
format: int64
type: string
data:
$ref: '#/components/schemas/TagData'
@ -3288,8 +3302,7 @@ components:
id:
type: string
revision:
type: integer
format: int64
type: string
data:
$ref: '#/components/schemas/ArticleData'
@ -3399,15 +3412,12 @@ components:
viewRevision:
type: integer
format: int64
articleRevision:
contentRevision:
type: integer
format: int64
profileRevision:
type: integer
format: int64
channelRevision:
type: integer
format: int64
handle:
type: string
name:
@ -3459,18 +3469,6 @@ components:
properties:
token:
type: string
profileRevision:
type: integer
format: int64
articleRevision:
type: integer
format: int64
channelRevision:
type: integer
format: int64
viewRevision:
type: integer
format: int64
status:
type: string
enum: [ pending, confirmed, requested, connecting, connected ]

View File

@ -110,6 +110,7 @@ func AddCard(w http.ResponseWriter, r *http.Request) {
}
}
} else {
if identity.Revision > card.ProfileRevision {
// update card data
@ -125,10 +126,10 @@ func AddCard(w http.ResponseWriter, r *http.Request) {
// save contact card
err = store.DB.Transaction(func(tx *gorm.DB) error {
slot = &card.CardSlot
if res := tx.Save(&card).Error; res != nil {
return res
}
slot = &card.CardSlot
if slot == nil {
slot = &store.CardSlot{
CardSlotId: uuid.New().String(),
@ -146,6 +147,7 @@ func AddCard(w http.ResponseWriter, r *http.Request) {
if res := tx.Model(&account).Update("card_revision", account.CardRevision + 1).Error; res != nil {
return res
}
slot.Card = &card
return nil
})
}

View File

@ -0,0 +1,32 @@
package databag
import (
"errors"
"net/http"
"gorm.io/gorm"
"github.com/gorilla/mux"
"databag/internal/store"
)
func GetCard(w http.ResponseWriter, r *http.Request) {
account, code, err := BearerAppToken(r, false);
if err != nil {
ErrResponse(w, code, err)
return
}
cardId := mux.Vars(r)["cardId"]
var slot store.CardSlot
if err := store.DB.Preload("Card.Groups").Where("account_id = ? AND card_slot_id = ?", account.ID, cardId).First(&slot).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
ErrResponse(w, http.StatusNotFound, err)
} else {
ErrResponse(w, http.StatusInternalServerError, err)
}
return
}
WriteResponse(w, getCardModel(&slot))
}

View File

@ -0,0 +1,29 @@
package databag
import (
"net/http"
)
func GetProfile(w http.ResponseWriter, r *http.Request) {
account, code, err := BearerAppToken(r, true);
if err != nil {
ErrResponse(w, code, err)
return
}
detail := account.AccountDetail
profile := &Profile{
Guid: account.Guid,
Handle: account.Username,
Description: detail.Description,
Location: detail.Location,
Image: detail.Image,
Revision: account.ProfileRevision,
Version: APP_VERSION,
Node: "https://" + getStrConfigValue(CONFIG_DOMAIN, "") + "/",
}
WriteResponse(w, profile)
}

View File

@ -13,21 +13,11 @@ import (
"net/http"
)
func GetProfile(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusOK)
}
func GetProfileImage(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusOK)
}
func SetProfile(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusOK)
}
func SetProfileImage(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusOK)

View File

@ -0,0 +1,49 @@
package databag
import (
"net/http"
"gorm.io/gorm"
"databag/internal/store"
)
func SetProfile(w http.ResponseWriter, r *http.Request) {
account, code, err := BearerAppToken(r, true);
if err != nil {
ErrResponse(w, code, err)
return
}
detail := account.AccountDetail
// extract profile data from body
var profileData ProfileData;
err = ParseRequest(r, w, &profileData)
if err != nil {
ErrResponse(w, http.StatusBadRequest, err)
return
}
// update record
detail.Name = profileData.Name
detail.Location = profileData.Location
detail.Description = profileData.Description
err = store.DB.Transaction(func(tx *gorm.DB) error {
if res := store.DB.Save(&detail).Error; res != nil {
return res
}
if res := store.DB.Model(&account).Update("profile_revision", account.ProfileRevision + 1).Error; res != nil {
return res
}
return nil
})
if err != nil {
ErrResponse(w, http.StatusInternalServerError, err)
return
}
SetProfileNotification(account)
SetStatus(account)
WriteResponse(w, nil)
}

View File

@ -145,6 +145,13 @@ var routes = Routes{
GetAccountUsername,
},
Route{
"GetCard",
strings.ToUpper("Get"),
"/contact/cards/{cardId}",
GetCard,
},
Route{
"GetPublicStatus",
strings.ToUpper("Get"),

View File

@ -6,9 +6,87 @@ import (
)
func TestUpdateProfile(t *testing.T) {
param := map[string]string{}
var msg DataMessage
var card Card
var bProfileRev int64
var bCardRev int64
var cProfileRev int64
var cCardRev int64
// setup testing group
set, err := AddTestGroup("updateprofile")
assert.NoError(t, err)
PrintMsg(set)
// setup testing group
_, ret := AddTestGroup("updateprofile")
assert.Error(t, ret)
// reset revision
bCardRev = GetTestRevision(set.B.Revisions).Card
cCardRev = GetTestRevision(set.C.Revisions).Card
param["cardId"] = set.B.A.CardId
assert.NoError(t, SendEndpointTest(GetCard, "GET", "/contact/cards/{cardId}",
&param, nil,
APP_TOKENAPP, set.B.Token, &card, nil))
bProfileRev = card.Data.NotifiedProfile
param["cardId"] = set.C.A.CardId
assert.NoError(t, SendEndpointTest(GetCard, "GET", "/contact/cards/{cardId}",
&param, nil,
APP_TOKENAPP, set.C.Token, &card, nil))
cProfileRev = card.Data.NotifiedProfile
// update A profile
profileData := &ProfileData{
Name: "Namer",
Location: "San Francisco",
Description: "databaggerr",
};
assert.NoError(t, SendEndpointTest(SetProfile, "PUT", "/profile/data",
nil, profileData,
APP_TOKENAPP, set.A.Token, nil, nil))
assert.NotEqual(t, bCardRev, GetTestRevision(set.B.Revisions).Card)
assert.NotEqual(t, cCardRev, GetTestRevision(set.C.Revisions).Card)
param["cardId"] = set.B.A.CardId
assert.NoError(t, SendEndpointTest(GetCard, "GET", "/contact/cards/{cardId}",
&param, nil,
APP_TOKENAPP, set.B.Token, &card, nil))
assert.NotEqual(t, bProfileRev, card.Data.NotifiedProfile)
assert.NotEqual(t, card.Data.ProfileRevision, card.Data.NotifiedProfile)
param["cardId"] = set.C.A.CardId
assert.NoError(t, SendEndpointTest(GetCard, "GET", "/contact/cards/{cardId}",
&param, nil,
APP_TOKENAPP, set.C.Token, &card, nil))
assert.NotEqual(t, cProfileRev, card.Data.NotifiedProfile)
assert.NotEqual(t, card.Data.ProfileRevision, card.Data.NotifiedProfile)
// update profile
assert.NoError(t, SendEndpointTest(GetProfileMessage, "GET", "/profile/message",
nil, nil,
APP_TOKENCONTACT, set.B.A.Token, &msg, nil))
assert.NoError(t, SendEndpointTest(AddCard, "POST", "/contact/cards",
nil, &msg,
APP_TOKENAPP, set.B.Token, &card, nil))
assert.Equal(t, card.Id, set.B.A.CardId)
assert.Equal(t, card.Data.ProfileRevision, card.Data.NotifiedProfile)
assert.Equal(t, card.Data.CardProfile.Name, "Namer")
// update profile
assert.NoError(t, SendEndpointTest(GetProfileMessage, "GET", "/profile/message",
nil, nil,
APP_TOKENCONTACT, set.C.A.Token, &msg, nil))
assert.NoError(t, SendEndpointTest(AddCard, "POST", "/contact/cards",
nil, &msg,
APP_TOKENAPP, set.C.Token, &card, nil))
assert.Equal(t, card.Id, set.C.A.CardId)
assert.Equal(t, card.Data.ProfileRevision, card.Data.NotifiedProfile)
assert.Equal(t, card.Data.CardProfile.Name, "Namer")
}