Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ public TooManyMappingException(String string) {

void addForwardMapping(MappingSource source, String address) throws RecipientRewriteTableException;

void addForwardMapping(MappingSource source, String address, String comment) throws RecipientRewriteTableException;

void removeForwardMapping(MappingSource source, String address) throws RecipientRewriteTableException;

void addGroupMapping(MappingSource source, String address) throws RecipientRewriteTableException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,30 @@ public interface Mapping {

static Mapping of(String mapping) {
Type type = Mapping.detectType(mapping);
return of(type, type.withoutPrefix(mapping));
String withoutType = type.withoutPrefix(mapping);
int separatorPosition = withoutType.indexOf(':');
String comment = parseComment(withoutType, separatorPosition);
String mappingValue = parseMappingValue(separatorPosition, withoutType);
return new Impl(type, mappingValue, comment);
}

private static String parseMappingValue(int separatorPosition, String withoutType) {
if (separatorPosition < 1) {
return withoutType;
} else {
return withoutType.substring(0, separatorPosition);
}
}

private static String parseComment(String withoutType, int separatorPosition) {
if (separatorPosition > 0 && separatorPosition < withoutType.length() - 1) {
return withoutType.substring(separatorPosition);
}
return "";
}

static Mapping of(Type type, String mapping) {
return new Impl(type, mapping);
return new Impl(type, mapping, "");
}

enum MailAddressConversionPolicy {
Expand Down Expand Up @@ -237,9 +256,11 @@ class Impl implements Mapping, Serializable {

private final Type type;
private final String mapping;
private final String comment;
private final UserRewritter rewriter;

private Impl(Type type, String mapping) {
private Impl(Type type, String mapping, String description) {
this.comment = description;
Preconditions.checkNotNull(type);
Preconditions.checkNotNull(mapping);
this.type = type;
Expand All @@ -249,7 +270,20 @@ private Impl(Type type, String mapping) {

@Override
public String asString() {
return type.asPrefix() + mapping;
if (comment.isEmpty()) {
return type.asPrefix() + mapping;
}
return type.asPrefix() + mapping + ":" + comment;
}

@Override
public String getComment() {
return comment;
}

@Override
public Mapping withComment(String comment) {
return new Impl(type,mapping, comment);
}

@Override
Expand Down Expand Up @@ -335,9 +369,13 @@ public String toString() {
Type getType();

String getMappingValue();

String getComment();

String asString();

Mapping withComment(String comment);

boolean hasDomain();

interface ThrowingDomainSupplier {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,14 @@ public void removeDomainAliasMapping(MappingSource source, Domain realDomain) th

@Override
public void addForwardMapping(MappingSource source, String address) throws RecipientRewriteTableException {
addForwardMapping(source, address, "");
}

@Override
public void addForwardMapping(MappingSource source, String address, String comment) throws RecipientRewriteTableException {
Mapping mapping = Mapping.forward(address)
.appendDomainFromThrowingSupplierIfNone(this::defaultDomain);
.appendDomainFromThrowingSupplierIfNone(this::defaultDomain)
.withComment(comment);

checkHasValidAddress(mapping);
checkDuplicateMapping(source, mapping);
Expand All @@ -318,6 +324,7 @@ public void addForwardMapping(MappingSource source, String address) throws Recip
addMapping(source, mapping);
}


@Override
public void removeForwardMapping(MappingSource source, String address) throws RecipientRewriteTableException {
Mapping mapping = Mapping.forward(address)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,18 @@

public class ForwardDestinationResponse {
private final String mailAddress;
private final String comment;

public ForwardDestinationResponse(String mailAddress) {
public ForwardDestinationResponse(String mailAddress, String comment) {
this.mailAddress = mailAddress;
this.comment = comment;
}

public String getMailAddress() {
return mailAddress;
}

public String getComment() {
return comment;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
import static org.apache.james.webadmin.Constants.SEPARATOR;
import static spark.Spark.halt;

import java.util.Comparator;
import java.util.List;
import java.util.Optional;

import jakarta.inject.Inject;

Expand Down Expand Up @@ -110,13 +112,14 @@ public HaltException addToForwardDestinations(Request request, Response response
ensureUserExist(forwardBaseAddress);
MailAddress destinationAddress = MailAddressParser.parseMailAddress(request.params(FORWARD_DESTINATION_ADDRESS), FORWARD_DESTINATION_ADDRESS_TYPE);
MappingSource source = MappingSource.fromUser(Username.fromLocalPartWithDomain(forwardBaseAddress.getLocalPart(), forwardBaseAddress.getDomain()));
addForward(source, destinationAddress);
String comment = Optional.ofNullable(request.queryParams("comment")).orElse("");
addForward(source, destinationAddress, comment);
return halt(HttpStatus.NO_CONTENT_204);
}

private void addForward(MappingSource source, MailAddress destinationAddress) throws RecipientRewriteTableException {
private void addForward(MappingSource source, MailAddress destinationAddress, String comment) throws RecipientRewriteTableException {
try {
recipientRewriteTable.addForwardMapping(source, destinationAddress.asString());
recipientRewriteTable.addForwardMapping(source, destinationAddress.asString(), comment);
} catch (MappingAlreadyExistsException e) {
// ignore
} catch (SourceDomainIsNotInDomainListException e) {
Expand Down Expand Up @@ -160,12 +163,12 @@ public ImmutableSet<ForwardDestinationResponse> listForwardDestinations(Request
ensureNonEmptyMappings(mappings);

return mappings.asStream()
.map(mapping -> mapping.asMailAddress()
.orElseThrow(() -> new IllegalStateException(String.format("Can not compute address for mapping %s", mapping.asString()))))
.map(mapping -> new ForwardDestinationResponse(mapping.asMailAddress()
.map(MailAddress::asString)
.sorted()
.map(ForwardDestinationResponse::new)
.collect(ImmutableSet.toImmutableSet());
.orElseThrow(() -> new IllegalStateException(String.format("Can not compute address for mapping %s", mapping.asString()))),
mapping.getComment()))
.sorted(Comparator.comparing(ForwardDestinationResponse::getMailAddress))
.collect(ImmutableSet.toImmutableSet());
}

private void ensureNonEmptyMappings(Mappings mappings) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,21 @@ void putUserInForwardWithEncodedSlashShouldCreateForward() {
.body("mailAddress", hasItems(BOB));
}

@Test
void putShouldAllowComments() {
given()
.queryParam("comment", "automated%20operation")
.put(ALICE_WITH_ENCODED_SLASH + SEPARATOR + "targets" + SEPARATOR + BOB);

when()
.get(ALICE_WITH_ENCODED_SLASH)
.then()
.contentType(ContentType.JSON)
.statusCode(HttpStatus.OK_200)
.body("mailAddress", hasItems(BOB))
.body("comment", hasItems("automated operation"));
}

@Test
void putSameUserInForwardTwiceShouldBeIdempotent() {
with()
Expand Down