This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit e52fb2c4a28db6f47e68ae314629f0353f8cdb36 Author: Tung Van TRAN <vtt...@linagora.com> AuthorDate: Fri Jun 16 08:14:09 2023 +0700 [CLEAN CODE] JMAP - Make standard error message when invalid json deserialize --- .../rfc8621/contract/DelegateSetContract.scala | 4 +- .../contract/EmailQueryMethodContract.scala | 16 +++---- .../rfc8621/contract/IdentitySetContract.scala | 4 +- .../contract/MailboxQueryMethodContract.scala | 10 ++-- .../contract/MailboxSetMethodContract.scala | 12 ++--- .../PushSubscriptionSetMethodContract.scala | 8 ++-- .../contract/QuotaChangesMethodContract.scala | 4 +- .../contract/QuotaQueryMethodContract.scala | 8 ++-- .../apache/james/jmap/delegation/DelegateSet.scala | 15 ++---- .../org/apache/james/jmap/mail/IdentitySet.scala | 13 +----- .../scala/org/apache/james/jmap/mail/MDNSend.scala | 17 ++----- .../james/jmap/method/DelegateGetMethod.scala | 10 ++-- .../james/jmap/method/DelegateSetMethod.scala | 8 +--- .../jmap/method/DelegatedAccountGetMethod.scala | 10 ++-- .../jmap/method/DelegatedAccountSetMethod.scala | 11 ++--- .../james/jmap/method/EmailChangesMethod.scala | 7 ++- .../apache/james/jmap/method/EmailGetMethod.scala | 11 ++--- .../james/jmap/method/EmailImportMethod.scala | 8 ++-- .../james/jmap/method/EmailParseMethod.scala | 54 ++++++++++------------ .../james/jmap/method/EmailQueryMethod.scala | 11 ++--- .../apache/james/jmap/method/EmailSetMethod.scala | 6 +-- .../jmap/method/EmailSubmissionSetMethod.scala | 34 +++++--------- .../james/jmap/method/IdentityChangesMethod.scala | 8 ++-- .../james/jmap/method/IdentityGetMethod.scala | 5 +- .../james/jmap/method/IdentitySetMethod.scala | 7 ++- .../apache/james/jmap/method/MDNParseMethod.scala | 9 ++-- .../apache/james/jmap/method/MDNSendMethod.scala | 8 ++-- .../james/jmap/method/MailboxChangesMethod.scala | 8 ++-- .../james/jmap/method/MailboxGetMethod.scala | 8 ++-- .../james/jmap/method/MailboxQueryMethod.scala | 6 +-- .../jmap/method/MailboxSetCreatePerformer.scala | 8 +--- .../james/jmap/method/MailboxSetMethod.scala | 6 +-- .../jmap/method/PushSubscriptionGetMethod.scala | 7 ++- .../PushSubscriptionSetCreatePerformer.scala | 8 +--- .../jmap/method/PushSubscriptionSetMethod.scala | 6 +-- .../james/jmap/method/QuotaChangesMethod.scala | 6 +-- .../apache/james/jmap/method/QuotaGetMethod.scala | 5 +- .../james/jmap/method/QuotaQueryMethod.scala | 8 ++-- .../james/jmap/method/ThreadChangesMethod.scala | 6 +-- .../apache/james/jmap/method/ThreadGetMethod.scala | 7 ++- .../jmap/method/VacationResponseGetMethod.scala | 6 +-- .../jmap/method/VacationResponseSetMethod.scala | 6 +-- .../org/apache/james/jmap/method/package.scala | 48 +++++++++++++++++++ 43 files changed, 217 insertions(+), 250 deletions(-) diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/DelegateSetContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/DelegateSetContract.scala index ac675eaa67..5eb3092b3a 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/DelegateSetContract.scala +++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/DelegateSetContract.scala @@ -226,7 +226,7 @@ trait DelegateSetContract { | "notCreated": { | "4f29": { | "type": "invalidArguments", - | "description": "Missing '/username' property in Delegate object" + | "description": "Missing '/username' property" | } | } | }, @@ -280,7 +280,7 @@ trait DelegateSetContract { | "notCreated": { | "4f29": { | "type": "invalidArguments", - | "description": "'/username' property in Delegate object is not valid: username needs to be represented by a JsString" + | "description": "'/username' property is not valid: username needs to be represented by a JsString" | } | } | }, diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailQueryMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailQueryMethodContract.scala index 15613ffd86..c06761c68e 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailQueryMethodContract.scala +++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailQueryMethodContract.scala @@ -1951,7 +1951,7 @@ trait EmailQueryMethodContract { | "error", | { | "type": "invalidArguments", - | "description": "{\\"errors\\":[{\\"path\\":\\"obj.filter.header\\",\\"messages\\":[\\"header filter needs to be an array of one or two strings\\"]}]}" + | "description": "'/filter/header' property is not valid: header filter needs to be an array of one or two strings" | }, | "c1" | ] @@ -3454,7 +3454,7 @@ trait EmailQueryMethodContract { .isEqualTo(""" { "type": "invalidArguments", - "description": "{\"errors\":[{\"path\":\"obj.sort[0].property\",\"messages\":[\"error.path.missing\"]}]}" + "description": "Missing '/sort(0)/property' property" } """) } @@ -3551,7 +3551,7 @@ trait EmailQueryMethodContract { .isEqualTo(""" { "type": "invalidArguments", - "description": "{\"errors\":[{\"path\":\"obj.sort[0].property\",\"messages\":[\"'unsupported' is not a supported sort property\"]}]}" + "description": "'/sort(0)/property' property is not valid: 'unsupported' is not a supported sort property" } """) } @@ -3994,7 +3994,7 @@ trait EmailQueryMethodContract { | "error", | { | "type": "invalidArguments", - | "description": "{\\"errors\\":[{\\"path\\":\\"obj.filter.maxSize\\",\\"messages\\":[\\"Predicate (-1 < 0) did not fail.\\"]}]}" + | "description": "'/filter/maxSize' property is not valid: Predicate (-1 < 0) did not fail." | }, | "c1" | ] @@ -4043,7 +4043,7 @@ trait EmailQueryMethodContract { | "error", | { | "type": "invalidArguments", - | "description": "{\\"errors\\":[{\\"path\\":\\"obj.filter.minSize\\",\\"messages\\":[\\"Predicate (-1 < 0) did not fail.\\"]}]}" + | "description": "'/filter/minSize' property is not valid: Predicate (-1 < 0) did not fail." | }, | "c1" | ] @@ -6936,7 +6936,7 @@ trait EmailQueryMethodContract { | "error", | { | "type": "invalidArguments", - | "description": "{\\"errors\\":[{\\"path\\":\\"obj.filter\\",\\"messages\\":[\\"Expecting filterOperator to contain only operator and conditions\\"]}]}" + | "description": "'/filter' property is not valid: Expecting filterOperator to contain only operator and conditions" | }, | "c1" | ] @@ -6982,7 +6982,7 @@ trait EmailQueryMethodContract { | "error", | { | "type": "invalidArguments", - | "description": "{\\"errors\\":[{\\"path\\":\\"obj.filter\\",\\"messages\\":[\\"Expecting filterOperator to contain only operator and conditions\\"]}]}" + | "description": "'/filter' property is not valid: Expecting filterOperator to contain only operator and conditions" | }, | "c1" | ] @@ -7404,7 +7404,7 @@ trait EmailQueryMethodContract { .isEqualTo( """{ | "type": "invalidArguments", - | "description": "{\"errors\":[{\"path\":\"obj.filter\",\"messages\":[\"These '[unsupported_option, role]' was unsupported filter options\"]}]}" + | "description": "'/filter' property is not valid: These '[unsupported_option, role]' was unsupported filter options" |} |""".stripMargin) } diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/IdentitySetContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/IdentitySetContract.scala index 55f4c8db35..f83d45a1c9 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/IdentitySetContract.scala +++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/IdentitySetContract.scala @@ -663,7 +663,7 @@ trait IdentitySetContract { | "notCreated": { | "4f29": { | "type": "invalidArguments", - | "description": "Missing '/email' property in Identity object" + | "description": "Missing '/email' property" | } | } |}""".stripMargin) @@ -721,7 +721,7 @@ trait IdentitySetContract { | "notCreated": { | "4f29": { | "type": "invalidArguments", - | "description": "'/email' property in Identity object is not valid: mail address needs to be represented with a JsString" + | "description": "'/email' property is not valid: mail address needs to be represented with a JsString" | } | } |}""".stripMargin) diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxQueryMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxQueryMethodContract.scala index 25ad0b2bd8..2b77c2db88 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxQueryMethodContract.scala +++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxQueryMethodContract.scala @@ -340,7 +340,7 @@ trait MailboxQueryMethodContract { | "error", | { | "type": "invalidArguments", - | "description": "{\\"errors\\":[{\\"path\\":\\"obj.filter.role\\",\\"messages\\":[\\"Invalid is not a valid role\\"]}]}" + | "description": "'/filter/role' property is not valid: Invalid is not a valid role" | }, | "c1" | ] @@ -385,7 +385,7 @@ trait MailboxQueryMethodContract { | "error", | { | "type": "invalidArguments", - | "description": "{\\"errors\\":[{\\"path\\":\\"obj.filter.role\\",\\"messages\\":[\\"Expecting a JsString to be representing a role\\"]}]}" + | "description": "'/filter/role' property is not valid: Expecting a JsString to be representing a role" | }, | "c1" | ] @@ -431,7 +431,7 @@ trait MailboxQueryMethodContract { | "error", | { | "type": "invalidArguments", - | "description": "{\\"errors\\":[{\\"path\\":\\"obj.filter.role\\",\\"messages\\":[\\"error.path.missing\\"]}]}" + | "description": "Missing '/filter/role' property" | }, | "c1" | ] @@ -479,7 +479,7 @@ trait MailboxQueryMethodContract { | "error", | { | "type": "invalidArguments", - | "description": "{\\"errors\\":[{\\"path\\":\\"obj.filter\\",\\"messages\\":[\\"These '[unsupported_option]' was unsupported filter options\\"]}]}" + | "description": "'/filter' property is not valid: These '[unsupported_option]' was unsupported filter options" | }, | "c1" | ] @@ -523,7 +523,7 @@ trait MailboxQueryMethodContract { | "error", | { | "type": "invalidArguments", - | "description": "{\\"errors\\":[{\\"path\\":\\"obj.filter\\",\\"messages\\":[\\"error.path.missing\\"]}]}" + | "description": "Missing '/filter' property" | }, | "c1" | ] diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxSetMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxSetMethodContract.scala index ba755bedfc..261eaab4ed 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxSetMethodContract.scala +++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxSetMethodContract.scala @@ -786,7 +786,7 @@ trait MailboxSetMethodContract { | "notCreated": { | "C42": { | "type": "invalidArguments", - | "description": "Missing '/name' property in mailbox object" + | "description": "Missing '/name' property" | } | } | }, @@ -843,7 +843,7 @@ trait MailboxSetMethodContract { | "notCreated": { | "C42": { | "type": "invalidArguments", - | "description": "'/name' property in mailbox object is not valid: Predicate isEmpty() did not fail." + | "description": "'/name' property is not valid: Predicate isEmpty() did not fail." | } | } | }, @@ -1077,7 +1077,7 @@ trait MailboxSetMethodContract { | "notCreated": { | "C42": { | "type": "invalidArguments", - | "description": "'/parentId' property in mailbox object is not valid: mailboxId does not match Id constraints: Predicate failed: '' contains some invalid characters. Should be [#a-zA-Z0-9-_] and no longer than 255 chars." + | "description": "'/parentId' property is not valid: mailboxId does not match Id constraints: Predicate failed: '' contains some invalid characters. Should be [#a-zA-Z0-9-_] and no longer than 255 chars." | } | } | }, @@ -1471,7 +1471,7 @@ trait MailboxSetMethodContract { | "notCreated": { | "C42": { | "type": "invalidArguments", - | "description": "'/rights/an...@domain.tld(0)' property in mailbox object is not valid: Rights must have size 1" + | "description": "'/rights/an...@domain.tld(0)' property is not valid: Rights must have size 1" | } | } | }, "c1"] @@ -1529,7 +1529,7 @@ trait MailboxSetMethodContract { | "notCreated": { | "C42": { | "type": "invalidArguments", - | "description": "'/rights/an...@domain.tld(0)' property in mailbox object is not valid: Unknown right 'z'" + | "description": "'/rights/an...@domain.tld(0)' property is not valid: Unknown right 'z'" | } | } | }, "c1"] @@ -1808,7 +1808,7 @@ trait MailboxSetMethodContract { | "notCreated": { | "C43": { | "type": "invalidArguments", - | "description": "Missing '/name' property in mailbox object" + | "description": "Missing '/name' property" | } | } | }, diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/PushSubscriptionSetMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/PushSubscriptionSetMethodContract.scala index ac5a01da6f..773186c0da 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/PushSubscriptionSetMethodContract.scala +++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/PushSubscriptionSetMethodContract.scala @@ -477,7 +477,7 @@ trait PushSubscriptionSetMethodContract { | "notCreated": { | "4f29": { | "type": "invalidArguments", - | "description": "Missing '/types' property in PushSubscription object" + | "description": "Missing '/types' property" | } | } | }, @@ -937,7 +937,7 @@ trait PushSubscriptionSetMethodContract { | "notCreated": { | "4f29": { | "type": "invalidArguments", - | "description": "'/url' property in PushSubscription object is not valid" + | "description": "'/url' property is not valid" | } | } | }, @@ -1164,7 +1164,7 @@ trait PushSubscriptionSetMethodContract { | "notCreated": { | "4f29": { | "type": "invalidArguments", - | "description": "'/types(0)' property in PushSubscription object is not valid: Unknown typeName invalid" + | "description": "'/types(0)' property is not valid: Unknown typeName invalid" | } | } | }, @@ -1462,7 +1462,7 @@ trait PushSubscriptionSetMethodContract { | "notCreated": { | "4f29": { | "type": "invalidArguments", - | "description": "'/types(0)' property in PushSubscription object is not valid: Unknown typeName invalid" + | "description": "'/types(0)' property is not valid: Unknown typeName invalid" | } | } | }, diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/QuotaChangesMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/QuotaChangesMethodContract.scala index 86029b2262..dacb2fa693 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/QuotaChangesMethodContract.scala +++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/QuotaChangesMethodContract.scala @@ -341,7 +341,7 @@ trait QuotaChangesMethodContract { | "error", | { | "type": "invalidArguments", - | "description": "{\\"errors\\":[{\\"path\\":\\"obj.sinceState\\",\\"messages\\":[\\"error.path.missing\\"]}]}" + | "description": "Missing '/sinceState' property" | }, | "c1" | ] @@ -382,7 +382,7 @@ trait QuotaChangesMethodContract { | "error", | { | "type": "invalidArguments", - | "description": "{\\"errors\\":[{\\"path\\":\\"obj.sinceState\\",\\"messages\\":[\\"error.expected.uuid\\"]}]}" + | "description": "'/sinceState' property is not valid: error.expected.uuid" | }, | "c1" | ] diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/QuotaQueryMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/QuotaQueryMethodContract.scala index 19b66125a0..8279966465 100644 --- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/QuotaQueryMethodContract.scala +++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/QuotaQueryMethodContract.scala @@ -254,7 +254,7 @@ trait QuotaQueryMethodContract { | "error", | { | "type": "invalidArguments", - | "description": "{\\"errors\\":[{\\"path\\":\\"obj.filter.resourceTypes[0]\\",\\"messages\\":[\\"Unexpected value invalid, only 'count' and 'octets' are managed\\"]}]}" + | "description": "'/filter/resourceTypes(0)' property is not valid: Unexpected value invalid, only 'count' and 'octets' are managed" | }, | "c1" | ] @@ -357,7 +357,7 @@ trait QuotaQueryMethodContract { | "error", | { | "type": "invalidArguments", - | "description": "{\\"errors\\":[{\\"path\\":\\"obj.filter.dataTypes[0]\\",\\"messages\\":[\\"Unexpected value invalid, only 'Mail' are managed\\"]}]}" + | "description": "'/filter/dataTypes(0)' property is not valid: Unexpected value invalid, only 'Mail' are managed" | }, | "c1" | ] @@ -460,7 +460,7 @@ trait QuotaQueryMethodContract { | "error", | { | "type": "invalidArguments", - | "description": "{\\"errors\\":[{\\"path\\":\\"obj.filter.scope[0]\\",\\"messages\\":[\\"Unexpected value invalidScope, only \'account\' is managed\\"]}]}" + | "description": "'/filter/scope(0)' property is not valid: Unexpected value invalidScope, only 'account' is managed" | }, | "c1" | ] @@ -724,7 +724,7 @@ trait QuotaQueryMethodContract { | "error", | { | "type": "invalidArguments", - | "description": "{\\"errors\\":[{\\"path\\":\\"obj.filter\\",\\"messages\\":[\\"These '[filterName1]' was unsupported filter options\\"]}]}" + | "description": "'/filter' property is not valid: These '[filterName1]' was unsupported filter options" | }, | "c1" | ] diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/delegation/DelegateSet.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/delegation/DelegateSet.scala index 9e8cacf0eb..899ba8cbea 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/delegation/DelegateSet.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/delegation/DelegateSet.scala @@ -21,9 +21,8 @@ package org.apache.james.jmap.delegation import org.apache.james.core.Username import org.apache.james.jmap.core.Id.Id -import org.apache.james.jmap.core.SetError.SetErrorDescription import org.apache.james.jmap.core.{AccountId, Id, SetError, UuidState} -import org.apache.james.jmap.method.WithAccountId +import org.apache.james.jmap.method.{WithAccountId, standardError} import play.api.libs.json.{JsObject, JsPath, JsonValidationError} case class DelegateCreationId(id: Id) { @@ -52,14 +51,6 @@ case class DelegateSetParseException(setError: SetError) extends IllegalArgument case class ForbiddenAccountManagementException() extends RuntimeException() object DelegateSetParseException { - def from(errors: collection.Seq[(JsPath, collection.Seq[JsonValidationError])]): DelegateSetParseException = { - val setError: SetError = errors.head match { - case (path, Seq()) => SetError.invalidArguments(SetErrorDescription(s"'$path' property in Delegate object is not valid")) - case (path, Seq(JsonValidationError(Seq("error.path.missing")))) => - SetError.invalidArguments(SetErrorDescription(s"Missing '$path' property in Delegate object")) - case (path, Seq(JsonValidationError(Seq(message)))) => SetError.invalidArguments(SetErrorDescription(s"'$path' property in Delegate object is not valid: $message")) - case (path, _) => SetError.invalidArguments(SetErrorDescription(s"Unknown error on property '$path'")) - } - DelegateSetParseException(setError) - } + def from(errors: collection.Seq[(JsPath, collection.Seq[JsonValidationError])]): DelegateSetParseException = + DelegateSetParseException(standardError(errors)) } \ No newline at end of file diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/IdentitySet.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/IdentitySet.scala index 356e82942e..6b44f773e7 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/IdentitySet.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/IdentitySet.scala @@ -24,7 +24,7 @@ import org.apache.james.jmap.core.Id.Id import org.apache.james.jmap.core.SetError.SetErrorDescription import org.apache.james.jmap.core.{AccountId, Properties, SetError, UuidState} import org.apache.james.jmap.method.IdentitySetUpdatePerformer.IdentitySetUpdateResponse -import org.apache.james.jmap.method.WithAccountId +import org.apache.james.jmap.method.{WithAccountId, standardError} import play.api.libs.json.{JsObject, JsPath, JsonValidationError} object IdentitySet { @@ -76,14 +76,5 @@ case class IdentitySetResponse(accountId: AccountId, case class IdentitySetParseException(setError: SetError) extends IllegalArgumentException object IdentitySetParseException { - def from(errors: collection.Seq[(JsPath, collection.Seq[JsonValidationError])]): IdentitySetParseException = { - val setError: SetError = errors.head match { - case (path, Seq()) => SetError.invalidArguments(SetErrorDescription(s"'$path' property in Identity object is not valid")) - case (path, Seq(JsonValidationError(Seq("error.path.missing")))) => - SetError.invalidArguments(SetErrorDescription(s"Missing '$path' property in Identity object")) - case (path, Seq(JsonValidationError(Seq(message)))) => SetError.invalidArguments(SetErrorDescription(s"'$path' property in Identity object is not valid: $message")) - case (path, _) => SetError.invalidArguments(SetErrorDescription(s"Unknown error on property '$path'")) - } - IdentitySetParseException(setError) - } + def from(errors: collection.Seq[(JsPath, collection.Seq[JsonValidationError])]): IdentitySetParseException = IdentitySetParseException(standardError(errors)) } \ No newline at end of file diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MDNSend.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MDNSend.scala index f0390ab4bd..c69effc27f 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MDNSend.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MDNSend.scala @@ -19,16 +19,16 @@ package org.apache.james.jmap.mail -import java.util.UUID - import cats.implicits.toTraverseOps import org.apache.james.jmap.core.Id.Id import org.apache.james.jmap.core.SetError.SetErrorDescription import org.apache.james.jmap.core.{AccountId, Id, Properties, SetError} -import org.apache.james.jmap.method.WithAccountId +import org.apache.james.jmap.method.{WithAccountId, standardError} import org.apache.james.mailbox.model.MessageId import play.api.libs.json.{JsObject, JsPath, JsonValidationError} +import java.util.UUID + object MDNSend { val MDN_ALREADY_SENT_FLAG: String = "$mdnsent" } @@ -42,15 +42,8 @@ case class MDNSendCreationId(id: Id) case class MDNId(value: Id) object MDNSendRequestInvalidException { - def parse(errors: collection.Seq[(JsPath, collection.Seq[JsonValidationError])]): MDNSendRequestInvalidException = { - val setError: SetError = errors.head match { - case (path, Seq()) => SetError.invalidArguments(SetErrorDescription(s"'$path' property in MDNSend object is not valid")) - case (path, Seq(JsonValidationError(Seq("error.path.missing")))) => SetError.invalidArguments(SetErrorDescription(s"Missing '$path' property in MDNSend object")) - case (path, Seq(JsonValidationError(Seq(message)))) => SetError.invalidArguments(SetErrorDescription(s"'$path' property in MDNSend object is not valid: $message")) - case (path, _) => SetError.invalidArguments(SetErrorDescription(s"Unknown error on property '$path'")) - } - MDNSendRequestInvalidException(setError) - } + def parse(errors: collection.Seq[(JsPath, collection.Seq[JsonValidationError])]): MDNSendRequestInvalidException = + MDNSendRequestInvalidException(standardError(errors)) } case class MDNSendRequestInvalidException(error: SetError) extends Exception diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegateGetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegateGetMethod.scala index b56fe00959..16cc71fab8 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegateGetMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegateGetMethod.scala @@ -20,14 +20,12 @@ package org.apache.james.jmap.method import eu.timepit.refined.auto._ -import javax.inject.Inject import org.apache.james.core.Username import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JAMES_DELEGATION, JMAP_CORE} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{ErrorCode, Invocation, Properties, SessionTranslator} -import org.apache.james.jmap.delegation.{Delegate, DelegateGet, DelegateGetRequest, DelegateGetResult, ForbiddenAccountManagementException} -import org.apache.james.jmap.delegation.{Delegate, DelegateGet, DelegateGetRequest, DelegateGetResult, DelegationId} -import org.apache.james.jmap.json.{DelegationSerializer, ResponseSerializer} +import org.apache.james.jmap.delegation.{Delegate, DelegateGet, DelegateGetRequest, DelegateGetResult, DelegationId, ForbiddenAccountManagementException} +import org.apache.james.jmap.json.DelegationSerializer import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.mailbox.MailboxSession import org.apache.james.metrics.api.MetricFactory @@ -36,6 +34,7 @@ import org.reactivestreams.Publisher import play.api.libs.json.JsObject import reactor.core.scala.publisher.{SFlux, SMono} +import javax.inject.Inject import scala.jdk.OptionConverters._ @@ -48,8 +47,7 @@ class DelegateGetMethod @Inject()(val metricFactory: MetricFactory, override val requiredCapabilities: Set[CapabilityIdentifier] = Set(JMAP_CORE, JAMES_DELEGATION) override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[Exception, DelegateGetRequest] = - DelegationSerializer.deserializeDelegateGetRequest(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + DelegationSerializer.deserializeDelegateGetRequest(invocation.arguments.value).asEitherRequest override def doProcess(capabilities: Set[CapabilityIdentifier], invocation: InvocationWithContext, mailboxSession: MailboxSession, request: DelegateGetRequest): Publisher[InvocationWithContext] = { val requestedProperties: Properties = request.properties.getOrElse(DelegateGet.allProperties) (requestedProperties -- DelegateGet.allProperties match { diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegateSetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegateSetMethod.scala index a49692cdc2..2b842908a0 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegateSetMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegateSetMethod.scala @@ -24,12 +24,11 @@ import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JA import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{ClientId, Id, Invocation, ServerId, SessionTranslator, UuidState} import org.apache.james.jmap.delegation.{DelegateSetRequest, DelegateSetResponse, ForbiddenAccountManagementException} -import org.apache.james.jmap.json.{DelegationSerializer, ResponseSerializer} +import org.apache.james.jmap.json.DelegationSerializer import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.mailbox.MailboxSession import org.apache.james.mailbox.MailboxSession.isPrimaryAccount import org.apache.james.metrics.api.MetricFactory -import play.api.libs.json.{JsError, JsSuccess} import reactor.core.scala.publisher.SMono import javax.inject.Inject @@ -43,10 +42,7 @@ class DelegateSetMethod @Inject()(createPerformer: DelegateSetCreatePerformer, override val requiredCapabilities: Set[CapabilityIdentifier] = Set(JMAP_CORE, JAMES_DELEGATION) override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[Exception, DelegateSetRequest] = - DelegationSerializer.deserializeDelegateSetRequest(invocation.arguments.value) match { - case JsSuccess(delegateSetRequest, _) => Right(delegateSetRequest) - case errors: JsError => Left(new IllegalArgumentException(ResponseSerializer.serialize(errors).toString)) - } + DelegationSerializer.deserializeDelegateSetRequest(invocation.arguments.value).asEitherRequest override def doProcess(capabilities: Set[CapabilityIdentifier], invocation: InvocationWithContext, mailboxSession: MailboxSession, request: DelegateSetRequest): SMono[InvocationWithContext] = if (isPrimaryAccount(mailboxSession)) { diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegatedAccountGetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegatedAccountGetMethod.scala index 96330d7eae..2e43eb916b 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegatedAccountGetMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegatedAccountGetMethod.scala @@ -20,14 +20,12 @@ package org.apache.james.jmap.method import eu.timepit.refined.auto._ -import javax.inject.Inject import org.apache.james.core.Username import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JAMES_DELEGATION, JMAP_CORE} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{ErrorCode, Invocation, Properties, SessionTranslator} -import org.apache.james.jmap.delegation.{Delegate, DelegatedAccountGet, DelegatedAccountGetRequest, DelegatedAccountGetResult, ForbiddenAccountManagementException} -import org.apache.james.jmap.delegation.{Delegate, DelegatedAccountGet, DelegatedAccountGetRequest, DelegatedAccountGetResult, DelegationId} -import org.apache.james.jmap.json.{DelegationSerializer, ResponseSerializer} +import org.apache.james.jmap.delegation.{Delegate, DelegatedAccountGet, DelegatedAccountGetRequest, DelegatedAccountGetResult, DelegationId, ForbiddenAccountManagementException} +import org.apache.james.jmap.json.DelegationSerializer import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.mailbox.MailboxSession import org.apache.james.metrics.api.MetricFactory @@ -36,6 +34,7 @@ import org.reactivestreams.Publisher import play.api.libs.json.JsObject import reactor.core.scala.publisher.{SFlux, SMono} +import javax.inject.Inject import scala.jdk.OptionConverters._ class DelegatedAccountGetMethod @Inject()(val metricFactory: MetricFactory, @@ -47,8 +46,7 @@ class DelegatedAccountGetMethod @Inject()(val metricFactory: MetricFactory, override val requiredCapabilities: Set[CapabilityIdentifier] = Set(JMAP_CORE, JAMES_DELEGATION) override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[Exception, DelegatedAccountGetRequest] = - DelegationSerializer.deserializeDelegatedAccountGetRequest(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + DelegationSerializer.deserializeDelegatedAccountGetRequest(invocation.arguments.value).asEitherRequest override def doProcess(capabilities: Set[CapabilityIdentifier], invocation: InvocationWithContext, mailboxSession: MailboxSession, request: DelegatedAccountGetRequest): Publisher[InvocationWithContext] = { val requestedProperties: Properties = request.properties.getOrElse(DelegatedAccountGet.allProperties) diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegatedAccountSetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegatedAccountSetMethod.scala index 3f9318fc24..c8fbfe44bd 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegatedAccountSetMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/DelegatedAccountSetMethod.scala @@ -20,19 +20,19 @@ package org.apache.james.jmap.method import eu.timepit.refined.auto._ -import javax.inject.Inject import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JAMES_DELEGATION, JMAP_CORE} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{Invocation, SessionTranslator, UuidState} import org.apache.james.jmap.delegation.{DelegatedAccountSetRequest, DelegatedAccountSetResponse, ForbiddenAccountManagementException} -import org.apache.james.jmap.json.{DelegationSerializer, ResponseSerializer} +import org.apache.james.jmap.json.DelegationSerializer import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.mailbox.MailboxSession import org.apache.james.mailbox.MailboxSession.isPrimaryAccount import org.apache.james.metrics.api.MetricFactory -import play.api.libs.json.{JsError, JsSuccess} import reactor.core.scala.publisher.SMono +import javax.inject.Inject + class DelegatedAccountSetMethod @Inject()(deletePerformer: DelegatedAccountDeletePerformer, val metricFactory: MetricFactory, val sessionSupplier: SessionSupplier, @@ -41,10 +41,7 @@ class DelegatedAccountSetMethod @Inject()(deletePerformer: DelegatedAccountDelet override val requiredCapabilities: Set[CapabilityIdentifier] = Set(JMAP_CORE, JAMES_DELEGATION) override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[Exception, DelegatedAccountSetRequest] = - DelegationSerializer.deserializeDelegatedAccountSetRequest(invocation.arguments.value) match { - case JsSuccess(delegatedAccountSetRequest, _) => Right(delegatedAccountSetRequest) - case errors: JsError => Left(new IllegalArgumentException(ResponseSerializer.serialize(errors).toString)) - } + DelegationSerializer.deserializeDelegatedAccountSetRequest(invocation.arguments.value).asEitherRequest override def doProcess(capabilities: Set[CapabilityIdentifier], invocation: InvocationWithContext, mailboxSession: MailboxSession, request: DelegatedAccountSetRequest): SMono[InvocationWithContext] = if (isPrimaryAccount(mailboxSession)) { diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailChangesMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailChangesMethod.scala index e5a0e91060..4b9913bbeb 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailChangesMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailChangesMethod.scala @@ -25,14 +25,14 @@ import org.apache.james.jmap.api.model.{AccountId => JavaAccountId} import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JAMES_SHARES, JMAP_MAIL} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{ErrorCode, Invocation, SessionTranslator, UuidState} -import org.apache.james.jmap.json.{EmailGetSerializer, ResponseSerializer} +import org.apache.james.jmap.json.EmailGetSerializer import org.apache.james.jmap.mail.{EmailChangesRequest, EmailChangesResponse, HasMoreChanges} import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.mailbox.MailboxSession import org.apache.james.metrics.api.MetricFactory import reactor.core.scala.publisher.SMono -import javax.inject.Inject +import javax.inject.Inject import scala.jdk.CollectionConverters._ import scala.jdk.OptionConverters._ @@ -74,6 +74,5 @@ class EmailChangesMethod @Inject()(val metricFactory: MetricFactory, } override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[IllegalArgumentException, EmailChangesRequest] = - EmailGetSerializer.deserializeEmailChangesRequest(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + EmailGetSerializer.deserializeEmailChangesRequest(invocation.arguments.value).asEitherRequest } diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailGetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailGetMethod.scala index ec853b2996..e5d420c09c 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailGetMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailGetMethod.scala @@ -18,17 +18,14 @@ ****************************************************************/ package org.apache.james.jmap.method -import java.time.ZoneId - import eu.timepit.refined.auto._ -import javax.inject.Inject import org.apache.james.jmap.api.change.{EmailChangeRepository, State => JavaState} import org.apache.james.jmap.api.model.{AccountId => JavaAccountId} import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JAMES_SHARES, JMAP_CORE, JMAP_MAIL} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.UuidState.INSTANCE import org.apache.james.jmap.core.{AccountId, ErrorCode, Invocation, SessionTranslator, UuidState} -import org.apache.james.jmap.json.{EmailGetSerializer, ResponseSerializer} +import org.apache.james.jmap.json.EmailGetSerializer import org.apache.james.jmap.mail.{Email, EmailGetRequest, EmailGetResponse, EmailIds, EmailNotFound, EmailView, EmailViewReaderFactory, UnparsedEmailId} import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.mailbox.MailboxSession @@ -38,6 +35,9 @@ import org.slf4j.{Logger, LoggerFactory} import play.api.libs.json.JsObject import reactor.core.scala.publisher.{SFlux, SMono} +import java.time.ZoneId +import javax.inject.Inject + object EmailGetResults { private val logger: Logger = LoggerFactory.getLogger(classOf[EmailGetResults]) @@ -92,8 +92,7 @@ class EmailGetMethod @Inject() (readerFactory: EmailViewReaderFactory, } override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[IllegalArgumentException, EmailGetRequest] = - EmailGetSerializer.deserializeEmailGetRequest(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + EmailGetSerializer.deserializeEmailGetRequest(invocation.arguments.value).asEitherRequest private def computeResponseInvocation(capabilities: Set[CapabilityIdentifier], request: EmailGetRequest, invocation: Invocation, mailboxSession: MailboxSession): SMono[Invocation] = Email.validateProperties(request.properties) diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailImportMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailImportMethod.scala index 799cf92838..d2da447b39 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailImportMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailImportMethod.scala @@ -27,7 +27,7 @@ import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JA import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.SetError.SetErrorDescription import org.apache.james.jmap.core.{ClientId, Id, Invocation, ServerId, SessionTranslator, SetError, UuidState} -import org.apache.james.jmap.json.{EmailSetSerializer, ResponseSerializer} +import org.apache.james.jmap.json.EmailSetSerializer import org.apache.james.jmap.mail.{BlobId, EmailCreationId, EmailCreationResponse, EmailImport, EmailImportRequest, EmailImportResponse, ThreadId, ValidatedEmailImport} import org.apache.james.jmap.method.EmailImportMethod.{ImportFailure, ImportResult, ImportResults, ImportSuccess, ImportWithBlob} import org.apache.james.jmap.routes.{Blob, BlobNotFoundException, BlobResolvers, ProcessingContext, SessionSupplier} @@ -42,10 +42,9 @@ import org.apache.james.mime4j.stream.MimeConfig import org.apache.james.util.ReactorUtils import org.reactivestreams.Publisher import reactor.core.scala.publisher.{SFlux, SMono} -import java.util.Date +import java.util.Date import javax.inject.Inject - import scala.util.{Try, Using} object EmailImportMethod { @@ -91,8 +90,7 @@ class EmailImportMethod @Inject() (val metricFactory: MetricFactory, override val requiredCapabilities: Set[CapabilityIdentifier] = Set(JMAP_CORE, JMAP_MAIL) override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[Exception, EmailImportRequest] = - serializer.deserializeEmailImportRequest(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + serializer.deserializeEmailImportRequest(invocation.arguments.value).asEitherRequest override def doProcess(capabilities: Set[CapabilityIdentifier], invocation: InvocationWithContext, mailboxSession: MailboxSession, request: EmailImportRequest): Publisher[InvocationWithContext] = for { diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailParseMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailParseMethod.scala index 6d6d65e2ce..2e89d3cc79 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailParseMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailParseMethod.scala @@ -19,24 +19,23 @@ package org.apache.james.jmap.method -import java.io.InputStream - import eu.timepit.refined.auto._ -import javax.inject.Inject import org.apache.james.jmap.api.model.Preview import org.apache.james.jmap.api.model.Size.Size import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JMAP_CORE, JMAP_MAIL} import org.apache.james.jmap.core.Invocation._ import org.apache.james.jmap.core.{Invocation, SessionTranslator} -import org.apache.james.jmap.json.{EmailGetSerializer, ResponseSerializer} +import org.apache.james.jmap.json.EmailGetSerializer import org.apache.james.jmap.mail.{BlobId, BlobUnParsableException, Email, EmailBody, EmailBodyMetadata, EmailBodyPart, EmailFullViewFactory, EmailHeaders, EmailParseMetadata, EmailParseRequest, EmailParseResponse, EmailParseResults, EmailParseView, HasAttachment} import org.apache.james.jmap.routes.{BlobNotFoundException, BlobResolvers, SessionSupplier} import org.apache.james.mailbox.MailboxSession import org.apache.james.metrics.api.MetricFactory import org.apache.james.util.html.HtmlTextExtractor -import play.api.libs.json.{JsError, JsObject, JsSuccess, Json} +import play.api.libs.json.JsObject import reactor.core.scala.publisher.{SFlux, SMono} +import java.io.InputStream +import javax.inject.Inject import scala.util.Try class EmailParseMethod @Inject()(val blobResolvers: BlobResolvers, @@ -57,10 +56,7 @@ class EmailParseMethod @Inject()(val blobResolvers: BlobResolvers, .map(InvocationWithContext(_, invocation.processingContext)) override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[Exception, EmailParseRequest] = - EmailGetSerializer.deserializeEmailParseRequest(invocation.arguments.value) match { - case JsSuccess(parseRequest, _) => Right(parseRequest) - case errors: JsError => Left(new IllegalArgumentException(Json.stringify(ResponseSerializer.serialize(errors)))) - } + EmailGetSerializer.deserializeEmailParseRequest(invocation.arguments.value).asEitherRequest def computeResponseInvocation(request: EmailParseRequest, invocation: Invocation, @@ -104,25 +100,25 @@ class EmailParseMethod @Inject()(val blobResolvers: BlobResolvers, } private def parse(request: EmailParseRequest, blobId: BlobId, blobContent: => InputStream, size: Size): SMono[EmailParseResults] = { - val result: SMono[EmailParseView] = for { - mime4JMessage <- SMono.fromTry(Email.parseStreamAsMime4JMessage(blobContent)) - bodyStructure <- SMono.fromTry(EmailBodyPart.of(request.bodyProperties, zoneIdProvider.get(), blobId, mime4JMessage)) - bodyValues <- SMono.fromTry(EmailFullViewFactory.extractBodyValuesForParse(htmlTextExtractor)(bodyStructure, request)) - preview <- SMono.fromTry(Try(previewFactory.fromMime4JMessage(mime4JMessage))) - } yield { - EmailParseView( - metadata = EmailParseMetadata(blobId = blobId, size = size), - header = EmailHeaders.from(zoneIdProvider.get())(mime4JMessage), - specificHeaders = EmailHeaders.extractSpecificHeaders(request.properties)(zoneIdProvider.get(), mime4JMessage.getHeader), - bodyMetadata = EmailBodyMetadata(hasAttachment = HasAttachment(bodyStructure.attachments.nonEmpty), - preview = preview), - body = EmailBody( - bodyStructure = bodyStructure, - textBody = bodyStructure.textBody, - htmlBody = bodyStructure.htmlBody, - attachments = bodyStructure.attachments, - bodyValues = bodyValues)) - } - result.map(EmailParseResults.parsed(blobId, _)) + val result: SMono[EmailParseView] = for { + mime4JMessage <- SMono.fromTry(Email.parseStreamAsMime4JMessage(blobContent)) + bodyStructure <- SMono.fromTry(EmailBodyPart.of(request.bodyProperties, zoneIdProvider.get(), blobId, mime4JMessage)) + bodyValues <- SMono.fromTry(EmailFullViewFactory.extractBodyValuesForParse(htmlTextExtractor)(bodyStructure, request)) + preview <- SMono.fromTry(Try(previewFactory.fromMime4JMessage(mime4JMessage))) + } yield { + EmailParseView( + metadata = EmailParseMetadata(blobId = blobId, size = size), + header = EmailHeaders.from(zoneIdProvider.get())(mime4JMessage), + specificHeaders = EmailHeaders.extractSpecificHeaders(request.properties)(zoneIdProvider.get(), mime4JMessage.getHeader), + bodyMetadata = EmailBodyMetadata(hasAttachment = HasAttachment(bodyStructure.attachments.nonEmpty), + preview = preview), + body = EmailBody( + bodyStructure = bodyStructure, + textBody = bodyStructure.textBody, + htmlBody = bodyStructure.htmlBody, + attachments = bodyStructure.attachments, + bodyValues = bodyValues)) + } + result.map(EmailParseResults.parsed(blobId, _)) } } \ No newline at end of file diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala index f1902846ba..d31424ba19 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailQueryMethod.scala @@ -18,12 +18,8 @@ ****************************************************************/ package org.apache.james.jmap.method -import java.time.ZonedDateTime - import cats.implicits._ import eu.timepit.refined.auto._ -import javax.inject.Inject -import javax.mail.Flags.Flag.DELETED import org.apache.james.jmap.JMAPConfiguration import org.apache.james.jmap.api.projections.EmailQueryView import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JMAP_CORE, JMAP_MAIL} @@ -31,7 +27,7 @@ import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.Limit.Limit import org.apache.james.jmap.core.Position.Position import org.apache.james.jmap.core.{CanCalculateChanges, Invocation, Limit, Position, QueryState, SessionTranslator} -import org.apache.james.jmap.json.{EmailQuerySerializer, ResponseSerializer} +import org.apache.james.jmap.json.EmailQuerySerializer import org.apache.james.jmap.mail.{Comparator, EmailQueryRequest, EmailQueryResponse, FilterCondition, UnsupportedRequestParameterException} import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.jmap.utils.search.MailboxFilter @@ -44,6 +40,9 @@ import org.apache.james.metrics.api.MetricFactory import org.apache.james.util.streams.{Limit => JavaLimit} import reactor.core.scala.publisher.{SFlux, SMono} +import java.time.ZonedDateTime +import javax.inject.Inject +import javax.mail.Flags.Flag.DELETED import scala.jdk.CollectionConverters._ class EmailQueryMethod @Inject() (serializer: EmailQuerySerializer, @@ -81,7 +80,7 @@ class EmailQueryMethod @Inject() (serializer: EmailQuerySerializer, override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[Exception, EmailQueryRequest] = serializer.deserializeEmailQueryRequest(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + .asEitherRequest .flatMap(validateRequestParameters) private def validateRequestParameters(request: EmailQueryRequest): Either[Exception, EmailQueryRequest] = diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetMethod.scala index 376fda8800..4bdef7d354 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetMethod.scala @@ -24,13 +24,14 @@ import org.apache.james.jmap.api.model.{AccountId => JavaAccountId} import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JAMES_SHARES, JMAP_CORE, JMAP_MAIL} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{ClientId, Id, Invocation, ServerId, SessionTranslator, UuidState} -import org.apache.james.jmap.json.{EmailSetSerializer, ResponseSerializer} +import org.apache.james.jmap.json.EmailSetSerializer import org.apache.james.jmap.mail.{EmailSetRequest, EmailSetResponse} import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.mailbox.MailboxSession import org.apache.james.mailbox.model.MessageId import org.apache.james.metrics.api.MetricFactory import reactor.core.scala.publisher.SMono + import javax.inject.Inject case class MessageNotFoundException(messageId: MessageId) extends Exception @@ -77,8 +78,7 @@ class EmailSetMethod @Inject()(serializer: EmailSetSerializer, } override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[IllegalArgumentException, EmailSetRequest] = - serializer.deserialize(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + serializer.deserialize(invocation.arguments.value).asEitherRequest private def retrieveState(capabilities: Set[CapabilityIdentifier], mailboxSession: MailboxSession): SMono[UuidState] = if (capabilities.contains(JAMES_SHARES)) { 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 cf4647e476..7bbbf6597a 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 @@ -19,23 +19,16 @@ package org.apache.james.jmap.method -import java.io.InputStream - import cats.implicits._ import eu.timepit.refined.auto._ import eu.timepit.refined.refineV -import javax.annotation.PreDestroy -import javax.inject.Inject -import javax.mail.Address -import javax.mail.Message.RecipientType -import javax.mail.internet.{InternetAddress, MimeMessage} import org.apache.james.core.{MailAddress, Username} import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, EMAIL_SUBMISSION, JMAP_CORE} import org.apache.james.jmap.core.Id.{Id, IdConstraint} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.SetError.{SetErrorDescription, SetErrorType} import org.apache.james.jmap.core.{ClientId, Invocation, Properties, ServerId, SessionTranslator, SetError, UuidState} -import org.apache.james.jmap.json.{EmailSubmissionSetSerializer, ResponseSerializer} +import org.apache.james.jmap.json.EmailSubmissionSetSerializer import org.apache.james.jmap.mail.{EmailSubmissionAddress, EmailSubmissionCreationId, EmailSubmissionCreationRequest, EmailSubmissionCreationResponse, EmailSubmissionId, EmailSubmissionSetRequest, EmailSubmissionSetResponse, Envelope} import org.apache.james.jmap.method.EmailSubmissionSetMethod.{CreationFailure, CreationResult, CreationResults, CreationSuccess, LOGGER, MAIL_METADATA_USERNAME_ATTRIBUTE} import org.apache.james.jmap.routes.{ProcessingContext, SessionSupplier} @@ -47,7 +40,6 @@ 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.ReactorUtils import org.apache.mailet.{Attribute, AttributeName, AttributeValue} import org.slf4j.{Logger, LoggerFactory} import play.api.libs.json._ @@ -55,6 +47,12 @@ import reactor.core.scala.publisher.{SFlux, SMono} import reactor.core.scheduler.Schedulers import reactor.util.concurrent.Queues +import java.io.InputStream +import javax.annotation.PreDestroy +import javax.inject.Inject +import javax.mail.Address +import javax.mail.Message.RecipientType +import javax.mail.internet.{InternetAddress, MimeMessage} import scala.jdk.CollectionConverters._ import scala.util.{Failure, Success, Try} @@ -190,13 +188,10 @@ class EmailSubmissionSetMethod @Inject()(serializer: EmailSubmissionSetSerialize SFlux.concat(SMono.just(explicitInvocation), emailSetCall) }) - override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[IllegalArgumentException, EmailSubmissionSetRequest] = { - val maybeRequestRequest = serializer.deserializeEmailSubmissionSetRequest(invocation.arguments.value) match { - case JsSuccess(emailSubmissionSetRequest, _) => Right(emailSubmissionSetRequest) - case errors: JsError => Left(new IllegalArgumentException(ResponseSerializer.serialize(errors).toString)) - } - maybeRequestRequest.flatMap(_.validate) - } + override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[IllegalArgumentException, EmailSubmissionSetRequest] = + serializer.deserializeEmailSubmissionSetRequest(invocation.arguments.value) + .asEitherRequest + .flatMap(_.validate) private def create(request: EmailSubmissionSetRequest, session: MailboxSession, @@ -241,12 +236,7 @@ class EmailSubmissionSetMethod @Inject()(serializer: EmailSubmissionSetSerialize }) private def emailSubmissionSetError(errors: collection.Seq[(JsPath, collection.Seq[JsonValidationError])]): SetError = - errors.head match { - case (path, Seq()) => SetError.invalidArguments(SetErrorDescription(s"'$path' property in EmailSubmission object is not valid")) - case (path, Seq(JsonValidationError(Seq("error.path.missing")))) => SetError.invalidArguments(SetErrorDescription(s"Missing '$path' property in EmailSubmission object")) - case (path, Seq(JsonValidationError(Seq(message)))) => SetError.invalidArguments(SetErrorDescription(s"'$path' property in EmailSubmission object is not valid: $message")) - case (path, _) => SetError.invalidArguments(SetErrorDescription(s"Unknown error on property '$path'")) - } + standardError(errors) private def sendEmail(mailboxSession: MailboxSession, request: EmailSubmissionCreationRequest): SMono[(EmailSubmissionCreationResponse, MessageId)] = diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/IdentityChangesMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/IdentityChangesMethod.scala index b4207de0b6..3a7a44ed27 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/IdentityChangesMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/IdentityChangesMethod.scala @@ -20,11 +20,10 @@ package org.apache.james.jmap.method import eu.timepit.refined.auto._ -import javax.inject.Inject import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, EMAIL_SUBMISSION} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{ErrorCode, Invocation, SessionTranslator, UuidState} -import org.apache.james.jmap.json.{IdentitySerializer, ResponseSerializer} +import org.apache.james.jmap.json.IdentitySerializer import org.apache.james.jmap.mail.{HasMoreChanges, IdentityChangesRequest, IdentityChangesResponse} import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.mailbox.MailboxSession @@ -32,6 +31,8 @@ import org.apache.james.metrics.api.MetricFactory import org.reactivestreams.Publisher import reactor.core.scala.publisher.SMono +import javax.inject.Inject + class IdentityChangesMethod @Inject()(val metricFactory: MetricFactory, val sessionSupplier: SessionSupplier, val sessionTranslator: SessionTranslator) extends MethodRequiringAccountId[IdentityChangesRequest] { @@ -61,6 +62,5 @@ class IdentityChangesMethod @Inject()(val metricFactory: MetricFactory, } override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[Exception, IdentityChangesRequest] = - IdentitySerializer.deserializeChanges(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + IdentitySerializer.deserializeChanges(invocation.arguments.value).asEitherRequest } diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/IdentityGetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/IdentityGetMethod.scala index acebe60236..4a4ef37ee7 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/IdentityGetMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/IdentityGetMethod.scala @@ -25,7 +25,7 @@ import org.apache.james.jmap.api.model.{Identity, IdentityId} import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, EMAIL_SUBMISSION, JMAP_CORE} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core._ -import org.apache.james.jmap.json.{IdentitySerializer, ResponseSerializer} +import org.apache.james.jmap.json.IdentitySerializer import org.apache.james.jmap.mail.{IdentityGet, IdentityGetRequest, IdentityGetResponse} import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.mailbox.MailboxSession @@ -60,8 +60,7 @@ class IdentityGetMethod @Inject() (identityRepository: IdentityRepository, } override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[IllegalArgumentException, IdentityGetRequest] = - IdentitySerializer.deserialize(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + IdentitySerializer.deserialize(invocation.arguments.value).asEitherRequest private def getIdentities(request: IdentityGetRequest, mailboxSession: MailboxSession): SMono[IdentityGetResponse] = diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/IdentitySetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/IdentitySetMethod.scala index 30e3ce530b..b885c3ab59 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/IdentitySetMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/IdentitySetMethod.scala @@ -23,12 +23,13 @@ import eu.timepit.refined.auto._ import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, EMAIL_SUBMISSION, JMAP_CORE} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{ClientId, Id, Invocation, ServerId, SessionTranslator, UuidState} -import org.apache.james.jmap.json.{IdentitySerializer, ResponseSerializer} +import org.apache.james.jmap.json.IdentitySerializer import org.apache.james.jmap.mail.{IdentitySetRequest, IdentitySetResponse} import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.mailbox.MailboxSession import org.apache.james.metrics.api.MetricFactory import reactor.core.scala.publisher.SMono + import javax.inject.Inject class IdentitySetMethod @Inject()(createPerformer: IdentitySetCreatePerformer, @@ -41,9 +42,7 @@ class IdentitySetMethod @Inject()(createPerformer: IdentitySetCreatePerformer, override val requiredCapabilities: Set[CapabilityIdentifier] = Set(JMAP_CORE, EMAIL_SUBMISSION) override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[Exception, IdentitySetRequest] = - IdentitySerializer.deserializeIdentitySetRequest(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) - + IdentitySerializer.deserializeIdentitySetRequest(invocation.arguments.value).asEitherRequest override def doProcess(capabilities: Set[CapabilityIdentifier], invocation: InvocationWithContext, mailboxSession: MailboxSession, request: IdentitySetRequest): SMono[InvocationWithContext] = for { creationResults <- createPerformer.create(request, mailboxSession) diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MDNParseMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MDNParseMethod.scala index 74f80dd13d..72bf5b5947 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MDNParseMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MDNParseMethod.scala @@ -21,9 +21,9 @@ package org.apache.james.jmap.method import eu.timepit.refined.auto._ import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JMAP_CORE, JMAP_MAIL, JMAP_MDN} -import org.apache.james.jmap.core.{Invocation, SessionTranslator} import org.apache.james.jmap.core.Invocation._ -import org.apache.james.jmap.json.{MDNSerializer, ResponseSerializer} +import org.apache.james.jmap.core.{Invocation, SessionTranslator} +import org.apache.james.jmap.json.MDNSerializer import org.apache.james.jmap.mail.{BlobId, BlobUnParsableException, MDNParseRequest, MDNParseResponse, MDNParseResults, MDNParsed} import org.apache.james.jmap.routes.{BlobNotFoundException, BlobResolvers, SessionSupplier} import org.apache.james.mailbox.model.{MessageId, MultimailboxesSearchQuery, SearchQuery} @@ -35,10 +35,9 @@ import org.apache.james.mime4j.dom.Message import org.apache.james.mime4j.message.DefaultMessageBuilder import play.api.libs.json.JsObject import reactor.core.scala.publisher.{SFlux, SMono} -import java.io.InputStream +import java.io.InputStream import javax.inject.Inject - import scala.jdk.OptionConverters._ import scala.util.{Try, Using} @@ -60,7 +59,7 @@ class MDNParseMethod @Inject()(serializer: MDNSerializer, override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[Exception, MDNParseRequest] = serializer.deserializeMDNParseRequest(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + .asEitherRequest .flatMap(_.validate) def computeResponseInvocation(request: MDNParseRequest, diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MDNSendMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MDNSendMethod.scala index 8f26bdd35e..143547ca6f 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MDNSendMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MDNSendMethod.scala @@ -22,9 +22,9 @@ package org.apache.james.jmap.method import eu.timepit.refined.auto._ import org.apache.james.jmap.api.model.Identity import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JMAP_CORE, JMAP_MAIL, JMAP_MDN} -import org.apache.james.jmap.core.{Invocation, SessionTranslator} import org.apache.james.jmap.core.Invocation._ -import org.apache.james.jmap.json.{MDNSerializer, ResponseSerializer} +import org.apache.james.jmap.core.{Invocation, SessionTranslator} +import org.apache.james.jmap.json.MDNSerializer import org.apache.james.jmap.mail.MDN._ import org.apache.james.jmap.mail.MDNSend.MDN_ALREADY_SENT_FLAG import org.apache.james.jmap.mail._ @@ -47,10 +47,10 @@ import org.apache.james.server.core.MailImpl import org.apache.james.util.ReactorUtils import play.api.libs.json.{JsError, JsObject, JsSuccess} import reactor.core.scala.publisher.{SFlux, SMono} + import javax.annotation.PreDestroy import javax.inject.Inject import javax.mail.internet.MimeMessage - import scala.jdk.CollectionConverters._ import scala.jdk.OptionConverters._ import scala.util.Try @@ -106,7 +106,7 @@ class MDNSendMethod @Inject()(serializer: MDNSerializer, override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[Exception, MDNSendRequest] = serializer.deserializeMDNSendRequest(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + .asEitherRequest .flatMap(_.validate) private def create(identity: Identity, diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxChangesMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxChangesMethod.scala index 0802cd2b5b..b65b4fc1f3 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxChangesMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxChangesMethod.scala @@ -25,15 +25,15 @@ import org.apache.james.jmap.api.model.{AccountId => JavaAccountId} import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JMAP_MAIL} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{CapabilityIdentifier, ErrorCode, Invocation, Properties, SessionTranslator, UuidState} -import org.apache.james.jmap.json.{MailboxSerializer, ResponseSerializer} +import org.apache.james.jmap.json.MailboxSerializer import org.apache.james.jmap.mail.{HasMoreChanges, MailboxChangesRequest, MailboxChangesResponse} import org.apache.james.jmap.method.MailboxChangesMethod.updatedProperties import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.mailbox.MailboxSession import org.apache.james.metrics.api.MetricFactory import reactor.core.scala.publisher.SMono -import javax.inject.Inject +import javax.inject.Inject import scala.jdk.CollectionConverters._ import scala.jdk.OptionConverters._ @@ -83,9 +83,7 @@ class MailboxChangesMethod @Inject()(mailboxSerializer: MailboxSerializer, }) override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[IllegalArgumentException, MailboxChangesRequest] = - mailboxSerializer.deserializeMailboxChangesRequest(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) - + mailboxSerializer.deserializeMailboxChangesRequest(invocation.arguments.value).asEitherRequest private def updateProperties(mailboxChanges: MailboxChanges): Option[Properties] = if (mailboxChanges.isCountChangesOnly) { Some(updatedProperties) diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxGetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxGetMethod.scala index 111fddefc3..bacbf3a1f6 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxGetMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxGetMethod.scala @@ -26,7 +26,7 @@ import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JA import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{AccountId, CapabilityIdentifier, ErrorCode, Invocation, Properties, SessionTranslator, UuidState} import org.apache.james.jmap.http.MailboxesProvisioner -import org.apache.james.jmap.json.{MailboxSerializer, ResponseSerializer} +import org.apache.james.jmap.json.MailboxSerializer import org.apache.james.jmap.mail.{Ids, Mailbox, MailboxFactory, MailboxGet, MailboxGetRequest, MailboxGetResponse, NotFound, PersonalNamespace, Subscriptions, UnparsedMailboxId} import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.jmap.utils.quotas.{QuotaLoaderWithPreloadedDefault, QuotaLoaderWithPreloadedDefaultFactory} @@ -37,8 +37,8 @@ import org.apache.james.mailbox.{MailboxManager, MailboxSession, SubscriptionMan import org.apache.james.metrics.api.MetricFactory import play.api.libs.json.JsObject import reactor.core.scala.publisher.{SFlux, SMono} -import javax.inject.Inject +import javax.inject.Inject import scala.util.Try object MailboxGetResults { @@ -102,9 +102,7 @@ class MailboxGetMethod @Inject() (serializer: MailboxSerializer, } override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[IllegalArgumentException, MailboxGetRequest] = - serializer.deserializeMailboxGetRequest(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) - + serializer.deserializeMailboxGetRequest(invocation.arguments.value).asEitherRequest private def getMailboxes(capabilities: Set[CapabilityIdentifier], mailboxGetRequest: MailboxGetRequest, mailboxSession: MailboxSession): SFlux[MailboxGetResults] = diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxQueryMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxQueryMethod.scala index b4ec36f72d..27a8cdd8ae 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxQueryMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxQueryMethod.scala @@ -22,12 +22,13 @@ import eu.timepit.refined.auto._ import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JMAP_CORE, JMAP_MAIL} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{CanCalculateChanges, ErrorCode, Invocation, Limit, Position, QueryState, SessionTranslator} -import org.apache.james.jmap.json.{MailboxQuerySerializer, ResponseSerializer} +import org.apache.james.jmap.json.MailboxQuerySerializer import org.apache.james.jmap.mail.{MailboxQueryRequest, MailboxQueryResponse} import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.mailbox.{MailboxSession, SystemMailboxesProvider} import org.apache.james.metrics.api.MetricFactory import reactor.core.scala.publisher.{SFlux, SMono} + import javax.inject.Inject class MailboxQueryMethod @Inject()(systemMailboxesProvider: SystemMailboxesProvider, @@ -51,8 +52,7 @@ class MailboxQueryMethod @Inject()(systemMailboxesProvider: SystemMailboxesProvi } override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[IllegalArgumentException, MailboxQueryRequest] = - MailboxQuerySerializer.deserialize(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + MailboxQuerySerializer.deserialize(invocation.arguments.value).asEitherRequest private def processRequest(mailboxSession: MailboxSession, invocation: Invocation, request: MailboxQueryRequest): SMono[Invocation] = SFlux.fromPublisher(systemMailboxesProvider.getMailboxByRole(request.filter.role, mailboxSession.getUser)) diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetCreatePerformer.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetCreatePerformer.scala index 4d8b192005..8e2f9c4b4b 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetCreatePerformer.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetCreatePerformer.scala @@ -154,13 +154,7 @@ class MailboxSetCreatePerformer @Inject()(serializer: MailboxSerializer, processingContext.recordCreatedId(ClientId(mailboxCreationId.id), ServerId(serverAssignedId)) } - private def mailboxSetError(errors: collection.Seq[(JsPath, collection.Seq[JsonValidationError])]): SetError = - errors.head match { - case (path, Seq()) => SetError.invalidArguments(SetErrorDescription(s"'$path' property in mailbox object is not valid")) - case (path, Seq(JsonValidationError(Seq("error.path.missing")))) => SetError.invalidArguments(SetErrorDescription(s"Missing '$path' property in mailbox object")) - case (path, Seq(JsonValidationError(Seq(message)))) => SetError.invalidArguments(SetErrorDescription(s"'$path' property in mailbox object is not valid: $message")) - case (path, _) => SetError.invalidArguments(SetErrorDescription(s"Unknown error on property '$path'")) - } + private def mailboxSetError(errors: collection.Seq[(JsPath, collection.Seq[JsonValidationError])]): SetError = standardError(errors) private def createMailbox(mailboxSession: MailboxSession, path: MailboxPath, diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetMethod.scala index 2dce9e51f5..f5d16fcaad 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/MailboxSetMethod.scala @@ -25,7 +25,7 @@ import org.apache.james.jmap.api.model.{AccountId => JavaAccountId} import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JAMES_SHARES, JMAP_CORE, JMAP_MAIL} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{Invocation, SessionTranslator, SetError, UuidState} -import org.apache.james.jmap.json.{MailboxSerializer, ResponseSerializer} +import org.apache.james.jmap.json.MailboxSerializer import org.apache.james.jmap.mail.{MailboxSetRequest, MailboxSetResponse} import org.apache.james.jmap.method.MailboxSetCreatePerformer.MailboxCreationResults import org.apache.james.jmap.method.MailboxSetDeletePerformer.MailboxDeletionResults @@ -36,6 +36,7 @@ import org.apache.james.mailbox.model.MailboxId import org.apache.james.metrics.api.MetricFactory import play.api.libs.json.JsObject import reactor.core.scala.publisher.SMono + import javax.inject.Inject case class MailboxHasMailException(mailboxId: MailboxId) extends Exception @@ -65,8 +66,7 @@ class MailboxSetMethod @Inject()(serializer: MailboxSerializer, } yield InvocationWithContext(response, creationResults._2) override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[IllegalArgumentException, MailboxSetRequest] = - serializer.deserializeMailboxSetRequest(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + serializer.deserializeMailboxSetRequest(invocation.arguments.value).asEitherRequest private def createResponse(capabilities: Set[CapabilityIdentifier], invocation: Invocation, diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/PushSubscriptionGetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/PushSubscriptionGetMethod.scala index 9187531bf3..bdb24de165 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/PushSubscriptionGetMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/PushSubscriptionGetMethod.scala @@ -25,15 +25,15 @@ import org.apache.james.jmap.api.pushsubscription.PushSubscriptionRepository import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JMAP_CORE} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{Ids, Invocation, PushSubscriptionDTO, PushSubscriptionGetRequest, PushSubscriptionGetResponse, SessionTranslator, UnparsedPushSubscriptionId} -import org.apache.james.jmap.json.{PushSubscriptionSerializer, ResponseSerializer} +import org.apache.james.jmap.json.PushSubscriptionSerializer import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.lifecycle.api.Startable import org.apache.james.mailbox.MailboxSession import org.apache.james.metrics.api.MetricFactory import play.api.libs.json.JsObject import reactor.core.scala.publisher.{SFlux, SMono} -import javax.inject.Inject +import javax.inject.Inject import scala.jdk.CollectionConverters._ case class PushSubscriptionGetResults(results: Seq[PushSubscriptionDTO], notFound: Set[UnparsedPushSubscriptionId]) { @@ -54,8 +54,7 @@ class PushSubscriptionGetMethod @Inject()(pushSubscriptionSerializer: PushSubscr override val requiredCapabilities: Set[CapabilityIdentifier] = Set(JMAP_CORE) override def getRequest(invocation: Invocation): Either[Exception, PushSubscriptionGetRequest] = - pushSubscriptionSerializer.deserializePushSubscriptionGetRequest(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + pushSubscriptionSerializer.deserializePushSubscriptionGetRequest(invocation.arguments.value).asEitherRequest override def doProcess(invocation: InvocationWithContext, session: MailboxSession, request: PushSubscriptionGetRequest): SMono[InvocationWithContext] = request.validateProperties diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/PushSubscriptionSetCreatePerformer.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/PushSubscriptionSetCreatePerformer.scala index 6a1b460704..4365fc21bc 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/PushSubscriptionSetCreatePerformer.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/PushSubscriptionSetCreatePerformer.scala @@ -87,13 +87,7 @@ class PushSubscriptionSetCreatePerformer @Inject()(pushSubscriptionRepository: P case _ => Some(expires) } - private def pushSubscriptionSetError(errors: collection.Seq[(JsPath, collection.Seq[JsonValidationError])]): SetError = - errors.head match { - case (path, Seq()) => SetError.invalidArguments(SetErrorDescription(s"'$path' property in PushSubscription object is not valid")) - case (path, Seq(JsonValidationError(Seq("error.path.missing")))) => SetError.invalidArguments(SetErrorDescription(s"Missing '$path' property in PushSubscription object")) - case (path, Seq(JsonValidationError(Seq(message)))) => SetError.invalidArguments(SetErrorDescription(s"'$path' property in PushSubscription object is not valid: $message")) - case (path, _) => SetError.invalidArguments(SetErrorDescription(s"Unknown error on property '$path'")) - } + private def pushSubscriptionSetError(errors: collection.Seq[(JsPath, collection.Seq[JsonValidationError])]): SetError = standardError(errors) } class PushSubscriptionSetCreateProcessor @Inject()(webPushClient: WebPushClient) { diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/PushSubscriptionSetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/PushSubscriptionSetMethod.scala index e3ca62ebe9..ee758cdf6f 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/PushSubscriptionSetMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/PushSubscriptionSetMethod.scala @@ -23,12 +23,13 @@ import eu.timepit.refined.auto._ import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JMAP_CORE} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{Invocation, PushSubscriptionSetRequest, PushSubscriptionSetResponse, SessionTranslator} -import org.apache.james.jmap.json.{PushSubscriptionSerializer, ResponseSerializer} +import org.apache.james.jmap.json.PushSubscriptionSerializer import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.lifecycle.api.Startable import org.apache.james.mailbox.MailboxSession import org.apache.james.metrics.api.MetricFactory import reactor.core.scala.publisher.SMono + import javax.inject.Inject class PushSubscriptionSetMethod @Inject()(createPerformer: PushSubscriptionSetCreatePerformer, @@ -42,8 +43,7 @@ class PushSubscriptionSetMethod @Inject()(createPerformer: PushSubscriptionSetCr override val requiredCapabilities: Set[CapabilityIdentifier] = Set(JMAP_CORE) override def getRequest(invocation: Invocation): Either[Exception, PushSubscriptionSetRequest] = - pushSubscriptionSerializer.deserializePushSubscriptionSetRequest(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + pushSubscriptionSerializer.deserializePushSubscriptionSetRequest(invocation.arguments.value).asEitherRequest override def doProcess(invocation: InvocationWithContext, mailboxSession: MailboxSession, request: PushSubscriptionSetRequest): SMono[InvocationWithContext] = for { diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/QuotaChangesMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/QuotaChangesMethod.scala index 87543161eb..8e7fe530c9 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/QuotaChangesMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/QuotaChangesMethod.scala @@ -27,7 +27,7 @@ import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JM import org.apache.james.jmap.core.Id.Id import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{ErrorCode, Invocation, SessionTranslator, UuidState} -import org.apache.james.jmap.json.{QuotaSerializer, ResponseSerializer} +import org.apache.james.jmap.json.QuotaSerializer import org.apache.james.jmap.mail.{JmapQuota, QuotaChangesRequest, QuotaChangesResponse} import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.mailbox.MailboxSession @@ -35,6 +35,7 @@ import org.apache.james.mailbox.quota.{QuotaManager, UserQuotaRootResolver} import org.apache.james.metrics.api.MetricFactory import org.reactivestreams.Publisher import reactor.core.scala.publisher.SMono + import javax.inject.Inject class QuotaChangesMethod @Inject()(val metricFactory: MetricFactory, @@ -64,8 +65,7 @@ class QuotaChangesMethod @Inject()(val metricFactory: MetricFactory, } override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[Exception, QuotaChangesRequest] = - QuotaSerializer.deserializeQuotaChangesRequest(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + QuotaSerializer.deserializeQuotaChangesRequest(invocation.arguments.value).asEitherRequest } case class QuotaChangesResolver(private val quotaManager: QuotaManager, diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/QuotaGetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/QuotaGetMethod.scala index 002418241f..c659a22049 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/QuotaGetMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/QuotaGetMethod.scala @@ -24,7 +24,7 @@ import org.apache.james.core.Username import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JAMES_SHARES, JMAP_CORE, JMAP_QUOTA} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{ErrorCode, Invocation, Properties, SessionTranslator} -import org.apache.james.jmap.json.{QuotaSerializer, ResponseSerializer} +import org.apache.james.jmap.json.QuotaSerializer import org.apache.james.jmap.mail.{CountResourceType, JmapQuota, OctetsResourceType, QuotaGetRequest, QuotaIdFactory, QuotaResponseGetResult} import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.lifecycle.api.Startable @@ -68,8 +68,7 @@ class QuotaGetMethod @Inject()(val metricFactory: MetricFactory, } override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[Exception, QuotaGetRequest] = - QuotaSerializer.deserializeQuotaGetRequest(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + QuotaSerializer.deserializeQuotaGetRequest(invocation.arguments.value).asEitherRequest private def getQuotaGetResponse(request: QuotaGetRequest, username: Username, capabilities: Set[CapabilityIdentifier]): SMono[QuotaResponseGetResult] = jmapQuotaManagerWrapper.list(username, capabilities) diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/QuotaQueryMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/QuotaQueryMethod.scala index da484f27fe..8d32198587 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/QuotaQueryMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/QuotaQueryMethod.scala @@ -23,15 +23,15 @@ import eu.timepit.refined.auto._ import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JMAP_CORE, JMAP_QUOTA} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{CanCalculateChanges, ErrorCode, Invocation, Limit, Position, QueryState, SessionTranslator} -import org.apache.james.jmap.json.{QuotaSerializer, ResponseSerializer} +import org.apache.james.jmap.json.QuotaSerializer import org.apache.james.jmap.mail.{JmapQuota, QuotaQueryFilter, QuotaQueryRequest, QuotaQueryResponse} import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.mailbox.MailboxSession import org.apache.james.mailbox.quota.{QuotaManager, UserQuotaRootResolver} import org.apache.james.metrics.api.MetricFactory import org.reactivestreams.Publisher -import play.api.libs.json.JsError import reactor.core.scala.publisher.SMono + import javax.inject.Inject class QuotaQueryMethod @Inject()(val metricFactory: MetricFactory, @@ -58,9 +58,7 @@ class QuotaQueryMethod @Inject()(val metricFactory: MetricFactory, .map(invocationResult => InvocationWithContext(invocationResult, invocation.processingContext)) override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[Exception, QuotaQueryRequest] = - QuotaSerializer.deserializeQuotaQueryRequest(invocation.arguments.value) - .asEither - .left.map(errors => new IllegalArgumentException(ResponseSerializer.serialize(JsError(errors)).toString)) + QuotaSerializer.deserializeQuotaQueryRequest(invocation.arguments.value).asEitherRequest private def processRequest(mailboxSession: MailboxSession, invocation: Invocation, request: QuotaQueryRequest, capabilities: Set[CapabilityIdentifier]): SMono[Invocation] = jmapQuotaManagerWrapper.list(mailboxSession.getUser, capabilities) diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/ThreadChangesMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/ThreadChangesMethod.scala index 998175f699..0266f05b45 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/ThreadChangesMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/ThreadChangesMethod.scala @@ -23,12 +23,13 @@ import eu.timepit.refined.auto._ import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JMAP_MAIL} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{ErrorCode, Invocation, SessionTranslator, UuidState} -import org.apache.james.jmap.json.{ResponseSerializer, ThreadSerializer} +import org.apache.james.jmap.json.ThreadSerializer import org.apache.james.jmap.mail.{HasMoreChanges, ThreadChangesRequest, ThreadChangesResponse} import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.mailbox.MailboxSession import org.apache.james.metrics.api.MetricFactory import reactor.core.scala.publisher.SMono + import javax.inject.Inject class ThreadChangesMethod @Inject()(val metricFactory: MetricFactory, @@ -60,6 +61,5 @@ class ThreadChangesMethod @Inject()(val metricFactory: MetricFactory, } override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[IllegalArgumentException, ThreadChangesRequest] = - ThreadSerializer.deserializeChanges(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + ThreadSerializer.deserializeChanges(invocation.arguments.value).asEitherRequest } diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/ThreadGetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/ThreadGetMethod.scala index b0069c940c..daee568bda 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/ThreadGetMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/ThreadGetMethod.scala @@ -23,7 +23,7 @@ import eu.timepit.refined.auto._ import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JMAP_CORE, JMAP_MAIL} import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.{AccountId, Invocation, SessionTranslator, UuidState} -import org.apache.james.jmap.json.{ResponseSerializer, ThreadSerializer} +import org.apache.james.jmap.json.ThreadSerializer import org.apache.james.jmap.mail.{Thread, ThreadGetRequest, ThreadGetResponse, ThreadNotFound, UnparsedThreadId} import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.mailbox.exception.ThreadNotFoundException @@ -31,8 +31,8 @@ import org.apache.james.mailbox.model.{ThreadId => JavaThreadId} import org.apache.james.mailbox.{MailboxManager, MailboxSession} import org.apache.james.metrics.api.MetricFactory import reactor.core.scala.publisher.{SFlux, SMono} -import javax.inject.Inject +import javax.inject.Inject import scala.util.Try object ThreadGetResult { @@ -78,8 +78,7 @@ class ThreadGetMethod @Inject()(val metricFactory: MetricFactory, .map(InvocationWithContext(_, invocation.processingContext)) override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[IllegalArgumentException, ThreadGetRequest] = - ThreadSerializer.deserialize(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + ThreadSerializer.deserialize(invocation.arguments.value).asEitherRequest private def getThreadResponse(threadGetRequest: ThreadGetRequest, mailboxSession: MailboxSession): SFlux[ThreadGetResult] = diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/VacationResponseGetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/VacationResponseGetMethod.scala index 246cb19ce2..a07c9384c8 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/VacationResponseGetMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/VacationResponseGetMethod.scala @@ -24,7 +24,7 @@ import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JM import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.UuidState.INSTANCE import org.apache.james.jmap.core.{AccountId, ErrorCode, Invocation, Properties, SessionTranslator} -import org.apache.james.jmap.json.{ResponseSerializer, VacationSerializer} +import org.apache.james.jmap.json.VacationSerializer import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.jmap.vacation.VacationResponse.UNPARSED_SINGLETON import org.apache.james.jmap.vacation.{UnparsedVacationResponseId, VacationResponse, VacationResponseGetRequest, VacationResponseGetResponse, VacationResponseNotFound} @@ -83,9 +83,7 @@ class VacationResponseGetMethod @Inject()(vacationService: VacationService, } override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[IllegalArgumentException, VacationResponseGetRequest] = - VacationSerializer.deserializeVacationResponseGetRequest(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) - + VacationSerializer.deserializeVacationResponseGetRequest(invocation.arguments.value).asEitherRequest private def getVacationResponse(vacationResponseGetRequest: VacationResponseGetRequest, mailboxSession: MailboxSession): SFlux[VacationResponseGetResult] = vacationResponseGetRequest.ids match { diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/VacationResponseSetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/VacationResponseSetMethod.scala index 0acfe169df..813938beaa 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/VacationResponseSetMethod.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/VacationResponseSetMethod.scala @@ -29,7 +29,7 @@ import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JM import org.apache.james.jmap.core.Invocation.{Arguments, MethodName} import org.apache.james.jmap.core.SetError.SetErrorDescription import org.apache.james.jmap.core.{Invocation, SessionTranslator, UuidState} -import org.apache.james.jmap.json.{ResponseSerializer, VacationSerializer} +import org.apache.james.jmap.json.VacationSerializer import org.apache.james.jmap.method.VacationResponseSetMethod.VACATION_RESPONSE_PATCH_OBJECT_KEY import org.apache.james.jmap.routes.SessionSupplier import org.apache.james.jmap.vacation.{VacationResponseSetError, VacationResponseSetRequest, VacationResponseSetResponse, VacationResponseUpdateResponse} @@ -38,6 +38,7 @@ import org.apache.james.metrics.api.MetricFactory import org.apache.james.vacation.api.{VacationPatch, VacationService, AccountId => VacationAccountId} import play.api.libs.json.JsObject import reactor.core.scala.publisher.{SFlux, SMono} + import javax.inject.{Inject, Named} object VacationResponseUpdateResults { @@ -97,8 +98,7 @@ class VacationResponseSetMethod @Inject()(@Named(InjectionKeys.JMAP) eventBus: E } override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[IllegalArgumentException, VacationResponseSetRequest] = - VacationSerializer.deserializeVacationResponseSetRequest(invocation.arguments.value) - .asEither.left.map(ResponseSerializer.asException) + VacationSerializer.deserializeVacationResponseSetRequest(invocation.arguments.value).asEitherRequest private def update(mailboxSession: MailboxSession, vacationResponseSetRequest: VacationResponseSetRequest): SMono[VacationResponseUpdateResults] = { SFlux.fromIterable(vacationResponseSetRequest.parsePatch() diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/package.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/package.scala new file mode 100644 index 0000000000..1a11ad529f --- /dev/null +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/package.scala @@ -0,0 +1,48 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.jmap + +import org.apache.james.jmap.core.SetError +import org.apache.james.jmap.core.SetError.SetErrorDescription +import org.apache.james.jmap.json.ResponseSerializer +import play.api.libs.json.{JsError, JsPath, JsResult, JsonValidationError} + +import scala.language.implicitConversions + +package object method { + + def standardErrorMessage(errors: collection.Seq[(JsPath, collection.Seq[JsonValidationError])]): String = + errors.head match { + case (path, Seq()) => s"'$path' property is not valid" + case (path, Seq(JsonValidationError(Seq("error.path.missing")))) => s"Missing '$path' property" + case (path, Seq(JsonValidationError(Seq("error.expected.jsarray")))) => s"'$path' property need to be an array" + case (path, Seq(JsonValidationError(Seq(message)))) => s"'$path' property is not valid: $message" + case (path, _) => s"Unknown error on property '$path'" + case _ => ResponseSerializer.serialize(JsError(errors)).toString() + } + + def standardError(errors: collection.Seq[(JsPath, collection.Seq[JsonValidationError])]): SetError = + SetError.invalidArguments(SetErrorDescription(standardErrorMessage(errors))) + + implicit class AsEitherRequest[T](val jsResult: JsResult[T]) { + def asEitherRequest: Either[IllegalArgumentException, T] = + jsResult.asEither.left.map(errors => new IllegalArgumentException(standardErrorMessage(errors))) + } +} \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org For additional commands, e-mail: notifications-h...@james.apache.org