From 145610cd4216d4ba805deb5dc849cd900443aa87 Mon Sep 17 00:00:00 2001 From: Dragomir Todorov Date: Fri, 11 Jan 2019 13:41:05 +0200 Subject: [PATCH 1/7] NY-6609: Add countrySelector to ContactInfo --- .../biz/nynja/account/models/ContactInfo.java | 16 +++++++++++++- .../account/phone/PhoneNumberNormalizer.java | 21 +++++++++++++++---- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/main/java/biz/nynja/account/models/ContactInfo.java b/src/main/java/biz/nynja/account/models/ContactInfo.java index 9fffa48..6acc182 100644 --- a/src/main/java/biz/nynja/account/models/ContactInfo.java +++ b/src/main/java/biz/nynja/account/models/ContactInfo.java @@ -8,6 +8,7 @@ import org.springframework.data.cassandra.core.mapping.UserDefinedType; import biz.nynja.account.grpc.ContactDetails; import biz.nynja.account.grpc.ContactDetails.Builder; import biz.nynja.account.grpc.ContactType; +import biz.nynja.account.phone.PhoneNumberUtils; @UserDefinedType public class ContactInfo { @@ -100,7 +101,20 @@ public class ContactInfo { builder.setType(contactType); } if (getValue() != null) { - builder.setValue(getValue()); + if(ContactType.PHONE_CONTACT.equals(contactType)) { + if(getValue().split(":").length == 2) { + // Here we consider the stored phone number is stored in format BG:359898123456 (new way) + String[] phoneParts = getValue().split(":"); + builder.setCountrySelector(phoneParts[0]); + builder.setValue(phoneParts[1]); + } else { + // Regular phone number stored in just 359898123456 + builder.setValue(getValue()); + builder.setCountrySelector(PhoneNumberUtils.getCountrySelector(getValue())); // TODO remove this after db clean up + } + } else { + builder.setValue(getValue()); + } } if (getLabel() != null) { builder.setLabel(getLabel()); diff --git a/src/main/java/biz/nynja/account/phone/PhoneNumberNormalizer.java b/src/main/java/biz/nynja/account/phone/PhoneNumberNormalizer.java index 7ffc912..d5834b4 100644 --- a/src/main/java/biz/nynja/account/phone/PhoneNumberNormalizer.java +++ b/src/main/java/biz/nynja/account/phone/PhoneNumberNormalizer.java @@ -28,7 +28,7 @@ public class PhoneNumberNormalizer { public AddContactInfoRequest normalizePhoneNumber(AddContactInfoRequest request) { // Get the normalized phone number from libphone ContactDetails newContactDetails = ContactDetails.newBuilder().setType(request.getContactInfo().getType()) - .setValue(getNormalizedPhoneNumber(request.getContactInfo().getValue())) + .setValue(getNormalizedPhoneNumberContactInfo(request.getContactInfo().getValue())) .setLabel(request.getContactInfo().getLabel()).build(); AddContactInfoRequest newRequest = AddContactInfoRequest.newBuilder().setAccountId(request.getAccountId()) .setContactInfo(newContactDetails).build(); @@ -39,7 +39,7 @@ public class PhoneNumberNormalizer { public DeleteContactInfoRequest normalizePhoneNumber(DeleteContactInfoRequest request) { // Get the normalized phone number from libphone ContactDetails newContactDetails = ContactDetails.newBuilder().setType(request.getContactInfo().getType()) - .setValue(getNormalizedPhoneNumber(request.getContactInfo().getValue())) + .setValue(getNormalizedPhoneNumberContactInfo(request.getContactInfo().getValue())) .setLabel(request.getContactInfo().getLabel()).build(); DeleteContactInfoRequest newRequest = DeleteContactInfoRequest.newBuilder().setAccountId(request.getAccountId()) .setContactInfo(newContactDetails).build(); @@ -51,12 +51,12 @@ public class PhoneNumberNormalizer { // Get the normalized phone number from libphone for the old number ContactDetails contactDetailsOldNumber = ContactDetails.newBuilder() .setType(request.getOldContactInfo().getType()) - .setValue(getNormalizedPhoneNumber(request.getOldContactInfo().getValue())) + .setValue(getNormalizedPhoneNumberContactInfo(request.getOldContactInfo().getValue())) .setLabel(request.getOldContactInfo().getLabel()).build(); // Get the normalized phone number from libphone for the edited number ContactDetails contactDetailsEditedNumber = ContactDetails.newBuilder() .setType(request.getEditedContactInfo().getType()) - .setValue(getNormalizedPhoneNumber(request.getEditedContactInfo().getValue())) + .setValue(getNormalizedPhoneNumberContactInfo(request.getEditedContactInfo().getValue())) .setLabel(request.getEditedContactInfo().getLabel()).build(); EditContactInfoRequest newRequest = EditContactInfoRequest.newBuilder().setAccountId(request.getAccountId()) .setOldContactInfo(contactDetailsOldNumber).setEditedContactInfo(contactDetailsEditedNumber).build(); @@ -134,4 +134,17 @@ public class PhoneNumberNormalizer { } return normalizedPhoneNumber; } + + public String getNormalizedPhoneNumberContactInfo(String rawPhoneNumber) throws InvalidPhoneNumberException { + String normalizedPhoneNumber = getNormalizedPhoneNumber(rawPhoneNumber); + + String country; + String[] provider = rawPhoneNumber.split(":"); + if (provider.length == 1) { + country = PhoneNumberUtils.getCountrySelector(provider[0]); + } else { + country = provider[0]; + } + return country + ":" + normalizedPhoneNumber; + } } -- GitLab From 1b55016179c68c22c8ae895ca1de04474f4b9541 Mon Sep 17 00:00:00 2001 From: sergeyPensov Date: Fri, 11 Jan 2019 16:30:16 +0200 Subject: [PATCH 2/7] Migrate to new update implementation in saga --- .../biz/nynja/account/models/Profile.java | 3 +- .../AccountRepositoryAdditionalImpl.java | 54 +++++++++---------- .../repositories/batch/Transaction.java | 10 +++- 3 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/main/java/biz/nynja/account/models/Profile.java b/src/main/java/biz/nynja/account/models/Profile.java index f4e2844..a8044eb 100644 --- a/src/main/java/biz/nynja/account/models/Profile.java +++ b/src/main/java/biz/nynja/account/models/Profile.java @@ -3,6 +3,7 @@ */ package biz.nynja.account.models; +import java.io.Serializable; import java.util.Set; import java.util.UUID; @@ -12,7 +13,7 @@ import biz.nynja.account.grpc.ProfileDetails; import biz.nynja.account.grpc.ProfileDetails.Builder; @Table -public class Profile { +public class Profile implements Serializable { @PrimaryKey private UUID profileId; diff --git a/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditionalImpl.java b/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditionalImpl.java index da4d683..c2c959c 100644 --- a/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditionalImpl.java +++ b/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditionalImpl.java @@ -18,6 +18,7 @@ import java.util.stream.Collectors; import biz.nynja.account.repositories.batch.SagaTransaction; import biz.nynja.account.repositories.batch.Transaction; import biz.nynja.account.services.erlang.ErlangAccountBridge; +import org.apache.commons.lang3.SerializationUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.cassandra.core.CassandraBatchOperations; @@ -158,14 +159,14 @@ public class AccountRepositoryAdditionalImpl implements AccountRepositoryAdditio return null; } - private Account newAccountInsert(CassandraBatchOperations batchOps, CompletePendingAccountCreationRequest request, + private Account newAccountInsert(Transaction batchOps, CompletePendingAccountCreationRequest request, PendingAccount pendingAccount, Long creationTimestamp) { Account newAccount = AccountBuilder.buildNewAccount(request, pendingAccount, creationTimestamp); batchOps.insert(newAccount); return newAccount; } - private Profile newProfileInsert(CassandraBatchOperations batchOps, CompletePendingAccountCreationRequest request, + private Profile newProfileInsert(Transaction batchOps, CompletePendingAccountCreationRequest request, PendingAccount pendingAccount, Long creationTimestamp) { Profile newProfile = new Profile(); newProfile.setProfileId(pendingAccount.getProfileId()); @@ -180,8 +181,7 @@ public class AccountRepositoryAdditionalImpl implements AccountRepositoryAdditio return newProfile; } - private void newProfileByAuthenticationProviderInsert(CassandraBatchOperations batchOps, - PendingAccount pendingAccount) { + private void newProfileByAuthenticationProviderInsert(Transaction batchOps, PendingAccount pendingAccount) { ProfileByAuthenticationProvider newProfileByAuthenticationProvider = new ProfileByAuthenticationProvider(); newProfileByAuthenticationProvider.setAuthenticationProvider(pendingAccount.getAuthenticationProvider()); newProfileByAuthenticationProvider @@ -295,7 +295,7 @@ public class AccountRepositoryAdditionalImpl implements AccountRepositoryAdditio * @param existingProfile * @return true or false according to the result of removing the account's creation provider */ - private boolean removeCreationProvider(CassandraBatchOperations batchOperations, Account existingAccount, + private boolean removeCreationProvider(Transaction batchOperations, Account existingAccount, Profile existingProfile) { // update authentication providers of the profile by removing the one of the deleted account (if not // already manually removed by the user) @@ -341,38 +341,38 @@ public class AccountRepositoryAdditionalImpl implements AccountRepositoryAdditio return false; } - private void updateAccountData(CassandraBatchOperations batchOps, UpdateAccountRequest request, - Account existingAccount, Long lastUpdateTimestamp) { - Account updatedAccount = existingAccount; - updatedAccount.setAvatar(request.getAvatar()); - updatedAccount.setAccountMark(request.getAccountMark()); - updatedAccount.setAccountName(request.getAccountName()); - updatedAccount.setFirstName(request.getFirstName()); - updatedAccount.setLastName(request.getLastName()); - updatedAccount.setUsername(request.getUsername()); - updatedAccount.setLastUpdateTimestamp(lastUpdateTimestamp); - updatedAccount.setAccessStatus(request.getAccessStatus().toString()); + private void updateAccountData(Transaction transaction, UpdateAccountRequest request, Account existingAccount, + Long lastUpdateTimestamp) { + Account updatedAccount = (Account) SerializationUtils.clone(existingAccount); + existingAccount.setAvatar(request.getAvatar()); + existingAccount.setAccountMark(request.getAccountMark()); + existingAccount.setAccountName(request.getAccountName()); + existingAccount.setFirstName(request.getFirstName()); + existingAccount.setLastName(request.getLastName()); + existingAccount.setUsername(request.getUsername()); + existingAccount.setLastUpdateTimestamp(lastUpdateTimestamp); + existingAccount.setAccessStatus(request.getAccessStatus().toString()); if (request.getRolesList() == null || request.getRolesList().isEmpty()) { - updatedAccount.setRoles(Set.of(Role.USER.toString())); + existingAccount.setRoles(Set.of(Role.USER.toString())); } else { - updatedAccount.setRoles(request.getRolesList().stream().map(Enum::toString).collect(Collectors.toSet())); + existingAccount.setRoles(request.getRolesList().stream().map(Enum::toString).collect(Collectors.toSet())); } if (util.validateBirthdayIsSet(request.getBirthday())) { - updatedAccount.setBirthday(LocalDate.of(request.getBirthday().getYear(), request.getBirthday().getMonth(), + existingAccount.setBirthday(LocalDate.of(request.getBirthday().getYear(), request.getBirthday().getMonth(), request.getBirthday().getDay())); } else { - updatedAccount.setBirthday(null); + existingAccount.setBirthday(null); } - batchOps.update(updatedAccount); + transaction.update(existingAccount, updatedAccount); } - private void updateAuthProvidersInProfileWhenDeletingAccount(CassandraBatchOperations batchOps, - Profile existingProfile, Set authProvidersToUpdate, Long lastUpdateTimestamp) { - Profile updatedProfile = existingProfile; + private void updateAuthProvidersInProfileWhenDeletingAccount(Transaction transaction, Profile existingProfile, + Set authProvidersToUpdate, Long lastUpdateTimestamp) { + Profile updatedProfile = (Profile) SerializationUtils.clone(existingProfile); if (authProvidersToUpdate != null) { - updatedProfile.setAuthenticationProviders(authProvidersToUpdate); - updatedProfile.setLastUpdateTimestamp(lastUpdateTimestamp); - batchOps.update(updatedProfile); + existingProfile.setAuthenticationProviders(authProvidersToUpdate); + existingProfile.setLastUpdateTimestamp(lastUpdateTimestamp); + transaction.update(existingProfile, updatedProfile); } } diff --git a/src/main/java/biz/nynja/account/repositories/batch/Transaction.java b/src/main/java/biz/nynja/account/repositories/batch/Transaction.java index 97f227a..ff745cb 100644 --- a/src/main/java/biz/nynja/account/repositories/batch/Transaction.java +++ b/src/main/java/biz/nynja/account/repositories/batch/Transaction.java @@ -1,5 +1,5 @@ /** - * Copyright (C) 2018 Nynja Inc. All rights reserved. + * Copyright (C) 2018 Nynja Inc. All rights reserved. */ package biz.nynja.account.repositories.batch; @@ -8,6 +8,14 @@ import org.springframework.data.cassandra.core.WriteResult; import org.springframework.data.cassandra.core.cql.WriteOptions; public interface Transaction extends CassandraBatchOperations { + @Deprecated + CassandraBatchOperations update(Object... objects); + + @Deprecated + CassandraBatchOperations update(Iterable iterable); + + @Deprecated + CassandraBatchOperations update(Iterable iterable, WriteOptions writeOptions); WriteResult rollBack(); -- GitLab From 980d43d8c03cc37cc90da9cc6f5054c70fdaaf44 Mon Sep 17 00:00:00 2001 From: Stoyan Tzenkov Date: Fri, 11 Jan 2019 16:51:33 +0200 Subject: [PATCH 3/7] NY-6635: accesspoint implementation using accesspoint table in auth keyspace. Signed-off-by: Stoyan Tzenkov --- .../nynja/account/StartupScriptsListener.java | 1 - .../accesspoints/AccessPointRepository.java | 14 +- .../accesspoints/AccessPointService.java | 13 +- .../components/PreparedStatementsCache.java | 6 +- .../CassandraAccessPointConfig.java | 26 -- .../configuration/CassandraAccountConfig.java | 90 ----- .../configuration/CassandraBaseConfig.java | 51 --- .../configuration/CassandraConfig.java | 154 ++++---- .../permissions/PermissionsInterceptor.java | 336 +++++++++--------- 9 files changed, 268 insertions(+), 423 deletions(-) delete mode 100644 src/main/java/biz/nynja/account/configuration/CassandraAccessPointConfig.java delete mode 100644 src/main/java/biz/nynja/account/configuration/CassandraAccountConfig.java delete mode 100644 src/main/java/biz/nynja/account/configuration/CassandraBaseConfig.java diff --git a/src/main/java/biz/nynja/account/StartupScriptsListener.java b/src/main/java/biz/nynja/account/StartupScriptsListener.java index ca66b87..88f09f5 100644 --- a/src/main/java/biz/nynja/account/StartupScriptsListener.java +++ b/src/main/java/biz/nynja/account/StartupScriptsListener.java @@ -32,7 +32,6 @@ public class StartupScriptsListener { private String keyspace; @Autowired - @Qualifier("accountSession") private Session session; @Autowired diff --git a/src/main/java/biz/nynja/account/accesspoints/AccessPointRepository.java b/src/main/java/biz/nynja/account/accesspoints/AccessPointRepository.java index 6888c6d..9f2c3c0 100644 --- a/src/main/java/biz/nynja/account/accesspoints/AccessPointRepository.java +++ b/src/main/java/biz/nynja/account/accesspoints/AccessPointRepository.java @@ -3,15 +3,23 @@ */ package biz.nynja.account.accesspoints; +import java.util.List; import java.util.UUID; - import org.springframework.data.cassandra.repository.CassandraRepository; +import org.springframework.data.cassandra.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import biz.nynja.account.accesspoints.AccessPoint; @Repository public interface AccessPointRepository extends CassandraRepository { - - AccessPoint findByAccountIdAndAccessToken(UUID accountId, String accessToken); + + @Query("select * from auth.accesspoint where accountid=:accountId and accesstoken=:accessToken;") + AccessPoint findByAccountIdAndAccessToken(@Param("accountId") UUID accountId, + @Param("accessToken") String accessToken); + + @Query("select * from auth.accesspoint where accountid=:accountId;") + List findAllByAccountId(@Param("accountId") UUID accountId); } diff --git a/src/main/java/biz/nynja/account/accesspoints/AccessPointService.java b/src/main/java/biz/nynja/account/accesspoints/AccessPointService.java index ca24bd2..2ac4a44 100644 --- a/src/main/java/biz/nynja/account/accesspoints/AccessPointService.java +++ b/src/main/java/biz/nynja/account/accesspoints/AccessPointService.java @@ -21,13 +21,18 @@ public class AccessPointService { } public Optional getAccessPoint(UUID accountId, String accessToken) { - AccessPoint accessPoint = accessPointRepository.findByAccountIdAndAccessToken(accountId, accessToken); - if (accessPoint != null) { - return Optional.of(accessPoint); + try { + AccessPoint accessPoint = accessPointRepository.findByAccountIdAndAccessToken(accountId, accessToken); + if (accessPoint != null) { + return Optional.of(accessPoint); + } + } catch (Exception e) { + logger.error("Error reading accesspoint record for accoint ID {}. Error message: {}", accountId, + e.getMessage()); } return Optional.empty(); } - + public AccessPoint buildAccessPoint(String deviceId, String accessToken, String accountId, long expiresIn) { AccessPoint accessPoint = new AccessPoint(); accessPoint.setDeviceId(deviceId); diff --git a/src/main/java/biz/nynja/account/components/PreparedStatementsCache.java b/src/main/java/biz/nynja/account/components/PreparedStatementsCache.java index 20be301..91b9b32 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.CassandraAccountConfig; +import biz.nynja.account.configuration.CassandraConfig; import biz.nynja.account.models.AuthenticationProvider; @Configuration public class PreparedStatementsCache { - private final CassandraAccountConfig cassandraConfig; + private final CassandraConfig cassandraConfig; private final Session session; private static Map statementsCache; @Autowired - public PreparedStatementsCache(Session session, CassandraAccountConfig cassandraConfig) { + public PreparedStatementsCache(Session session, CassandraConfig 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 deleted file mode 100644 index 1c67b4d..0000000 --- a/src/main/java/biz/nynja/account/configuration/CassandraAccessPointConfig.java +++ /dev/null @@ -1,26 +0,0 @@ -//package biz.nynja.account.configuration; -// -//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.repository.config.EnableCassandraRepositories; -// -//@Configuration -//@EnableCassandraRepositories(basePackages = { "biz.nynja.account.accesspoints" }) -//@ConditionalOnMissingClass("org.springframework.test.context.junit4.SpringRunner") -//public class CassandraAccessPointConfig extends CassandraBaseConfig { -// -// @Value("${spring.data.cassandra.accesspoint.keyspace-name}") -// private String keyspaceName; -// -// @Override -// protected String getKeyspaceName() { -// return keyspaceName; -// } -// -// @Override -// public String[] getEntityBasePackages() { -// return new String[] { "biz.nynja.account.accesspoints" }; -// } -// -//} diff --git a/src/main/java/biz/nynja/account/configuration/CassandraAccountConfig.java b/src/main/java/biz/nynja/account/configuration/CassandraAccountConfig.java deleted file mode 100644 index 547b535..0000000 --- a/src/main/java/biz/nynja/account/configuration/CassandraAccountConfig.java +++ /dev/null @@ -1,90 +0,0 @@ -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.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -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.core.CassandraAdminTemplate; -import org.springframework.data.cassandra.core.cql.keyspace.CreateKeyspaceSpecification; -import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories; - -import biz.nynja.account.StartupScriptsListener; - -@Configuration -@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; - } - - @Override - public String[] getEntityBasePackages() { - return new String[] { "biz.nynja.account.models", "biz.nynja.account.repositories" }; - } - - @Override - public SchemaAction getSchemaAction() { - return SchemaAction.CREATE_IF_NOT_EXISTS; - } - - /** - * See {@link StartupScriptsListener} for scripts - * that require JPA annotated tables - */ - @Override - protected List getStartupScripts() { - return super.getStartupScripts(); - } - - public String getConfiguredKeyspaceName() { - return getKeyspaceName(); - } - - @Override - protected List getKeyspaceCreations() { - CreateKeyspaceSpecification specification = CreateKeyspaceSpecification.createKeyspace(getKeyspaceName()) - .ifNotExists().withSimpleReplication(); - return Arrays.asList(specification); - } - - @Override -// @Primary - @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; - } -} diff --git a/src/main/java/biz/nynja/account/configuration/CassandraBaseConfig.java b/src/main/java/biz/nynja/account/configuration/CassandraBaseConfig.java deleted file mode 100644 index 98dcffb..0000000 --- a/src/main/java/biz/nynja/account/configuration/CassandraBaseConfig.java +++ /dev/null @@ -1,51 +0,0 @@ -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.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.core.cql.keyspace.CreateKeyspaceSpecification; -import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories; - -@Configuration -@EnableCassandraRepositories(basePackages = { "biz.nynja.account.accesspoints" }) // to be moved to CassandraAccessPointConfig -@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; - } - - public CassandraAdminOperations cassandraTemplate(CassandraSessionFactoryBean session) throws Exception { - return null; - } - -} diff --git a/src/main/java/biz/nynja/account/configuration/CassandraConfig.java b/src/main/java/biz/nynja/account/configuration/CassandraConfig.java index 35906d7..f5aedc7 100644 --- a/src/main/java/biz/nynja/account/configuration/CassandraConfig.java +++ b/src/main/java/biz/nynja/account/configuration/CassandraConfig.java @@ -1,77 +1,77 @@ -///** -// * 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.account.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(); -// } -//} \ No newline at end of file +/** + * 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.account.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(); + } +} diff --git a/src/main/java/biz/nynja/account/permissions/PermissionsInterceptor.java b/src/main/java/biz/nynja/account/permissions/PermissionsInterceptor.java index b67ce52..7a37de8 100644 --- a/src/main/java/biz/nynja/account/permissions/PermissionsInterceptor.java +++ b/src/main/java/biz/nynja/account/permissions/PermissionsInterceptor.java @@ -1,177 +1,177 @@ -///** -// * Copyright (C) 2018 Nynja Inc. All rights reserved. -// */ -//package biz.nynja.account.permissions; -// -//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: -// * - 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; -// * - if rpc has either @Permitted(role = RoleConstants.ANY) - PERMISSION GRANTED; -// * - if rpc has an annotation @PerformPermissionCheck - @Permitted annotations are checked and an additional check is performed in the rpc; -// * - if no role from the request matches any Permitted annotation for the rpc - PERMISSION DENIED -// */ -// -//@GRpcGlobalInterceptor -//public class PermissionsInterceptor implements ServerInterceptor { -// -// private static final Logger logger = LoggerFactory.getLogger(PermissionsInterceptor.class); -// private static final Class SERVICE_CLASS = AccountServiceImpl.class; -// -// public static final Metadata.Key ACCESS_TOKEN_METADATA = Metadata.Key.of("Authorization", -// ASCII_STRING_MARSHALLER); -// public static final Context.Key ACCESS_TOKEN_CTX = Context.key("accessToken"); -// -// 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); -// -// /* -// * 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 && 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) { -// // Get name of endpoint/rpc called -// String callName = call.getMethodDescriptor().getFullMethodName(); -// return callName.substring(callName.lastIndexOf('/') + 1); -// } -// -//// 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 +/** + * Copyright (C) 2018 Nynja Inc. All rights reserved. + */ +package biz.nynja.account.permissions; + +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: + * - 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; + * - if rpc has either @Permitted(role = RoleConstants.ANY) - PERMISSION GRANTED; + * - if rpc has an annotation @PerformPermissionCheck - @Permitted annotations are checked and an additional check is performed in the rpc; + * - if no role from the request matches any Permitted annotation for the rpc - PERMISSION DENIED + */ + +@GRpcGlobalInterceptor +public class PermissionsInterceptor implements ServerInterceptor { + + private static final Logger logger = LoggerFactory.getLogger(PermissionsInterceptor.class); + private static final Class SERVICE_CLASS = AccountServiceImpl.class; + + public static final Metadata.Key ACCESS_TOKEN_METADATA = Metadata.Key.of("Authorization", + ASCII_STRING_MARSHALLER); + public static final Context.Key ACCESS_TOKEN_CTX = Context.key("accessToken"); + + 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); + + /* + * 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; // -// Claim claim = decodedToken.getClaim("roles"); -// if (claim != null) { -// requestingRoles = claim.asArray(String.class); +// if (accessToken == null && accessToken.isEmpty()) { +// permissionDenied(call, headers, "Permission denied for rpc {}. Access token not in headers", rpc ); // } -// return requestingRoles; -// } -// -// private Method getMethod(String rpc) { -// // Get the rpc method called -// Method[] allMethods = SERVICE_CLASS.getDeclaredMethods(); +// ctx = Context.current().withValue(ACCESS_TOKEN_CTX, accessToken); +// DecodedJWT decodedToken = JWT.decode(accessToken); // -// for (Method method : allMethods) { -// if (method.getName().equals(rpc)) { -// return method; -// } +// if (!accessPointAvailable(accessToken, decodedToken, rpc)) { +// permissionDenied(call, headers, "Permission denied for rpc {}. No access point available for this account and access token.", rpc ); // } -// return null; -// } -// -// private boolean checkPermissions(String[] requestingRoles, Permitted[] permittedRoles) { // -// for (Permitted permitted : permittedRoles) { -// if (permitted.role().equals(RoleConstants.ANY)) { -// return true; -// } -// for (String role : requestingRoles) { -// if (role.equals(permitted.role()) || role.equals(RoleConstants.ACCOUNT_ADMIN) -// || role.equals(RoleConstants.AUTH_SERVICE)) { -// return true; -// } -// } +// requestingRoles = getRolesFromAccessToken(decodedToken); +// if (requestingRoles == null) { +// permissionDenied(call, headers, "Permission denied for rpc {}. No roles found for requesting account in access token.", rpc ); // } -// 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; -// } +// 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) { + // Get name of endpoint/rpc called + String callName = call.getMethodDescriptor().getFullMethodName(); + return callName.substring(callName.lastIndexOf('/') + 1); + } + + 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; + + Claim claim = decodedToken.getClaim("roles"); + if (claim != null) { + requestingRoles = claim.asArray(String.class); + } + return requestingRoles; + } + + private Method getMethod(String rpc) { + // Get the rpc method called + Method[] allMethods = SERVICE_CLASS.getDeclaredMethods(); + + for (Method method : allMethods) { + if (method.getName().equals(rpc)) { + return method; + } + } + return null; + } + + private boolean checkPermissions(String[] requestingRoles, Permitted[] permittedRoles) { + + for (Permitted permitted : permittedRoles) { + if (permitted.role().equals(RoleConstants.ANY)) { + return true; + } + for (String role : requestingRoles) { + if (role.equals(permitted.role()) || role.equals(RoleConstants.ACCOUNT_ADMIN) + || role.equals(RoleConstants.AUTH_SERVICE)) { + return true; + } + } + } + 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; + } + +} -- GitLab From a460d57238b6afe35ac66fcb00be8f107c53a033 Mon Sep 17 00:00:00 2001 From: Stoyan Tzenkov Date: Mon, 14 Jan 2019 09:00:29 +0200 Subject: [PATCH 4/7] NY-6635: Made Cassandra replication configurable. Signed-off-by: Stoyan Tzenkov --- .../nynja/account/configuration/CassandraConfig.java | 11 +++++++++-- src/main/resources/application-dev.yml | 6 ++---- src/main/resources/application-production.yml | 6 ++---- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/main/java/biz/nynja/account/configuration/CassandraConfig.java b/src/main/java/biz/nynja/account/configuration/CassandraConfig.java index f5aedc7..8a5ae1b 100644 --- a/src/main/java/biz/nynja/account/configuration/CassandraConfig.java +++ b/src/main/java/biz/nynja/account/configuration/CassandraConfig.java @@ -21,7 +21,7 @@ import biz.nynja.account.StartupScriptsListener; @ConditionalOnMissingClass("org.springframework.test.context.junit4.SpringRunner") public class CassandraConfig extends AbstractCassandraConfiguration { - @Value("${spring.data.cassandra.account.keyspace-name}") + @Value("${spring.data.cassandra.keyspace-name}") private String keyspace; @Override @@ -40,11 +40,18 @@ public class CassandraConfig extends AbstractCassandraConfiguration { @Value("${spring.data.cassandra.port}") private int port; + @Value("${spring.data.cassandra.replication}") + private int replication; + @Override protected int getPort() { return port; } + private int getReplication() { + return replication; + } + @Override public SchemaAction getSchemaAction() { return SchemaAction.CREATE_IF_NOT_EXISTS; @@ -53,7 +60,7 @@ public class CassandraConfig extends AbstractCassandraConfiguration { @Override protected List getKeyspaceCreations() { CreateKeyspaceSpecification specification = CreateKeyspaceSpecification.createKeyspace(getKeyspaceName()) - .ifNotExists().withSimpleReplication(); + .ifNotExists().withSimpleReplication(getReplication()); return Arrays.asList(specification); } diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 4956ef2..4746d23 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -12,10 +12,8 @@ spring: cassandra: contact-points: localhost port: 9042 - account: - keyspace-name: account - accesspoint: - keyspace-name: accesspoint + keyspace-name: account + replication: 3 # 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/main/resources/application-production.yml b/src/main/resources/application-production.yml index 178b0ec..a404f31 100644 --- a/src/main/resources/application-production.yml +++ b/src/main/resources/application-production.yml @@ -13,10 +13,8 @@ spring: keyspace-name: ${CASSANDRA_KEYSPACE:account} contact-points: ${CASSANDRA_CONTACT_POINTS:cassandra.cassandra.svc.cluster.local} port: ${CASSANDRA_PORT:9042} - account: - keyspace-name: ${CASSANDRA_KEYSPACE:account} - accesspoint: - keyspace-name: ${CASSANDRA_ACCESS_POINT_KEYSPACE:accesspoint} + keyspace-name: ${CASSANDRA_KEYSPACE:account} + replication: 3 logging: level: -- GitLab From 0e11562d7e8ef00c5542e88c32d53d46f8ffa5b7 Mon Sep 17 00:00:00 2001 From: sergeyPensov Date: Mon, 14 Jan 2019 10:25:31 +0200 Subject: [PATCH 5/7] Fix naming and usage in transaction --- .../AccountRepositoryAdditionalImpl.java | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditionalImpl.java b/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditionalImpl.java index c2c959c..6092f0c 100644 --- a/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditionalImpl.java +++ b/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditionalImpl.java @@ -341,38 +341,39 @@ public class AccountRepositoryAdditionalImpl implements AccountRepositoryAdditio return false; } - private void updateAccountData(Transaction transaction, UpdateAccountRequest request, Account existingAccount, + private void updateAccountData(Transaction transaction, UpdateAccountRequest request, Account currentAccountState, Long lastUpdateTimestamp) { - Account updatedAccount = (Account) SerializationUtils.clone(existingAccount); - existingAccount.setAvatar(request.getAvatar()); - existingAccount.setAccountMark(request.getAccountMark()); - existingAccount.setAccountName(request.getAccountName()); - existingAccount.setFirstName(request.getFirstName()); - existingAccount.setLastName(request.getLastName()); - existingAccount.setUsername(request.getUsername()); - existingAccount.setLastUpdateTimestamp(lastUpdateTimestamp); - existingAccount.setAccessStatus(request.getAccessStatus().toString()); + Account newAccountState = (Account) SerializationUtils.clone(currentAccountState); + currentAccountState.setAvatar(request.getAvatar()); + currentAccountState.setAccountMark(request.getAccountMark()); + currentAccountState.setAccountName(request.getAccountName()); + currentAccountState.setFirstName(request.getFirstName()); + currentAccountState.setLastName(request.getLastName()); + currentAccountState.setUsername(request.getUsername()); + currentAccountState.setLastUpdateTimestamp(lastUpdateTimestamp); + currentAccountState.setAccessStatus(request.getAccessStatus().toString()); if (request.getRolesList() == null || request.getRolesList().isEmpty()) { - existingAccount.setRoles(Set.of(Role.USER.toString())); + currentAccountState.setRoles(Set.of(Role.USER.toString())); } else { - existingAccount.setRoles(request.getRolesList().stream().map(Enum::toString).collect(Collectors.toSet())); + currentAccountState + .setRoles(request.getRolesList().stream().map(Enum::toString).collect(Collectors.toSet())); } if (util.validateBirthdayIsSet(request.getBirthday())) { - existingAccount.setBirthday(LocalDate.of(request.getBirthday().getYear(), request.getBirthday().getMonth(), - request.getBirthday().getDay())); + currentAccountState.setBirthday(LocalDate.of(request.getBirthday().getYear(), + request.getBirthday().getMonth(), request.getBirthday().getDay())); } else { - existingAccount.setBirthday(null); + currentAccountState.setBirthday(null); } - transaction.update(existingAccount, updatedAccount); + transaction.update(newAccountState, currentAccountState); } - private void updateAuthProvidersInProfileWhenDeletingAccount(Transaction transaction, Profile existingProfile, + private void updateAuthProvidersInProfileWhenDeletingAccount(Transaction transaction, Profile currentProfileState, Set authProvidersToUpdate, Long lastUpdateTimestamp) { - Profile updatedProfile = (Profile) SerializationUtils.clone(existingProfile); + Profile newProfileState = (Profile) SerializationUtils.clone(currentProfileState); if (authProvidersToUpdate != null) { - existingProfile.setAuthenticationProviders(authProvidersToUpdate); - existingProfile.setLastUpdateTimestamp(lastUpdateTimestamp); - transaction.update(existingProfile, updatedProfile); + currentProfileState.setAuthenticationProviders(authProvidersToUpdate); + currentProfileState.setLastUpdateTimestamp(lastUpdateTimestamp); + transaction.update(newProfileState, currentProfileState); } } -- GitLab From 425b3207e8b205db01b0f7fd4bd9f6082a1d12c9 Mon Sep 17 00:00:00 2001 From: sergeyPensov Date: Mon, 14 Jan 2019 11:59:22 +0200 Subject: [PATCH 6/7] Fix naming --- .../AccountRepositoryAdditionalImpl.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditionalImpl.java b/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditionalImpl.java index 6092f0c..649b92f 100644 --- a/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditionalImpl.java +++ b/src/main/java/biz/nynja/account/repositories/AccountRepositoryAdditionalImpl.java @@ -344,25 +344,25 @@ public class AccountRepositoryAdditionalImpl implements AccountRepositoryAdditio private void updateAccountData(Transaction transaction, UpdateAccountRequest request, Account currentAccountState, Long lastUpdateTimestamp) { Account newAccountState = (Account) SerializationUtils.clone(currentAccountState); - currentAccountState.setAvatar(request.getAvatar()); - currentAccountState.setAccountMark(request.getAccountMark()); - currentAccountState.setAccountName(request.getAccountName()); - currentAccountState.setFirstName(request.getFirstName()); - currentAccountState.setLastName(request.getLastName()); - currentAccountState.setUsername(request.getUsername()); - currentAccountState.setLastUpdateTimestamp(lastUpdateTimestamp); - currentAccountState.setAccessStatus(request.getAccessStatus().toString()); + newAccountState.setAvatar(request.getAvatar()); + newAccountState.setAccountMark(request.getAccountMark()); + newAccountState.setAccountName(request.getAccountName()); + newAccountState.setFirstName(request.getFirstName()); + newAccountState.setLastName(request.getLastName()); + newAccountState.setUsername(request.getUsername()); + newAccountState.setLastUpdateTimestamp(lastUpdateTimestamp); + newAccountState.setAccessStatus(request.getAccessStatus().toString()); if (request.getRolesList() == null || request.getRolesList().isEmpty()) { - currentAccountState.setRoles(Set.of(Role.USER.toString())); + newAccountState.setRoles(Set.of(Role.USER.toString())); } else { - currentAccountState + newAccountState .setRoles(request.getRolesList().stream().map(Enum::toString).collect(Collectors.toSet())); } if (util.validateBirthdayIsSet(request.getBirthday())) { - currentAccountState.setBirthday(LocalDate.of(request.getBirthday().getYear(), + newAccountState.setBirthday(LocalDate.of(request.getBirthday().getYear(), request.getBirthday().getMonth(), request.getBirthday().getDay())); } else { - currentAccountState.setBirthday(null); + newAccountState.setBirthday(null); } transaction.update(newAccountState, currentAccountState); } -- GitLab From 44eeaf7bc6dacfcede35f785571a9b3e75f410e4 Mon Sep 17 00:00:00 2001 From: Dragomir Todorov Date: Mon, 14 Jan 2019 18:57:25 +0200 Subject: [PATCH 7/7] NY-6611: Add roles for admin endpoints --- .../java/biz/nynja/account/grid/ag/AdminServiceImpl.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/biz/nynja/account/grid/ag/AdminServiceImpl.java b/src/main/java/biz/nynja/account/grid/ag/AdminServiceImpl.java index 87fb0fa..d86831a 100644 --- a/src/main/java/biz/nynja/account/grid/ag/AdminServiceImpl.java +++ b/src/main/java/biz/nynja/account/grid/ag/AdminServiceImpl.java @@ -23,6 +23,8 @@ import biz.nynja.account.grpc.CreatePendingAccountRequest; import biz.nynja.account.grpc.CreatePendingAccountResponse; import biz.nynja.account.grpc.ErrorResponse; import biz.nynja.account.grpc.ErrorResponse.Cause; +import biz.nynja.account.permissions.Permitted; +import biz.nynja.account.permissions.RoleConstants; import biz.nynja.account.repositories.AccountRepository; import biz.nynja.account.services.decomposition.AccountCreator; import biz.nynja.account.validation.Validation; @@ -51,6 +53,7 @@ public class AdminServiceImpl extends AdminAccountServiceGrpc.AdminAccountServic } @Override + @Permitted(role = RoleConstants.ACCOUNT_ADMIN) public void getAllAccounts(GetAllAccountsRequest request, StreamObserver responseObserver) { logger.info("Getting accounts ..."); logger.debug("Getting accounts: {} ...", request); @@ -119,6 +122,7 @@ public class AdminServiceImpl extends AdminAccountServiceGrpc.AdminAccountServic } @Override + @Permitted(role = RoleConstants.ACCOUNT_ADMIN) public void getCountOfAllAccounts(EmptyRequest request, StreamObserver responseObserver) { logger.info("Getting count of all accounts ..."); @@ -129,6 +133,7 @@ public class AdminServiceImpl extends AdminAccountServiceGrpc.AdminAccountServic } @Override + @Permitted(role = RoleConstants.ACCOUNT_ADMIN) public void createAccount(CreateAccountRequest request, StreamObserver responseObserver) { logger.info("Creating account from admin console..."); -- GitLab