package com.sequenceiq.cloudbreak.service.recipe;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.transaction.Transactional;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.stereotype.Service;
import com.sequenceiq.cloudbreak.common.type.APIResourceType;
import com.sequenceiq.cloudbreak.common.type.CbUserRole;
import com.sequenceiq.cloudbreak.controller.BadRequestException;
import com.sequenceiq.cloudbreak.controller.NotFoundException;
import com.sequenceiq.cloudbreak.domain.CbUser;
import com.sequenceiq.cloudbreak.domain.Recipe;
import com.sequenceiq.cloudbreak.repository.HostGroupRepository;
import com.sequenceiq.cloudbreak.repository.RecipeRepository;
import com.sequenceiq.cloudbreak.service.DuplicateKeyValueException;
@Service
@Transactional
public class RecipeService {
@Inject
private RecipeRepository recipeRepository;
@Inject
private HostGroupRepository hostGroupRepository;
@Inject
private RecipeMigration recipeMigration;
@PostConstruct
public void migrate() {
recipeMigration.migrate();
}
@Transactional(Transactional.TxType.NEVER)
public Recipe create(CbUser user, Recipe recipe) {
recipe.setOwner(user.getUserId());
recipe.setAccount(user.getAccount());
try {
return recipeRepository.save(recipe);
} catch (DataIntegrityViolationException ex) {
throw new DuplicateKeyValueException(APIResourceType.RECIPE, recipe.getName(), ex);
}
}
@PostAuthorize("hasPermission(returnObject,'read')")
public Recipe get(Long id) {
Recipe recipe = recipeRepository.findOne(id);
if (recipe == null) {
throw new NotFoundException(String.format("Recipe '%s' not found", id));
}
return recipe;
}
public Set<Recipe> retrievePrivateRecipes(CbUser user) {
return recipeRepository.findForUser(user.getUserId());
}
public Set<Recipe> retrieveAccountRecipes(CbUser user) {
if (user.getRoles().contains(CbUserRole.ADMIN)) {
return recipeRepository.findAllInAccount(user.getAccount());
} else {
return recipeRepository.findPublicInAccountForUser(user.getUserId(), user.getAccount());
}
}
public Recipe getPrivateRecipe(String name, CbUser user) {
Recipe recipe = recipeRepository.findByNameForUser(name, user.getUserId());
if (recipe == null) {
throw new NotFoundException(String.format("Recipe '%s' not found.", name));
}
return recipe;
}
public Recipe getPublicRecipe(String name, CbUser user) {
Recipe recipe = recipeRepository.findByNameInAccount(name, user.getAccount());
if (recipe == null) {
throw new NotFoundException(String.format("Recipe '%s' not found.", name));
}
return recipe;
}
public void delete(Long id, CbUser user) {
Recipe recipe = get(id);
if (recipe == null) {
throw new NotFoundException(String.format("Recipe '%s' not found.", id));
}
delete(recipe, user);
}
public void delete(String name, CbUser user) {
Recipe recipe = recipeRepository.findByNameInAccount(name, user.getAccount());
if (recipe == null) {
throw new NotFoundException(String.format("Recipe '%s' not found.", name));
}
delete(recipe, user);
}
private void delete(Recipe recipe, CbUser user) {
if (hostGroupRepository.findAllHostGroupsByRecipe(recipe.getId()).isEmpty()) {
if (!user.getUserId().equals(recipe.getOwner()) && !user.getRoles().contains(CbUserRole.ADMIN)) {
throw new BadRequestException("Public recipes can only be deleted by owners or account admins.");
} else {
recipeRepository.delete(recipe);
}
} else {
throw new BadRequestException(String.format(
"There are clusters associated with recipe '%s'. Please remove these before deleting the recipe.", recipe.getId()));
}
}
}