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 b9e7792ca75a42241bcf495598b4c7122e80f11c Author: Florent Azavant <fazav...@linagora.com> AuthorDate: Wed Nov 6 10:50:12 2024 +0100 [ISSUE-5314] refactored `Rights.scala` to use `EntryKey` instead of `Username` --- .../org/apache/james/mailbox/model/MailboxACL.java | 14 +++-- .../apache/james/jmap/json/MailboxSerializer.scala | 12 ++-- .../scala/org/apache/james/jmap/mail/Rights.scala | 43 ++++++------- .../james/jmap/json/MailboxSerializationTest.scala | 7 ++- .../org/apache/james/jmap/mail/RightsTest.scala | 73 +++++++++++----------- 5 files changed, 78 insertions(+), 71 deletions(-) diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java index 34204359b5..575763647e 100644 --- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java +++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MailboxACL.java @@ -375,15 +375,19 @@ public class MailboxACL { } public static EntryKey createUserEntryKey(Username name) { - return new EntryKey(name.asString(), NameType.user, POSITIVE_KEY); + return createUserEntryKey(name.asString()); } - public static EntryKey createNegativeUserEntryKey(Username name) { - return new EntryKey(name.asString(), NameType.user, NEGATIVE_KEY); + public static EntryKey createUserEntryKey(Username name, boolean negative) { + return createUserEntryKey(name.asString(), negative); } - public static EntryKey createUserEntryKey(Username name, boolean negative) { - return new EntryKey(name.asString(), NameType.user, negative); + public static EntryKey createUserEntryKey(String name) { + return createUserEntryKey(name, POSITIVE_KEY); + } + + public static EntryKey createUserEntryKey(String name, boolean negative) { + return new EntryKey(name, NameType.user, negative); } private final String name; diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/MailboxSerializer.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/MailboxSerializer.scala index d22e9c4a95..f4c027f675 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/MailboxSerializer.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/MailboxSerializer.scala @@ -22,13 +22,13 @@ package org.apache.james.jmap.json import eu.timepit.refined import eu.timepit.refined._ import jakarta.inject.Inject -import org.apache.james.core.{Domain, Username} +import org.apache.james.core.Domain import org.apache.james.jmap.core.CapabilityIdentifier.CapabilityIdentifier import org.apache.james.jmap.core.Id.IdConstraint import org.apache.james.jmap.core.{ClientId, Properties, SetError, UuidState} import org.apache.james.jmap.mail.{Ids, IsSubscribed, Mailbox, MailboxChangesRequest, MailboxChangesResponse, MailboxCreationId, MailboxCreationRequest, MailboxCreationResponse, MailboxGetRequest, MailboxGetResponse, MailboxNamespace, MailboxPatchObject, MailboxRights, MailboxSetRequest, MailboxSetResponse, MailboxUpdateResponse, MayAddItems, MayCreateChild, MayDelete, MayReadItems, MayRemoveItems, MayRename, MaySetKeywords, MaySetSeen, MaySubmit, NotFound, Quota, QuotaId, QuotaRoot, Quo [...] import org.apache.james.mailbox.Role -import org.apache.james.mailbox.model.MailboxACL.{Right => JavaRight} +import org.apache.james.mailbox.model.MailboxACL.{EntryKey, Right => JavaRight} import org.apache.james.mailbox.model.{MailboxACL, MailboxId} import play.api.libs.json._ @@ -92,13 +92,13 @@ class MailboxSerializer @Inject()(mailboxIdFactory: MailboxId.Factory) { private implicit val mailboxJavaRightReads: Reads[JavaRight] = value => rightRead.reads(value).map(right => right.toMailboxRight) private implicit val mailboxRfc4314RightsReads: Reads[Rfc4314Rights] = Json.valueReads[Rfc4314Rights] private implicit val rightSeqWrites: Writes[Seq[Right]] = seq => JsArray(seq.map(rightWrites.writes)) - private implicit val rightsMapWrites: Writes[Map[Username, Seq[Right]]] = - mapWrites[Username, Seq[Right]](_.asString(), rightSeqWrites) + private implicit val rightsMapWrites: Writes[Map[EntryKey, Seq[Right]]] = + mapWrites[EntryKey, Seq[Right]](_.toString(), rightSeqWrites) private implicit val rightsWrites: Writes[Rights] = Json.valueWrites[Rights] - private implicit val mapRightsReads: Reads[Map[Username, Seq[Right]]] = _.validate[Map[String, Seq[Right]]] + private implicit val mapRightsReads: Reads[Map[EntryKey, Seq[Right]]] = _.validate[Map[String, Seq[Right]]] .map(rawMap => - rawMap.map(entry => (Username.of(entry._1), entry._2))) + rawMap.map(entry => (EntryKey.deserialize(entry._1), entry._2))) private implicit val rightsReads: Reads[Rights] = json => mapRightsReads.reads(json).map(rawMap => Rights(rawMap)) private implicit val domainWrites: Writes[Domain] = domain => JsString(domain.asString) diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/Rights.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/Rights.scala index 5b8fe06732..ee6edd3495 100644 --- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/Rights.scala +++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/Rights.scala @@ -19,7 +19,6 @@ package org.apache.james.jmap.mail -import org.apache.james.core.Username import org.apache.james.mailbox.model.MailboxACL.{EntryKey, Rfc4314Rights => JavaRfc4314Rights, Right => JavaRight} import org.apache.james.mailbox.model.{MailboxACL => JavaMailboxACL} import org.slf4j.{Logger, LoggerFactory} @@ -87,12 +86,12 @@ object Rights { val EMPTY = Rights(Map()) - def of(username: Username, right: Right): Rights = of(username, Seq(right)) + def of(entryKey: EntryKey, right: Right): Rights = of(entryKey, Seq(right)) - def of(username: Username, rights: Seq[Right]): Rights = { + def of(entryKey: EntryKey, rights: Seq[Right]): Rights = { require(rights.nonEmpty, "'rights' should not be empty") - Rights(Map(username -> rights)) + Rights(Map(entryKey -> rights)) } def fromACL(acl: MailboxACL): Rights = acl.entries @@ -104,15 +103,17 @@ object Rights { } .fold(EMPTY)(_ combine _) - private def toRights(entryKey: EntryKey, aclRights: Rfc4314Rights): Rights = of(Username.of(entryKey.getName), aclRights.toRights) + private def toRights(entryKey: EntryKey, aclRights: Rfc4314Rights): Rights = of(entryKey, aclRights.toRights) private def isSupported(key: EntryKey): Boolean = key match { case k if k.isNegative => LOGGER.info("Negative keys are not supported") false - case JavaMailboxACL.OWNER_KEY => false - case k if k.getNameType ne JavaMailboxACL.NameType.user => - LOGGER.info("{} is not supported. Only 'user' is.", key.getNameType) + case k if k.getNameType == JavaMailboxACL.NameType.special && k.getName != JavaMailboxACL.SpecialName.anyone.name() => + LOGGER.info("Special name {} is not supported. Only 'anyone' is.", key.getName) + false + case k if k.getNameType == JavaMailboxACL.NameType.group => + LOGGER.info("Name type {} is not supported. Only 'user' and 'special.anyone' are.", key.getNameType) false case _ => true } @@ -123,39 +124,39 @@ case object Applicable extends RightsApplicability case object NotApplicable extends RightsApplicability case object Unsupported extends RightsApplicability -case class Rights(rights: Map[Username, Seq[Right]]) { - def removeEntriesFor(username: Username) = copy(rights = rights - username) +case class Rights(rights: Map[EntryKey, Seq[Right]]) { + def removeEntriesFor(entryKey: EntryKey) = copy(rights = rights - entryKey) def toMailboxAcl: MailboxACL = { val map: Map[EntryKey, Rfc4314Rights] = rights.view .mapValues(Rfc4314Rights.fromRights) .toMap .map { - case (user, rfc4314Rights) => (EntryKey.createUserEntryKey(user), rfc4314Rights) + case (entryKey, rfc4314Rights) => (entryKey, rfc4314Rights) } MailboxACL(map) } - def append(username: Username, right: Right): Rights = append(username, Seq(right)) + def append(entryKey: EntryKey, right: Right): Rights = append(entryKey, Seq(right)) - def append(username: Username, rights: Seq[Right]): Rights = copy(rights = this.rights + (username -> rights)) + def append(entryKey: EntryKey, rights: Seq[Right]): Rights = copy(rights = this.rights + (entryKey -> rights)) def combine(that: Rights): Rights = Rights(this.rights ++ that.rights) - def mayReadItems(username: Username): RightsApplicability = containsRight(username, Right.Read) + def mayReadItems(entryKey: EntryKey): RightsApplicability = containsRight(entryKey, Right.Read) - def mayAddItems(username: Username): RightsApplicability = containsRight(username, Right.Insert) + def mayAddItems(entryKey: EntryKey): RightsApplicability = containsRight(entryKey, Right.Insert) - def mayRemoveItems(username: Username): RightsApplicability = containsRight(username, Right.DeleteMessages) + def mayRemoveItems(entryKey: EntryKey): RightsApplicability = containsRight(entryKey, Right.DeleteMessages) - def mayCreateChild(username: Username): RightsApplicability = Unsupported + def mayCreateChild(entryKey: EntryKey): RightsApplicability = Unsupported - def mayRename(username: Username): RightsApplicability = Unsupported + def mayRename(entryKey: EntryKey): RightsApplicability = Unsupported - def mayDelete(username: Username): RightsApplicability = Unsupported + def mayDelete(entryKey: EntryKey): RightsApplicability = Unsupported - private def containsRight(username: Username, right: Right): RightsApplicability = { - val contains = rights.get(username) + private def containsRight(entryKey: EntryKey, right: Right): RightsApplicability = { + val contains = rights.get(entryKey) .map(_.contains(right)) contains match { case Some(true) => Applicable diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/MailboxSerializationTest.scala b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/MailboxSerializationTest.scala index c9f5891bff..f7b2c63c22 100644 --- a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/MailboxSerializationTest.scala +++ b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/json/MailboxSerializationTest.scala @@ -21,11 +21,12 @@ package org.apache.james.jmap.json import eu.timepit.refined.auto._ import net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson -import org.apache.james.core.{Domain, Username} +import org.apache.james.core.Domain import org.apache.james.jmap.json.MailboxSerializationTest.MAILBOX import org.apache.james.jmap.mail.MailboxName.MailboxName import org.apache.james.jmap.mail.{IsSubscribed, Mailbox, MailboxNamespace, MailboxRights, MayAddItems, MayCreateChild, MayDelete, MayReadItems, MayRemoveItems, MayRename, MaySetKeywords, MaySetSeen, MaySubmit, PersonalNamespace, Quota, QuotaId, QuotaRoot, Quotas, Right, Rights, SortOrder, TotalEmails, TotalThreads, UnreadEmails, UnreadThreads, Value} import org.apache.james.mailbox.Role +import org.apache.james.mailbox.model.MailboxACL.EntryKey import org.apache.james.mailbox.model.{MailboxId, TestId} import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec @@ -56,8 +57,8 @@ object MailboxSerializationTest { maySubmit = MaySubmit(false) ) - private val RIGHTS: Rights = Rights.of(Username.of("bob"), Seq(Right.Expunge, Right.Lookup)) - .append(Username.of("alice"), Seq(Right.Read, Right.Write)) + private val RIGHTS: Rights = Rights.of(EntryKey.createUserEntryKey("bob"), Seq(Right.Expunge, Right.Lookup)) + .append(EntryKey.createUserEntryKey("alice"), Seq(Right.Read, Right.Write)) private val QUOTAS = Quotas(Map( QuotaId(QuotaRoot("quotaRoot", None)) -> Quota(Map( diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/mail/RightsTest.scala b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/mail/RightsTest.scala index cae2864741..c6f6d594b1 100644 --- a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/mail/RightsTest.scala +++ b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/mail/RightsTest.scala @@ -29,8 +29,9 @@ import scala.jdk.CollectionConverters._ class RightsTest extends AnyWordSpec with Matchers { val NEGATIVE = true - val USERNAME: Username = Username.of("user") - val OTHER_USERNAME: Username = Username.of("otherUser") + val USER: String = "user" + val USER_ENTRYKEY: EntryKey = EntryKey.createUserEntryKey(USER) + val OTHER_USER_ENTRYKEY: EntryKey = EntryKey.createUserEntryKey("otherUser") "Right ofCharacter" should { "recognise 'a'" in { @@ -70,21 +71,21 @@ class RightsTest extends AnyWordSpec with Matchers { } "filter out negative users" in { val acl = new JavaMailboxACL(Map( - EntryKey.createUserEntryKey(USERNAME, NEGATIVE) -> JavaRfc4314Rights.fromSerializedRfc4314Rights("aet")).asJava) + EntryKey.createUserEntryKey(USER, NEGATIVE) -> JavaRfc4314Rights.fromSerializedRfc4314Rights("aet")).asJava) Rights.fromACL(MailboxACL.fromJava(acl)) must be(Rights.EMPTY) } "accept users" in { val acl = new JavaMailboxACL(Map( - EntryKey.createUserEntryKey(USERNAME) -> JavaRfc4314Rights.fromSerializedRfc4314Rights("aet")).asJava) + USER_ENTRYKEY -> JavaRfc4314Rights.fromSerializedRfc4314Rights("aet")).asJava) - Rights.fromACL(MailboxACL.fromJava(acl)) must be(Rights.of(USERNAME, Seq(Right.Administer, Right.Expunge, Right.DeleteMessages))) + Rights.fromACL(MailboxACL.fromJava(acl)) must be(Rights.of(USER_ENTRYKEY, Seq(Right.Administer, Right.Expunge, Right.DeleteMessages))) } "filter out unknown rights" in { val acl = new JavaMailboxACL(Map( - EntryKey.createUserEntryKey(USERNAME) -> JavaRfc4314Rights.fromSerializedRfc4314Rights("aetxk")).asJava) + USER_ENTRYKEY -> JavaRfc4314Rights.fromSerializedRfc4314Rights("aetxk")).asJava) - Rights.fromACL(MailboxACL.fromJava(acl)) must be(Rights.of(USERNAME, Seq(Right.Administer, Right.Expunge, Right.DeleteMessages))) + Rights.fromACL(MailboxACL.fromJava(acl)) must be(Rights.of(USER_ENTRYKEY, Seq(Right.Administer, Right.Expunge, Right.DeleteMessages))) } } "To ACL" should { @@ -92,11 +93,11 @@ class RightsTest extends AnyWordSpec with Matchers { Rights.EMPTY.toMailboxAcl.asJava must be(new JavaMailboxACL()) } "return acl conversion" in { - val user1 = Username.of("user1") - val user2 = Username.of("user2") + val user1 = EntryKey.createUserEntryKey("user1") + val user2 = EntryKey.createUserEntryKey("user2") val expected = new JavaMailboxACL(Map( - EntryKey.createUserEntryKey(user1) -> new JavaRfc4314Rights(JavaRight.Administer, JavaRight.DeleteMessages), - EntryKey.createUserEntryKey(user2) -> new JavaRfc4314Rights(JavaRight.PerformExpunge, JavaRight.Lookup)) + user1 -> new JavaRfc4314Rights(JavaRight.Administer, JavaRight.DeleteMessages), + user2 -> new JavaRfc4314Rights(JavaRight.PerformExpunge, JavaRight.Lookup)) .asJava) val jmapPojo = Rights.of(user1, Seq(Right.Administer, Right.DeleteMessages)) .append(user2, Seq(Right.Expunge, Right.Lookup)) @@ -106,72 +107,72 @@ class RightsTest extends AnyWordSpec with Matchers { } "Remove entries" should { "return empty when empty" in { - Rights.EMPTY.removeEntriesFor(USERNAME) must be(Rights.EMPTY) + Rights.EMPTY.removeEntriesFor(USER_ENTRYKEY) must be(Rights.EMPTY) } "return empty when only user" in { - Rights.of(USERNAME, Right.Lookup) - .removeEntriesFor(USERNAME) must be(Rights.EMPTY) + Rights.of(USER_ENTRYKEY, Right.Lookup) + .removeEntriesFor(USER_ENTRYKEY) must be(Rights.EMPTY) } "only remove specified users" in { - val expected = Rights.of(OTHER_USERNAME, Right.Lookup) + val expected = Rights.of(OTHER_USER_ENTRYKEY, Right.Lookup) - Rights.of(USERNAME, Right.Lookup) - .append(OTHER_USERNAME, Right.Lookup) - .removeEntriesFor(USERNAME) must be(expected) + Rights.of(USER_ENTRYKEY, Right.Lookup) + .append(OTHER_USER_ENTRYKEY, Right.Lookup) + .removeEntriesFor(USER_ENTRYKEY) must be(expected) } } "mayAddItems" should { "return empty when no user" in { - Rights.EMPTY.mayAddItems(USERNAME) must be(NotApplicable) + Rights.EMPTY.mayAddItems(USER_ENTRYKEY) must be(NotApplicable) } "return false when no insert right" in { - Rights.of(USERNAME, Seq(Right.Administer, Right.Expunge, Right.Lookup, Right.DeleteMessages, Right.Read, Right.Seen, Right.Write)) - .mayAddItems(USERNAME) must be(NotApplicable) + Rights.of(USER_ENTRYKEY, Seq(Right.Administer, Right.Expunge, Right.Lookup, Right.DeleteMessages, Right.Read, Right.Seen, Right.Write)) + .mayAddItems(USER_ENTRYKEY) must be(NotApplicable) } "return true when insert right" in { - Rights.of(USERNAME, Right.Insert) - .mayAddItems(USERNAME) must be(Applicable) + Rights.of(USER_ENTRYKEY, Right.Insert) + .mayAddItems(USER_ENTRYKEY) must be(Applicable) } } "mayReadItems" should { "return empty when no user" in { - Rights.EMPTY.mayReadItems(USERNAME) must be(NotApplicable) + Rights.EMPTY.mayReadItems(USER_ENTRYKEY) must be(NotApplicable) } "return false when no read right" in { - Rights.of(USERNAME, Seq(Right.Administer, Right.Expunge, Right.Lookup, Right.DeleteMessages, Right.Administer, Right.Seen, Right.Write)) - .mayReadItems(USERNAME) must be(NotApplicable) + Rights.of(USER_ENTRYKEY, Seq(Right.Administer, Right.Expunge, Right.Lookup, Right.DeleteMessages, Right.Administer, Right.Seen, Right.Write)) + .mayReadItems(USER_ENTRYKEY) must be(NotApplicable) } "return true when read right" in { - Rights.of(USERNAME, Right.Read) - .mayReadItems(USERNAME) must be(Applicable) + Rights.of(USER_ENTRYKEY, Right.Read) + .mayReadItems(USER_ENTRYKEY) must be(Applicable) } } "mayRemoveItems" should { "return empty when no user" in { - Rights.EMPTY.mayRemoveItems(USERNAME) must be(NotApplicable) + Rights.EMPTY.mayRemoveItems(USER_ENTRYKEY) must be(NotApplicable) } "return false when no delete right" in { - Rights.of(USERNAME, Seq(Right.Administer, Right.Expunge, Right.Lookup, Right.Read, Right.Administer, Right.Seen, Right.Write)) - .mayRemoveItems(USERNAME) must be(NotApplicable) + Rights.of(USER_ENTRYKEY, Seq(Right.Administer, Right.Expunge, Right.Lookup, Right.Read, Right.Administer, Right.Seen, Right.Write)) + .mayRemoveItems(USER_ENTRYKEY) must be(NotApplicable) } "return true when delete right" in { - Rights.of(USERNAME, Right.DeleteMessages) - .mayRemoveItems(USERNAME) must be(Applicable) + Rights.of(USER_ENTRYKEY, Right.DeleteMessages) + .mayRemoveItems(USER_ENTRYKEY) must be(Applicable) } } "mayRename" should { "return unsupported" in { - Rights.EMPTY.mayRename(USERNAME) must be(Unsupported) + Rights.EMPTY.mayRename(USER_ENTRYKEY) must be(Unsupported) } } "mayDelete" should { "return unsupported" in { - Rights.EMPTY.mayDelete(USERNAME) must be(Unsupported) + Rights.EMPTY.mayDelete(USER_ENTRYKEY) must be(Unsupported) } } "mayCreateChild" should { "return unsupported" in { - Rights.EMPTY.mayCreateChild(USERNAME) must be(Unsupported) + Rights.EMPTY.mayCreateChild(USER_ENTRYKEY) must be(Unsupported) } } } --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org For additional commands, e-mail: notifications-h...@james.apache.org