Skip to content

Commit 5343c59

Browse files
authored
Merge pull request #64 from rashmithachamikara/feature/display-names-in-consent-get
Display names in consent get and purpose get
2 parents d1add59 + ab44ca5 commit 5343c59

10 files changed

Lines changed: 401 additions & 66 deletions

File tree

api/consent-management-API.yaml

Lines changed: 203 additions & 20 deletions
Large diffs are not rendered by default.

consent-server/internal/consent/handler.go

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ func (h *consentHandler) getConsent(w http.ResponseWriter, r *http.Request) {
101101
}
102102

103103
includeStatusHistory := r.URL.Query().Get("includeStatusHistory") == "true"
104+
details := r.URL.Query().Get("details") == "true"
104105
var out *model.ConsentOutput
105106
var serviceErr *serviceerror.ServiceError
106107
if includeStatusHistory {
@@ -114,7 +115,7 @@ func (h *consentHandler) getConsent(w http.ResponseWriter, r *http.Request) {
114115
}
115116

116117
w.Header().Set(constants.HeaderContentType, constants.ContentTypeJSON)
117-
json.NewEncoder(w).Encode(consentOutputToResponse(out))
118+
json.NewEncoder(w).Encode(consentOutputToResponseWithDetails(out, details))
118119
}
119120

120121
// getConsentHistory handles GET /consents/{consentId}/history
@@ -270,7 +271,8 @@ func (h *consentHandler) listConsents(w http.ResponseWriter, r *http.Request) {
270271
}
271272

272273
w.Header().Set(constants.HeaderContentType, constants.ContentTypeJSON)
273-
json.NewEncoder(w).Encode(consentListOutputToResponse(listOut))
274+
details := r.URL.Query().Get("details") == "true"
275+
json.NewEncoder(w).Encode(consentListOutputToResponse(listOut, details))
274276
}
275277

276278
// updateConsent handles PUT /consents/{consentId}
@@ -537,6 +539,18 @@ func authorizationRequestToInput(ar model.AuthorizationRequest) authmodel.Create
537539

538540
// consentOutputToResponse converts a ConsentOutput to the JSON-ready ConsentResponse.
539541
func consentOutputToResponse(out *model.ConsentOutput) *model.ConsentResponse {
542+
// Preserve the existing create/update and internal snapshot response shape:
543+
// display names are included, while descriptions remain GET/search details.
544+
return consentOutputToResponseWithOptions(out, true, false)
545+
}
546+
547+
// consentOutputToResponseWithDetails converts a ConsentOutput to a response and
548+
// includes purpose/element definition details only when requested.
549+
func consentOutputToResponseWithDetails(out *model.ConsentOutput, details bool) *model.ConsentResponse {
550+
return consentOutputToResponseWithOptions(out, details, details)
551+
}
552+
553+
func consentOutputToResponseWithOptions(out *model.ConsentOutput, includeDisplayNames, includeDescriptions bool) *model.ConsentResponse {
540554
if out == nil {
541555
return nil
542556
}
@@ -545,22 +559,38 @@ func consentOutputToResponse(out *model.ConsentOutput) *model.ConsentResponse {
545559
for _, p := range out.Purposes {
546560
elements := make([]model.ConsentPurposeElementApprovalResponse, 0, len(p.Elements))
547561
for _, e := range p.Elements {
562+
var elementDisplayName, elementDescription *string
563+
if includeDisplayNames {
564+
elementDisplayName = e.DisplayName
565+
}
566+
if includeDescriptions {
567+
elementDescription = e.Description
568+
}
548569
elements = append(elements, model.ConsentPurposeElementApprovalResponse{
549570
ElementID: e.ElementID,
550571
Name: e.Name,
551572
Namespace: e.Namespace,
552573
Version: formatVersion(e.VersionNum),
553-
DisplayName: e.DisplayName,
574+
DisplayName: elementDisplayName,
575+
Description: elementDescription,
554576
Mandatory: e.Mandatory,
555577
Approved: e.Approved,
556578
Value: valueStringToInterface(e.Value, e.ElementType),
557579
})
558580
}
581+
var purposeDisplayName, purposeDescription *string
582+
if includeDisplayNames {
583+
purposeDisplayName = p.DisplayName
584+
}
585+
if includeDescriptions {
586+
purposeDescription = p.Description
587+
}
559588
purposes = append(purposes, model.ConsentPurposeResponse{
560589
PurposeID: p.PurposeID,
561590
Name: p.Name,
562591
Version: formatVersion(p.VersionNum),
563-
DisplayName: p.DisplayName,
592+
DisplayName: purposeDisplayName,
593+
Description: purposeDescription,
564594
Elements: elements,
565595
})
566596
}
@@ -606,10 +636,10 @@ func consentOutputToResponse(out *model.ConsentOutput) *model.ConsentResponse {
606636
}
607637

608638
// consentListOutputToResponse converts a ConsentListOutput to the JSON-ready ConsentListResponse.
609-
func consentListOutputToResponse(out *model.ConsentListOutput) *model.ConsentListResponse {
639+
func consentListOutputToResponse(out *model.ConsentListOutput, details bool) *model.ConsentListResponse {
610640
data := make([]model.ConsentResponse, 0, len(out.Data))
611641
for i := range out.Data {
612-
r := consentOutputToResponse(&out.Data[i])
642+
r := consentOutputToResponseWithDetails(&out.Data[i], details)
613643
data = append(data, *r)
614644
}
615645
return &model.ConsentListResponse{

consent-server/internal/consent/handler_test.go

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,9 @@ func TestHandlerCreateConsent_ServiceError(t *testing.T) {
181181
func TestHandlerGetConsent_Success(t *testing.T) {
182182
mockSvc := NewMockConsentService(t)
183183
purposeDisplayName := "Account management"
184+
purposeDescription := "Manage account access"
184185
elementDisplayName := "User email address"
186+
elementDescription := "The user's email address"
185187

186188
out := &model.ConsentOutput{
187189
ConsentID: handlerTestConsentID,
@@ -193,19 +195,21 @@ func TestHandlerGetConsent_Success(t *testing.T) {
193195
Name: "account_management",
194196
VersionNum: 1,
195197
DisplayName: &purposeDisplayName,
198+
Description: &purposeDescription,
196199
Elements: []model.ConsentElementApprovalOutput{{
197200
ElementID: "element-1",
198201
Name: "user_email",
199202
Namespace: "default",
200203
VersionNum: 1,
201204
DisplayName: &elementDisplayName,
205+
Description: &elementDescription,
202206
}},
203207
}},
204208
}
205209
mockSvc.On("GetConsent", mock.Anything, handlerTestConsentID, handlerTestOrgID).Return(out, nil)
206210

207211
handler := newConsentHandler(mockSvc)
208-
req := httptest.NewRequest(http.MethodGet, "/consents/"+handlerTestConsentID, nil)
212+
req := httptest.NewRequest(http.MethodGet, "/consents/"+handlerTestConsentID+"?details=true", nil)
209213
req.Header.Set(constants.HeaderOrgID, handlerTestOrgID)
210214
req.SetPathValue("consentId", handlerTestConsentID)
211215
rr := httptest.NewRecorder()
@@ -218,7 +222,42 @@ func TestHandlerGetConsent_Success(t *testing.T) {
218222
require.NoError(t, json.NewDecoder(rr.Body).Decode(&resp))
219223
require.Equal(t, handlerTestConsentID, resp.ConsentID)
220224
require.Equal(t, purposeDisplayName, *resp.Purposes[0].DisplayName)
225+
require.Equal(t, purposeDescription, *resp.Purposes[0].Description)
221226
require.Equal(t, elementDisplayName, *resp.Purposes[0].Elements[0].DisplayName)
227+
require.Equal(t, elementDescription, *resp.Purposes[0].Elements[0].Description)
228+
}
229+
230+
func TestHandlerGetConsent_DefaultOmitsDefinitionDetails(t *testing.T) {
231+
mockSvc := NewMockConsentService(t)
232+
purposeDisplayName := "Account management"
233+
purposeDescription := "Manage account access"
234+
elementDisplayName := "User email address"
235+
elementDescription := "The user's email address"
236+
237+
out := &model.ConsentOutput{
238+
ConsentID: handlerTestConsentID,
239+
Purposes: []model.ConsentPurposeOutput{{
240+
DisplayName: &purposeDisplayName,
241+
Description: &purposeDescription,
242+
Elements: []model.ConsentElementApprovalOutput{{
243+
DisplayName: &elementDisplayName,
244+
Description: &elementDescription,
245+
}},
246+
}},
247+
}
248+
mockSvc.On("GetConsent", mock.Anything, handlerTestConsentID, handlerTestOrgID).Return(out, nil)
249+
250+
handler := newConsentHandler(mockSvc)
251+
req := httptest.NewRequest(http.MethodGet, "/consents/"+handlerTestConsentID, nil)
252+
req.Header.Set(constants.HeaderOrgID, handlerTestOrgID)
253+
req.SetPathValue("consentId", handlerTestConsentID)
254+
rr := httptest.NewRecorder()
255+
256+
handler.getConsent(rr, req)
257+
258+
require.Equal(t, http.StatusOK, rr.Code)
259+
require.NotContains(t, rr.Body.String(), "displayName")
260+
require.NotContains(t, rr.Body.String(), "description")
222261
}
223262

224263
func TestHandlerGetConsent_NotFound(t *testing.T) {
@@ -259,7 +298,9 @@ func TestHandlerGetConsent_MissingOrgID(t *testing.T) {
259298
func TestHandlerListConsents_Success(t *testing.T) {
260299
mockSvc := NewMockConsentService(t)
261300
purposeDisplayName := "Account management"
301+
purposeDescription := "Manage account access"
262302
elementDisplayName := "User email address"
303+
elementDescription := "The user's email address"
263304

264305
listOut := &model.ConsentListOutput{
265306
Data: []model.ConsentOutput{{
@@ -270,10 +311,12 @@ func TestHandlerListConsents_Success(t *testing.T) {
270311
Name: "account_management",
271312
VersionNum: 1,
272313
DisplayName: &purposeDisplayName,
314+
Description: &purposeDescription,
273315
Elements: []model.ConsentElementApprovalOutput{{
274316
Name: "user_email",
275317
VersionNum: 1,
276318
DisplayName: &elementDisplayName,
319+
Description: &elementDescription,
277320
}},
278321
}},
279322
}},
@@ -285,7 +328,7 @@ func TestHandlerListConsents_Success(t *testing.T) {
285328
mockSvc.On("SearchConsents", mock.Anything, mock.Anything).Return(listOut, nil)
286329

287330
handler := newConsentHandler(mockSvc)
288-
req := httptest.NewRequest(http.MethodGet, "/consents", nil)
331+
req := httptest.NewRequest(http.MethodGet, "/consents?details=true", nil)
289332
req.Header.Set(constants.HeaderOrgID, handlerTestOrgID)
290333
rr := httptest.NewRecorder()
291334

@@ -297,7 +340,42 @@ func TestHandlerListConsents_Success(t *testing.T) {
297340
require.NoError(t, json.NewDecoder(rr.Body).Decode(&resp))
298341
require.Len(t, resp.Data, 1)
299342
require.Equal(t, purposeDisplayName, *resp.Data[0].Purposes[0].DisplayName)
343+
require.Equal(t, purposeDescription, *resp.Data[0].Purposes[0].Description)
300344
require.Equal(t, elementDisplayName, *resp.Data[0].Purposes[0].Elements[0].DisplayName)
345+
require.Equal(t, elementDescription, *resp.Data[0].Purposes[0].Elements[0].Description)
346+
}
347+
348+
func TestHandlerListConsents_DefaultOmitsDefinitionDetails(t *testing.T) {
349+
mockSvc := NewMockConsentService(t)
350+
purposeDisplayName := "Account management"
351+
purposeDescription := "Manage account access"
352+
elementDisplayName := "User email address"
353+
elementDescription := "The user's email address"
354+
355+
listOut := &model.ConsentListOutput{
356+
Data: []model.ConsentOutput{{
357+
Purposes: []model.ConsentPurposeOutput{{
358+
DisplayName: &purposeDisplayName,
359+
Description: &purposeDescription,
360+
Elements: []model.ConsentElementApprovalOutput{{
361+
DisplayName: &elementDisplayName,
362+
Description: &elementDescription,
363+
}},
364+
}},
365+
}},
366+
}
367+
mockSvc.On("SearchConsents", mock.Anything, mock.Anything).Return(listOut, nil)
368+
369+
handler := newConsentHandler(mockSvc)
370+
req := httptest.NewRequest(http.MethodGet, "/consents", nil)
371+
req.Header.Set(constants.HeaderOrgID, handlerTestOrgID)
372+
rr := httptest.NewRecorder()
373+
374+
handler.listConsents(rr, req)
375+
376+
require.Equal(t, http.StatusOK, rr.Code)
377+
require.NotContains(t, rr.Body.String(), "displayName")
378+
require.NotContains(t, rr.Body.String(), "description")
301379
}
302380

303381
func TestHandlerListConsents_MissingOrgID(t *testing.T) {

consent-server/internal/consent/model/consent.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ type ConsentPurposeElementApprovalResponse struct {
399399
Namespace string `json:"namespace"`
400400
Version string `json:"version"` // "v1", "v2", ...
401401
DisplayName *string `json:"displayName,omitempty"`
402+
Description *string `json:"description,omitempty"`
402403
Mandatory bool `json:"mandatory"`
403404
Approved bool `json:"approved"`
404405
Value interface{} `json:"value,omitempty"`
@@ -410,6 +411,7 @@ type ConsentPurposeResponse struct {
410411
Name string `json:"name"`
411412
Version string `json:"version"` // "v1", "v2", ...
412413
DisplayName *string `json:"displayName,omitempty"`
414+
Description *string `json:"description,omitempty"`
413415
Elements []ConsentPurposeElementApprovalResponse `json:"elements"`
414416
}
415417

consent-server/internal/consentpurpose/handler.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -379,11 +379,13 @@ func purposeToResponse(p *model.PurposeOutput) model.PurposeResponse {
379379
elems := make([]model.PurposeElementResponse, 0, len(p.Elements))
380380
for _, e := range p.Elements {
381381
elems = append(elems, model.PurposeElementResponse{
382-
ElementID: e.ElementID,
383-
Name: e.Name,
384-
Namespace: e.Namespace,
385-
Version: fmt.Sprintf("v%d", e.VersionNum),
386-
Mandatory: e.Mandatory,
382+
ElementID: e.ElementID,
383+
Name: e.Name,
384+
Namespace: e.Namespace,
385+
Version: fmt.Sprintf("v%d", e.VersionNum),
386+
DisplayName: e.DisplayName,
387+
Description: e.Description,
388+
Mandatory: e.Mandatory,
387389
})
388390
}
389391
resp.Elements = elems
@@ -404,11 +406,13 @@ func purposeToItem(p *model.PurposeOutput) model.PurposeVersionItem {
404406
elems := make([]model.PurposeElementResponse, 0, len(p.Elements))
405407
for _, e := range p.Elements {
406408
elems = append(elems, model.PurposeElementResponse{
407-
ElementID: e.ElementID,
408-
Name: e.Name,
409-
Namespace: e.Namespace,
410-
Version: fmt.Sprintf("v%d", e.VersionNum),
411-
Mandatory: e.Mandatory,
409+
ElementID: e.ElementID,
410+
Name: e.Name,
411+
Namespace: e.Namespace,
412+
Version: fmt.Sprintf("v%d", e.VersionNum),
413+
DisplayName: e.DisplayName,
414+
Description: e.Description,
415+
Mandatory: e.Mandatory,
412416
})
413417
}
414418
item.Elements = elems

consent-server/internal/consentpurpose/handler_test.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -765,11 +765,21 @@ func TestDeletePurposeVersion_ServiceError(t *testing.T) {
765765

766766
func TestGetPurpose_WithElements(t *testing.T) {
767767
mockSvc := NewMockConsentPurposeService(t)
768+
elementDisplayName := "Email address"
769+
elementDescription := "The user's email address"
768770

769771
pv := &model.PurposeOutput{
770772
ID: testPurposeID, Name: "Marketing", GroupID: testOrgID, VersionNum: 1,
771773
Elements: []model.PurposeElementOutput{
772-
{ElementID: "eid-1", Name: "email", Namespace: "default", VersionNum: 2, Mandatory: true},
774+
{
775+
ElementID: "eid-1",
776+
Name: "email",
777+
Namespace: "default",
778+
VersionNum: 2,
779+
DisplayName: &elementDisplayName,
780+
Description: &elementDescription,
781+
Mandatory: true,
782+
},
773783
},
774784
}
775785
mockSvc.On("GetPurpose", mock.Anything, testPurposeID, testOrgID).Return(pv, nil)
@@ -788,19 +798,31 @@ func TestGetPurpose_WithElements(t *testing.T) {
788798
require.Len(t, resp.Elements, 1)
789799
require.Equal(t, "email", resp.Elements[0].Name)
790800
require.Equal(t, "v2", resp.Elements[0].Version)
801+
require.Equal(t, elementDisplayName, *resp.Elements[0].DisplayName)
802+
require.Equal(t, elementDescription, *resp.Elements[0].Description)
791803
require.True(t, resp.Elements[0].Mandatory)
792804
}
793805

794806
func TestListPurposeVersions_WithElements(t *testing.T) {
795807
mockSvc := NewMockConsentPurposeService(t)
796808

809+
elementDisplayName := "Email address"
810+
elementDescription := "The user's email address"
797811
out := &model.PurposeVersionListOutput{
798812
PurposeID: testPurposeID, Name: "Marketing", GroupID: testOrgID,
799813
Versions: []model.PurposeOutput{
800814
{
801815
ID: testPurposeID, VersionNum: 1,
802816
Elements: []model.PurposeElementOutput{
803-
{ElementID: "eid-1", Name: "email", Namespace: "default", VersionNum: 1, Mandatory: false},
817+
{
818+
ElementID: "eid-1",
819+
Name: "email",
820+
Namespace: "default",
821+
VersionNum: 1,
822+
DisplayName: &elementDisplayName,
823+
Description: &elementDescription,
824+
Mandatory: false,
825+
},
804826
},
805827
},
806828
},
@@ -820,6 +842,8 @@ func TestListPurposeVersions_WithElements(t *testing.T) {
820842
require.NoError(t, json.NewDecoder(rr.Body).Decode(&resp))
821843
require.Len(t, resp.Versions[0].Elements, 1)
822844
require.Equal(t, "email", resp.Versions[0].Elements[0].Name)
845+
require.Equal(t, elementDisplayName, *resp.Versions[0].Elements[0].DisplayName)
846+
require.Equal(t, elementDescription, *resp.Versions[0].Elements[0].Description)
823847
}
824848

825849
// =============================================================================

0 commit comments

Comments
 (0)