mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
creating contact from identity message
This commit is contained in:
parent
59ae141d31
commit
7eb7cb8f61
@ -4089,8 +4089,12 @@ components:
|
||||
CardProfile:
|
||||
type: object
|
||||
required:
|
||||
- guid
|
||||
- version
|
||||
- node
|
||||
properties:
|
||||
guid:
|
||||
type: string
|
||||
handle:
|
||||
type: string
|
||||
name:
|
||||
@ -4104,6 +4108,8 @@ components:
|
||||
format: int64
|
||||
imageSet:
|
||||
type: boolean
|
||||
version:
|
||||
type: string
|
||||
node:
|
||||
type: string
|
||||
|
||||
|
@ -4,6 +4,7 @@ go 1.17
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
|
@ -2,6 +2,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
|
112
net/server/internal/api_addCard.go
Normal file
112
net/server/internal/api_addCard.go
Normal file
@ -0,0 +1,112 @@
|
||||
package databag
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"gorm.io/gorm"
|
||||
"github.com/google/uuid"
|
||||
"databag/internal/store"
|
||||
)
|
||||
|
||||
func AddCard(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
account, code, err := BearerAppToken(r, false)
|
||||
if err != nil {
|
||||
ErrResponse(w, code, err)
|
||||
return
|
||||
}
|
||||
|
||||
var message DataMessage
|
||||
if err := ParseRequest(r, w, &message); err != nil {
|
||||
ErrResponse(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
var identity Identity
|
||||
guid, messageType, _, err := ReadDataMessage(&message, &identity)
|
||||
if messageType != APP_MSGIDENTITY || err != nil {
|
||||
ErrResponse(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
var card store.Card
|
||||
if err := store.DB.Preload("Groups").Where("account_id = ? AND guid = ?", account.ID, guid).First(&card).Error; err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
ErrResponse(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
|
||||
// update record if revision changed
|
||||
if identity.Revision > card.ProfileRevision {
|
||||
card.Username = identity.Handle
|
||||
card.Name = identity.Name
|
||||
card.Description = identity.Description
|
||||
card.Location = identity.Location
|
||||
card.Image = identity.Image
|
||||
card.Version = identity.Version
|
||||
card.Node = identity.Node
|
||||
card.ProfileRevision = identity.Revision
|
||||
if err := store.DB.Save(&card).Error; err != nil {
|
||||
ErrResponse(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
WriteResponse(w, getCardModel(&card))
|
||||
return
|
||||
}
|
||||
|
||||
// save new record
|
||||
card.CardId = uuid.New().String()
|
||||
card.AccountID = account.ID
|
||||
card.Guid = guid
|
||||
card.Username = identity.Handle
|
||||
card.Name = identity.Name
|
||||
card.Description = identity.Description
|
||||
card.Location = identity.Location
|
||||
card.Image = identity.Image
|
||||
card.Version = identity.Version
|
||||
card.Node = identity.Node
|
||||
card.ProfileRevision = identity.Revision
|
||||
card.Status = APP_CARDCONFIRMED
|
||||
if err := store.DB.Save(&card).Error; err != nil {
|
||||
ErrResponse(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
WriteResponse(w, getCardModel(&card))
|
||||
}
|
||||
|
||||
func getCardModel(card *store.Card) *Card {
|
||||
|
||||
// populate group id list
|
||||
var groups []string;
|
||||
for _, group := range card.Groups {
|
||||
groups = append(groups, group.GroupId)
|
||||
}
|
||||
|
||||
return &Card{
|
||||
CardId: card.CardId,
|
||||
ProfileRevision: card.RemoteProfile,
|
||||
ContentRevision: card.RemoteContent,
|
||||
CardProfile: &CardProfile{
|
||||
Guid: card.Guid,
|
||||
Handle: card.Username,
|
||||
Name: card.Name,
|
||||
Description: card.Description,
|
||||
Location: card.Location,
|
||||
Revision: card.ProfileRevision,
|
||||
ImageSet: card.Image != "",
|
||||
Version: card.Version,
|
||||
Node: card.Node,
|
||||
},
|
||||
CardData: &CardData {
|
||||
Revision: card.DataRevision,
|
||||
Status: card.Status,
|
||||
Notes: card.Notes,
|
||||
Groups: groups,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,13 +6,9 @@ import (
|
||||
|
||||
func Authorize(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
account, res := BearerAppToken(r, true);
|
||||
account, code, res := BearerAppToken(r, true);
|
||||
if res != nil {
|
||||
ErrResponse(w, http.StatusUnauthorized, res)
|
||||
return
|
||||
}
|
||||
if account.Disabled {
|
||||
ErrResponse(w, http.StatusGone, res)
|
||||
ErrResponse(w, code, res)
|
||||
return
|
||||
}
|
||||
detail := account.AccountDetail
|
||||
|
@ -13,11 +13,6 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func AddCard(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func ClearCardGroup(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
@ -6,13 +6,9 @@ import (
|
||||
|
||||
func GetProfile(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
account, err := BearerAppToken(r, true);
|
||||
account, code, err := BearerAppToken(r, true);
|
||||
if err != nil {
|
||||
ErrResponse(w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
if account.Disabled {
|
||||
ErrResponse(w, http.StatusGone, nil)
|
||||
ErrResponse(w, code, err)
|
||||
return
|
||||
}
|
||||
detail := account.AccountDetail
|
||||
|
@ -6,13 +6,9 @@ import (
|
||||
|
||||
func GetProfileMessage(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
account, res := BearerAppToken(r, true);
|
||||
account, code, res := BearerAppToken(r, true);
|
||||
if res != nil {
|
||||
ErrResponse(w, http.StatusUnauthorized, res)
|
||||
return
|
||||
}
|
||||
if account.Disabled {
|
||||
ErrResponse(w, http.StatusGone, res)
|
||||
ErrResponse(w, code, res)
|
||||
return
|
||||
}
|
||||
detail := account.AccountDetail
|
||||
|
@ -8,13 +8,9 @@ import (
|
||||
|
||||
func SetProfile(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
account, err := BearerAppToken(r, true);
|
||||
account, code, err := BearerAppToken(r, true);
|
||||
if err != nil {
|
||||
ErrResponse(w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
if account.Disabled {
|
||||
ErrResponse(w, http.StatusGone, nil)
|
||||
ErrResponse(w, code, err)
|
||||
return
|
||||
}
|
||||
detail := account.AccountDetail
|
||||
@ -47,7 +43,6 @@ func SetProfile(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
SetStatus(account)
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
WriteResponse(w, nil)
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ func Status(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// send current version
|
||||
rev := getRevision(app.Account)
|
||||
rev := getRevision(&app.Account)
|
||||
var msg []byte
|
||||
msg, err = json.Marshal(rev)
|
||||
if err != nil {
|
||||
@ -95,7 +95,7 @@ func Status(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func getRevision(account store.Account) Revision {
|
||||
func getRevision(account *store.Account) Revision {
|
||||
var r Revision
|
||||
r.Profile = account.ProfileRevision
|
||||
r.Content = account.ContentRevision
|
||||
@ -111,7 +111,7 @@ func ExitStatus() {
|
||||
wsExit <- true
|
||||
}
|
||||
|
||||
func SetStatus(account store.Account) {
|
||||
func SetStatus(account *store.Account) {
|
||||
|
||||
// get revisions for the account
|
||||
rev := getRevision(account);
|
||||
|
@ -13,3 +13,9 @@ const APP_MSGAUTHENTICATE = "authenticate"
|
||||
const APP_MSGIDENTITY = "identity"
|
||||
const APP_MSGCONNECT = "connect"
|
||||
const APP_MSGDISCONNECT = "disconnect"
|
||||
const APP_CARDPENDING = "pending"
|
||||
const APP_CARDCONFIRMED = "confirmed"
|
||||
const APP_CARDREQUESTED = "requested"
|
||||
const APP_CARDCONNECTING = "connecting"
|
||||
const APP_CARDCONNECTED = "connected"
|
||||
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
"net/http"
|
||||
"encoding/base64"
|
||||
"gorm.io/gorm"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"databag/internal/store"
|
||||
)
|
||||
@ -81,7 +82,7 @@ func BearerAccountToken(r *http.Request) (store.AccountToken, error) {
|
||||
return accountToken, nil
|
||||
}
|
||||
|
||||
func BearerAppToken(r *http.Request, detail bool) (store.Account, error) {
|
||||
func BearerAppToken(r *http.Request, detail bool) (*store.Account, int, error) {
|
||||
|
||||
// parse bearer authentication
|
||||
auth := r.Header.Get("Authorization")
|
||||
@ -91,14 +92,26 @@ func BearerAppToken(r *http.Request, detail bool) (store.Account, error) {
|
||||
var app store.App
|
||||
if detail {
|
||||
if err := store.DB.Preload("Account.AccountDetail").Where("token = ?", token).First(&app).Error; err != nil {
|
||||
return app.Account, err
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, http.StatusNotFound, err
|
||||
} else {
|
||||
return nil, http.StatusInternalServerError, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err := store.DB.Preload("Account").Where("token = ?", token).First(&app).Error; err != nil {
|
||||
return app.Account, err
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, http.StatusNotFound, err
|
||||
} else {
|
||||
return nil, http.StatusInternalServerError, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return app.Account, nil
|
||||
if app.Account.Disabled {
|
||||
return nil, http.StatusGone, errors.New("account is inactive")
|
||||
}
|
||||
|
||||
return &app.Account, http.StatusOK, nil
|
||||
}
|
||||
|
||||
func BasicCredentials(r *http.Request) (string, []byte, error) {
|
||||
|
51
net/server/internal/contact_test.go
Normal file
51
net/server/internal/contact_test.go
Normal file
@ -0,0 +1,51 @@
|
||||
package databag
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"strconv"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func AddTestContacts(t *testing.T, prefix string, count int) []string {
|
||||
|
||||
var access []string
|
||||
app := AppData{
|
||||
Name: "Appy",
|
||||
Description: "A test app",
|
||||
Url: "http://app.example.com",
|
||||
};
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
var token string
|
||||
var login = prefix + strconv.Itoa(i) + ":pass"
|
||||
|
||||
// get account token
|
||||
r, w, _ := NewRequest("POST", "/admin/accounts", nil)
|
||||
SetBasicAuth(r, "admin:pass")
|
||||
AddNodeAccount(w, r)
|
||||
assert.NoError(t, ReadResponse(w, &token))
|
||||
|
||||
// set account profile
|
||||
r, w, _ = NewRequest("GET", "/account/profile", nil)
|
||||
SetBearerAuth(r, token);
|
||||
SetCredentials(r, login)
|
||||
AddAccount(w, r)
|
||||
assert.NoError(t, ReadResponse(w, nil))
|
||||
|
||||
// acquire new token for attaching app
|
||||
r, w, _ = NewRequest("POST", "/account/apps", nil)
|
||||
SetBasicAuth(r, login);
|
||||
AddAccountApp(w, r);
|
||||
assert.NoError(t, ReadResponse(w, &token))
|
||||
|
||||
// attach app with token
|
||||
r, w, _ = NewRequest("PUT", "/account/apps", &app)
|
||||
SetBearerAuth(r, token)
|
||||
SetAccountApp(w, r)
|
||||
assert.NoError(t, ReadResponse(w, &token))
|
||||
|
||||
access = append(access, token)
|
||||
}
|
||||
|
||||
return access
|
||||
}
|
@ -85,12 +85,14 @@ type CardData struct {
|
||||
}
|
||||
|
||||
type CardProfile struct {
|
||||
Guid string `json:"guid"`
|
||||
Handle string `json:"handle,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Location string `json:"location,omitempty"`
|
||||
Revision int64 `json:"revision,omitempty"`
|
||||
ImageSet bool `json:"imageSet,omitempty"`
|
||||
Version string `json:"version"`
|
||||
Node string `json:"node"`
|
||||
}
|
||||
|
||||
|
@ -115,19 +115,24 @@ type Label struct {
|
||||
type Card struct {
|
||||
ID uint `gorm:"primaryKey;not null;unique;autoIncrement"`
|
||||
CardId string `gorm:"not null;index:card,unique"`
|
||||
AccountID uint `gorm:"not null;index:card,unique"`
|
||||
GUID string `gorm:"not null"`
|
||||
AccountID uint `gorm:"not null;index:card,unique;index:guid,unqiue"`
|
||||
Guid string `gorm:"not null;index:guid,unique"`
|
||||
Username string
|
||||
Name string
|
||||
Description string
|
||||
Location string
|
||||
Revision uint64 `gorm:"not null"`
|
||||
Image string
|
||||
Version string `gorm:"not null"`
|
||||
Node string `gorm:"not null"`
|
||||
ProfileRevision int64 `gorm:"not null"`
|
||||
Status string `gorm:"not null"`
|
||||
Token string
|
||||
Notes string
|
||||
DataRevision int64 `gorm:"not null"`
|
||||
Created int64 `gorm:"autoCreateTime"`
|
||||
Updated int64 `gorm:"autoUpdateTime"`
|
||||
RemoteProfile int64
|
||||
RemoteContent int64
|
||||
Account Account
|
||||
Groups []Group `gorm:"many2many:card_groups;"`
|
||||
}
|
||||
|
@ -7,81 +7,26 @@ import (
|
||||
|
||||
func TestConnectContact(t *testing.T) {
|
||||
|
||||
app := AppData{
|
||||
Name: "Appy",
|
||||
Description: "A test app",
|
||||
Url: "http://app.example.com",
|
||||
};
|
||||
var token string
|
||||
|
||||
// get account token
|
||||
r, w, _ := NewRequest("POST", "/admin/accounts", nil)
|
||||
SetBasicAuth(r, "admin:pass")
|
||||
AddNodeAccount(w, r)
|
||||
assert.NoError(t, ReadResponse(w, &token))
|
||||
|
||||
// set account profile
|
||||
r, w, _ = NewRequest("GET", "/account/profile", nil)
|
||||
SetBearerAuth(r, token);
|
||||
SetCredentials(r, "connecta:pass")
|
||||
AddAccount(w, r)
|
||||
assert.NoError(t, ReadResponse(w, nil))
|
||||
|
||||
// acquire new token for attaching app
|
||||
r, w, _ = NewRequest("POST", "/account/apps", nil)
|
||||
SetBasicAuth(r, "attachapp:pass");
|
||||
AddAccountApp(w, r);
|
||||
assert.NoError(t, ReadResponse(w, &token))
|
||||
|
||||
// attach app with token
|
||||
r, w, _ = NewRequest("PUT", "/account/apps", &app)
|
||||
SetBearerAuth(r, token)
|
||||
SetAccountApp(w, r)
|
||||
var aToken string
|
||||
assert.NoError(t, ReadResponse(w, &aToken))
|
||||
|
||||
// get account token
|
||||
r, w, _ = NewRequest("POST", "/admin/accounts", nil)
|
||||
SetBasicAuth(r, "admin:pass")
|
||||
AddNodeAccount(w, r)
|
||||
assert.NoError(t, ReadResponse(w, &token))
|
||||
|
||||
// set account profile
|
||||
r, w, _ = NewRequest("GET", "/account/profile", nil)
|
||||
SetBearerAuth(r, token);
|
||||
SetCredentials(r, "connectb:pass")
|
||||
AddAccount(w, r)
|
||||
assert.NoError(t, ReadResponse(w, nil))
|
||||
|
||||
// acquire new token for attaching app
|
||||
r, w, _ = NewRequest("POST", "/account/apps", nil)
|
||||
SetBasicAuth(r, "connectb:pass");
|
||||
AddAccountApp(w, r);
|
||||
assert.NoError(t, ReadResponse(w, &token))
|
||||
|
||||
// attach app with token
|
||||
r, w, _ = NewRequest("PUT", "/account/apps", &app)
|
||||
SetBearerAuth(r, token)
|
||||
SetAccountApp(w, r)
|
||||
var bToken string
|
||||
assert.NoError(t, ReadResponse(w, &bToken))
|
||||
// create some contacts for this test
|
||||
access := AddTestContacts(t, "connect", 2)
|
||||
|
||||
// get B identity message
|
||||
r, w, _ = NewRequest("GET", "/profile/message", nil)
|
||||
SetBearerAuth(r, bToken)
|
||||
r, w, _ := NewRequest("GET", "/profile/message", nil)
|
||||
SetBearerAuth(r, access[0])
|
||||
GetProfileMessage(w, r)
|
||||
var msg DataMessage
|
||||
assert.NoError(t, ReadResponse(w, &msg))
|
||||
|
||||
var identity Identity
|
||||
guid, messageType, ts, err := ReadDataMessage(&msg, &identity)
|
||||
// add B card in A
|
||||
r, w, _ = NewRequest("POST", "/contact/cards", &msg)
|
||||
SetBearerAuth(r, access[1])
|
||||
AddCard(w, r)
|
||||
var card Card
|
||||
assert.NoError(t, ReadResponse(w, &card))
|
||||
|
||||
PrintMsg(msg)
|
||||
PrintMsg(guid)
|
||||
PrintMsg(messageType)
|
||||
PrintMsg(ts)
|
||||
PrintMsg(err)
|
||||
PrintMsg(identity)
|
||||
PrintMsg(card)
|
||||
|
||||
// A request B
|
||||
|
||||
// set B card in A
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user