diff --git a/net/server/internal/api_removeGroup.go b/net/server/internal/api_removeGroup.go new file mode 100644 index 00000000..684a6572 --- /dev/null +++ b/net/server/internal/api_removeGroup.go @@ -0,0 +1,38 @@ +package databag + +import ( + "net/http" + "gorm.io/gorm" + "github.com/gorilla/mux" + "databag/internal/store" +) + +func RemoveGroup(w http.ResponseWriter, r *http.Request) { + + account, code, err := BearerAppToken(r, false) + if err != nil { + ErrResponse(w, code, err) + return + } + params := mux.Vars(r) + groupId := params["groupId"] + + err = store.DB.Transaction(func(tx *gorm.DB) error { + if res := tx.Where("account_id = ? AND group_id = ?", account.ID, groupId).Delete(&store.Group{}).Error; res != nil { + return res + } + if res := tx.Model(&account).Updates(store.Account{ViewRevision: account.ViewRevision + 1, GroupRevision: account.GroupRevision + 1}).Error; res != nil { + return res + } + return nil + }) + if err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + + WriteResponse(w, nil) + SetStatus(account) + SetContentNotification(account) +} + diff --git a/net/server/internal/api_setCardGroup.go b/net/server/internal/api_setCardGroup.go index 07b6b1b9..5416b5c1 100644 --- a/net/server/internal/api_setCardGroup.go +++ b/net/server/internal/api_setCardGroup.go @@ -48,10 +48,10 @@ func SetCardGroup(w http.ResponseWriter, r *http.Request) { 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 { + if res := tx.Model(&account).Update("card_revision", account.CardRevision + 1).Error; res != nil { return res } - if res := store.DB.Preload("Groups").Save(&card).Error; res != nil { + if res := tx.Preload("Groups").Save(&card).Error; res != nil { return res } return nil @@ -66,7 +66,6 @@ func SetCardGroup(w http.ResponseWriter, r *http.Request) { Status: card.Status, Notes: card.Notes, Token: card.OutToken, - Groups: nil, } for _, group := range card.Groups { cardData.Groups = append(cardData.Groups, group.GroupId) diff --git a/net/server/internal/api_share.go b/net/server/internal/api_share.go deleted file mode 100644 index 548b628d..00000000 --- a/net/server/internal/api_share.go +++ /dev/null @@ -1,24 +0,0 @@ -/* - * DataBag - * - * DataBag provides storage for decentralized identity based self-hosting apps. It is intended to support sharing of personal data and hosting group conversations. - * - * API version: 0.0.1 - * Contact: roland.osborne@gmail.com - * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) - */ -package databag - -import ( - "net/http" -) - -func RemoveGroup(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json; charset=UTF-8") - w.WriteHeader(http.StatusOK) -} - -func UpdateGroup(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_updateGroup.go b/net/server/internal/api_updateGroup.go new file mode 100644 index 00000000..e0349584 --- /dev/null +++ b/net/server/internal/api_updateGroup.go @@ -0,0 +1,59 @@ +package databag + +import ( + "errors" + "net/http" + "gorm.io/gorm" + "github.com/gorilla/mux" + "databag/internal/store" +) + +func UpdateGroup(w http.ResponseWriter, r *http.Request) { + + account, code, err := BearerAppToken(r, false) + if err != nil { + ErrResponse(w, code, err) + return + } + params := mux.Vars(r) + groupId := params["groupId"] + + var subject Subject + if err := ParseRequest(r, w, &subject); err != nil { + ErrResponse(w, http.StatusBadRequest, err) + return + } + + // load specified 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 + } + + // update specified group + group.DataType = subject.DataType + group.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/main_test.go b/net/server/internal/main_test.go index ee3197b2..9e916f29 100644 --- a/net/server/internal/main_test.go +++ b/net/server/internal/main_test.go @@ -7,7 +7,7 @@ import ( func TestMain(m *testing.M) { -// SetHideLog(true) + SetHideLog(true) SetKeySize(2048) store.SetPath("file::memory:?cache=shared"); // store.SetPath("databag.db"); diff --git a/net/server/internal/ucGroupContact_test.go b/net/server/internal/ucGroupContact_test.go index 66e3f8d0..20f002de 100644 --- a/net/server/internal/ucGroupContact_test.go +++ b/net/server/internal/ucGroupContact_test.go @@ -18,6 +18,12 @@ func TestGroupContact(t *testing.T) { var revision Revision var vars map[string]string var cardData CardData + var contactRevision int64 + var card Card + var contactCardRevision int64 + + // start notification thread + go SendNotifications() // connect contacts access := AddTestContacts(t, "groupcontact", 2); @@ -28,12 +34,20 @@ func TestGroupContact(t *testing.T) { announce := Announce{ AppToken: access[0] } data, _ := json.Marshal(&announce) wsA.WriteMessage(websocket.TextMessage, data) + wsB := getTestWebsocket() + announce = Announce{ AppToken: access[1] } + data, _ = json.Marshal(&announce) + wsB.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 + wsB.SetReadDeadline(time.Now().Add(2 * time.Second)) + _, data, _ = wsB.ReadMessage() + assert.NoError(t, json.Unmarshal(data, &revision)) + contactRevision = revision.Card // add group to conatact 0 subject = &Subject{ @@ -52,6 +66,15 @@ func TestGroupContact(t *testing.T) { assert.NotEqual(t, groupRevision, revision.Group) cardRevision = revision.Card + // get contact revision + r, w, _ = NewRequest("GET", "/contact/cards/{cardId}", nil) + vars = map[string]string{ "cardId": contact[1].ContactCardId } + r = mux.SetURLVars(r, vars) + SetBearerAuth(r, access[1]) + GetCard(w, r) + assert.NoError(t, ReadResponse(w, &card)) + contactCardRevision = card.ContentRevision + // set contact group r, w, _ = NewRequest("PUT", "/contact/cards/{cardId}/groups/{groupId}", nil) vars = make(map[string]string) @@ -68,6 +91,22 @@ func TestGroupContact(t *testing.T) { _, data, _ = wsA.ReadMessage() assert.NoError(t, json.Unmarshal(data, &revision)) assert.NotEqual(t, cardRevision, revision.Card) + groupRevision = revision.Group + wsB.SetReadDeadline(time.Now().Add(2 * time.Second)) + _, data, _ = wsB.ReadMessage() + assert.NoError(t, json.Unmarshal(data, &revision)) + assert.NotEqual(t, contactRevision, revision.Card) + contactRevision = revision.Card + + // get contact revision + r, w, _ = NewRequest("GET", "/contact/cards/{cardId}", nil) + vars = map[string]string{ "cardId": contact[1].ContactCardId } + r = mux.SetURLVars(r, vars) + SetBearerAuth(r, access[1]) + GetCard(w, r) + assert.NoError(t, ReadResponse(w, &card)) + assert.NotEqual(t, contactCardRevision, card.ContentRevision) + contactCardRevision = card.ContentRevision // show group view r, w, _ = NewRequest("GET", "/share/groups", nil) @@ -76,9 +115,62 @@ func TestGroupContact(t *testing.T) { assert.NoError(t, ReadResponse(w, &groups)) assert.Equal(t, 1, len(groups)) -PrintMsg(groups) + // update group in conatact 0 + subject = &Subject{ + DataType: "imagroupEDIT", + Data: "group data with name and logo", + } + r, w, _ = NewRequest("POST", "/share/groups", subject) + vars = make(map[string]string) + vars["groupId"] = group.GroupId + r = mux.SetURLVars(r, vars) + SetBearerAuth(r, access[0]) + UpdateGroup(w, r) + assert.NoError(t, ReadResponse(w, &group)) + assert.Equal(t, group.DataType, "imagroupEDIT") - // add 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) + groupRevision = revision.Group + + // delete group + r, w, _ = NewRequest("DELETE", "/share/groups", nil) + vars = make(map[string]string) + vars["groupId"] = group.GroupId + r = mux.SetURLVars(r, vars) + SetBearerAuth(r, access[0]) + RemoveGroup(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) + wsB.SetReadDeadline(time.Now().Add(2 * time.Second)) + _, data, _ = wsB.ReadMessage() + assert.NoError(t, json.Unmarshal(data, &revision)) + assert.NotEqual(t, contactRevision, revision.Card) + + // get contact revision + r, w, _ = NewRequest("GET", "/contact/cards/{cardId}", nil) + vars = map[string]string{ "cardId": contact[1].ContactCardId } + r = mux.SetURLVars(r, vars) + SetBearerAuth(r, access[1]) + GetCard(w, r) + assert.NoError(t, ReadResponse(w, &card)) + assert.NotEqual(t, contactCardRevision, card.ContentRevision) // 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, 0, len(groups)) + + // stop notification thread + ExitNotifications() }