2626use OAuth2 \IResourceServerContext ;
2727use OAuth2 \Models \IClient ;
2828use Services \OAuth2 \ResourceServerContext ;
29+ use OpenTelemetry \API \Baggage \Baggage ;
2930
3031/**
3132 * Class AuditEventListener
@@ -99,6 +100,17 @@ private function getAuditStrategy($em): ?IAuditStrategy
99100
100101 private function buildAuditContext (): AuditContext
101102 {
103+
104+ if (app ()->runningInConsole ()) {
105+ Log::debug ('AuditEventListener::buildAuditContext - running in console, attempting to get baggage context ' );
106+ $ contextFromBaggage = $ this ->buildContextFromBaggage ();
107+ if ($ contextFromBaggage ) {
108+ Log::debug ('AuditEventListener::buildAuditContext - context successfully loaded from baggage ' );
109+ return $ contextFromBaggage ;
110+ }
111+ Log::debug ('AuditEventListener::buildAuditContext - failed to load context from baggage, will use current request context ' );
112+ }
113+
102114 /***
103115 * here we have 2 cases
104116 * 1. we are connecting to the IDP using an external APi ( under oauth2 ) so the
@@ -157,4 +169,77 @@ private function buildAuditContext(): AuditContext
157169 rawRoute: $ rawRoute
158170 );
159171 }
172+
173+ /**
174+ * Rebuild audit context from OpenTelemetry Baggage (propagated from request to job)
175+ */
176+ private function buildContextFromBaggage (): ?AuditContext
177+ {
178+ try {
179+ $ baggage = Baggage::getCurrent ();
180+
181+ Log::debug ('AuditEventListener::buildContextFromBaggage - baggage obtained ' , [
182+ 'baggage_class ' => get_class ($ baggage ),
183+ ]);
184+
185+ $ userIdEntry = $ baggage ->getEntry ('audit.userId ' );
186+ Log::debug ('AuditEventListener::buildContextFromBaggage - userId entry ' , [
187+ 'entry_exists ' => $ userIdEntry !== null ,
188+ 'entry_class ' => $ userIdEntry ? get_class ($ userIdEntry ) : 'null ' ,
189+ ]);
190+
191+ $ userId = $ userIdEntry ? $ userIdEntry ->getValue () : null ;
192+
193+ Log::debug ('AuditEventListener::buildContextFromBaggage - userId value ' , [
194+ 'userId ' => $ userId ,
195+ 'userId_type ' => gettype ($ userId ),
196+ 'isEmpty ' => empty ($ userId ),
197+ ]);
198+
199+ if (!$ userId ) {
200+ Log::debug ('AuditEventListener: no userId in baggage ' );
201+ return null ;
202+ }
203+
204+ $ userEmail = $ baggage ->getEntry ('audit.userEmail ' )?->getValue();
205+ $ userFirstName = $ baggage ->getEntry ('audit.userFirstName ' )?->getValue();
206+ $ userLastName = $ baggage ->getEntry ('audit.userLastName ' )?->getValue();
207+ $ route = $ baggage ->getEntry ('audit.route ' )?->getValue();
208+ $ httpMethod = $ baggage ->getEntry ('audit.httpMethod ' )?->getValue();
209+ $ clientIp = $ baggage ->getEntry ('audit.clientIp ' )?->getValue();
210+ $ userAgent = $ baggage ->getEntry ('audit.userAgent ' )?->getValue();
211+
212+ Log::debug ('AuditEventListener::buildContextFromBaggage - extracted values ' , [
213+ 'userId ' => $ userId ,
214+ 'userEmail ' => $ userEmail ,
215+ 'userFirstName ' => $ userFirstName ,
216+ 'userLastName ' => $ userLastName ,
217+ 'route ' => $ route ,
218+ 'httpMethod ' => $ httpMethod ,
219+ 'clientIp ' => $ clientIp ,
220+ 'userAgent ' => $ userAgent ,
221+ ]);
222+
223+ $ auditContext = new AuditContext (
224+ userId: (int )$ userId > 0 ? (int )$ userId : null ,
225+ userEmail: $ userEmail ,
226+ userFirstName: $ userFirstName ,
227+ userLastName: $ userLastName ,
228+ route: $ route ,
229+ httpMethod: $ httpMethod ,
230+ clientIp: $ clientIp ,
231+ userAgent: $ userAgent ,
232+ );
233+
234+ Log::debug ('AuditEventListener::buildContextFromBaggage - context created successfully ' );
235+
236+ return $ auditContext ;
237+ } catch (\Exception $ e ) {
238+ Log::debug ('AuditEventListener: could not build context from baggage ' , [
239+ 'error ' => $ e ->getMessage (),
240+ 'trace ' => $ e ->getTraceAsString (),
241+ ]);
242+ return null ;
243+ }
244+ }
160245}
0 commit comments