11package handlers
22
33import (
4+ "context"
45 "encoding/json"
56 "errors"
67 "fmt"
78 "log/slog"
89 "net/http"
10+ "time"
911
12+ auditmodels "github.com/gov-dx-sandbox/audit-service/v1/models"
13+ "github.com/gov-dx-sandbox/exchange/consent-engine/v1/middleware"
1014 "github.com/gov-dx-sandbox/exchange/consent-engine/v1/models"
1115 "github.com/gov-dx-sandbox/exchange/consent-engine/v1/services"
1216 "github.com/gov-dx-sandbox/exchange/consent-engine/v1/utils"
@@ -46,6 +50,9 @@ func (h *InternalHandler) GetConsent(w http.ResponseWriter, r *http.Request) {
4650 return
4751 }
4852
53+ // Extract trace ID from request and add to context
54+ ctx := middleware .ExtractTraceIDFromRequest (r )
55+
4956 // Parse query parameters
5057 ownerEmail := r .URL .Query ().Get ("ownerEmail" )
5158 ownerID := r .URL .Query ().Get ("ownerId" )
@@ -62,20 +69,26 @@ func (h *InternalHandler) GetConsent(w http.ResponseWriter, r *http.Request) {
6269 return
6370 }
6471
72+ // Log consent check request
73+ h .logConsentCheckRequest (ctx , appID , ownerEmail , ownerID )
74+
6575 // Get consent from service (context with timeout is propagated)
6676 var consent * models.ConsentResponseInternalView
6777 var err error
6878
6979 if ownerEmail != "" {
70- consent , err = h .consentService .GetConsentInternalView (r . Context () , nil , nil , & ownerEmail , & appID )
80+ consent , err = h .consentService .GetConsentInternalView (ctx , nil , nil , & ownerEmail , & appID )
7181 } else {
72- consent , err = h .consentService .GetConsentInternalView (r . Context () , nil , & ownerID , nil , & appID )
82+ consent , err = h .consentService .GetConsentInternalView (ctx , nil , & ownerID , nil , & appID )
7383 }
7484
85+ // Log consent check response
86+ h .logConsentCheckResponse (ctx , appID , consent , err )
87+
7588 if err != nil {
7689 // Check if error is due to context cancellation or timeout
77- if r . Context () .Err () != nil {
78- slog .Warn ("Request context cancelled during service call" , "error" , r . Context () .Err ())
90+ if ctx .Err () != nil {
91+ slog .Warn ("Request context cancelled during service call" , "error" , ctx .Err ())
7992 utils .RespondWithError (w , http .StatusRequestTimeout , models .ErrorCodeInternalError , "Request timeout or cancelled" )
8093 return
8194 }
@@ -91,6 +104,104 @@ func (h *InternalHandler) GetConsent(w http.ResponseWriter, r *http.Request) {
91104 utils .RespondWithJSON (w , http .StatusOK , consent )
92105}
93106
107+ // logConsentCheckRequest logs a CONSENT_CHECK_REQUEST event from consent-engine's perspective
108+ func (h * InternalHandler ) logConsentCheckRequest (ctx context.Context , appID , ownerEmail , ownerID string ) {
109+ traceID := middleware .GetTraceIDFromContext (ctx )
110+ if traceID == "" {
111+ return
112+ }
113+
114+ eventType := "CONSENT_CHECK_REQUEST"
115+ actorType := "SERVICE"
116+ actorID := "consent-engine"
117+ targetType := "SERVICE"
118+ targetID := "orchestration-engine"
119+
120+ requestMetadata := map [string ]interface {}{
121+ "applicationId" : appID ,
122+ }
123+ if ownerEmail != "" {
124+ requestMetadata ["ownerEmail" ] = ownerEmail
125+ }
126+ if ownerID != "" {
127+ requestMetadata ["ownerId" ] = ownerID
128+ }
129+
130+ requestMetadataJSON , err := json .Marshal (requestMetadata )
131+ if err != nil {
132+ slog .Error ("Failed to marshal request metadata for audit" , "error" , err )
133+ return
134+ }
135+
136+ auditRequest := & auditmodels.CreateAuditLogRequest {
137+ TraceID : & traceID ,
138+ Timestamp : time .Now ().UTC ().Format (time .RFC3339 ),
139+ EventType : & eventType ,
140+ Status : auditmodels .StatusSuccess ,
141+ ActorType : actorType ,
142+ ActorID : actorID ,
143+ TargetType : targetType ,
144+ TargetID : & targetID ,
145+ RequestMetadata : json .RawMessage (requestMetadataJSON ),
146+ }
147+
148+ middleware .LogGeneralizedAuditEvent (ctx , auditRequest )
149+ }
150+
151+ // logConsentCheckResponse logs a CONSENT_CHECK_RESPONSE event from consent-engine's perspective
152+ func (h * InternalHandler ) logConsentCheckResponse (ctx context.Context , appID string , consent * models.ConsentResponseInternalView , err error ) {
153+ traceID := middleware .GetTraceIDFromContext (ctx )
154+ if traceID == "" {
155+ return
156+ }
157+
158+ eventType := "CONSENT_CHECK_RESPONSE"
159+ actorType := "SERVICE"
160+ actorID := "consent-engine"
161+ targetType := "SERVICE"
162+ targetID := "orchestration-engine"
163+
164+ status := auditmodels .StatusSuccess
165+ responseMetadata := make (map [string ]interface {})
166+
167+ if err != nil {
168+ status = auditmodels .StatusFailure
169+ responseMetadata ["error" ] = err .Error ()
170+ if errors .Is (err , models .ErrConsentNotFound ) {
171+ responseMetadata ["consentNotFound" ] = true
172+ }
173+ } else if consent != nil {
174+ responseMetadata ["consentId" ] = consent .ConsentID
175+ responseMetadata ["status" ] = consent .Status
176+ if consent .ConsentPortalURL != nil {
177+ responseMetadata ["consentPortalUrl" ] = * consent .ConsentPortalURL
178+ }
179+ if consent .Fields != nil {
180+ responseMetadata ["fieldsCount" ] = len (* consent .Fields )
181+ }
182+ }
183+
184+ responseMetadataJSON , jsonErr := json .Marshal (responseMetadata )
185+ if jsonErr != nil {
186+ slog .Error ("Failed to marshal response metadata for audit" , "error" , jsonErr )
187+ responseMetadataJSON = []byte ("{}" )
188+ }
189+
190+ auditRequest := & auditmodels.CreateAuditLogRequest {
191+ TraceID : & traceID ,
192+ Timestamp : time .Now ().UTC ().Format (time .RFC3339 ),
193+ EventType : & eventType ,
194+ Status : status ,
195+ ActorType : actorType ,
196+ ActorID : actorID ,
197+ TargetType : targetType ,
198+ TargetID : & targetID ,
199+ ResponseMetadata : json .RawMessage (responseMetadataJSON ),
200+ }
201+
202+ middleware .LogGeneralizedAuditEvent (ctx , auditRequest )
203+ }
204+
94205// CreateConsent handles POST /internal/api/v1/consents
95206// Body: models.CreateConsentRequest
96207// Returns: []models.ConsentResponseInternalView
0 commit comments