Skip to content

Commit

Permalink
JAMES-1644 Add guice injection in JMAP module
Browse files Browse the repository at this point in the history
git-svn-id: https://svn.apache.org/repos/asf/james/project/trunk@1719323 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
mbaechler committed Dec 11, 2015
1 parent c95449c commit af23766
Show file tree
Hide file tree
Showing 18 changed files with 136 additions and 50 deletions.
4 changes: 4 additions & 0 deletions server/container/cassandra-guice/pom.xml
Expand Up @@ -265,6 +265,10 @@
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
<artifactId>james-server-filesystem-api</artifactId> <artifactId>james-server-filesystem-api</artifactId>
</dependency> </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>james-server-jmap</artifactId>
</dependency>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
<artifactId>james-server-lifecycle-api</artifactId> <artifactId>james-server-lifecycle-api</artifactId>
Expand Down
@@ -0,0 +1,52 @@
/****************************************************************
* 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 java.util.concurrent.TimeUnit;

import org.apache.james.jmap.api.AccessTokenManager;
import org.apache.james.jmap.api.ContinuationTokenManager;
import org.apache.james.jmap.api.access.AccessTokenRepository;
import org.apache.james.jmap.crypto.AccessTokenManagerImpl;
import org.apache.james.jmap.crypto.JamesSignatureHandler;
import org.apache.james.jmap.crypto.SignatureHandler;
import org.apache.james.jmap.crypto.SignedContinuationTokenManager;
import org.apache.james.jmap.memory.access.MemoryAccessTokenRepository;
import org.apache.james.jmap.utils.DefaultZonedDateTimeProvider;
import org.apache.james.jmap.utils.ZonedDateTimeProvider;

import com.google.inject.AbstractModule;
import com.google.inject.name.Names;

public class JMAPCommonModule extends AbstractModule {

private static final long DEFAULT_TOKEN_EXPIRATION_IN_MS = TimeUnit.MILLISECONDS.convert(15, TimeUnit.MINUTES);

@Override
protected void configure() {
bind(SignatureHandler.class).to(JamesSignatureHandler.class);
bind(ZonedDateTimeProvider.class).to(DefaultZonedDateTimeProvider.class);
bind(ContinuationTokenManager.class).to(SignedContinuationTokenManager.class);

bindConstant().annotatedWith(Names.named(AccessTokenRepository.TOKEN_EXPIRATION_IN_MS)).to(DEFAULT_TOKEN_EXPIRATION_IN_MS);
bind(AccessTokenRepository.class).to(MemoryAccessTokenRepository.class);
bind(AccessTokenManager.class).to(AccessTokenManagerImpl.class);
}

}
Expand Up @@ -24,6 +24,8 @@


public interface AccessTokenRepository { public interface AccessTokenRepository {


String TOKEN_EXPIRATION_IN_MS = "tokenExpirationInMs";

void addToken(String username, AccessToken accessToken) throws AccessTokenAlreadyStored; void addToken(String username, AccessToken accessToken) throws AccessTokenAlreadyStored;


void removeToken(AccessToken accessToken); void removeToken(AccessToken accessToken);
Expand Down
Expand Up @@ -22,6 +22,7 @@
import java.util.Optional; import java.util.Optional;


import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;


import org.apache.commons.collections4.map.PassiveExpiringMap; import org.apache.commons.collections4.map.PassiveExpiringMap;
Expand All @@ -38,7 +39,7 @@ public class MemoryAccessTokenRepository implements AccessTokenRepository {
private final PassiveExpiringMap<AccessToken, String> tokensExpirationDates; private final PassiveExpiringMap<AccessToken, String> tokensExpirationDates;


@Inject @Inject
public MemoryAccessTokenRepository(long durationInMilliseconds) { public MemoryAccessTokenRepository(@Named(TOKEN_EXPIRATION_IN_MS) long durationInMilliseconds) {
tokensExpirationDates = new PassiveExpiringMap<>(durationInMilliseconds); tokensExpirationDates = new PassiveExpiringMap<>(durationInMilliseconds);
} }


Expand Down
Expand Up @@ -32,7 +32,7 @@ public class MemoryAccessTokenRepositoryTest {


private static final AccessToken TOKEN = AccessToken.generate(); private static final AccessToken TOKEN = AccessToken.generate();
private static final String USERNAME = "username"; private static final String USERNAME = "username";
private static final int TTL_IN_MS = 100; private static final long TTL_IN_MS = 100;


private MemoryAccessTokenRepository accessTokenRepository; private MemoryAccessTokenRepository accessTokenRepository;


Expand Down
5 changes: 5 additions & 0 deletions server/pom.xml
Expand Up @@ -537,6 +537,11 @@
<scope>test</scope> <scope>test</scope>
<type>test-jar</type> <type>test-jar</type>
</dependency> </dependency>
<dependency>
<groupId>org.apache.james</groupId>
<artifactId>james-server-jmap</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.james.protocols</groupId> <groupId>org.apache.james.protocols</groupId>
<artifactId>protocols-smtp</artifactId> <artifactId>protocols-smtp</artifactId>
Expand Down
Expand Up @@ -21,6 +21,7 @@
import java.io.IOException; import java.io.IOException;
import java.util.Optional; import java.util.Optional;


import javax.inject.Inject;
import javax.servlet.Filter; import javax.servlet.Filter;
import javax.servlet.FilterChain; import javax.servlet.FilterChain;
import javax.servlet.FilterConfig; import javax.servlet.FilterConfig;
Expand All @@ -37,6 +38,7 @@ public class AuthenticationFilter implements Filter {


private AccessTokenManager accessTokenManager; private AccessTokenManager accessTokenManager;


@Inject
public AuthenticationFilter(AccessTokenManager accessTokenManager) { public AuthenticationFilter(AccessTokenManager accessTokenManager) {
this.accessTokenManager = accessTokenManager; this.accessTokenManager = accessTokenManager;
} }
Expand Down
Expand Up @@ -21,6 +21,7 @@
import java.io.IOException; import java.io.IOException;


import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
Expand All @@ -45,6 +46,7 @@
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;


@Singleton
public class AuthenticationServlet extends HttpServlet { public class AuthenticationServlet extends HttpServlet {


public static final String JSON_CONTENT_TYPE = "application/json"; public static final String JSON_CONTENT_TYPE = "application/json";
Expand Down
Expand Up @@ -19,17 +19,22 @@


package org.apache.james.jmap.crypto; package org.apache.james.jmap.crypto;


import javax.inject.Inject;
import javax.inject.Singleton;

import org.apache.james.jmap.api.AccessTokenManager; import org.apache.james.jmap.api.AccessTokenManager;
import org.apache.james.jmap.api.access.AccessToken; import org.apache.james.jmap.api.access.AccessToken;
import org.apache.james.jmap.api.access.AccessTokenRepository; import org.apache.james.jmap.api.access.AccessTokenRepository;
import org.apache.james.jmap.api.access.exceptions.InvalidAccessToken; import org.apache.james.jmap.api.access.exceptions.InvalidAccessToken;


import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;


@Singleton
public class AccessTokenManagerImpl implements AccessTokenManager { public class AccessTokenManagerImpl implements AccessTokenManager {


private final AccessTokenRepository accessTokenRepository; private final AccessTokenRepository accessTokenRepository;


@Inject
public AccessTokenManagerImpl(AccessTokenRepository accessTokenRepository) { public AccessTokenManagerImpl(AccessTokenRepository accessTokenRepository) {
this.accessTokenRepository = accessTokenRepository; this.accessTokenRepository = accessTokenRepository;
} }
Expand Down
Expand Up @@ -29,6 +29,9 @@
import java.security.Signature; import java.security.Signature;
import java.security.SignatureException; import java.security.SignatureException;


import javax.inject.Inject;
import javax.inject.Singleton;

import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.commons.configuration.HierarchicalConfiguration;
Expand All @@ -37,9 +40,11 @@
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;


import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;


@Singleton
public class JamesSignatureHandler implements SignatureHandler, Configurable { public class JamesSignatureHandler implements SignatureHandler, Configurable {


private static final Logger LOGGER = LoggerFactory.getLogger(JamesSignatureHandler.class); private static final Logger LOGGER = LoggerFactory.getLogger(JamesSignatureHandler.class);
Expand All @@ -54,7 +59,8 @@ public class JamesSignatureHandler implements SignatureHandler, Configurable {
private PrivateKey privateKey; private PrivateKey privateKey;
private PublicKey publicKey; private PublicKey publicKey;


public JamesSignatureHandler(FileSystem fileSystem) { @Inject
@VisibleForTesting JamesSignatureHandler(FileSystem fileSystem) {
this.fileSystem = fileSystem; this.fileSystem = fileSystem;
} }


Expand All @@ -63,6 +69,7 @@ public void configure(HierarchicalConfiguration configuration) throws Configurat
secret = configuration.getString("tls.secret", ""); secret = configuration.getString("tls.secret", "");
} }


@Override
public void init() throws Exception { public void init() throws Exception {
KeyStore keystore = KeyStore.getInstance(JKS); KeyStore keystore = KeyStore.getInstance(JKS);
InputStream fis = fileSystem.getResource(keystoreURL); InputStream fis = fileSystem.getResource(keystoreURL);
Expand Down
Expand Up @@ -20,6 +20,8 @@
package org.apache.james.jmap.crypto; package org.apache.james.jmap.crypto;


public interface SignatureHandler { public interface SignatureHandler {

void init() throws Exception;


String sign(String source); String sign(String source);


Expand Down
Expand Up @@ -22,17 +22,22 @@
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;


import javax.inject.Inject;
import javax.inject.Singleton;

import org.apache.james.jmap.api.ContinuationTokenManager; import org.apache.james.jmap.api.ContinuationTokenManager;
import org.apache.james.jmap.model.ContinuationToken; import org.apache.james.jmap.model.ContinuationToken;
import org.apache.james.jmap.utils.ZonedDateTimeProvider; import org.apache.james.jmap.utils.ZonedDateTimeProvider;


import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;


@Singleton
public class SignedContinuationTokenManager implements ContinuationTokenManager { public class SignedContinuationTokenManager implements ContinuationTokenManager {


private final SignatureHandler signatureHandler; private final SignatureHandler signatureHandler;
private final ZonedDateTimeProvider zonedDateTimeProvider; private final ZonedDateTimeProvider zonedDateTimeProvider;


@Inject
public SignedContinuationTokenManager(SignatureHandler signatureHandler, ZonedDateTimeProvider zonedDateTimeProvider) { public SignedContinuationTokenManager(SignatureHandler signatureHandler, ZonedDateTimeProvider zonedDateTimeProvider) {
this.signatureHandler = signatureHandler; this.signatureHandler = signatureHandler;
this.zonedDateTimeProvider = zonedDateTimeProvider; this.zonedDateTimeProvider = zonedDateTimeProvider;
Expand All @@ -41,7 +46,7 @@ public SignedContinuationTokenManager(SignatureHandler signatureHandler, ZonedDa
@Override @Override
public ContinuationToken generateToken(String username) { public ContinuationToken generateToken(String username) {
Preconditions.checkNotNull(username); Preconditions.checkNotNull(username);
ZonedDateTime expirationTime = zonedDateTimeProvider.provide().plusMinutes(15); ZonedDateTime expirationTime = zonedDateTimeProvider.get().plusMinutes(15);
return new ContinuationToken(username, return new ContinuationToken(username,
expirationTime, expirationTime,
signatureHandler.sign(username + ContinuationToken.SEPARATOR + DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(expirationTime))); signatureHandler.sign(username + ContinuationToken.SEPARATOR + DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(expirationTime)));
Expand Down Expand Up @@ -70,6 +75,6 @@ private boolean isCorrectlySigned(ContinuationToken token) {
} }


private boolean isExpired(ContinuationToken token) { private boolean isExpired(ContinuationToken token) {
return token.getExpirationDate().isBefore(zonedDateTimeProvider.provide()); return token.getExpirationDate().isBefore(zonedDateTimeProvider.get());
} }
} }
Expand Up @@ -18,11 +18,12 @@
****************************************************************/ ****************************************************************/
package org.apache.james.jmap.model; package org.apache.james.jmap.model;


import org.apache.james.jmap.exceptions.MalformedContinuationTokenException;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import org.apache.james.jmap.exceptions.MalformedContinuationTokenException;


@JsonDeserialize(builder=AccessTokenRequest.Builder.class) @JsonDeserialize(builder = AccessTokenRequest.Builder.class)
public class AccessTokenRequest { public class AccessTokenRequest {


public static final String UNIQUE_JSON_PATH = "/token"; public static final String UNIQUE_JSON_PATH = "/token";
Expand Down
Expand Up @@ -25,7 +25,7 @@
public class DefaultZonedDateTimeProvider implements ZonedDateTimeProvider { public class DefaultZonedDateTimeProvider implements ZonedDateTimeProvider {


@Override @Override
public ZonedDateTime provide() { public ZonedDateTime get() {
return ZonedDateTime.now(ZoneOffset.UTC); return ZonedDateTime.now(ZoneOffset.UTC);
} }
} }
Expand Up @@ -21,8 +21,8 @@


import java.time.ZonedDateTime; import java.time.ZonedDateTime;


public interface ZonedDateTimeProvider { import javax.inject.Provider;


ZonedDateTime provide(); public interface ZonedDateTimeProvider extends Provider<ZonedDateTime> {


} }

0 comments on commit af23766

Please sign in to comment.