diff --git a/pom.xml b/pom.xml
index 931932d99b791fcc5d6fdd0c41750a512b2b2d04..7a41f5d74bc1599557bcc375794b4a8ce12f2456 100644
--- a/pom.xml
+++ b/pom.xml
@@ -165,6 +165,11 @@
3.4.0
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
diff --git a/src/main/java/biz/nynja/account/StartupScriptsListener.java b/src/main/java/biz/nynja/account/StartupScriptsListener.java
index 4dcf578dae24fd8e7e8a238d8038603141dfc154..ca66b8792a2d8424d27993222867d2dd03e11b77 100644
--- a/src/main/java/biz/nynja/account/StartupScriptsListener.java
+++ b/src/main/java/biz/nynja/account/StartupScriptsListener.java
@@ -9,6 +9,7 @@ import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@@ -16,11 +17,9 @@ import org.springframework.stereotype.Component;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.exceptions.InvalidQueryException;
-import biz.nynja.account.configuration.CassandraConfig;
import biz.nynja.account.repositories.AccountRepositoryAdditional;
-
/**
- * This acts as {@link CassandraConfig} startupScripts executor but activated after the spring has setup the needed
+ * This acts as {@link CassandraAccountConfig} startupScripts executor but activated after the spring has setup the needed
* tables though JPA
*
* @author dragomir.todorov
@@ -33,6 +32,7 @@ public class StartupScriptsListener {
private String keyspace;
@Autowired
+ @Qualifier("accountSession")
private Session session;
@Autowired
diff --git a/src/main/java/biz/nynja/account/accesspoints/AccessPoint.java b/src/main/java/biz/nynja/account/accesspoints/AccessPoint.java
new file mode 100644
index 0000000000000000000000000000000000000000..978d6e18398521800bd5a706400663827dc62a9b
--- /dev/null
+++ b/src/main/java/biz/nynja/account/accesspoints/AccessPoint.java
@@ -0,0 +1,126 @@
+/**
+ * Copyright (C) 2018 Nynja Inc. All rights reserved.
+ */
+package biz.nynja.account.accesspoints;
+
+
+import java.io.Serializable;
+import java.util.UUID;
+
+import org.springframework.data.cassandra.core.cql.PrimaryKeyType;
+import org.springframework.data.cassandra.core.mapping.PrimaryKeyColumn;
+import org.springframework.data.cassandra.core.mapping.Table;
+
+@Table
+public class AccessPoint implements Serializable {
+
+ @PrimaryKeyColumn(ordinal = 0, type = PrimaryKeyType.PARTITIONED)
+ private UUID accountId;
+ @PrimaryKeyColumn(ordinal = 1, type = PrimaryKeyType.CLUSTERED)
+ private String accessToken;
+ private String deviceId;
+ private Long creationTimestamp;
+ private Long expirationTimestamp;
+
+ public String getDeviceId() {
+ return deviceId;
+ }
+
+ public void setDeviceId(String deviceId) {
+ this.deviceId = deviceId;
+ }
+
+ public UUID getAccountId() {
+ return accountId;
+ }
+
+ public void setAccountId(UUID accountId) {
+ this.accountId = accountId;
+ }
+
+ public String getAccessToken() {
+ return accessToken;
+ }
+
+ public void setAccessToken(String accessToken) {
+ this.accessToken = accessToken;
+ }
+
+ public Long getCreationTimestamp() {
+ return creationTimestamp;
+ }
+
+ public void setCreationTimestamp(Long creationTimestamp) {
+ this.creationTimestamp = creationTimestamp;
+ }
+
+ public Long getExpirationTimestamp() {
+ return expirationTimestamp;
+ }
+
+ public void setExpirationTimestamp(Long expirationTimestamp) {
+ this.expirationTimestamp = expirationTimestamp;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((deviceId == null) ? 0 : deviceId.hashCode());
+ result = prime * result + ((accountId == null) ? 0 : accountId.hashCode());
+ result = prime * result + ((accessToken == null) ? 0 : accessToken.hashCode());
+ result = prime * result + ((creationTimestamp == null) ? 0 : creationTimestamp.hashCode());
+ result = prime * result + ((expirationTimestamp == null) ? 0 : expirationTimestamp.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ AccessPoint other = (AccessPoint) obj;
+ if (deviceId == null) {
+ if (other.deviceId != null)
+ return false;
+ } else if (!deviceId.equals(other.deviceId))
+ return false;
+ if (accountId == null) {
+ if (other.accountId != null)
+ return false;
+ } else if (!accountId.equals(other.accountId))
+ return false;
+ if (accessToken == null) {
+ if (other.accessToken != null)
+ return false;
+ } else if (!accessToken.equals(other.accessToken))
+ return false;
+ if (creationTimestamp == null) {
+ if (other.creationTimestamp != null)
+ return false;
+ } else if (!creationTimestamp.equals(other.creationTimestamp))
+ return false;
+ if (expirationTimestamp == null) {
+ if (other.expirationTimestamp != null)
+ return false;
+ } else if (!expirationTimestamp.equals(other.expirationTimestamp))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("AccessPoint [accountId=").append(accountId)
+ .append(", deviceId=").append(deviceId)
+ .append(", accessToken=").append(accessToken)
+ .append(", creationTimestamp=").append(creationTimestamp)
+ .append(", expirationTimestamp=").append(expirationTimestamp)
+ .append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/src/main/java/biz/nynja/account/accesspoints/AccessPointRepository.java b/src/main/java/biz/nynja/account/accesspoints/AccessPointRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..6888c6df5cea70596cc543c8bdda533c5ef1b7bc
--- /dev/null
+++ b/src/main/java/biz/nynja/account/accesspoints/AccessPointRepository.java
@@ -0,0 +1,17 @@
+/**
+ * Copyright (C) 2018 Nynja Inc. All rights reserved.
+ */
+package biz.nynja.account.accesspoints;
+
+import java.util.UUID;
+
+import org.springframework.data.cassandra.repository.CassandraRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface AccessPointRepository
+ extends CassandraRepository {
+
+ AccessPoint findByAccountIdAndAccessToken(UUID accountId, String accessToken);
+
+}
diff --git a/src/main/java/biz/nynja/account/accesspoints/AccessPointService.java b/src/main/java/biz/nynja/account/accesspoints/AccessPointService.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca24bd22e1bb812ec898871c76dd9cdd1d7793ae
--- /dev/null
+++ b/src/main/java/biz/nynja/account/accesspoints/AccessPointService.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright (C) 2018 Nynja Inc. All rights reserved.
+ */
+package biz.nynja.account.accesspoints;
+
+import java.util.Date;
+import java.util.Optional;
+import java.util.UUID;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+@Service
+public class AccessPointService {
+ private final Logger logger = LoggerFactory.getLogger(AccessPointService.class);
+ private AccessPointRepository accessPointRepository;
+
+ public AccessPointService(AccessPointRepository accessPointRepository) {
+ this.accessPointRepository = accessPointRepository;
+ }
+
+ public Optional getAccessPoint(UUID accountId, String accessToken) {
+ AccessPoint accessPoint = accessPointRepository.findByAccountIdAndAccessToken(accountId, accessToken);
+ if (accessPoint != null) {
+ return Optional.of(accessPoint);
+ }
+ return Optional.empty();
+ }
+
+ public AccessPoint buildAccessPoint(String deviceId, String accessToken, String accountId, long expiresIn) {
+ AccessPoint accessPoint = new AccessPoint();
+ accessPoint.setDeviceId(deviceId);
+ accessPoint.setAccountId(UUID.fromString(accountId));
+ accessPoint.setAccessToken(accessToken);
+ accessPoint.setCreationTimestamp(new Date().getTime());
+ accessPoint.setExpirationTimestamp(new Date().getTime() + expiresIn);
+ return accessPoint;
+ }
+
+}
diff --git a/src/main/java/biz/nynja/account/components/PreparedStatementsCache.java b/src/main/java/biz/nynja/account/components/PreparedStatementsCache.java
index 91b9b32575dc5804591380f851ee8366510e02e4..20be301ffa8a81bd42aaea6160e46f4d00a1885e 100644
--- a/src/main/java/biz/nynja/account/components/PreparedStatementsCache.java
+++ b/src/main/java/biz/nynja/account/components/PreparedStatementsCache.java
@@ -18,20 +18,20 @@ import com.datastax.driver.core.UDTValue;
import com.datastax.driver.core.UserType;
import biz.nynja.account.codecs.AuthenticationProviderCodec;
-import biz.nynja.account.configuration.CassandraConfig;
+import biz.nynja.account.configuration.CassandraAccountConfig;
import biz.nynja.account.models.AuthenticationProvider;
@Configuration
public class PreparedStatementsCache {
- private final CassandraConfig cassandraConfig;
+ private final CassandraAccountConfig cassandraConfig;
private final Session session;
private static Map statementsCache;
@Autowired
- public PreparedStatementsCache(Session session, CassandraConfig cassandraConfig) {
+ public PreparedStatementsCache(Session session, CassandraAccountConfig cassandraConfig) {
this.session = session;
this.cassandraConfig = cassandraConfig;
}
diff --git a/src/main/java/biz/nynja/account/configuration/CassandraAccessPointConfig.java b/src/main/java/biz/nynja/account/configuration/CassandraAccessPointConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..1b5472a3d35cd828b6d560900e30f381ce2f7a43
--- /dev/null
+++ b/src/main/java/biz/nynja/account/configuration/CassandraAccessPointConfig.java
@@ -0,0 +1,92 @@
+package biz.nynja.account.configuration;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.data.cassandra.config.CassandraClusterFactoryBean;
+import org.springframework.data.cassandra.config.CassandraSessionFactoryBean;
+import org.springframework.data.cassandra.core.CassandraAdminOperations;
+import org.springframework.data.cassandra.core.CassandraAdminTemplate;
+import org.springframework.data.cassandra.core.cql.keyspace.CreateKeyspaceSpecification;
+import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
+import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
+
+import biz.nynja.account.StartupScriptsListener;
+
+@Configuration
+@ConfigurationProperties("spring.data.cassandra.accesspoint")
+@EnableCassandraRepositories(
+ basePackages = { "biz.nynja.account.accesspoints" },
+ cassandraTemplateRef = "CassandraAccessPointTemplate")
+@ConditionalOnMissingClass("org.springframework.test.context.junit4.SpringRunner")
+public class CassandraAccessPointConfig extends CassandraBaseConfig {
+
+ @Value("${spring.data.cassandra.accesspoint.keyspace-name}")
+ protected String keyspaceName;
+
+ @Override
+ protected String getKeyspaceName() {
+ return keyspaceName;
+ }
+
+ public void setKeyspaceName(String keyspaceName) {
+ this.keyspaceName = keyspaceName;
+ }
+
+ @Bean
+ public CassandraMappingContext mappingContext() {
+ return new CassandraMappingContext();
+ }
+
+ @Override
+ public String[] getEntityBasePackages() {
+ return new String[] { "biz.nynja.account.accesspoints" };
+ }
+
+ @Override
+ @Primary
+ @Bean(name = "CassandraAccessPointTemplate")
+ public CassandraAdminOperations cassandraTemplate() throws Exception {
+ return new CassandraAdminTemplate(session().getObject(), cassandraConverter());
+ }
+
+ @Override
+ @Bean(name = "accessPointSession")
+ public CassandraSessionFactoryBean session() {
+
+ CassandraSessionFactoryBean session = new CassandraSessionFactoryBean();
+
+ session.setCluster(cluster().getObject());
+ session.setConverter(cassandraConverter());
+ session.setKeyspaceName(getKeyspaceName());
+ session.setSchemaAction(getSchemaAction());
+ session.setStartupScripts(getStartupScripts());
+ session.setShutdownScripts(getShutdownScripts());
+
+ return session;
+ }
+
+ @Override
+ protected List getKeyspaceCreations() {
+ CreateKeyspaceSpecification specification = CreateKeyspaceSpecification.createKeyspace(getKeyspaceName())
+ .ifNotExists().withSimpleReplication();
+ return Arrays.asList(specification);
+ }
+
+ @Bean
+ public CassandraClusterFactoryBean cluster() {
+ CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
+ cluster.setContactPoints(getContactPoints());
+ cluster.setPort(getPort());
+ cluster.setKeyspaceCreations(getKeyspaceCreations());
+
+ return cluster;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/biz/nynja/account/configuration/CassandraAccountConfig.java b/src/main/java/biz/nynja/account/configuration/CassandraAccountConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..311fa8d4d258eddd6b69566d0083cf960f2adf46
--- /dev/null
+++ b/src/main/java/biz/nynja/account/configuration/CassandraAccountConfig.java
@@ -0,0 +1,103 @@
+package biz.nynja.account.configuration;
+
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.cassandra.config.CassandraClusterFactoryBean;
+import org.springframework.data.cassandra.config.CassandraSessionFactoryBean;
+import org.springframework.data.cassandra.core.CassandraAdminOperations;
+import org.springframework.data.cassandra.core.CassandraAdminTemplate;
+import org.springframework.data.cassandra.core.cql.keyspace.CreateKeyspaceSpecification;
+import org.springframework.data.cassandra.core.mapping.CassandraMappingContext;
+import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
+
+import biz.nynja.account.StartupScriptsListener;
+
+@Configuration
+@ConfigurationProperties("spring.data.cassandra.account")
+@EnableCassandraRepositories(
+ basePackages = { "biz.nynja.account.models", "biz.nynja.account.repositories"},
+ cassandraTemplateRef = "CassandraAccountTemplate")
+@ConditionalOnMissingClass("org.springframework.test.context.junit4.SpringRunner")
+public class CassandraAccountConfig extends CassandraBaseConfig {
+
+ @Value("${spring.data.cassandra.account.keyspace-name}")
+ protected String keyspaceName;
+
+ @Override
+ protected String getKeyspaceName() {
+ return keyspaceName;
+ }
+
+ public void setKeyspaceName(String keyspaceName) {
+ this.keyspaceName = keyspaceName;
+ }
+
+ @Bean
+ public CassandraMappingContext mappingContext() {
+ return new CassandraMappingContext();
+ }
+
+ @Override
+ public String[] getEntityBasePackages() {
+ return new String[] { "biz.nynja.account.models", "biz.nynja.account.repositories" };
+ }
+
+ @Override
+ @Bean(name = "CassandraAccountTemplate")
+ public CassandraAdminOperations cassandraTemplate(
+ @Qualifier("accountSession") final CassandraSessionFactoryBean session) throws Exception {
+ return new CassandraAdminTemplate(session().getObject(), cassandraConverter());
+ }
+
+ @Override
+ @Bean(name = "accountSession")
+ public CassandraSessionFactoryBean session() {
+
+ CassandraSessionFactoryBean session = new CassandraSessionFactoryBean();
+
+ session.setCluster(cluster().getObject());
+ session.setConverter(cassandraConverter());
+ session.setKeyspaceName(getKeyspaceName());
+ session.setSchemaAction(getSchemaAction());
+ session.setStartupScripts(getStartupScripts());
+ session.setShutdownScripts(getShutdownScripts());
+
+ return session;
+ }
+
+ @Override
+ protected List getKeyspaceCreations() {
+ CreateKeyspaceSpecification specification = CreateKeyspaceSpecification.createKeyspace(getKeyspaceName())
+ .ifNotExists().withSimpleReplication();
+ return Arrays.asList(specification);
+ }
+
+ @Bean
+ public CassandraClusterFactoryBean cluster() {
+ CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
+ cluster.setContactPoints(getContactPoints());
+// cluster.setContactPoints(InetAddress.getLocalHost().getHostName());
+ cluster.setPort(getPort());
+ cluster.setKeyspaceCreations(getKeyspaceCreations());
+
+ return cluster;
+ }
+
+ /**
+ * See {@link StartupScriptsListener} for scripts
+ * that require JPA annotated tables
+ */
+ @Override
+ protected List getStartupScripts() {
+ return super.getStartupScripts();
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/biz/nynja/account/configuration/CassandraConfig.java b/src/main/java/biz/nynja/account/configuration/CassandraBaseConfig.java
similarity index 52%
rename from src/main/java/biz/nynja/account/configuration/CassandraConfig.java
rename to src/main/java/biz/nynja/account/configuration/CassandraBaseConfig.java
index 739d5063f39b8523254bf50a494cdee7e90b7e96..873dae4af0abd918a9f1fe9b874d68bbb161bf56 100644
--- a/src/main/java/biz/nynja/account/configuration/CassandraConfig.java
+++ b/src/main/java/biz/nynja/account/configuration/CassandraBaseConfig.java
@@ -1,77 +1,66 @@
-/**
- * Copyright (C) 2018 Nynja Inc. All rights reserved.
- */
-package biz.nynja.account.configuration;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.data.cassandra.config.AbstractCassandraConfiguration;
-import org.springframework.data.cassandra.config.SchemaAction;
-import org.springframework.data.cassandra.core.cql.keyspace.CreateKeyspaceSpecification;
-import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
-
-import biz.nynja.account.StartupScriptsListener;
-
-@Configuration
-@EnableCassandraRepositories
-@ConditionalOnMissingClass("org.springframework.test.context.junit4.SpringRunner")
-public class CassandraConfig extends AbstractCassandraConfiguration {
-
- @Value("${spring.data.cassandra.keyspace-name}")
- private String keyspace;
-
- @Override
- protected String getKeyspaceName() {
- return keyspace;
- }
-
- @Value("${spring.data.cassandra.contact-points}")
- private String contactPoints;
-
- @Override
- protected String getContactPoints() {
- return contactPoints;
- }
-
- @Value("${spring.data.cassandra.port}")
- private int port;
-
- @Override
- protected int getPort() {
- return port;
- }
-
- @Override
- public SchemaAction getSchemaAction() {
- return SchemaAction.CREATE_IF_NOT_EXISTS;
- }
-
- @Override
- protected List getKeyspaceCreations() {
- CreateKeyspaceSpecification specification = CreateKeyspaceSpecification.createKeyspace(getKeyspaceName())
- .ifNotExists().withSimpleReplication();
- return Arrays.asList(specification);
- }
-
- @Override
- public String[] getEntityBasePackages() {
- return new String[] { "biz.nynja.account.models" };
- }
-
- /**
- * See {@link StartupScriptsListener} for scripts
- * that require JPA annotated tables
- */
- @Override
- protected List getStartupScripts() {
- return super.getStartupScripts();
- }
-
- public String getConfiguredKeyspaceName() {
- return getKeyspaceName();
- }
-}
+package biz.nynja.account.configuration;
+
+
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.cassandra.config.AbstractCassandraConfiguration;
+import org.springframework.data.cassandra.config.CassandraClusterFactoryBean;
+import org.springframework.data.cassandra.config.CassandraSessionFactoryBean;
+import org.springframework.data.cassandra.config.SchemaAction;
+import org.springframework.data.cassandra.core.CassandraAdminOperations;
+import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
+
+@Configuration
+@EnableCassandraRepositories
+@ConditionalOnMissingClass("org.springframework.test.context.junit4.SpringRunner")
+public abstract class CassandraBaseConfig extends AbstractCassandraConfiguration {
+
+ @Value("${spring.data.cassandra.contact-points}")
+ protected String contactPoints;
+
+ @Value("${spring.data.cassandra.port}")
+ protected int port;
+
+ @Override
+ protected String getContactPoints() {
+ return contactPoints;
+ }
+
+ public void setContactPoints(String contactPoints) {
+ this.contactPoints = contactPoints;
+ }
+
+ @Override
+ protected int getPort() {
+ return port;
+ }
+
+ protected int setPort() {
+ return port;
+ }
+
+ @Override
+ public SchemaAction getSchemaAction() {
+ return SchemaAction.CREATE_IF_NOT_EXISTS;
+ }
+
+ @Override
+ protected List getStartupScripts() {
+ return super.getStartupScripts();
+ }
+
+ public String getConfiguredKeyspaceName() {
+ return getKeyspaceName();
+ }
+
+ public CassandraAdminOperations cassandraTemplate(CassandraSessionFactoryBean session) throws Exception {
+ return null;
+ }
+
+
+}
diff --git a/src/main/java/biz/nynja/account/permissions/PermissionsInterceptor.java b/src/main/java/biz/nynja/account/permissions/PermissionsInterceptor.java
index 1fc1d1362e52e8e49827a30e84d78302742cabff..7a37de8e11b6aedf94ee692b6c545e67f03f8170 100644
--- a/src/main/java/biz/nynja/account/permissions/PermissionsInterceptor.java
+++ b/src/main/java/biz/nynja/account/permissions/PermissionsInterceptor.java
@@ -7,27 +7,36 @@ import static io.grpc.Metadata.ASCII_STRING_MARSHALLER;
import java.lang.reflect.Method;
import java.util.Base64;
+import java.util.Optional;
+import java.util.UUID;
import org.lognet.springboot.grpc.GRpcGlobalInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
import com.auth0.jwt.JWT;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import biz.nynja.account.services.AccountServiceImpl;
+import biz.nynja.account.accesspoints.AccessPointService;
+import biz.nynja.account.accesspoints.AccessPoint;
import io.grpc.Context;
+import io.grpc.Contexts;
import io.grpc.Metadata;
import io.grpc.ServerCall;
+import io.grpc.ServerCall.Listener;
import io.grpc.ServerCallHandler;
import io.grpc.ServerInterceptor;
+import io.grpc.Status;
/**
- * @author Stoyan.Tzenkov - account-service ServerInterceptor. Validates roles for granting permissions to
- * account-service endpoints(rpcs).
- * General rules:
+ * @author Stoyan.Tzenkov - account-service ServerInterceptor.
+ * Validates roles for granting permissions to account-service endpoints(rpcs).
+ * General rules:
* - if access token is not present - PERMISSION DENIED;
+ * - if no accesspoint found for the requesting account ID and access token - PERMISSION DENIED;
* - if no roles found in the access token - PERMISSION DENIED;
* - if rpc not found in the account-service class - PERMISSION DENIED;
* - if no Permitted annotation found for the rpc method - PERMISSION DENIED;
@@ -49,48 +58,59 @@ public class PermissionsInterceptor implements ServerInterceptor {
private static final ServerCall.Listener NOOP_LISTENER = new ServerCall.Listener() {
};
+ @Autowired
+ private AccessPointService accessPointService;
+
@Override
public ServerCall.Listener interceptCall(ServerCall call, Metadata headers,
ServerCallHandler next) {
// WARNING: THe line bellow is to be removed and code following uncommented
// when Istio starts sending an access token with each and every request
- return next.startCall(call, headers);
+ return next.startCall(call, headers);
/*
* Expected metadata is "Authorization" : "Bearer --accessTokenValue--" so we can skip validation as istio won't
* allow this request through
*/
- // String accessToken = (headers.get(ACCESS_TOKEN_METADATA).split(" "))[1];
- // String rpc = getRpcName(call);
- //
- // boolean permitted = false;
- // Context ctx = null;
- // String[] requestingRoles = null;
- //
- // if (accessToken != null) {
- // ctx = Context.current().withValue(ACCESS_TOKEN_CTX, accessToken);
- // requestingRoles = getRolesFromAccessToken(accessToken, rpc);
- //
- // if (requestingRoles != null) {
- // Method method = getMethod(rpc);
- //
- // if (method != null) {
- // Permitted[] permittedRoles = method.getAnnotationsByType(Permitted.class);
- // permitted = checkPermissions(requestingRoles, permittedRoles);
- // }
- // }
- // }
- //
- // if (permitted) {
- // logger.info("Permission granted to rpc {}.", rpc);
- // return Contexts.interceptCall(ctx, call, headers, next);
- // } else {
- // logger.error("Permission denied for rpc {}, roles {}.", rpc, requestingRoles);
- // call.close(Status.PERMISSION_DENIED.withDescription("An unauthorized call was made to " + rpc + "."),
- // headers);
- // return NOOP_LISTENER;
- // }
+// String accessToken = (headers.get(ACCESS_TOKEN_METADATA).split(" "))[1];
+// String rpc = getRpcName(call);
+//
+// boolean permitted = false;
+// Context ctx = null;
+// String[] requestingRoles = null;
+//
+// if (accessToken == null && accessToken.isEmpty()) {
+// permissionDenied(call, headers, "Permission denied for rpc {}. Access token not in headers", rpc );
+// }
+// ctx = Context.current().withValue(ACCESS_TOKEN_CTX, accessToken);
+// DecodedJWT decodedToken = JWT.decode(accessToken);
+//
+// if (!accessPointAvailable(accessToken, decodedToken, rpc)) {
+// permissionDenied(call, headers, "Permission denied for rpc {}. No access point available for this account and access token.", rpc );
+// }
+//
+// requestingRoles = getRolesFromAccessToken(decodedToken);
+// if (requestingRoles == null) {
+// permissionDenied(call, headers, "Permission denied for rpc {}. No roles found for requesting account in access token.", rpc );
+// }
+//
+// Method method = getMethod(rpc);
+// if (method == null) {
+// permissionDenied(call, headers, "Permission denied for rpc {}. Could not identify the method implementing this rpc.", rpc );
+// }
+//
+// Permitted[] permittedRoles = method.getAnnotationsByType(Permitted.class);
+// permitted = checkPermissions(requestingRoles, permittedRoles);
+// if (permitted) {
+// logger.info("Permission granted to rpc {}.", rpc);
+// return Contexts.interceptCall(ctx, call, headers, next);
+// } else {
+// logger.error("Permission denied for rpc {}, roles {}.", rpc, requestingRoles);
+// call.close(Status.PERMISSION_DENIED.withDescription("An unauthorized call was made to " + rpc + "."),
+// headers);
+// return NOOP_LISTENER;
+// }
}
private String getRpcName(ServerCall call) {
@@ -99,19 +119,22 @@ public class PermissionsInterceptor implements ServerInterceptor {
return callName.substring(callName.lastIndexOf('/') + 1);
}
- private String[] getRolesFromAccessToken(String accessToken, String rpc) {
+ private boolean accessPointAvailable(String accessToken, DecodedJWT decodedToken, String rpc) {
+
+ String accountId = new String(Base64.getDecoder().decode(decodedToken.getSubject()));
+ logger.info("Verifying permissions for rpc {} for user with account id {}.", rpc, accountId);
+
+ Optional accessPoint = accessPointService.getAccessPoint(UUID.fromString(accountId), accessToken);
+ return accessPoint.isPresent();
+ }
+
+ private String[] getRolesFromAccessToken(DecodedJWT decodedToken) {
// Get roles from access token
String[] requestingRoles = null;
- if (accessToken != null && !accessToken.isEmpty()) {
- DecodedJWT decodedToken = JWT.decode(accessToken);
- String requestingAccountId = new String(Base64.getDecoder().decode(decodedToken.getSubject()));
- logger.info("Verifying permissions for rpc {} for user with account id {}.", rpc, requestingAccountId);
-
- Claim claim = decodedToken.getClaim("roles");
- if (claim != null) {
- requestingRoles = claim.asArray(String.class);
- }
+ Claim claim = decodedToken.getClaim("roles");
+ if (claim != null) {
+ requestingRoles = claim.asArray(String.class);
}
return requestingRoles;
}
@@ -135,7 +158,7 @@ public class PermissionsInterceptor implements ServerInterceptor {
return true;
}
for (String role : requestingRoles) {
- if (role.equals(permitted.role()) || role.equals(RoleConstants.ADMIN)
+ if (role.equals(permitted.role()) || role.equals(RoleConstants.ACCOUNT_ADMIN)
|| role.equals(RoleConstants.AUTH_SERVICE)) {
return true;
}
@@ -144,4 +167,11 @@ public class PermissionsInterceptor implements ServerInterceptor {
return false;
}
+ private ServerCall.Listener permissionDenied(ServerCall call, Metadata headers, String message, String rpc ) {
+ logger.error(message, rpc);
+ call.close(Status.PERMISSION_DENIED.withDescription("An unauthorized call was made to " + rpc + "."),
+ headers);
+ return NOOP_LISTENER;
+ }
+
}
diff --git a/src/main/java/biz/nynja/account/permissions/PermissionsValidator.java b/src/main/java/biz/nynja/account/permissions/PermissionsValidator.java
index 10144e4859bd42fd0836047ff2ea6b86dac942ea..c213cab71771f05f1aac833e789a35445d75a1a2 100644
--- a/src/main/java/biz/nynja/account/permissions/PermissionsValidator.java
+++ b/src/main/java/biz/nynja/account/permissions/PermissionsValidator.java
@@ -68,7 +68,7 @@ public class PermissionsValidator {
private static boolean isAuthorized(String[] requestingRoles) {
for (String role : requestingRoles) {
switch (role) {
- case RoleConstants.ADMIN:
+ case RoleConstants.ACCOUNT_ADMIN:
case RoleConstants.AUTH_SERVICE:
return true;
}
diff --git a/src/main/java/biz/nynja/account/permissions/RoleConstants.java b/src/main/java/biz/nynja/account/permissions/RoleConstants.java
index 4a9b8d4afb5540b2c2bda5cbfa5f785f30a0ac0b..ff0185c051a1b68291a246e6b40a35ebaf6b8960 100644
--- a/src/main/java/biz/nynja/account/permissions/RoleConstants.java
+++ b/src/main/java/biz/nynja/account/permissions/RoleConstants.java
@@ -8,7 +8,7 @@ package biz.nynja.account.permissions;
*/
public class RoleConstants {
- public static final String ADMIN = "ADMIN";
+ public static final String ACCOUNT_ADMIN = "ACCOUNT_ADMIN";
public static final String USER = "USER";
public static final String ANY = "ANY";
public static final String AUTH_SERVICE = "AUTH_SERVICE";
diff --git a/src/main/java/biz/nynja/account/services/AccountServiceImpl.java b/src/main/java/biz/nynja/account/services/AccountServiceImpl.java
index 636d301a4192f30890e5d201a2867ab422540a0f..ae63d023c7b8016a3c5cd227aacd77527cceb196 100644
--- a/src/main/java/biz/nynja/account/services/AccountServiceImpl.java
+++ b/src/main/java/biz/nynja/account/services/AccountServiceImpl.java
@@ -11,6 +11,7 @@ import static biz.nynja.account.validation.Validators.util;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
+import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.lognet.springboot.grpc.GRpcService;
@@ -105,7 +106,8 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
AccountByQrCodeRepository accountByQrCodeRepository,
AccountByUsernameRepository accountByUsernameRepository, AccountProvider accountProvider,
AccountByProfileIdRepository accountByProfileIdRepository, PhoneNumberNormalizer phoneNumberNormalizer,
- AccountCreator accountCreator, ProfileProvider profileProvider, PermissionsValidator permissionsValidator) {
+ AccountCreator accountCreator, ProfileProvider profileProvider,
+ PermissionsValidator permissionsValidator) {
this.accountRepositoryAdditional = accountRepositoryAdditional;
this.profileRepository = profileRepository;
this.profileByAutheticationProviderRepository = profileByAutheticationProviderRepository;
@@ -121,7 +123,7 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
@Override
@PerformPermissionCheck
- @Permitted(role = RoleConstants.ADMIN)
+ @Permitted(role = RoleConstants.ACCOUNT_ADMIN)
@Permitted(role = RoleConstants.AUTH_SERVICE)
@Permitted(role = RoleConstants.USER)
public void getAccountByCreationProvider(AuthenticationProviderRequest request,
@@ -240,7 +242,7 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
@Override
@PerformPermissionCheck
- @Permitted(role = RoleConstants.ADMIN)
+ @Permitted(role = RoleConstants.ACCOUNT_ADMIN)
@Permitted(role = RoleConstants.USER)
public void getAccountByUsername(GetByUsernameRequest request, StreamObserver responseObserver) {
logger.info("Getting account by username: {}", request.getUsername());
@@ -325,7 +327,7 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
@Override
@PerformPermissionCheck
- @Permitted(role = RoleConstants.ADMIN)
+ @Permitted(role = RoleConstants.ACCOUNT_ADMIN)
@Permitted(role = RoleConstants.USER)
public void getAccountByQrCode(GetByQrCodeRequest request, StreamObserver responseObserver) {
logger.info("Search account by QR code: {}", request.getQrCode());
@@ -383,7 +385,7 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
}
@Override
- @Permitted(role = RoleConstants.ADMIN)
+ @Permitted(role = RoleConstants.ACCOUNT_ADMIN)
public void getAllAccountsByProfileId(AccountsByProfileIdRequest request,
StreamObserver responseObserver) {
logger.info("Getting accounts by profile id: {}", request.getProfileId());
@@ -413,7 +415,7 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
@Override
@PerformPermissionCheck
- @Permitted(role = RoleConstants.ADMIN)
+ @Permitted(role = RoleConstants.ACCOUNT_ADMIN)
@Permitted(role = RoleConstants.AUTH_SERVICE)
@Permitted(role = RoleConstants.USER)
public void getAccountByAccountId(AccountByAccountIdRequest request,
@@ -449,7 +451,7 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
}
@Override
- @Permitted(role = RoleConstants.ADMIN)
+ @Permitted(role = RoleConstants.ACCOUNT_ADMIN)
@Permitted(role = RoleConstants.AUTH_SERVICE)
@Permitted(role = RoleConstants.USER)
public void createPendingAccount(CreatePendingAccountRequest request,
@@ -479,7 +481,7 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
@Override
@PerformPermissionCheck
- @Permitted(role = RoleConstants.ADMIN)
+ @Permitted(role = RoleConstants.ACCOUNT_ADMIN)
@Permitted(role = RoleConstants.USER)
public void updateAccount(UpdateAccountRequest request, StreamObserver responseObserver) {
logger.info("Updating account...");
@@ -526,7 +528,7 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
@Override
@PerformPermissionCheck
- @Permitted(role = RoleConstants.ADMIN)
+ @Permitted(role = RoleConstants.ACCOUNT_ADMIN)
@Permitted(role = RoleConstants.USER)
public void deleteAccount(DeleteAccountRequest request, StreamObserver responseObserver) {
logger.debug("Deleting account...: {}", request);
@@ -563,7 +565,7 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
@Override
@PerformPermissionCheck
- @Permitted(role = RoleConstants.ADMIN)
+ @Permitted(role = RoleConstants.ACCOUNT_ADMIN)
@Permitted(role = RoleConstants.USER)
public void deleteProfile(DeleteProfileRequest request, StreamObserver responseObserver) {
logger.debug("Deleting profile: {}", request);
@@ -593,7 +595,7 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
@Override
@PerformPermissionCheck
- @Permitted(role = RoleConstants.ADMIN)
+ @Permitted(role = RoleConstants.ACCOUNT_ADMIN)
@Permitted(role = RoleConstants.AUTH_SERVICE)
@Permitted(role = RoleConstants.USER)
public void addAuthenticationProviderToProfile(AddAuthenticationProviderRequest request,
@@ -674,7 +676,7 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
@Override
@PerformPermissionCheck
- @Permitted(role = RoleConstants.ADMIN)
+ @Permitted(role = RoleConstants.ACCOUNT_ADMIN)
@Permitted(role = RoleConstants.USER)
public void addContactInfoToAccount(AddContactInfoRequest request,
StreamObserver responseObserver) {
@@ -727,7 +729,7 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
@Override
@PerformPermissionCheck
- @Permitted(role = RoleConstants.ADMIN)
+ @Permitted(role = RoleConstants.ACCOUNT_ADMIN)
@Permitted(role = RoleConstants.USER)
public void deleteContactInfoFromAccount(DeleteContactInfoRequest request,
StreamObserver responseObserver) {
@@ -770,7 +772,7 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
@Override
@PerformPermissionCheck
- @Permitted(role = RoleConstants.ADMIN)
+ @Permitted(role = RoleConstants.ACCOUNT_ADMIN)
@Permitted(role = RoleConstants.USER)
public void deleteAuthenticationProviderFromProfile(DeleteAuthenticationProviderRequest request,
StreamObserver responseObserver) {
@@ -877,7 +879,7 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
@Override
@PerformPermissionCheck
- @Permitted(role = RoleConstants.ADMIN)
+ @Permitted(role = RoleConstants.ACCOUNT_ADMIN)
@Permitted(role = RoleConstants.USER)
public void getProfileByProfileId(ProfileByProfileIdRequest request,
StreamObserver responseObserver) {
@@ -918,7 +920,7 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
@Override
@PerformPermissionCheck
- @Permitted(role = RoleConstants.ADMIN)
+ @Permitted(role = RoleConstants.ACCOUNT_ADMIN)
@Permitted(role = RoleConstants.USER)
public void editContactInfoForAccount(EditContactInfoRequest request,
StreamObserver responseObserver) {
@@ -998,7 +1000,7 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
@Override
@PerformPermissionCheck
- @Permitted(role = RoleConstants.ADMIN)
+ @Permitted(role = RoleConstants.ACCOUNT_ADMIN)
@Permitted(role = RoleConstants.AUTH_SERVICE)
@Permitted(role = RoleConstants.USER)
public void updateAuthenticationProviderForProfile(UpdateAuthenticationProviderRequest request,
@@ -1067,38 +1069,9 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
return;
}
- private static void logAndBuildGrpcAccountResponse(StreamObserver responseObserver,
- AccountResponse.Builder newBuilder, String logMessage, String logValue, Cause cause) {
-
- logger.error(logMessage, logValue);
- responseObserver.onNext(newBuilder.setError(ErrorResponse.newBuilder().setCause(cause)).build());
- responseObserver.onCompleted();
- }
-
- private static void logAndBuildGrpcAccountsResponse(StreamObserver responseObserver,
- AccountsResponse.Builder newBuilder, String logMessage, String logValue, Cause cause) {
- logger.error(logMessage, logValue);
- responseObserver.onNext(newBuilder.setError(ErrorResponse.newBuilder().setCause(cause)).build());
- responseObserver.onCompleted();
- }
-
- private static void logAndBuildGrpcProfileResponse(StreamObserver responseObserver,
- ProfileResponse.Builder newBuilder, String logMessage, String logValue, Cause cause) {
- logger.error(logMessage, logValue);
- responseObserver.onNext(newBuilder.setError(ErrorResponse.newBuilder().setCause(cause)).build());
- responseObserver.onCompleted();
- }
-
- private static void logAndBuildGrpcStatusResponse(StreamObserver responseObserver,
- StatusResponse.Builder newBuilder, String logMessage, String logValue, Cause cause) {
- logger.error(logMessage, logValue);
- responseObserver.onNext(newBuilder.setError(ErrorResponse.newBuilder().setCause(cause)).build());
- responseObserver.onCompleted();
- }
-
@Override
@PerformPermissionCheck
- @Permitted(role = RoleConstants.ADMIN)
+ @Permitted(role = RoleConstants.ACCOUNT_ADMIN)
@Permitted(role = RoleConstants.USER)
@Permitted(role = RoleConstants.AUTH_SERVICE)
public void getAccountByLoginOption(AuthenticationProviderRequest request,
@@ -1182,4 +1155,33 @@ public class AccountServiceImpl extends AccountServiceGrpc.AccountServiceImplBas
responseObserver.onCompleted();
}
+ private static void logAndBuildGrpcAccountResponse(StreamObserver responseObserver,
+ AccountResponse.Builder newBuilder, String logMessage, String logValue, Cause cause) {
+
+ logger.error(logMessage, logValue);
+ responseObserver.onNext(newBuilder.setError(ErrorResponse.newBuilder().setCause(cause)).build());
+ responseObserver.onCompleted();
+ }
+
+ private static void logAndBuildGrpcAccountsResponse(StreamObserver responseObserver,
+ AccountsResponse.Builder newBuilder, String logMessage, String logValue, Cause cause) {
+ logger.error(logMessage, logValue);
+ responseObserver.onNext(newBuilder.setError(ErrorResponse.newBuilder().setCause(cause)).build());
+ responseObserver.onCompleted();
+ }
+
+ private static void logAndBuildGrpcProfileResponse(StreamObserver responseObserver,
+ ProfileResponse.Builder newBuilder, String logMessage, String logValue, Cause cause) {
+ logger.error(logMessage, logValue);
+ responseObserver.onNext(newBuilder.setError(ErrorResponse.newBuilder().setCause(cause)).build());
+ responseObserver.onCompleted();
+ }
+
+ private static void logAndBuildGrpcStatusResponse(StreamObserver responseObserver,
+ StatusResponse.Builder newBuilder, String logMessage, String logValue, Cause cause) {
+ logger.error(logMessage, logValue);
+ responseObserver.onNext(newBuilder.setError(ErrorResponse.newBuilder().setCause(cause)).build());
+ responseObserver.onCompleted();
+ }
+
}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 5a241bc80df56519b99c9e210327f745986fec9f..5de0eb4131e96a65d07733a20701b83b0977a70c 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -10,9 +10,12 @@ grpc:
spring:
data:
cassandra:
- keyspace-name: account
contact-points: localhost
port: 9042
+ account:
+ keyspace-name: account
+ accesspoint:
+ keyspace-name: accesspoint
# To enable colors in Eclipse:
# spring.output.ansi.enabled=ALWAYS and in eclipse
# Help -> Install New Software... and click "Add..." to add the following URL:
diff --git a/src/test/java/biz/nynja/account/configurations/CassandraTestsConfig.java b/src/test/java/biz/nynja/account/configurations/CassandraTestsConfig.java
index f57d3f5524930b8cec693735cb13e539ac4b6f24..9a599b08b393effe79fb9019986c8a7b16329e8a 100644
--- a/src/test/java/biz/nynja/account/configurations/CassandraTestsConfig.java
+++ b/src/test/java/biz/nynja/account/configurations/CassandraTestsConfig.java
@@ -1,5 +1,6 @@
package biz.nynja.account.configurations;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Bean;
@@ -17,6 +18,7 @@ import com.datastax.driver.core.Session;
public class CassandraTestsConfig {
@MockBean
+ @Qualifier("accountSession")
private Session session;
@Bean
diff --git a/src/test/java/biz/nynja/account/services/AccountServiceTests.java b/src/test/java/biz/nynja/account/services/AccountServiceTests.java
index 8c06861cf7a0981bbbe1869d842819e4af7ddc45..fce0d7d6bd0498b5c945278f655b56c5556639ea 100644
--- a/src/test/java/biz/nynja/account/services/AccountServiceTests.java
+++ b/src/test/java/biz/nynja/account/services/AccountServiceTests.java
@@ -3,15 +3,20 @@
*/
package biz.nynja.account.services;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.verify;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
-import org.apache.commons.lang3.tuple.ImmutablePair;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -25,21 +30,78 @@ import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
+import biz.nynja.account.accesspoints.AccessPoint;
+import biz.nynja.account.accesspoints.AccessPointService;
import biz.nynja.account.components.AccountServiceHelper;
import biz.nynja.account.components.PreparedStatementsCache;
import biz.nynja.account.configurations.CassandraTestsConfig;
-import biz.nynja.account.grpc.*;
+import biz.nynja.account.grpc.AccountByAccountIdRequest;
+import biz.nynja.account.grpc.AccountDetails;
+import biz.nynja.account.grpc.AccountResponse;
+import biz.nynja.account.grpc.AccountServiceGrpc;
+import biz.nynja.account.grpc.AccountsByProfileIdRequest;
+import biz.nynja.account.grpc.AccountsList;
+import biz.nynja.account.grpc.AccountsResponse;
+import biz.nynja.account.grpc.AddAuthenticationProviderRequest;
+import biz.nynja.account.grpc.AddContactInfoRequest;
+import biz.nynja.account.grpc.AuthProviderDetails;
+import biz.nynja.account.grpc.AuthenticationProviderRequest;
+import biz.nynja.account.grpc.AuthenticationType;
+import biz.nynja.account.grpc.CompletePendingAccountCreationRequest;
+import biz.nynja.account.grpc.ContactDetails;
+import biz.nynja.account.grpc.ContactType;
+import biz.nynja.account.grpc.CreatePendingAccountRequest;
+import biz.nynja.account.grpc.CreatePendingAccountResponse;
import biz.nynja.account.grpc.Date;
+import biz.nynja.account.grpc.DeleteAccountRequest;
+import biz.nynja.account.grpc.DeleteAuthenticationProviderRequest;
+import biz.nynja.account.grpc.DeleteContactInfoRequest;
+import biz.nynja.account.grpc.DeleteProfileRequest;
+import biz.nynja.account.grpc.EditContactInfoRequest;
import biz.nynja.account.grpc.ErrorResponse.Cause;
-import biz.nynja.account.models.*;
+import biz.nynja.account.grpc.GetByEmailRequest;
+import biz.nynja.account.grpc.GetByPhoneNumberRequest;
+import biz.nynja.account.grpc.GetByQrCodeRequest;
+import biz.nynja.account.grpc.GetByUsernameRequest;
+import biz.nynja.account.grpc.ProfileByProfileIdRequest;
+import biz.nynja.account.grpc.ProfileResponse;
+import biz.nynja.account.grpc.Role;
+import biz.nynja.account.grpc.SearchResponse;
+import biz.nynja.account.grpc.StatusResponse;
+import biz.nynja.account.grpc.UpdateAccountRequest;
+import biz.nynja.account.grpc.UpdateAuthenticationProviderRequest;
import biz.nynja.account.models.Account;
-import biz.nynja.account.repositories.*;
+import biz.nynja.account.models.AccountByAuthenticationProvider;
+import biz.nynja.account.models.AccountByProfileId;
+import biz.nynja.account.models.AccountByQrCode;
+import biz.nynja.account.models.AccountByUsername;
+import biz.nynja.account.models.AuthenticationProvider;
+import biz.nynja.account.models.ContactInfo;
+import biz.nynja.account.models.PendingAccount;
+import biz.nynja.account.models.PendingAccountByAuthenticationProvider;
+import biz.nynja.account.models.Profile;
+import biz.nynja.account.models.ProfileByAuthenticationProvider;
+import biz.nynja.account.permissions.PermissionsInterceptor;
+import biz.nynja.account.repositories.AccountByAuthenticationProviderRepository;
+import biz.nynja.account.repositories.AccountByProfileIdRepository;
+import biz.nynja.account.repositories.AccountByQrCodeRepository;
+import biz.nynja.account.repositories.AccountByUsernameRepository;
+import biz.nynja.account.repositories.AccountRepository;
+import biz.nynja.account.repositories.AccountRepositoryAdditional;
+import biz.nynja.account.repositories.PendingAccountRepository;
+import biz.nynja.account.repositories.ProfileByAuthenticationProviderRepository;
+import biz.nynja.account.repositories.ProfileRepository;
import biz.nynja.account.services.decomposition.AccountProvider;
import biz.nynja.account.services.decomposition.IncorrectAccountCountException;
import biz.nynja.account.services.decomposition.ProfileProvider;
import biz.nynja.account.utils.GrpcServerTestBase;
import biz.nynja.account.utils.Util;
+import io.grpc.Context;
+import io.grpc.Contexts;
import io.grpc.Metadata;
+import io.grpc.ServerCall;
+import io.grpc.ServerCallHandler;
+import io.grpc.ServerInterceptor;
import io.grpc.stub.MetadataUtils;
/**
@@ -174,23 +236,31 @@ public class AccountServiceTests extends GrpcServerTestBase {
@MockBean
private ProfileProvider profileProvider;
+ @MockBean
+ private AccessPointService accessPointService;
+
private AccountServiceGrpc.AccountServiceBlockingStub accountServiceBlockingStub;
private AccountServiceGrpc.AccountServiceBlockingStub searchServiceBlockingStub;
@Before
public void setupTest() {
- String adminAccessToken = "eyJraWQiOiIyMDE4MDYwOCIsInR5cCI6IkpXVCIsImFsZyI6IkVTMjU2In0.eyJzdWIiOiJZemt4T0dOalpqWXRPRFl3WkMwME1EVmtMV0l5WVdFdE9USmhZV0pqTURKa1ltUXgiLCJhdWQiOiJibmx1YW1FPTpueW5qYTpueW5qYSIsInNjb3BlIjoiYWNjZXNzIiwicm9sZXMiOlsiQURNSU4iLCJVU0VSIl0sImlzcyI6Imh0dHBzOi8vYXV0aC5ueW5qYS5iaXovIiwiZXhwIjoxNTQzMzEwMTI4LCJpYXQiOjE1NDMzMDY1Mjh9.IdfUiOx_cPdp3lUIVbTKx51L9BrTigzWh3-yUc9-sLNMonO1GFaM2lJrpus4-Wi5G7D1lsX5PLWxt85pRJ0AnQ";
+ AccessPoint accessPoint = new AccessPoint();
+ String accountId = "0994566e-ac7b-45b2-b6ef-36440e44a15a";
+ String adminAccessToken = "eyJraWQiOiIyMDE4MTEzMCIsInR5cCI6IkpXVCIsImFsZyI6IkVTMjU2In0.eyJzdWIiOiJNRGs1TkRVMk5tVXRZV00zWWkwME5XSXlMV0kyWldZdE16WTBOREJsTkRSaE1UVmgiLCJhdWQiOiJibmx1YW1FPTpueW5qYTpueW5qYSIsInNjb3BlIjoiYWNjZXNzIiwicm9sZXMiOlsiQURNSU4iLCJVU0VSIl0sImlzcyI6Imh0dHBzOi8vYXV0aC5ueW5qYS5iaXovIiwiZXhwIjoxNTQ1MTQzNTY0LCJpYXQiOjE1NDUxMzk5NjR9.w9LZEKB8GLRHDRpa80Lp2EFlGOjmJA4mWP6__Fk0JDu8HlJPk5GyXAm7081s6BqH99ixsKXsGGea6CuT0NHKqQ";
- accountServiceBlockingStub = AccountServiceGrpc.newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
- searchServiceBlockingStub = AccountServiceGrpc.newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
+ accountServiceBlockingStub = AccountServiceGrpc
+ .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
+ searchServiceBlockingStub = AccountServiceGrpc
+ .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
Metadata headers = new Metadata();
- Metadata.Key key = Metadata.Key.of("accessToken", Metadata.ASCII_STRING_MARSHALLER);
- headers.put(key, adminAccessToken);
+ Metadata.Key key = Metadata.Key.of("Authorization", Metadata.ASCII_STRING_MARSHALLER);
+ headers.put(key, "Bearer " + adminAccessToken);
accountServiceBlockingStub = MetadataUtils.attachHeaders(accountServiceBlockingStub, headers);
searchServiceBlockingStub = MetadataUtils.attachHeaders(searchServiceBlockingStub, headers);
-
+ given(accessPointService.getAccessPoint(UUID.fromString(accountId), adminAccessToken))
+ .willReturn(Optional.of(accessPoint));
}
@Test
@@ -204,7 +274,7 @@ public class AccountServiceTests extends GrpcServerTestBase {
Optional accountResponse = Optional.of(response);
given(accountProvider.getAccountByAccountId(request)).willReturn(accountResponse);
- final AccountResponse reply = accountServiceBlockingStub.getAccountByAccountId(request);
+ final AccountResponse reply = accountServiceBlockingStub.getAccountByAccountId(request);
assertNotNull("Reply should not be null", reply);
assertTrue(String.format("Reply should contain profile ID '%s'", Util.ACCOUNT_ID.toString()),
@@ -432,8 +502,6 @@ public class AccountServiceTests extends GrpcServerTestBase {
.authenticationProviderAlreadyUsedInProfile(Mockito.any(AuthenticationProvider.class)))
.willReturn(true);
- final AccountServiceGrpc.AccountServiceBlockingStub accountServiceBlockingStub = AccountServiceGrpc
- .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
final CreatePendingAccountResponse reply = accountServiceBlockingStub.createPendingAccount(request);
assertNotNull("Reply should not be null", reply);
assertTrue(String.format("Reply should contain account id '%s'", Cause.AUTH_PROVIDER_ALREADY_USED),
@@ -606,9 +674,6 @@ public class AccountServiceTests extends GrpcServerTestBase {
.completePendingAccountCreation(Mockito.any(CompletePendingAccountCreationRequest.class)))
.willReturn(null);
- final AccountServiceGrpc.AccountServiceBlockingStub accountServiceBlockingStub = AccountServiceGrpc
- .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
-
final AccountResponse respose = accountServiceBlockingStub.completePendingAccountCreation(request);
assertNotNull("Reply should not be null", respose);
assertTrue(String.format("Reply should contain cause '%s'", Cause.ERROR_CREATING_ACCOUNT),
@@ -688,7 +753,8 @@ public class AccountServiceTests extends GrpcServerTestBase {
final DeleteProfileRequest request = DeleteProfileRequest.newBuilder()
.setProfileId(Util.PROFILE_ID_NOT_FOUND.toString()).build();
- given(accountRepositoryAdditional.deleteProfile(Util.PROFILE_ID_NOT_FOUND)).willReturn(Optional.of(Cause.ERROR_DELETING_PROFILE));
+ given(accountRepositoryAdditional.deleteProfile(Util.PROFILE_ID_NOT_FOUND))
+ .willReturn(Optional.of(Cause.ERROR_DELETING_PROFILE));
final StatusResponse reply = accountServiceBlockingStub.deleteProfile(request);
assertNotNull("Reply should not be null", reply);
@@ -735,7 +801,7 @@ public class AccountServiceTests extends GrpcServerTestBase {
Util.PHONE_NUMBER_STREIGHT, AuthenticationType.PHONE.name()))
.willReturn(profileByAuthenticationProvider);
- final StatusResponse reply = accountServiceBlockingStub.addAuthenticationProviderToProfile(request);
+ final StatusResponse reply = accountServiceBlockingStub.addAuthenticationProviderToProfile(request);
assertNotNull("Reply should not be null", reply);
assertTrue(String.format("Reply should contain cause '%s'", Cause.AUTH_PROVIDER_ALREADY_USED),
reply.getError().getCause().equals(Cause.AUTH_PROVIDER_ALREADY_USED));
@@ -745,8 +811,7 @@ public class AccountServiceTests extends GrpcServerTestBase {
public void testAddAuthenticationProviderToProfileAuthProviderIdMissing() {
final AddAuthenticationProviderRequest request = AddAuthenticationProviderRequest.newBuilder()
.setAuthenticationProvider(AuthProviderDetails.newBuilder()
- .setAuthenticationProvider(Util.PHONE_PROVIDER)
- .setAuthenticationType(AuthenticationType.PHONE))
+ .setAuthenticationProvider(Util.PHONE_PROVIDER).setAuthenticationType(AuthenticationType.PHONE))
.build();
given(accountRepositoryAdditional.addAuthenticationProvider(Mockito.any(UUID.class),
@@ -780,7 +845,7 @@ public class AccountServiceTests extends GrpcServerTestBase {
.findByAuthenticationProviderAndAuthenticationProviderType(Util.PHONE_PROVIDER, "PHONE"))
.willReturn(null);
- final StatusResponse reply = accountServiceBlockingStub.addAuthenticationProviderToProfile(request);
+ final StatusResponse reply = accountServiceBlockingStub.addAuthenticationProviderToProfile(request);
assertNotNull("Reply should not be null", reply);
assertTrue(String.format("Reply should contain cause '%s'", Cause.MISSING_AUTH_PROVIDER_ID),
reply.getError().getCause().equals(Cause.MISSING_AUTH_PROVIDER_ID));
@@ -1872,8 +1937,6 @@ public class AccountServiceTests extends GrpcServerTestBase {
given(accountProvider.getAccountResponseByLoginOption(AuthenticationType.PHONE, Util.PHONE_PROVIDER))
.willReturn(accountResponse);
- final AccountServiceGrpc.AccountServiceBlockingStub accountServiceBlockingStub = AccountServiceGrpc
- .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
final AccountResponse reply = accountServiceBlockingStub.getAccountByLoginOption(request);
assertNotNull("Reply should not be null", reply);
@@ -1891,8 +1954,6 @@ public class AccountServiceTests extends GrpcServerTestBase {
given(accountProvider.getAccountResponseByLoginOption(AuthenticationType.EMAIL, Util.EMAIL))
.willReturn(accountResponse);
- final AccountServiceGrpc.AccountServiceBlockingStub accountServiceBlockingStub = AccountServiceGrpc
- .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
final AccountResponse reply = accountServiceBlockingStub.getAccountByLoginOption(request);
assertNotNull("Reply should not be null", reply);
@@ -1908,8 +1969,6 @@ public class AccountServiceTests extends GrpcServerTestBase {
given(accountProvider.getAccountResponseByLoginOption(AuthenticationType.EMAIL, Util.EMAIL_NOT_USED))
.willReturn(Optional.empty());
- final AccountServiceGrpc.AccountServiceBlockingStub accountServiceBlockingStub = AccountServiceGrpc
- .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
final AccountResponse reply = accountServiceBlockingStub.getAccountByLoginOption(request);
assertNotNull("Reply should not be null", reply);
@@ -1921,8 +1980,6 @@ public class AccountServiceTests extends GrpcServerTestBase {
final AuthenticationProviderRequest request = AuthenticationProviderRequest.newBuilder()
.setAuthenticationIdentifier(Util.PHONE_PROVIDER).build();
- final AccountServiceGrpc.AccountServiceBlockingStub accountServiceBlockingStub = AccountServiceGrpc
- .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
final AccountResponse reply = accountServiceBlockingStub.getAccountByLoginOption(request);
assertNotNull("Reply should not be null", reply);
@@ -1934,8 +1991,6 @@ public class AccountServiceTests extends GrpcServerTestBase {
final AuthenticationProviderRequest request = AuthenticationProviderRequest.newBuilder()
.setAuthenticationType(AuthenticationType.PHONE).build();
- final AccountServiceGrpc.AccountServiceBlockingStub accountServiceBlockingStub = AccountServiceGrpc
- .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
final AccountResponse reply = accountServiceBlockingStub.getAccountByLoginOption(request);
assertNotNull("Reply should not be null", reply);
@@ -1948,8 +2003,6 @@ public class AccountServiceTests extends GrpcServerTestBase {
.setAuthenticationIdentifier(Util.INVALID_PHONE_PROVIDER)
.setAuthenticationType(AuthenticationType.PHONE).build();
- final AccountServiceGrpc.AccountServiceBlockingStub accountServiceBlockingStub = AccountServiceGrpc
- .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
final AccountResponse reply = accountServiceBlockingStub.getAccountByLoginOption(request);
assertNotNull("Reply should not be null", reply);
@@ -1962,8 +2015,6 @@ public class AccountServiceTests extends GrpcServerTestBase {
.setAuthenticationIdentifier(Util.INVALID_EMAIL).setAuthenticationType(AuthenticationType.EMAIL)
.build();
- final AccountServiceGrpc.AccountServiceBlockingStub accountServiceBlockingStub = AccountServiceGrpc
- .newBlockingStub(Optional.ofNullable(channel).orElse(inProcChannel));
final AccountResponse reply = accountServiceBlockingStub.getAccountByLoginOption(request);
assertNotNull("Reply should not be null", reply);