From 2a8fe4b6b8df6a8aeae3333cc4949a4c24eefc4e Mon Sep 17 00:00:00 2001 From: Roland Osborne Date: Mon, 24 Jan 2022 21:22:33 -0800 Subject: [PATCH] adding group test --- doc/api.oa3 | 53 ++++++------ net/server/go.mod | 4 +- net/server/go.sum | 4 + net/server/internal/api_addGroup.go | 50 +++++++++++ net/server/internal/api_contact.go | 5 -- net/server/internal/api_getGroups.go | 28 +++++++ net/server/internal/api_setCardGroup.go | 79 +++++++++++++++++ net/server/internal/api_share.go | 10 --- net/server/internal/appValues.go | 1 + net/server/internal/contact_test.go | 40 +++++---- net/server/internal/main_test.go | 4 +- .../internal/{cardUtil.go => modelUtil.go} | 10 +++ net/server/internal/models.go | 11 ++- net/server/internal/notify.go | 37 ++++---- net/server/internal/store/schema.go | 54 ++---------- net/server/internal/ucGroupContact_test.go | 84 +++++++++++++++++++ 16 files changed, 344 insertions(+), 130 deletions(-) create mode 100644 net/server/internal/api_addGroup.go create mode 100644 net/server/internal/api_getGroups.go create mode 100644 net/server/internal/api_setCardGroup.go rename net/server/internal/{cardUtil.go => modelUtil.go} (78%) create mode 100644 net/server/internal/ucGroupContact_test.go diff --git a/doc/api.oa3 b/doc/api.oa3 index 10a57098..7a02d9df 100644 --- a/doc/api.oa3 +++ b/doc/api.oa3 @@ -859,7 +859,11 @@ paths: - bearerAuth: [] responses: '200': - description: entry created + description: success + content: + application/json: + schema: + $ref: '#/components/schemas/Group' '401': description: permission denied '410': @@ -870,15 +874,7 @@ paths: content: application/json: schema: - type: object - required: - - type - - data - properties: - type: - type: string - data: - type: string + $ref: '#/components/schemas/Subject' /share/groups/{groupId}: put: @@ -898,6 +894,10 @@ paths: responses: '200': description: success + content: + application/json: + schema: + $ref: '#/components/schemas/Group' '401': description: permission denied '404': @@ -910,15 +910,7 @@ paths: content: application/json: schema: - type: object - required: - - type - - data - properties: - type: - type: string - data: - type: string + $ref: '#/components/schemas/Subject' delete: tags: - share @@ -4022,6 +4014,17 @@ components: location: type: string + Subject: + type: object + required: + - dataType + - data + properties: + dataType: + type: string + data: + type: string + Account: type: object required: @@ -4358,25 +4361,25 @@ components: type: object required: - groupId - - groupRevision - - type + - revision + - dataType - data - created - - modified + - updated properties: groupId: type: string - groupRevision: + revision: type: integer format: int64 - type: + dataType: type: string data: type: string created: type: integer format: int64 - modified: + updated: type: integer format: int64 diff --git a/net/server/go.mod b/net/server/go.mod index 919998a7..34a56ad9 100644 --- a/net/server/go.mod +++ b/net/server/go.mod @@ -8,7 +8,7 @@ require ( github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.3 // indirect + github.com/jinzhu/now v1.1.4 // indirect github.com/kr/pretty v0.3.0 // indirect github.com/kr/text v0.2.0 // indirect github.com/mattn/go-sqlite3 v1.14.9 // indirect @@ -19,5 +19,5 @@ require ( golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect gorm.io/driver/sqlite v1.2.6 // indirect - gorm.io/gorm v1.22.4 // indirect + gorm.io/gorm v1.22.5 // indirect ) diff --git a/net/server/go.sum b/net/server/go.sum index f275ff33..b21c5f05 100644 --- a/net/server/go.sum +++ b/net/server/go.sum @@ -13,6 +13,8 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.3 h1:PlHq1bSCSZL9K0wUhbm2pGLoTWs2GwVhsP6emvGV/ZI= github.com/jinzhu/now v1.1.3/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas= +github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= @@ -43,3 +45,5 @@ gorm.io/driver/sqlite v1.2.6/go.mod h1:gyoX0vHiiwi0g49tv+x2E7l8ksauLK0U/gShcdUsj gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= gorm.io/gorm v1.22.4 h1:8aPcyEJhY0MAt8aY6Dc524Pn+pO29K+ydu+e/cXSpQM= gorm.io/gorm v1.22.4/go.mod h1:1aeVC+pe9ZmvKZban/gW4QPra7PRoTEssyc922qCAkk= +gorm.io/gorm v1.22.5 h1:lYREBgc02Be/5lSCTuysZZDb6ffL2qrat6fg9CFbvXU= +gorm.io/gorm v1.22.5/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= diff --git a/net/server/internal/api_addGroup.go b/net/server/internal/api_addGroup.go new file mode 100644 index 00000000..4f685090 --- /dev/null +++ b/net/server/internal/api_addGroup.go @@ -0,0 +1,50 @@ +package databag + +import ( + "net/http" + "gorm.io/gorm" + "github.com/google/uuid" + "databag/internal/store" +) + +func AddGroup(w http.ResponseWriter, r *http.Request) { + + account, code, err := BearerAppToken(r, false) + if err != nil { + ErrResponse(w, code, err) + return + } + + var subject Subject + if err := ParseRequest(r, w, &subject); err != nil { + ErrResponse(w, http.StatusBadRequest, err) + return + } + + group := &store.Group{ + GroupId: uuid.New().String(), + AccountID: account.ID, + Revision: 0, + DataType: subject.DataType, + Data: subject.Data, + } + err = store.DB.Transaction(func(tx *gorm.DB) error { + if res := store.DB.Save(group).Error; res != nil { + return res + } + if res := store.DB.Model(&account).Update("group_revision", account.GroupRevision + 1).Error; res != nil { + return res + } + return nil + }) + if err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + + SetStatus(account) + WriteResponse(w, getGroupModel(group)) +} + + + diff --git a/net/server/internal/api_contact.go b/net/server/internal/api_contact.go index 26634731..61580774 100644 --- a/net/server/internal/api_contact.go +++ b/net/server/internal/api_contact.go @@ -48,11 +48,6 @@ func RemoveCard(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) } -func SetCardGroup(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json; charset=UTF-8") - w.WriteHeader(http.StatusOK) -} - func SetCardNotes(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.WriteHeader(http.StatusOK) diff --git a/net/server/internal/api_getGroups.go b/net/server/internal/api_getGroups.go new file mode 100644 index 00000000..0670a9e0 --- /dev/null +++ b/net/server/internal/api_getGroups.go @@ -0,0 +1,28 @@ +package databag + +import ( + "net/http" + "databag/internal/store" +) + +func GetGroups(w http.ResponseWriter, r *http.Request) { + + account, code, err := BearerAppToken(r, false) + if err != nil { + ErrResponse(w, code, err) + return + } + + var storeGroups []store.Group + if err := store.DB.Where("account_id = ?", account.ID).Find(&storeGroups).Error; err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + + var groups []*Group + for _, group := range storeGroups { + groups = append(groups, getGroupModel(&group)) + } + WriteResponse(w, groups) +} + diff --git a/net/server/internal/api_setCardGroup.go b/net/server/internal/api_setCardGroup.go new file mode 100644 index 00000000..07b6b1b9 --- /dev/null +++ b/net/server/internal/api_setCardGroup.go @@ -0,0 +1,79 @@ +package databag + +import ( + "errors" + "net/http" + "gorm.io/gorm" + "github.com/gorilla/mux" + "databag/internal/store" +) + +func SetCardGroup(w http.ResponseWriter, r *http.Request) { + account, code, err := BearerAppToken(r, false); + if err != nil { + ErrResponse(w, code, err) + return + } + + // scan parameters + params := mux.Vars(r) + cardId := params["cardId"] + groupId := params["groupId"] + + + // load referenced card + var card store.Card + if err := store.DB.Where("account_id = ? AND card_id = ?", account.Guid, cardId).First(&card).Error; err != nil { + if !errors.Is(err, gorm.ErrRecordNotFound) { + ErrResponse(w, http.StatusInternalServerError, err) + } else { + ErrResponse(w, http.StatusNotFound, err) + } + return + } + + // load referenced group + var group store.Group + if err := store.DB.Where("account_id = ? AND group_id = ?", account.ID, groupId).First(&group).Error; err != nil { + if !errors.Is(err, gorm.ErrRecordNotFound) { + ErrResponse(w, http.StatusInternalServerError, err) + } else { + ErrResponse(w, http.StatusNotFound, err) + } + return + } + + // save and update revision + card.Groups = append(card.Groups, group) + card.ViewRevision += 1 + card.DataRevision += 1 + err = store.DB.Transaction(func(tx *gorm.DB) error { + if res := store.DB.Model(&account).Update("card_revision", account.CardRevision + 1).Error; res != nil { + return res + } + if res := store.DB.Preload("Groups").Save(&card).Error; res != nil { + return res + } + return nil + }) + if err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + + cardData := &CardData{ + Revision: card.DataRevision, + Status: card.Status, + Notes: card.Notes, + Token: card.OutToken, + Groups: nil, + } + for _, group := range card.Groups { + cardData.Groups = append(cardData.Groups, group.GroupId) + } + WriteResponse(w, cardData) + SetContactContentNotification(account, &card) + SetStatus(account) +} + + diff --git a/net/server/internal/api_share.go b/net/server/internal/api_share.go index 2fc77972..548b628d 100644 --- a/net/server/internal/api_share.go +++ b/net/server/internal/api_share.go @@ -13,16 +13,6 @@ import ( "net/http" ) -func AddGroup(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json; charset=UTF-8") - w.WriteHeader(http.StatusOK) -} - -func GetGroups(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json; charset=UTF-8") - w.WriteHeader(http.StatusOK) -} - func RemoveGroup(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.WriteHeader(http.StatusOK) diff --git a/net/server/internal/appValues.go b/net/server/internal/appValues.go index 04e7cf10..a12ef381 100644 --- a/net/server/internal/appValues.go +++ b/net/server/internal/appValues.go @@ -24,6 +24,7 @@ const APP_MODULEPROFILE = "profile" const APP_MODULECONTENT = "content" const APP_TOKENAPP = "app" const APP_TOKENCONTACT = "contact" +const APP_NOTIFYBUFFER = 4096 func AppCardStatus(status string) bool { if status == APP_CARDPENDING { diff --git a/net/server/internal/contact_test.go b/net/server/internal/contact_test.go index ab3b8c64..0eedc1f1 100644 --- a/net/server/internal/contact_test.go +++ b/net/server/internal/contact_test.go @@ -7,6 +7,13 @@ import ( "github.com/stretchr/testify/assert" ) +type TestAccount struct { + AppToken string + ContactGuid string + ContactToken string + ContactCardId string +} + func AddTestContacts(t *testing.T, prefix string, count int) []string { var access []string @@ -52,32 +59,35 @@ func AddTestContacts(t *testing.T, prefix string, count int) []string { return access } -func ConnectTestContacts(t *testing.T, accessA string, accessB string) (contact [2]string) { +func ConnectTestContacts(t *testing.T, accessA string, accessB string) (contact [2]TestAccount) { var card Card var msg DataMessage var vars map[string]string var contactStatus ContactStatus var id string - access := [2]string{accessA, accessB} + contact[0].AppToken = accessA + contact[1].AppToken = accessB // get A identity message r, w, _ := NewRequest("GET", "/profile/message", nil) r.Header.Add("TokenType", APP_TOKENAPP) - SetBearerAuth(r, access[0]) + SetBearerAuth(r, accessA) GetProfileMessage(w, r) assert.NoError(t, ReadResponse(w, &msg)) // add A card in B r, w, _ = NewRequest("POST", "/contact/cards", &msg) - SetBearerAuth(r, access[1]) + SetBearerAuth(r, accessB) AddCard(w, r) assert.NoError(t, ReadResponse(w, &card)) + contact[1].ContactCardId = card.CardId + contact[1].ContactGuid = card.CardProfile.Guid // update A status to connecting r, w, _ = NewRequest("PUT", "/contact/cards/{cardId}/status", APP_CARDCONNECTING) vars = map[string]string{ "cardId": card.CardId } r = mux.SetURLVars(r, vars) - SetBearerAuth(r, access[1]) + SetBearerAuth(r, accessB) SetCardStatus(w, r) assert.NoError(t, ReadResponse(w, &card)) @@ -85,7 +95,7 @@ func ConnectTestContacts(t *testing.T, accessA string, accessB string) (contact r, w, _ = NewRequest("GET", "/contact/cards/{cardId}/openMessage", nil) vars = map[string]string{ "cardId": card.CardId } r = mux.SetURLVars(r, vars) - SetBearerAuth(r, access[1]) + SetBearerAuth(r, accessB) GetOpenMessage(w, r) assert.NoError(t, ReadResponse(w, &msg)) id = card.CardId @@ -97,7 +107,7 @@ func ConnectTestContacts(t *testing.T, accessA string, accessB string) (contact // get view of cards in A r, w, _ = NewRequest("GET", "/contact/cards/view", nil) - SetBearerAuth(r, access[0]) + SetBearerAuth(r, accessA) GetCardView(w, r) var views []CardView assert.NoError(t, ReadResponse(w, &views)) @@ -107,15 +117,17 @@ func ConnectTestContacts(t *testing.T, accessA string, accessB string) (contact r, w, _ = NewRequest("GET", "/contact/cards/{cardId}", nil) vars = map[string]string{ "cardId": views[0].CardId } r = mux.SetURLVars(r, vars) - SetBearerAuth(r, access[0]) + SetBearerAuth(r, accessA) GetCard(w, r) assert.NoError(t, ReadResponse(w, &card)) + contact[0].ContactCardId = card.CardId + contact[0].ContactGuid = card.CardProfile.Guid // update B status to connecting r, w, _ = NewRequest("PUT", "/contact/cards/{cardId}/status", APP_CARDCONNECTING) vars = map[string]string{ "cardId": views[0].CardId } r = mux.SetURLVars(r, vars) - SetBearerAuth(r, access[0]) + SetBearerAuth(r, accessA) SetCardStatus(w, r) assert.NoError(t, ReadResponse(w, &card)) @@ -123,7 +135,7 @@ func ConnectTestContacts(t *testing.T, accessA string, accessB string) (contact r, w, _ = NewRequest("GET", "/contact/cards/{cardId}/openMessage", nil) vars = map[string]string{ "cardId": views[0].CardId } r = mux.SetURLVars(r, vars) - SetBearerAuth(r, access[0]) + SetBearerAuth(r, accessA) GetOpenMessage(w, r) assert.NoError(t, ReadResponse(w, &msg)) @@ -137,19 +149,19 @@ func ConnectTestContacts(t *testing.T, accessA string, accessB string) (contact r, w, _ = NewRequest("PUT", "/contact/cards/{cardId}/status?token=" + contactStatus.Token, APP_CARDCONNECTED) vars = map[string]string{ "cardId": views[0].CardId } r = mux.SetURLVars(r, vars) - SetBearerAuth(r, access[0]) + SetBearerAuth(r, accessA) SetCardStatus(w, r) assert.NoError(t, ReadResponse(w, &card)) // extract contact tokens - contact[0] = card.CardData.Token + contact[0].ContactToken = card.CardData.Token r, w, _ = NewRequest("GET", "/contact/cards/{cardId}", nil) vars = map[string]string{ "cardId": id } r = mux.SetURLVars(r, vars) - SetBearerAuth(r, access[1]) + SetBearerAuth(r, accessB) GetCard(w, r) assert.NoError(t, ReadResponse(w, &card)) - contact[1] = card.CardData.Token + contact[1].ContactToken = card.CardData.Token return } diff --git a/net/server/internal/main_test.go b/net/server/internal/main_test.go index 2e781185..ee3197b2 100644 --- a/net/server/internal/main_test.go +++ b/net/server/internal/main_test.go @@ -7,10 +7,10 @@ import ( func TestMain(m *testing.M) { - SetHideLog(true) +// SetHideLog(true) SetKeySize(2048) store.SetPath("file::memory:?cache=shared"); - //store.SetPath("databag.db"); +// store.SetPath("databag.db"); r, w, _ := NewRequest("GET", "/admin/claimable", nil) GetNodeClaimable(w, r) diff --git a/net/server/internal/cardUtil.go b/net/server/internal/modelUtil.go similarity index 78% rename from net/server/internal/cardUtil.go rename to net/server/internal/modelUtil.go index e3b5efe9..dea81c77 100644 --- a/net/server/internal/cardUtil.go +++ b/net/server/internal/modelUtil.go @@ -37,3 +37,13 @@ func getCardModel(card *store.Card) *Card { } } +func getGroupModel(group *store.Group) *Group { + return &Group{ + GroupId: group.GroupId, + Revision: group.Revision, + DataType: group.DataType, + Data: group.Data, + Created: group.Created, + Updated: group.Updated, + } +} diff --git a/net/server/internal/models.go b/net/server/internal/models.go index ca751b23..bb95249a 100644 --- a/net/server/internal/models.go +++ b/net/server/internal/models.go @@ -38,6 +38,11 @@ type AppData struct { Image string `json:"image,omitempty"` } +type Subject struct { + DataType string `json:"dataType"` + Data string `json:"data"` +} + type Article struct { ArticleId string `json:"articleId"` ArticleRevision int64 `json:"articleRevision"` @@ -137,11 +142,11 @@ type DialogueInsights struct { type Group struct { GroupId string `json:"groupId"` - GroupRevision int64 `json:"groupRevision"` - Type_ string `json:"type"` + Revision int64 `json:"revision"` + DataType string `json:"dataType"` Data string `json:"data"` Created int64 `json:"created"` - Modified int64 `json:"modified"` + Updated int64 `json:"updated"` } type GroupsGroupIdBody struct { diff --git a/net/server/internal/notify.go b/net/server/internal/notify.go index 27610f2d..3d32581e 100644 --- a/net/server/internal/notify.go +++ b/net/server/internal/notify.go @@ -6,7 +6,7 @@ import ( "databag/internal/store" ) -var notify = make(chan *store.Notification) +var notify = make(chan *store.Notification, APP_NOTIFYBUFFER) var notifyExit = make(chan bool) func ExitNotifications() { @@ -139,33 +139,24 @@ func SetContentNotification(account *store.Account) { // notify single card of content change // card.View incremented by adding or removing card from group or label -func SetContactContentNotification(account *store.Account, cardId string) { +func SetContactContentNotification(account *store.Account, card *store.Card) { - // select card if connected - var cards []store.Card - if err := store.DB.Where("account_id = ? AND status = ? AND card_id = ?", account.Guid, APP_CARDCONNECTED, cardId).Find(&cards).Error; err != nil { - ErrMsg(err) + if card.Status != APP_CARDCONNECTED { return } // add new notification for card - err := store.DB.Transaction(func(tx *gorm.DB) error { - for _, card := range cards { - notification := &store.Notification{ - Node: card.Node, - Module: APP_MODULECONTENT, - Token: card.OutToken, - Revision: account.ViewRevision + account.ContentRevision + card.ViewRevision, - } - if err := tx.Save(notification).Error; err != nil { - return err - } - notify <- notification - } - return nil - }) - if err != nil { - ErrMsg(err) + notification := &store.Notification{ + Node: card.Node, + Module: APP_MODULECONTENT, + Token: card.OutToken, + Revision: account.ViewRevision + account.ContentRevision + card.ViewRevision, + } + + if res := store.DB.Save(notification).Error; res != nil { + ErrMsg(res) + } else { + notify <- notification } } diff --git a/net/server/internal/store/schema.go b/net/server/internal/store/schema.go index 3bff6210..772ad249 100644 --- a/net/server/internal/store/schema.go +++ b/net/server/internal/store/schema.go @@ -11,16 +11,11 @@ func AutoMigrate(db *gorm.DB) { db.AutoMigrate(&Group{}); db.AutoMigrate(&Label{}); db.AutoMigrate(&Card{}); - db.AutoMigrate(&CardGroup{}); - db.AutoMigrate(&LabelGroup{}); db.AutoMigrate(&Asset{}); db.AutoMigrate(&Article{}); db.AutoMigrate(&ArticleAsset{}); db.AutoMigrate(&ArticleTag{}); - db.AutoMigrate(&ArticleGroup{}); - db.AutoMigrate(&ArticleLabel{}); db.AutoMigrate(&Dialogue{}); - db.AutoMigrate(&DialogueMember{}); db.AutoMigrate(&Insight{}); db.AutoMigrate(&Topic{}); db.AutoMigrate(&TopicAsset{}); @@ -54,6 +49,9 @@ type AccountToken struct { Account Account } +// NOTE: card & app reference account by guid, all other tables by id +// because token lookup uses guid and is most common and wanted to avoid join +// int foreign key should be faster, so left other tables with id reference type Account struct { ID uint `gorm:"primaryKey;not null;unique;autoIncrement"` AccountDetailID uint `gorm:"not null"` @@ -118,6 +116,7 @@ type Label struct { Data string Created int64 `gorm:"autoCreateTime"` Updated int64 `gorm:"autoUpdateTime"` + Groups []Group `gorm:"many2many:label_groups;"` Account Account } @@ -148,22 +147,6 @@ type Card struct { Account Account `gorm:"references:Guid"` } -type CardGroup struct { - ID uint `gorm:"primaryKey;not null;unique;autoIncrement"` - CardID uint `gorm:"not null;index:cardgroup,unique"` - GroupID uint `gorm:"not null;index:cardgroup,unique"` - Card Card - Group Group -} - -type LabelGroup struct { - ID uint `gorm:"primaryKey;not null;unique;autoIncrement"` - LabelID uint `gorm:"not null;index:labelgroup,unique"` - GroupID uint `gorm:"not null;index:labelgroup,unique"` - Label Label - Group Group -} - type Asset struct { ID uint `gorm:"primaryKey;not null;unique;autoIncrement"` AssetId string `gorm:"not null;index:asset,unique"` @@ -187,10 +170,13 @@ type Article struct { DataType string `gorm:"index"` Data string Status string `gorm:"not null;index"` + Expires int64 Created int64 `gorm:"autoCreateTime"` Updated int64 `gorm:"autoUpdateTime"` TagUpdated int64 `gorm:"not null"` TagRevision uint64 `gorm:"not null"` + Groups []Group `gorm:"many2many:article_groups;"` + Labels []Label `gorm:"many2many:article_labels;"` Account Account } @@ -216,22 +202,6 @@ type ArticleTag struct { Card Card } -type ArticleGroup struct { - ID uint `gorm:"primaryKey;not null;unique;autoIncrement"` - ArticleID uint `gorm:"not null;index"` - GroupID uint `gorm:"not null;index"` - Article Article - Group Group -} - -type ArticleLabel struct { - ID uint `gorm:"primaryKey;not null;unique;autoIncrement"` - ArticleID uint `gorm:"not null;index"` - LabelID uint `gorm:"not null;index"` - Article Article - Label Label -} - type Dialogue struct { ID uint `gorm:"primaryKey;not null;unique;autoIncrement"` DialogueId string `gorm:"not null;index:dialogue,unique"` @@ -245,16 +215,8 @@ type Dialogue struct { MemberRevision uint64 `gorm:"not null"` TopicUpdated int64 TopicRevision uint64 `gorm:"not null"` + Cards []Card `gorm:"many2many:dialog_cards;"` Account Account - Cards []Card `gorm:"many2many:dialogue_member"` -} - -type DialogueMember struct { - ID uint `gorm:"primaryKey;not null;unique;autoIncrement"` - DialogueID uint `gorm:"not null;index` - CardID uint `gorm:"not null;index` - Created int64 `gorm:"autoCreateTime"` - Card Card } type Insight struct { diff --git a/net/server/internal/ucGroupContact_test.go b/net/server/internal/ucGroupContact_test.go new file mode 100644 index 00000000..66e3f8d0 --- /dev/null +++ b/net/server/internal/ucGroupContact_test.go @@ -0,0 +1,84 @@ +package databag + +import ( + "time" + "testing" + "encoding/json" + "github.com/gorilla/mux" + "github.com/gorilla/websocket" + "github.com/stretchr/testify/assert" +) + +func TestGroupContact(t *testing.T) { + var subject *Subject + var group Group + var groups []Group + var groupRevision int64 + var cardRevision int64 + var revision Revision + var vars map[string]string + var cardData CardData + + // connect contacts + access := AddTestContacts(t, "groupcontact", 2); + contact := ConnectTestContacts(t, access[0], access[1]) + + // app connects websocket + wsA := getTestWebsocket() + announce := Announce{ AppToken: access[0] } + data, _ := json.Marshal(&announce) + wsA.WriteMessage(websocket.TextMessage, data) + + // receive revision + wsA.SetReadDeadline(time.Now().Add(2 * time.Second)) + _, data, _ = wsA.ReadMessage() + assert.NoError(t, json.Unmarshal(data, &revision)) + groupRevision = revision.Group + + // add group to conatact 0 + subject = &Subject{ + DataType: "imagroup", + Data: "group data with name and logo", + } + r, w, _ := NewRequest("POST", "/share/groups", subject) + SetBearerAuth(r, access[0]) + AddGroup(w, r) + assert.NoError(t, ReadResponse(w, &group)) + + // receive revision + wsA.SetReadDeadline(time.Now().Add(2 * time.Second)) + _, data, _ = wsA.ReadMessage() + assert.NoError(t, json.Unmarshal(data, &revision)) + assert.NotEqual(t, groupRevision, revision.Group) + cardRevision = revision.Card + + // set contact group + r, w, _ = NewRequest("PUT", "/contact/cards/{cardId}/groups/{groupId}", nil) + vars = make(map[string]string) + vars["groupId"] = group.GroupId + vars["cardId"] = contact[0].ContactCardId + r = mux.SetURLVars(r, vars) + SetBearerAuth(r, access[0]) + SetCardGroup(w, r) + assert.NoError(t, ReadResponse(w, &cardData)) + assert.Equal(t, 1, len(cardData.Groups)) + + // receive revision + wsA.SetReadDeadline(time.Now().Add(2 * time.Second)) + _, data, _ = wsA.ReadMessage() + assert.NoError(t, json.Unmarshal(data, &revision)) + assert.NotEqual(t, cardRevision, revision.Card) + + // show group view + r, w, _ = NewRequest("GET", "/share/groups", nil) + SetBearerAuth(r, access[0]) + GetGroups(w, r) + assert.NoError(t, ReadResponse(w, &groups)) + assert.Equal(t, 1, len(groups)) + +PrintMsg(groups) + + // add group + + // show group view +}