Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/****************************************************************
* 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.model.mailbox;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.BinaryOperator;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.mailbox.model.MailboxACL;
import org.apache.james.mailbox.model.MailboxACL.EntryKey;
import org.apache.james.mailbox.model.MailboxACL.Rfc4314Rights;
import org.apache.james.mailbox.model.MailboxPath;
import org.apache.james.util.GuavaUtils;
import org.apache.james.util.OptionalUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import com.github.fge.lambdas.Throwing;
import com.github.steveash.guavate.Guavate;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;
public class Rights {
@VisibleForTesting
static final Optional UNSUPPORTED = Optional.empty();
public enum Right {
Administer(MailboxACL.Right.Administer),
Expunge(MailboxACL.Right.PerformExpunge),
Insert(MailboxACL.Right.Insert),
Lookup(MailboxACL.Right.Lookup),
Read(MailboxACL.Right.Read),
Seen(MailboxACL.Right.WriteSeenFlag),
DeleteMessages(MailboxACL.Right.DeleteMessages),
Write(MailboxACL.Right.Write);
private final MailboxACL.Right right;
Right(MailboxACL.Right right) {
this.right = right;
}
@JsonValue
public char asCharacter() {
return right.asCharacter();
}
public MailboxACL.Right toMailboxRight() {
return right;
}
public static Optional forRight(MailboxACL.Right right) {
return OptionalUtils.executeIfEmpty(
Arrays.stream(values())
.filter(jmapRight -> jmapRight.right == right)
.findAny(),
() -> LOGGER.warn("Non handled right '{}'", right));
}
public static Right forChar(char c) {
return Arrays.stream(values())
.filter(right -> right.asCharacter() == c)
.findAny()
.orElseThrow(() -> new IllegalArgumentException("No matching right for '" + c + "'"));
}
}
public static class Username {
public static Username forMailboxPath(MailboxPath mailboxPath) {
return new Username(mailboxPath.getUser());
}
public static Username fromSession(MailboxSession mailboxSession) {
return new Username(mailboxSession.getUser().getUserName());
}
private final String value;
public Username(String value) {
this.value = value;
}
@JsonValue
public String getValue() {
return value;
}
@Override
public final boolean equals(Object o) {
if (o instanceof Username) {
Username username = (Username) o;
return Objects.equals(this.value, username.value);
}
return false;
}
@Override
public final int hashCode() {
return Objects.hash(value);
}
}
public static class Builder {
private Multimap rights;
public Builder() {
rights = ArrayListMultimap.create();
}
public Builder delegateTo(Username username, Right... rights) {
delegateTo(username, Arrays.asList(rights));
return this;
}
public Builder delegateTo(Username username, Collection rights) {
this.rights.putAll(username, rights);
return this;
}
public Builder combine(Builder builder) {
this.rights.putAll(builder.rights);
return this;
}
public Rights build() {
return new Rights(rights);
}
}
public static Builder builder() {
return new Builder();
}
public static Rights fromACL(MailboxACL acl) {
return acl.getEntries()
.entrySet()
.stream()
.filter(entry -> isSupported(entry.getKey()))
.map(Rights::toRightsBuilder)
.reduce(builder(), Builder::combine)
.build();
}
private static Builder toRightsBuilder(Map.Entry entry) {
return builder().delegateTo(
new Username(entry.getKey().getName()),
fromACL(entry.getValue()));
}
private static List fromACL(MailboxACL.Rfc4314Rights rights) {
return rights.list()
.stream()
.flatMap(right -> OptionalUtils.toStream(Right.forRight(right)))
.collect(Guavate.toImmutableList());
}
private static boolean isSupported(EntryKey key) {
if (key.isNegative()) {
LOGGER.info("Negative keys are not supported");
return false;
}
if (key.equals(MailboxACL.OWNER_KEY)) {
return false;
}
if (key.getNameType() != MailboxACL.NameType.user) {
LOGGER.info("{} is not supported. Only 'user' is.", key.getNameType());
return false;
}
return true;
}
public static final Rights EMPTY = new Rights(ArrayListMultimap.create());
private static final Logger LOGGER = LoggerFactory.getLogger(Rights.class);
private final Multimap rights;
@JsonCreator
public Rights(Map> rights) {
this(GuavaUtils.toMultimap(rights));
}
private Rights(Multimap rights) {
this.rights = rights;
}
@JsonAnyGetter
public Map> getRights() {
return rights.asMap();
}
public Rights removeEntriesFor(Username username) {
return new Rights(
rights.asMap()
.entrySet()
.stream()
.filter(entry -> !entry.getKey().equals(username))
.flatMap(entry -> entry.getValue()
.stream()
.map(v -> Pair.of(entry.getKey(), v)))
.collect(Guavate.toImmutableListMultimap(Pair::getKey, Pair::getValue)));
}
public MailboxACL toMailboxAcl() {
BinaryOperator union = Throwing.binaryOperator(MailboxACL::union);
return rights.asMap()
.entrySet()
.stream()
.map(entry -> new MailboxACL(
ImmutableMap.of(
EntryKey.createUserEntryKey(entry.getKey().value),
toMailboxAclRights(entry.getValue()))))
.reduce(MailboxACL.EMPTY, union);
}
public Optional mayReadItems(Username username) {
return containsRight(username, Right.Read);
}
public Optional mayAddItems(Username username) {
return containsRight(username, Right.Insert);
}
public Optional mayCreateChild(Username username) {
return UNSUPPORTED;
}
public Optional mayRemoveItems(Username username) {
return containsRight(username, Right.DeleteMessages);
}
public Optional mayRename(Username username) {
return UNSUPPORTED;
}
public Optional mayDelete(Username username) {
return UNSUPPORTED;
}
private Optional containsRight(Username username, Right right) {
return Optional.ofNullable(rights.get(username))
.filter(rightList -> !rightList.isEmpty())
.map(rightList -> rightList.contains(right));
}
private Rfc4314Rights toMailboxAclRights(Collection rights) {
BinaryOperator union = Throwing.binaryOperator(Rfc4314Rights::union);
return rights.stream()
.map(Right::toMailboxRight)
.map(Throwing.function(Rfc4314Rights::new))
.reduce(new Rfc4314Rights(), union);
}
@Override
public final boolean equals(Object o) {
if (o instanceof Rights) {
Rights that = (Rights) o;
return Objects.equals(this.rights, that.rights);
}
return false;
}
@Override
public final int hashCode() {
return Objects.hash(rights);
}
}