This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch x-forwarded-for
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 2a56444c68fe5a6608490c0f8c9748801f3dff65
Author: Benoit TELLIER <btell...@linagora.com>
AuthorDate: Thu Dec 5 08:36:16 2024 +0100

    [ENHANCEMENT] ip and x-forwarded-for im JMAP logging context
---
 .../java/org/apache/james/util/ReactorUtils.java   |  2 +-
 .../jmap/method/DelegateSetCreatePerformer.scala   | 19 +++---
 .../jmap/method/DelegateSetDeletePerformer.scala   | 18 +++---
 .../method/DelegatedAccountDeletePerformer.scala   | 17 +++---
 .../jmap/method/EmailSetDeletePerformer.scala      | 11 ++--
 .../jmap/method/EmailSubmissionSetMethod.scala     | 70 ++++++++++++----------
 .../jmap/method/MailboxSetUpdatePerformer.scala    | 23 +++----
 .../apache/james/jmap/routes/JMAPApiRoutes.scala   |  4 ++
 8 files changed, 95 insertions(+), 69 deletions(-)

diff --git 
a/server/container/util/src/main/java/org/apache/james/util/ReactorUtils.java 
b/server/container/util/src/main/java/org/apache/james/util/ReactorUtils.java
index 8c26be6382..beb2c0dc5e 100644
--- 
a/server/container/util/src/main/java/org/apache/james/util/ReactorUtils.java
+++ 
b/server/container/util/src/main/java/org/apache/james/util/ReactorUtils.java
@@ -194,7 +194,7 @@ public class ReactorUtils {
         return signal -> logWithContext(logStatement, signal.getContextView());
     }
 
-    private static void logWithContext(Runnable logStatement, ContextView 
contextView) {
+    public static void logWithContext(Runnable logStatement, ContextView 
contextView) {
         try (Closeable mdc = retrieveMDCBuilder(contextView).build()) {
             logStatement.run();
         } catch (IOException e) {
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegateSetCreatePerformer.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegateSetCreatePerformer.scala
index dd72143d0c..da3ff86305 100644
--- 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegateSetCreatePerformer.scala
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegateSetCreatePerformer.scala
@@ -30,7 +30,7 @@ import 
org.apache.james.jmap.method.DelegateSetCreatePerformer.{CreationFailure,
 import org.apache.james.mailbox.MailboxSession
 import org.apache.james.mailbox.exception.UserDoesNotExistException
 import org.apache.james.user.api.{DelegationStore, UsersRepository}
-import org.apache.james.util.AuditTrail
+import org.apache.james.util.{AuditTrail, ReactorUtils}
 import org.slf4j.LoggerFactory
 import play.api.libs.json.JsObject
 import reactor.core.scala.publisher.{SFlux, SMono}
@@ -98,13 +98,16 @@ class DelegateSetCreatePerformer @Inject()(delegationStore: 
DelegationStore,
     SMono.fromPublisher(usersRepository.containsReactive(request.username))
       .filter(bool => bool)
       .flatMap(_ => 
SMono.fromPublisher(delegationStore.addAuthorizedUser(mailboxSession.getUser, 
request.username))
-        .doOnSuccess(_ => AuditTrail.entry
-          .username(() => mailboxSession.getUser.asString())
-          .protocol("JMAP")
-          .action("DelegateSet/create")
-          .parameters(() => ImmutableMap.of("delegator", 
mailboxSession.getUser.asString(),
-            "delegatee", request.username.asString()))
-          .log("Delegation added."))
+        .subscriberContext(context => {
+          ReactorUtils.logWithContext(() => AuditTrail.entry
+            .username(() => mailboxSession.getUser.asString())
+            .protocol("JMAP")
+            .action("DelegateSet/create")
+            .parameters(() => ImmutableMap.of("delegator", 
mailboxSession.getUser.asString(),
+              "delegatee", request.username.asString()))
+            .log("Delegation added."), context)
+          context
+        })
         .`then`(SMono.just[CreationResult](CreationSuccess(delegateCreationId, 
evaluateCreationResponse(request, mailboxSession))))
         .onErrorResume(e => 
SMono.just[CreationResult](CreationFailure(delegateCreationId, e))))
       
.switchIfEmpty(SMono.just[CreationResult](CreationFailure(delegateCreationId, 
new UserDoesNotExistException(request.username))))
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegateSetDeletePerformer.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegateSetDeletePerformer.scala
index 2e7f88e4dc..cf8487366c 100644
--- 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegateSetDeletePerformer.scala
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegateSetDeletePerformer.scala
@@ -80,12 +80,16 @@ class DelegateSetDeletePerformer @Inject()(delegationStore: 
DelegationStore) {
           .filter(authorizedUser => DelegationId.from(baseUser, 
authorizedUser).equals(id))
           .next()
           .flatMap(authorizedUser => 
SMono(delegationStore.removeAuthorizedUser(baseUser, authorizedUser))
-            .doOnSuccess(_ => AuditTrail.entry
-              .username(() => baseUser.asString())
-              .protocol("JMAP")
-              .action("DelegateSet/destroy")
-              .parameters(() => ImmutableMap.of("delegator", 
baseUser.asString(),
-                "delegatee", authorizedUser.asString()))
-              .log("Delegation removed.")))
+
+            .subscriberContext(context => {
+              ReactorUtils.logWithContext(() => AuditTrail.entry
+                .username(() => baseUser.asString())
+                .protocol("JMAP")
+                .action("DelegateSet/destroy")
+                .parameters(() => ImmutableMap.of("delegator", 
baseUser.asString(),
+                  "delegatee", authorizedUser.asString()))
+                .log("Delegation removed."), context)
+              context
+            }))
           
.`then`(SMono.just[DelegateDeletionResult](DelegateDeletionSuccess(id))))
 }
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegatedAccountDeletePerformer.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegatedAccountDeletePerformer.scala
index 677b46c492..149fceaabf 100644
--- 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegatedAccountDeletePerformer.scala
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegatedAccountDeletePerformer.scala
@@ -80,12 +80,15 @@ class DelegatedAccountDeletePerformer 
@Inject()(delegationStore: DelegationStore
           .filter(delegatedUser => DelegationId.from(delegatedUser, 
baseUser).equals(id))
           .next()
           .flatMap(delegatedUser => 
SMono(delegationStore.removeDelegatedUser(baseUser, delegatedUser))
-            .doOnSuccess(_ => AuditTrail.entry
-              .username(() => baseUser.asString())
-              .protocol("JMAP")
-              .action("DelegatedAccountSet/destroy")
-              .parameters(() => ImmutableMap.of("delegator", 
delegatedUser.asString(),
-                "delegatee", baseUser.asString()))
-              .log("Delegation removed.")))
+            .subscriberContext(context => {
+              ReactorUtils.logWithContext(() => AuditTrail.entry
+                .username(() => baseUser.asString())
+                .protocol("JMAP")
+                .action("DelegatedAccountSet/destroy")
+                .parameters(() => ImmutableMap.of("delegator", 
delegatedUser.asString(),
+                  "delegatee", baseUser.asString()))
+                .log("Delegation removed."), context)
+              context
+            }))
           
.`then`(SMono.just[DelegatedAccountDeletionResult](DelegatedAccountDeletionSuccess(id))))
 }
\ No newline at end of file
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetDeletePerformer.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetDeletePerformer.scala
index b75764f300..72e8d56d18 100644
--- 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetDeletePerformer.scala
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetDeletePerformer.scala
@@ -97,7 +97,10 @@ class EmailSetDeletePerformer @Inject()(messageIdManager: 
MessageIdManager,
       }
 
       SMono(messageIdManager.delete(messageIds.toSet.asJava, mailboxSession))
-        .doOnSuccess(auditTrail(_, mailboxSession))
+        .subscriberContext(context => {
+          auditTrail(messageIds, mailboxSession)
+          context
+        })
         .map(DestroyResult.from)
         .onErrorResume(e => SMono.just(messageIds.map(id => 
DestroyFailure(EmailSet.asUnparsed(id), e))))
         .map(_ ++ parsingErrors)
@@ -107,13 +110,13 @@ class EmailSetDeletePerformer @Inject()(messageIdManager: 
MessageIdManager,
     }
   }
 
-  private def auditTrail(deleteResult: DeleteResult, mailboxSession: 
MailboxSession): Unit =
-    if (!deleteResult.getDestroyed.isEmpty) {
+  private def auditTrail(deleteResult: Seq[MessageId], mailboxSession: 
MailboxSession): Unit =
+    if (deleteResult.nonEmpty) {
       AuditTrail.entry
         .username(() => mailboxSession.getUser.asString())
         .protocol("JMAP")
         .action("Email/set destroy")
-        .parameters(() => ImmutableMap.of("messageIds", 
StringUtils.join(deleteResult.getDestroyed),
+        .parameters(() => ImmutableMap.of("messageIds", 
StringUtils.join(deleteResult),
           "loggedInUser", mailboxSession.getLoggedInUser.toScala
             .map(_.asString())
             .getOrElse("")))
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSubmissionSetMethod.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSubmissionSetMethod.scala
index 95fa095a44..d5c5939e58 100644
--- 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSubmissionSetMethod.scala
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSubmissionSetMethod.scala
@@ -51,7 +51,7 @@ import org.apache.james.queue.api.MailQueueFactory.SPOOL
 import org.apache.james.queue.api.{MailQueue, MailQueueFactory}
 import org.apache.james.rrt.api.CanSendFrom
 import org.apache.james.server.core.{MailImpl, MimeMessageSource, 
MimeMessageWrapper}
-import org.apache.james.util.AuditTrail
+import org.apache.james.util.{AuditTrail, ReactorUtils}
 import org.apache.mailet.{Attribute, AttributeName, AttributeValue, Mail}
 import org.slf4j.{Logger, LoggerFactory}
 import play.api.libs.json._
@@ -298,38 +298,44 @@ class EmailSubmissionSetMethod @Inject()(serializer: 
EmailSubmissionSetSerialize
   private def enqueue(mail: Mail, delay: Duration, mailboxSession: 
MailboxSession): SMono[Unit] =
     (delay match {
       case d if d.isNegative || d.isZero => SMono(queue.enqueueReactive(mail))
-        .doOnSuccess(_ => AuditTrail.entry
-          .username(() => mailboxSession.getUser.asString())
-          .protocol("JMAP")
-          .action("EmailSubmission")
-          .parameters(() => ImmutableMap.of("mailId", mail.getName,
-            "mimeMessageId", Option(mail.getMessage)
-              .flatMap(message => Option(message.getMessageID))
-              .getOrElse(""),
-            "sender", mail.getMaybeSender.asString,
-            "recipients", StringUtils.join(mail.getRecipients),
-            "size", mail.getMessageSize.toString,
-            "loggedInUser", mailboxSession.getLoggedInUser.toScala
-              .map(_.asString())
-              .getOrElse("")))
-          .log("JMAP mail spooled."))
+        .subscriberContext(context => {
+          ReactorUtils.logWithContext(() => AuditTrail.entry
+            .username(() => mailboxSession.getUser.asString())
+            .protocol("JMAP")
+            .action("EmailSubmission")
+            .parameters(() => ImmutableMap.of("mailId", mail.getName,
+              "mimeMessageId", Option(mail.getMessage)
+                .flatMap(message => Option(message.getMessageID))
+                .getOrElse(""),
+              "sender", mail.getMaybeSender.asString,
+              "recipients", StringUtils.join(mail.getRecipients),
+              "size", mail.getMessageSize.toString,
+              "loggedInUser", mailboxSession.getLoggedInUser.toScala
+                .map(_.asString())
+                .getOrElse("")))
+            .log("JMAP mail spooled."), context)
+          context
+        })
       case _ => SMono(queue.enqueueReactive(mail, delay))
-        .doOnSuccess(_ => AuditTrail.entry
-          .username(() => mailboxSession.getUser.asString())
-          .protocol("JMAP")
-          .action("EmailSubmission")
-          .parameters(() => ImmutableMap.of("mailId", mail.getName,
-            "mimeMessageId", Option(mail.getMessage)
-              .flatMap(message => Option(message.getMessageID))
-              .getOrElse(""),
-            "size", mail.getMessageSize.toString,
-            "sender", mail.getMaybeSender.asString,
-            "recipients", StringUtils.join(mail.getRecipients),
-            "holdFor", delay.toString,
-            "loggedInUser", mailboxSession.getLoggedInUser.toScala
-              .map(_.asString())
-              .getOrElse("")))
-          .log("JMAP mail spooled."))
+        .subscriberContext(context => {
+          ReactorUtils.logWithContext(() => AuditTrail.entry
+            .username(() => mailboxSession.getUser.asString())
+            .protocol("JMAP")
+            .action("EmailSubmission")
+            .parameters(() => ImmutableMap.of("mailId", mail.getName,
+              "mimeMessageId", Option(mail.getMessage)
+                .flatMap(message => Option(message.getMessageID))
+                .getOrElse(""),
+              "size", mail.getMessageSize.toString,
+              "sender", mail.getMaybeSender.asString,
+              "recipients", StringUtils.join(mail.getRecipients),
+              "holdFor", delay.toString,
+              "loggedInUser", mailboxSession.getLoggedInUser.toScala
+                .map(_.asString())
+                .getOrElse("")))
+            .log("JMAP mail spooled."), context)
+          context
+        })
     }).`then`(SMono.fromCallable(() => 
LifecycleUtil.dispose(mail)).subscribeOn(Schedulers.boundedElastic()))
 
   private def retrieveDelay(mailParameters: Option[Map[ParameterName, 
Option[ParameterValue]]]): Try[Duration] =
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetUpdatePerformer.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetUpdatePerformer.scala
index 7824aff7d2..3a4c8b0697 100644
--- 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetUpdatePerformer.scala
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetUpdatePerformer.scala
@@ -251,16 +251,19 @@ class MailboxSetUpdatePerformer @Inject()(serializer: 
MailboxSerializer,
 
     val partialUpdatesOperation: SMono[Unit] = 
SFlux.fromIterable(validatedPatch.rightsPartialUpdates)
       .flatMap(partialUpdate => SMono.fromCallable(() => 
mailboxManager.applyRightsCommand(mailboxId, partialUpdate.asACLCommand(), 
mailboxSession))
-        .doOnSuccess(_ => AuditTrail.entry
-          .username(() => mailboxSession.getUser.asString())
-          .protocol("JMAP")
-          .action("Mailbox/set update")
-          .parameters(() => ImmutableMap.of("loggedInUser", 
mailboxSession.getLoggedInUser.toScala.map(_.asString()).getOrElse(""),
-            "delegator", mailboxSession.getUser.asString(),
-            "delegatee", partialUpdate.entryKey.getName,
-            "mailboxId", mailboxId.serialize(),
-            "rights", partialUpdate.rights.asJava.serialize()))
-          .log("JMAP mailbox shared.")),
+        .subscriberContext(context => {
+          ReactorUtils.logWithContext(() => AuditTrail.entry
+            .username(() => mailboxSession.getUser.asString())
+            .protocol("JMAP")
+            .action("Mailbox/set update")
+            .parameters(() => ImmutableMap.of("loggedInUser", 
mailboxSession.getLoggedInUser.toScala.map(_.asString()).getOrElse(""),
+              "delegator", mailboxSession.getUser.asString(),
+              "delegatee", partialUpdate.entryKey.getName,
+              "mailboxId", mailboxId.serialize(),
+              "rights", partialUpdate.rights.asJava.serialize()))
+            .log("JMAP mailbox shared."), context)
+          context
+        }),
         maxConcurrency = 5)
       .`then`()
 
diff --git 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/routes/JMAPApiRoutes.scala
 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/routes/JMAPApiRoutes.scala
index 5873ab3fb0..377c1e0cdc 100644
--- 
a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/routes/JMAPApiRoutes.scala
+++ 
b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/routes/JMAPApiRoutes.scala
@@ -37,6 +37,7 @@ import org.apache.james.jmap.http.{Authenticator, 
UserProvisioning}
 import org.apache.james.jmap.json.ResponseSerializer
 import org.apache.james.jmap.{Endpoint, JMAPRoute, JMAPRoutes}
 import org.apache.james.mailbox.MailboxSession
+import org.apache.james.util.{MDCBuilder, ReactorUtils}
 import org.slf4j.{Logger, LoggerFactory}
 import play.api.libs.json.{JsError, JsSuccess, Json}
 import reactor.core.publisher.{Mono, SynchronousSink}
@@ -75,6 +76,9 @@ class JMAPApiRoutes @Inject() (@Named(InjectionKeys.RFC_8621) 
val authenticator:
       .onErrorResume(throwable => handleError(throwable, httpServerResponse))
       .asJava()
       .`then`()
+      .contextWrite(ReactorUtils.context("MDCBuilder.IP", MDCBuilder.create()
+        .addToContext(MDCBuilder.IP, 
Option(httpServerRequest.hostAddress()).map(_.toString()).getOrElse(""))
+        .addToContext("x-forwarded-for", 
Option(httpServerRequest.requestHeaders().get("X-Forwarded-For")).getOrElse(""))))
 
   private def requestAsJsonStream(httpServerRequest: HttpServerRequest): 
SMono[RequestObject] =
     SMono.fromPublisher(httpServerRequest


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org
For additional commands, e-mail: notifications-h...@james.apache.org

Reply via email to