org.finra.herd.service.impl.UserNamespaceAuthorizationServiceImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of herd-service Show documentation
Show all versions of herd-service Show documentation
This project contains the business service code. This is a classic service tier where business logic is defined along with it's associated
transaction management configuration.
/*
* Copyright 2015 herd contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.finra.herd.service.impl;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.finra.herd.dao.UserNamespaceAuthorizationDao;
import org.finra.herd.dao.config.DaoSpringModuleConfig;
import org.finra.herd.model.AlreadyExistsException;
import org.finra.herd.model.ObjectNotFoundException;
import org.finra.herd.model.annotation.NamespacePermission;
import org.finra.herd.model.annotation.PublishNotificationMessages;
import org.finra.herd.model.api.xml.NamespacePermissionEnum;
import org.finra.herd.model.api.xml.UserAuthorizations;
import org.finra.herd.model.api.xml.UserNamespaceAuthorization;
import org.finra.herd.model.api.xml.UserNamespaceAuthorizationCreateRequest;
import org.finra.herd.model.api.xml.UserNamespaceAuthorizationKey;
import org.finra.herd.model.api.xml.UserNamespaceAuthorizationUpdateRequest;
import org.finra.herd.model.api.xml.UserNamespaceAuthorizations;
import org.finra.herd.model.jpa.NamespaceEntity;
import org.finra.herd.model.jpa.UserNamespaceAuthorizationEntity;
import org.finra.herd.service.CurrentUserService;
import org.finra.herd.service.MessageNotificationEventService;
import org.finra.herd.service.NotificationEventService;
import org.finra.herd.service.UserNamespaceAuthorizationService;
import org.finra.herd.service.helper.AlternateKeyHelper;
import org.finra.herd.service.helper.NamespaceDaoHelper;
import org.finra.herd.service.helper.UserNamespaceAuthorizationHelper;
/**
* The user namespace authorization service implementation.
*/
@Service
@Transactional(value = DaoSpringModuleConfig.HERD_TRANSACTION_MANAGER_BEAN_NAME)
public class UserNamespaceAuthorizationServiceImpl implements UserNamespaceAuthorizationService
{
@Autowired
private AlternateKeyHelper alternateKeyHelper;
@Autowired
private CurrentUserService currentUserService;
@Autowired
private NamespaceDaoHelper namespaceDaoHelper;
@Autowired
private UserNamespaceAuthorizationDao userNamespaceAuthorizationDao;
@Autowired
private UserNamespaceAuthorizationHelper userNamespaceAuthorizationHelper;
@Autowired
private MessageNotificationEventService messageNotificationEventService;
@PublishNotificationMessages
@NamespacePermission(fields = "#request?.userNamespaceAuthorizationKey?.namespace", permissions = NamespacePermissionEnum.GRANT)
@Override
public UserNamespaceAuthorization createUserNamespaceAuthorization(UserNamespaceAuthorizationCreateRequest request)
{
// Validate and trim the request parameters.
validateUserNamespaceAuthorizationCreateRequest(request);
// Get the user namespace authorization key.
UserNamespaceAuthorizationKey key = request.getUserNamespaceAuthorizationKey();
// Ensure a user namespace authorization with the specified name doesn't already exist for the specified namespace.
UserNamespaceAuthorizationEntity userNamespaceAuthorizationEntity = userNamespaceAuthorizationDao.getUserNamespaceAuthorizationByKey(key);
if (userNamespaceAuthorizationEntity != null)
{
throw new AlreadyExistsException(String
.format("Unable to create user namespace authorization with user id \"%s\" and namespace \"%s\" because it already exists.", key.getUserId(),
key.getNamespace()));
}
// Retrieve and ensure that namespace exists with the specified user namespace authorization namespace code.
NamespaceEntity namespaceEntity = namespaceDaoHelper.getNamespaceEntity(key.getNamespace());
// Create and persist a new user namespace authorization entity from the request information.
userNamespaceAuthorizationEntity = createUserNamespaceAuthorizationEntity(key.getUserId(), namespaceEntity, request.getNamespacePermissions());
// Create a user namespace authorization change notification to be sent on create user namespace authorization event.
messageNotificationEventService.processUserNamespaceAuthorizationChangeNotificationEvent(key);
// Create and return the user namespace authorization object from the persisted entity.
return createUserNamespaceAuthorizationFromEntity(userNamespaceAuthorizationEntity);
}
@PublishNotificationMessages
@NamespacePermission(fields = "#key?.namespace", permissions = NamespacePermissionEnum.GRANT)
@Override
public UserNamespaceAuthorization updateUserNamespaceAuthorization(UserNamespaceAuthorizationKey key, UserNamespaceAuthorizationUpdateRequest request)
{
// Validate and trim the key.
validateUserNamespaceAuthorizationKey(key);
// Validate and trim the request parameters.
validateUserNamespaceAuthorizationUpdateRequest(request);
// Retrieve and ensure that a user namespace authorization exists with the specified key.
UserNamespaceAuthorizationEntity userNamespaceAuthorizationEntity = getUserNamespaceAuthorizationEntity(key);
// Get the current user
UserAuthorizations userAuthorizations = currentUserService.getCurrentUser();
// If the current user id is equal to the user id in the namespace authorization key
// and the user namespace authorization entity contains the grant permission
if (userAuthorizations.getUserId().equalsIgnoreCase(key.getUserId()) && userNamespaceAuthorizationEntity.getGrantPermission())
{
// Assert that the request contains the grant namespace permission
Assert.isTrue(request.getNamespacePermissions().contains(NamespacePermissionEnum.GRANT),
"Users are not allowed to remove their own GRANT namespace permission." +
" Please include the GRANT namespace permission in this request, or have another user remove the GRANT permission.");
}
// Update the permissions.
updateNamespacePermissions(userNamespaceAuthorizationEntity, request.getNamespacePermissions());
userNamespaceAuthorizationDao.saveAndRefresh(userNamespaceAuthorizationEntity);
// Create a user namespace authorization change notification to be sent on update user namespace authorization event.
messageNotificationEventService.processUserNamespaceAuthorizationChangeNotificationEvent(key);
// Create and return the user namespace authorization object from the updated entity.
return createUserNamespaceAuthorizationFromEntity(userNamespaceAuthorizationEntity);
}
@NamespacePermission(fields = "#key?.namespace", permissions = NamespacePermissionEnum.READ)
@Override
public UserNamespaceAuthorization getUserNamespaceAuthorization(UserNamespaceAuthorizationKey key)
{
// Validate and trim the key.
validateUserNamespaceAuthorizationKey(key);
// Retrieve and ensure that a user namespace authorization exists with the specified key.
UserNamespaceAuthorizationEntity userNamespaceAuthorizationEntity = getUserNamespaceAuthorizationEntity(key);
// Create and return the user namespace authorization object from the persisted entity.
return createUserNamespaceAuthorizationFromEntity(userNamespaceAuthorizationEntity);
}
@PublishNotificationMessages
@NamespacePermission(fields = "#key?.namespace", permissions = NamespacePermissionEnum.GRANT)
@Override
public UserNamespaceAuthorization deleteUserNamespaceAuthorization(UserNamespaceAuthorizationKey key)
{
// Validate and trim the key.
validateUserNamespaceAuthorizationKey(key);
// Retrieve and ensure that a user namespace authorization exists with the specified key.
UserNamespaceAuthorizationEntity userNamespaceAuthorizationEntity = getUserNamespaceAuthorizationEntity(key);
// Delete the business object definition.
userNamespaceAuthorizationDao.delete(userNamespaceAuthorizationEntity);
// Create a user namespace authorization change notification to be sent on delete user namespace authorization event.
messageNotificationEventService.processUserNamespaceAuthorizationChangeNotificationEvent(key);
// Create and return the user namespace authorization object from the deleted entity.
return createUserNamespaceAuthorizationFromEntity(userNamespaceAuthorizationEntity);
}
@Override
public UserNamespaceAuthorizations getUserNamespaceAuthorizationsByUserId(String userId)
{
// Validate and trim the user id.
Assert.hasText(userId, "A user id must be specified.");
String userIdLocal = userId.trim();
// Retrieve and return a list of user namespace authorization entities for the specified user id.
List userNamespaceAuthorizationEntities =
userNamespaceAuthorizationDao.getUserNamespaceAuthorizationsByUserId(userIdLocal);
// Create and populate the user namespace authorizations object from the returned entities.
UserNamespaceAuthorizations userNamespaceAuthorizations = new UserNamespaceAuthorizations();
userNamespaceAuthorizations.getUserNamespaceAuthorizations().addAll(createUserNamespaceAuthorizationsFromEntities(userNamespaceAuthorizationEntities));
return userNamespaceAuthorizations;
}
@NamespacePermission(fields = "#namespace", permissions = NamespacePermissionEnum.READ)
@Override
public UserNamespaceAuthorizations getUserNamespaceAuthorizationsByNamespace(String namespace)
{
// Validate and trim the namespace code.
Assert.hasText(namespace, "A namespace must be specified.");
String namespaceLocal = namespace.trim();
// Validate that specified namespace exists.
namespaceDaoHelper.getNamespaceEntity(namespaceLocal);
// Retrieve and return a list of user namespace authorization entities for the specified namespace.
List userNamespaceAuthorizationEntities =
userNamespaceAuthorizationDao.getUserNamespaceAuthorizationsByNamespace(namespaceLocal);
// Create and populate the user namespace authorizations object from the returned entities.
UserNamespaceAuthorizations userNamespaceAuthorizations = new UserNamespaceAuthorizations();
userNamespaceAuthorizations.getUserNamespaceAuthorizations().addAll(createUserNamespaceAuthorizationsFromEntities(userNamespaceAuthorizationEntities));
return userNamespaceAuthorizations;
}
/**
* Validates the user namespace authorization create request. This method also trims the request parameters.
*
* @param request the user namespace authorization create request
*/
private void validateUserNamespaceAuthorizationCreateRequest(UserNamespaceAuthorizationCreateRequest request)
{
Assert.notNull(request, "A user namespace authorization create request must be specified.");
validateUserNamespaceAuthorizationKey(request.getUserNamespaceAuthorizationKey());
validateNamespacePermissions(request.getNamespacePermissions());
}
/**
* Validates the user namespace authorization update request. This method also trims the request parameters.
*
* @param request the user namespace authorization update request
*/
private void validateUserNamespaceAuthorizationUpdateRequest(UserNamespaceAuthorizationUpdateRequest request)
{
Assert.notNull(request, "A user namespace authorization update request must be specified.");
validateNamespacePermissions(request.getNamespacePermissions());
}
/**
* Validates the user namespace authorization key. This method also trims the key parameters.
*
* @param key the user namespace authorization key
*
* @throws IllegalArgumentException if any validation errors were found
*/
public void validateUserNamespaceAuthorizationKey(UserNamespaceAuthorizationKey key) throws IllegalArgumentException
{
Assert.notNull(key, "A user namespace authorization key must be specified.");
key.setNamespace(alternateKeyHelper.validateStringParameter("namespace", key.getNamespace()));
key.setUserId(alternateKeyHelper.validateStringParameter("user id", key.getUserId()));
}
/**
* Validates a list of namespace permissions.
*
* @param namespacePermissions the list of namespace permissions
*
* @throws IllegalArgumentException if any validation errors were found
*/
public void validateNamespacePermissions(List namespacePermissions) throws IllegalArgumentException
{
Assert.isTrue(!CollectionUtils.isEmpty(namespacePermissions), "Namespace permissions must be specified.");
// Ensure permission isn't a duplicate by using a hash set with uppercase permission values for case insensitivity.
Set validatedNamespacePermissions = new HashSet<>();
// Validate the permissions.
for (NamespacePermissionEnum namespacePermission : namespacePermissions)
{
// Fail if duplicate permission value is detected.
if (validatedNamespacePermissions.contains(namespacePermission))
{
throw new IllegalArgumentException(String.format("Duplicate namespace permission \"%s\" is found.", namespacePermission.value()));
}
validatedNamespacePermissions.add(namespacePermission);
}
}
/**
* Creates and persists a new user namespace authorization entity.
*
* @param userId the user id
* @param namespaceEntity the namespace entity
* @param namespacePermissions the list of namespace permissions
*
* @return the newly created user namespace authorization entity
*/
private UserNamespaceAuthorizationEntity createUserNamespaceAuthorizationEntity(String userId, NamespaceEntity namespaceEntity,
List namespacePermissions)
{
UserNamespaceAuthorizationEntity userNamespaceAuthorizationEntity = new UserNamespaceAuthorizationEntity();
userNamespaceAuthorizationEntity.setUserId(userId);
userNamespaceAuthorizationEntity.setNamespace(namespaceEntity);
updateNamespacePermissions(userNamespaceAuthorizationEntity, namespacePermissions);
return userNamespaceAuthorizationDao.saveAndRefresh(userNamespaceAuthorizationEntity);
}
/**
* Sets relative flags on the user namespace authorization entity as per specified list of namespace permissions.
*
* @param userNamespaceAuthorizationEntity the user namespace authorization entity
* @param namespacePermissions the list of namespace permissions
*/
private void updateNamespacePermissions(UserNamespaceAuthorizationEntity userNamespaceAuthorizationEntity,
List namespacePermissions)
{
userNamespaceAuthorizationEntity.setReadPermission(namespacePermissions.contains(NamespacePermissionEnum.READ));
userNamespaceAuthorizationEntity.setWritePermission(namespacePermissions.contains(NamespacePermissionEnum.WRITE));
userNamespaceAuthorizationEntity.setExecutePermission(namespacePermissions.contains(NamespacePermissionEnum.EXECUTE));
userNamespaceAuthorizationEntity.setGrantPermission(namespacePermissions.contains(NamespacePermissionEnum.GRANT));
userNamespaceAuthorizationEntity.setWriteDescriptiveContentPermission(namespacePermissions.contains(NamespacePermissionEnum.WRITE_DESCRIPTIVE_CONTENT));
userNamespaceAuthorizationEntity.setWriteAttributePermission(namespacePermissions.contains(NamespacePermissionEnum.WRITE_ATTRIBUTE));
}
/**
* Creates a list of user namespace authorizations from the list of persisted entities.
*
* @param userNamespaceAuthorizationEntities the list of user namespace authorization entities
*
* @return the list of user namespace authorizations
*/
private List createUserNamespaceAuthorizationsFromEntities(
List userNamespaceAuthorizationEntities)
{
List userNamespaceAuthorizations = new ArrayList<>();
for (UserNamespaceAuthorizationEntity userNamespaceAuthorizationEntity : userNamespaceAuthorizationEntities)
{
userNamespaceAuthorizations.add(createUserNamespaceAuthorizationFromEntity(userNamespaceAuthorizationEntity));
}
return userNamespaceAuthorizations;
}
/**
* Creates the user namespace authorization from the persisted entity.
*
* @param userNamespaceAuthorizationEntity the user namespace authorization entity
*
* @return the user namespace authorization
*/
private UserNamespaceAuthorization createUserNamespaceAuthorizationFromEntity(UserNamespaceAuthorizationEntity userNamespaceAuthorizationEntity)
{
UserNamespaceAuthorization userNamespaceAuthorization = new UserNamespaceAuthorization();
userNamespaceAuthorization.setId(userNamespaceAuthorizationEntity.getId());
UserNamespaceAuthorizationKey userNamespaceAuthorizationKey = new UserNamespaceAuthorizationKey();
userNamespaceAuthorization.setUserNamespaceAuthorizationKey(userNamespaceAuthorizationKey);
userNamespaceAuthorizationKey.setUserId(userNamespaceAuthorizationEntity.getUserId());
userNamespaceAuthorizationKey.setNamespace(userNamespaceAuthorizationEntity.getNamespace().getCode());
userNamespaceAuthorization.setNamespacePermissions(userNamespaceAuthorizationHelper.getNamespacePermissions(userNamespaceAuthorizationEntity));
return userNamespaceAuthorization;
}
/**
* Gets a storage entity based on the storage name and makes sure that it exists.
*
* @param key the user namespace authorization key (case insensitive)
*
* @return the user namespace authorization entity
* @throws org.finra.herd.model.ObjectNotFoundException if the user namespace authorization entity doesn't exist
*/
private UserNamespaceAuthorizationEntity getUserNamespaceAuthorizationEntity(UserNamespaceAuthorizationKey key) throws ObjectNotFoundException
{
UserNamespaceAuthorizationEntity userNamespaceAuthorizationEntity = userNamespaceAuthorizationDao.getUserNamespaceAuthorizationByKey(key);
if (userNamespaceAuthorizationEntity == null)
{
throw new ObjectNotFoundException(
String.format("User namespace authorization with user id \"%s\" and namespace \"%s\" doesn't exist.", key.getUserId(), key.getNamespace()));
}
return userNamespaceAuthorizationEntity;
}
}