Skip to content

Commit

Permalink
Make using full domain path converter configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
j-hellenberg committed Dec 4, 2024
1 parent 6e325d8 commit 479aa7c
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Boolean. Optional, default to false. Whether full domain display is enabled for team mailboxes.
imap.teamMailbox.fullDomain.enabled=false
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public record PostgresTmailConfiguration(ConfigurationPath configurationPath, Ja
LinagoraServicesDiscoveryModuleChooserConfiguration linagoraServicesDiscoveryModuleChooserConfiguration,
boolean jmapEnabled,
boolean rlsEnabled,
boolean teamMailboxFullDomainEnabled,
PropertiesProvider propertiesProvider,
PostgresJamesConfiguration.EventBusImpl eventBusImpl) implements Configuration {
public static class Builder {
Expand All @@ -50,6 +51,7 @@ public static class Builder {
private Optional<LinagoraServicesDiscoveryModuleChooserConfiguration> linagoraServicesDiscoveryModuleChooserConfiguration;
private Optional<Boolean> jmapEnabled;
private Optional<Boolean> rlsEnabled;
private Optional<Boolean> teamMailboxFullDomainEnabled;
private Optional<PostgresJamesConfiguration.EventBusImpl> eventBusImpl;

private Builder() {
Expand All @@ -64,6 +66,7 @@ private Builder() {
linagoraServicesDiscoveryModuleChooserConfiguration = Optional.empty();
jmapEnabled = Optional.empty();
rlsEnabled = Optional.empty();
teamMailboxFullDomainEnabled = Optional.empty();
eventBusImpl = Optional.empty();
}

Expand Down Expand Up @@ -140,6 +143,11 @@ public Builder rlsEnabled(Optional<Boolean> rlsEnabled) {
return this;
}

public Builder teamMailboxFullDomainEnabled(Optional<Boolean> teamMailboxFullDomainEnabled) {
this.teamMailboxFullDomainEnabled = teamMailboxFullDomainEnabled;
return this;
}

public Builder eventBusImpl(PostgresJamesConfiguration.EventBusImpl eventBusImpl) {
this.eventBusImpl = Optional.of(eventBusImpl);
return this;
Expand Down Expand Up @@ -190,6 +198,16 @@ public PostgresTmailConfiguration build() {

boolean rlsEnabled = this.rlsEnabled.orElse(readRLSEnabledFromFile(propertiesProvider));

boolean teamMailboxFullDomainEnabled = this.teamMailboxFullDomainEnabled.orElseGet(() -> {
try {
return propertiesProvider.getConfiguration("imap").getBoolean("imap.teamMailbox.fullDomain.enabled");
} catch (FileNotFoundException e) {
return false;
} catch (ConfigurationException e) {
throw new RuntimeException(e);
}
});

PostgresJamesConfiguration.EventBusImpl eventBusImpl = this.eventBusImpl.orElseGet(() -> PostgresJamesConfiguration.EventBusImpl.from(propertiesProvider));

return new PostgresTmailConfiguration(
Expand All @@ -204,6 +222,7 @@ public PostgresTmailConfiguration build() {
servicesDiscoveryModuleChooserConfiguration,
jmapEnabled,
rlsEnabled,
teamMailboxFullDomainEnabled,
propertiesProvider,
eventBusImpl);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.Set;
import java.util.function.Function;

import com.linagora.tmail.imap.TMailCrossDomainIMAPModule;
import org.apache.commons.lang3.NotImplementedException;
import org.apache.james.ExtraProperties;
import org.apache.james.GuiceJamesServer;
Expand Down Expand Up @@ -307,7 +308,7 @@ public static GuiceJamesServer createServer(PostgresTmailConfiguration configura
new PostgresTicketStoreModule(),
new TasksHeathCheckModule(),
chooseEventBusModules(configuration),
new TMailIMAPModule());
chooseIMAPModule(configuration));

private static final Module SCANNING_QUOTA_SEARCH_MODULE = new AbstractModule() {
@Override
Expand Down Expand Up @@ -413,6 +414,14 @@ public static Module chooseJmapEventBusModule(PostgresTmailConfiguration configu
return Modules.EMPTY_MODULE;
}

public static Module chooseIMAPModule(PostgresTmailConfiguration configuration) {
if (configuration.teamMailboxFullDomainEnabled()) {
return new TMailCrossDomainIMAPModule();
} else {
return new TMailIMAPModule();
}
}

private static List<Module> chooseFirebase(FirebaseModuleChooserConfiguration moduleChooserConfiguration) {
if (moduleChooserConfiguration.enable()) {
return List.of(new PostgresFirebaseRepositoryModule(), new FirebaseCommonModule());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.linagora.tmail.imap;

import com.google.inject.AbstractModule;
import com.google.inject.Scopes;
import org.apache.james.imap.main.PathConverter;
import org.apache.james.imap.processor.NamespaceSupplier;

public class TMailCrossDomainIMAPModule extends AbstractModule {

@Override
protected void configure() {
bind(NamespaceSupplier.class).to(TMailNamespaceSupplier.class).in(Scopes.SINGLETON);
bind(PathConverter.Factory.class).to(TMailCrossDomainPathConverter.Factory.class).in(Scopes.SINGLETON);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.linagora.tmail.imap;

import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.linagora.tmail.team.TeamMailbox;
import com.linagora.tmail.team.TeamMailboxNameSpace;
import org.apache.commons.lang3.StringUtils;
import org.apache.james.core.Domain;
import org.apache.james.core.Username;
import org.apache.james.imap.api.display.ModifiedUtf7;
import org.apache.james.imap.api.process.ImapSession;
import org.apache.james.imap.main.PathConverter;
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.mailbox.model.MailboxPath;
import org.apache.james.mailbox.model.search.MailboxQuery;
import org.apache.james.mailbox.model.search.PrefixedRegex;
import org.apache.james.mailbox.model.search.Wildcard;

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

public class TMailCrossDomainPathConverter extends TMailPathConverter implements PathConverter {

public static class Factory implements PathConverter.Factory {
public TMailCrossDomainPathConverter forSession(ImapSession session) {
return new TMailCrossDomainPathConverter(session.getMailboxSession());
}

public TMailCrossDomainPathConverter forSession(MailboxSession session) {
return new TMailCrossDomainPathConverter(session);
}
}

private TMailCrossDomainPathConverter(MailboxSession mailboxSession) {
super(mailboxSession);
}

public Optional<String> mailboxName(boolean relative, MailboxPath path, MailboxSession session) {
// TODO: thunderbird zombie folders :(
// https://bugzilla.mozilla.org/show_bug.cgi?id=544883
if (path.getNamespace().equalsIgnoreCase(TeamMailboxNameSpace.TEAM_MAILBOX_NAMESPACE())) {
// FIXME: hacky implementation
// Convert local path like MailboxPath(#Teammailbox, team-mailbox@<domain>, <teamXXX>/<folder>)
// to external representation like #TeamMailbox/<teamXXX>@<domain>/<folder>
List<String> mailboxNameParts = Splitter.on(session.getPathDelimiter()).splitToList(path.getName());
String rest = Joiner.on(mailboxSession.getPathDelimiter()).join(Iterables.skip(mailboxNameParts, 1));
if (!rest.isEmpty()) {
rest = mailboxSession.getPathDelimiter() + rest;
}
Optional<String> res = Optional.of(path.getNamespace() + session.getPathDelimiter() + mailboxNameParts.getFirst()
+ "@" + path.getUser().getDomainPart().map(Domain::asString).orElse("local").replace(String.valueOf(session.getPathDelimiter()), "__")
+ rest);
return res;
} else {
return defaultpathConverter.mailboxName(relative, path, session);
}
}

protected MailboxPath getTeamMailboxPath(String absolutePath) {
// FIXME: hacky implementation
// Convert absolute path like #TeamMailbox/<teamXXX>@<domain>/<folder> to local representation
// MailboxPath(#Teammailbox, team-mailbox@<domain>, <teamXXX>/<folder>)

List<String> mailboxPathParts = Splitter.on(mailboxSession.getPathDelimiter()).splitToList(absolutePath);
String mailboxName = Joiner.on(mailboxSession.getPathDelimiter()).join(Iterables.skip(mailboxPathParts, 1));
List<String> mailboxNameParts = Splitter.on("@").splitToList(mailboxName);
if (mailboxNameParts.size() < 2) {
return new MailboxPath(TeamMailboxNameSpace.TEAM_MAILBOX_NAMESPACE(), null, mailboxNameParts.getFirst());
}

List<String> mailboxNameParts2 = Splitter.on(mailboxSession.getPathDelimiter()).splitToList(mailboxNameParts.get(1));
String rest = Joiner.on(mailboxSession.getPathDelimiter()).join(Iterables.skip(mailboxNameParts2, 1));
if (!rest.isEmpty()) {
rest = mailboxSession.getPathDelimiter() + rest;
}
MailboxPath res = new MailboxPath(TeamMailboxNameSpace.TEAM_MAILBOX_NAMESPACE(), teamMailboxUsername(mailboxNameParts2.getFirst().replace("__", String.valueOf(mailboxSession.getPathDelimiter()))), mailboxNameParts.getFirst() + rest);
return res;
}

protected Username teamMailboxUsername(String domain) {
return Username.from(TeamMailbox.TEAM_MAILBOX_LOCAL_PART(), Optional.of(domain));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ public TMailPathConverter forSession(MailboxSession session) {
}
}

private final MailboxSession mailboxSession;
private final PathConverter defaultpathConverter;
protected final MailboxSession mailboxSession;
protected final PathConverter defaultpathConverter;

private TMailPathConverter(MailboxSession mailboxSession) {
protected TMailPathConverter(MailboxSession mailboxSession) {
this.mailboxSession = mailboxSession;
this.defaultpathConverter = PathConverter.Factory.DEFAULT.forSession(mailboxSession);
}
Expand All @@ -50,20 +50,8 @@ public MailboxPath buildFullPath(String mailboxName) {
}

public Optional<String> mailboxName(boolean relative, MailboxPath path, MailboxSession session) {

if (path.getNamespace().equalsIgnoreCase(TeamMailboxNameSpace.TEAM_MAILBOX_NAMESPACE())) {
// FIXME: hacky implementation
// Convert local path like MailboxPath(#Teammailbox, team-mailbox@<domain>, <teamXXX>/<folder>)
// to external representation like #TeamMailbox/<teamXXX>@<domain>/<folder>
List<String> mailboxNameParts = Splitter.on(session.getPathDelimiter()).splitToList(path.getName());
String rest = Joiner.on(mailboxSession.getPathDelimiter()).join(Iterables.skip(mailboxNameParts, 1));
if (!rest.isEmpty()) {
rest = mailboxSession.getPathDelimiter() + rest;
}
Optional<String> res = Optional.of(path.getNamespace() + session.getPathDelimiter() + mailboxNameParts.getFirst()
+ "@" + path.getUser().getDomainPart().map(Domain::asString).orElse("local").replace(String.valueOf(session.getPathDelimiter()), "__")
+ rest);
return res;
return Optional.of(path.getNamespace() + session.getPathDelimiter() + path.getName());
} else {
return defaultpathConverter.mailboxName(relative, path, session);
}
Expand Down Expand Up @@ -104,28 +92,13 @@ public MailboxQuery mailboxQuery(String finalReferencename, String mailboxName,
return defaultpathConverter.mailboxQuery(finalReferencename, mailboxName, session);
}

private MailboxPath getTeamMailboxPath(String absolutePath) {
// FIXME: hacky implementation
// Convert absolute path like #TeamMailbox/<teamXXX>@<domain>/<folder> to local representation
// MailboxPath(#Teammailbox, team-mailbox@<domain>, <teamXXX>/<folder>)

protected MailboxPath getTeamMailboxPath(String absolutePath) {
List<String> mailboxPathParts = Splitter.on(mailboxSession.getPathDelimiter()).splitToList(absolutePath);
String mailboxName = Joiner.on(mailboxSession.getPathDelimiter()).join(Iterables.skip(mailboxPathParts, 1));
List<String> mailboxNameParts = Splitter.on("@").splitToList(mailboxName);
if (mailboxNameParts.size() < 2) {
return new MailboxPath(TeamMailboxNameSpace.TEAM_MAILBOX_NAMESPACE(), null, mailboxNameParts.getFirst());
}

List<String> mailboxNameParts2 = Splitter.on(mailboxSession.getPathDelimiter()).splitToList(mailboxNameParts.get(1));
String rest = Joiner.on(mailboxSession.getPathDelimiter()).join(Iterables.skip(mailboxNameParts2, 1));
if (!rest.isEmpty()) {
rest = mailboxSession.getPathDelimiter() + rest;
}
MailboxPath res = new MailboxPath(TeamMailboxNameSpace.TEAM_MAILBOX_NAMESPACE(), teamMailboxUsername(mailboxNameParts2.getFirst().replace("__", String.valueOf(mailboxSession.getPathDelimiter()))), mailboxNameParts.getFirst() + rest);
return res;
return new MailboxPath(TeamMailboxNameSpace.TEAM_MAILBOX_NAMESPACE(), teamMailboxUsername(mailboxSession), mailboxName);
}

private Username teamMailboxUsername(String domain) {
return Username.from(TeamMailbox.TEAM_MAILBOX_LOCAL_PART(), Optional.of(domain));
protected Username teamMailboxUsername(MailboxSession mailboxSession) {
return Username.from(TeamMailbox.TEAM_MAILBOX_LOCAL_PART(), mailboxSession.getUser().getDomainPart().map(Domain::asString));
}
}

0 comments on commit 479aa7c

Please sign in to comment.