From 977ed5d2234112740cc93620696c862d6db2767d Mon Sep 17 00:00:00 2001 From: Albin Antony Date: Tue, 24 Oct 2023 15:18:26 +0530 Subject: [PATCH] Fix #331 Config: Purpose field is required in the response of list all data attributes --- src/v2/dataattribute/dataattributes.go | 53 ++++++++++-- .../config_list_dataattributes.go | 80 +++++++++---------- 2 files changed, 83 insertions(+), 50 deletions(-) diff --git a/src/v2/dataattribute/dataattributes.go b/src/v2/dataattribute/dataattributes.go index 53deb73..4c747c1 100644 --- a/src/v2/dataattribute/dataattributes.go +++ b/src/v2/dataattribute/dataattributes.go @@ -35,15 +35,14 @@ type DataAgreementForDataAttribute struct { type DataAttributeForLists struct { Id primitive.ObjectID `json:"id" bson:"_id,omitempty"` Version string `json:"version"` - AgreementIds string `json:"-"` + AgreementIds []string `json:"agreementIds"` Name string `json:"name" valid:"required"` Description string `json:"description" valid:"required"` Sensitivity bool `json:"sensitivity"` Category string `json:"category"` OrganisationId string `json:"-"` IsDeleted bool `json:"-"` - DataAgreements interface{} `json:"agreementIds"` - AgreementData []DataAgreementForDataAttribute `json:"agreements"` + AgreementData []DataAgreementForDataAttribute `json:"dataAgreements"` } type DataAttributeRepository struct { DefaultFilter bson.M @@ -168,16 +167,18 @@ func ListDataAttributesBasedOnMethodOfUse(methodOfUse string, organisationId str pipeline := []bson.M{ {"$match": bson.M{"organisationid": organisationId, "isdeleted": false}}, - {"$addFields": bson.M{"dataAgreements": "$agreementids"}}, - {"$unwind": "$agreementids"}, {"$lookup": bson.M{ "from": "dataAgreements", - "let": bson.M{"localId": "$agreementids"}, + "let": bson.M{"localIds": "$agreementids"}, "pipeline": bson.A{ bson.M{ "$match": bson.M{ "$expr": bson.M{ - "$eq": []interface{}{"$_id", bson.M{"$toObjectId": "$$localId"}}, + "$in": bson.A{"$_id", bson.M{"$map": bson.M{ + "input": "$$localIds", + "as": "r", + "in": bson.M{"$toObjectId": "$$r"}, + }}}, }, }, }, @@ -198,3 +199,41 @@ func ListDataAttributesBasedOnMethodOfUse(methodOfUse string, organisationId str } return results, nil } + +// ListDataAttributesWithDataAgreement lists data attributes with data agreements +func ListDataAttributesWithDataAgreement(organisationId string) ([]DataAttributeForLists, error) { + var results []DataAttributeForLists + + pipeline := []bson.M{ + {"$match": bson.M{"organisationid": organisationId, "isdeleted": false}}, + {"$lookup": bson.M{ + "from": "dataAgreements", + "let": bson.M{"localIds": "$agreementids"}, + "pipeline": bson.A{ + bson.M{ + "$match": bson.M{ + "$expr": bson.M{ + "$in": bson.A{"$_id", bson.M{"$map": bson.M{ + "input": "$$localIds", + "as": "r", + "in": bson.M{"$toObjectId": "$$r"}, + }}}, + }, + }, + }, + }, + "as": "agreementData", + }}, + } + + cursor, err := Collection().Aggregate(context.TODO(), pipeline) + if err != nil { + return results, err + } + defer cursor.Close(context.TODO()) + + if err = cursor.All(context.TODO(), &results); err != nil { + return results, err + } + return results, nil +} diff --git a/src/v2/handler/dataattribute/config_list_dataattributes.go b/src/v2/handler/dataattribute/config_list_dataattributes.go index 1c5bca3..155a49e 100644 --- a/src/v2/handler/dataattribute/config_list_dataattributes.go +++ b/src/v2/handler/dataattribute/config_list_dataattributes.go @@ -1,7 +1,6 @@ package dataattribute import ( - "context" "encoding/json" "errors" "fmt" @@ -10,6 +9,7 @@ import ( "github.com/bb-consent/api/src/common" "github.com/bb-consent/api/src/config" + "github.com/bb-consent/api/src/v2/dataagreement" "github.com/bb-consent/api/src/v2/dataattribute" "github.com/bb-consent/api/src/v2/paginate" "github.com/bb-consent/api/src/v2/revision" @@ -99,65 +99,39 @@ func ConfigListDataAttributes(w http.ResponseWriter, r *http.Request) { methodOfUse, err := ParseMethodOfUseDataAttributesQueryParams(r) methodOfUse = common.Sanitize(methodOfUse) + var res []dataattribute.DataAttributeForLists if err != nil && errors.Is(err, MethodOfUseIsMissingError) { - // Repository - dataAttributeRepo := dataattribute.DataAttributeRepository{} - dataAttributeRepo.Init(organisationId) // Return all data attributes - var dataAttributes []dataattribute.DataAttribute - query := paginate.PaginateDBObjectsQuery{ - Filter: dataAttributeRepo.DefaultFilter, - Collection: dataattribute.Collection(), - Context: context.Background(), - Limit: limit, - Offset: offset, - } - result, err := paginate.PaginateDBObjects(query, &dataAttributes) + res, err = dataattribute.ListDataAttributesWithDataAgreement(organisationId) if err != nil { - if errors.Is(err, paginate.EmptyDBError) { - emptyDataAttributes := make([]interface{}, 0) - resp = listDataAttributesResp{ - DataAttributes: emptyDataAttributes, - Pagination: result.Pagination, - } - returnHTTPResponse(resp, w) - return - } - m := "Failed to paginate data attribute" + m := fmt.Sprintf("Failed to fetch data attribute by method of use: %v", methodOfUse) common.HandleErrorV2(w, http.StatusInternalServerError, m, err) return - } - resp = listDataAttributesResp{ - DataAttributes: result.Items, - Pagination: result.Pagination, - } - returnHTTPResponse(resp, w) - return } else { // List by method of use - res, err := dataattribute.ListDataAttributesBasedOnMethodOfUse(methodOfUse, organisationId) + res, err = dataattribute.ListDataAttributesBasedOnMethodOfUse(methodOfUse, organisationId) if err != nil { m := fmt.Sprintf("Failed to fetch data attribute by method of use: %v", methodOfUse) common.HandleErrorV2(w, http.StatusInternalServerError, m, err) return } - query := paginate.PaginateObjectsQuery{ - Limit: limit, - Offset: offset, - } - interfaceSlice := dataAttributesToInterfaceSlice(res) - result := paginate.PaginateObjects(query, interfaceSlice) - resp = listDataAttributesResp{ - DataAttributes: result.Items, - Pagination: result.Pagination, - } - returnHTTPResponse(resp, w) - return } + query := paginate.PaginateObjectsQuery{ + Limit: limit, + Offset: offset, + } + interfaceSlice := dataAttributesToInterfaceSlice(res) + result := paginate.PaginateObjects(query, interfaceSlice) + resp = listDataAttributesResp{ + DataAttributes: result.Items, + Pagination: result.Pagination, + } + returnHTTPResponse(resp, w) + return } else { // Fetch revision by id @@ -175,6 +149,26 @@ func ConfigListDataAttributes(w http.ResponseWriter, r *http.Request) { common.HandleErrorV2(w, http.StatusInternalServerError, m, err) return } + // Repository + darepo := dataagreement.DataAgreementRepository{} + darepo.Init(organisationId) + + var dataAgreements []dataattribute.DataAgreementForDataAttribute + for _, a := range da.AgreementIds { + var dA dataattribute.DataAgreementForDataAttribute + dataAgreement, err := darepo.Get(a) + if err != nil { + m := fmt.Sprintf("Failed to fetch data agreement by revision: %v", revisionId) + common.HandleErrorV2(w, http.StatusInternalServerError, m, err) + return + } + dA.Id = dataAgreement.Id.Hex() + dA.Purpose = dataAgreement.Purpose + dataAgreements = append(dataAgreements, dA) + } + + var dataAttributes dataattribute.DataAttributeForLists + dataAttributes.AgreementData = dataAgreements interfaceSlice := make([]interface{}, 0) interfaceSlice = append(interfaceSlice, da)