package eu.dnetlib.uoamonitorservice.controllers; import eu.dnetlib.uoaadmintoolslibrary.handlers.ForbiddenException; import eu.dnetlib.uoaadmintoolslibrary.handlers.utils.RolesUtils; import eu.dnetlib.uoamonitorservice.dao.CategoryDAO; import eu.dnetlib.uoamonitorservice.dao.StakeholderDAO; import eu.dnetlib.uoamonitorservice.dao.SubCategoryDAO; import eu.dnetlib.uoamonitorservice.dao.TopicDAO; import eu.dnetlib.uoamonitorservice.entities.*; import eu.dnetlib.uoamonitorservice.handlers.EntityNotFoundException; import eu.dnetlib.uoamonitorservice.handlers.PathNotValidException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; @RestController @CrossOrigin(origins = "*") public class CategoryController { private final Logger log = LogManager.getLogger(this.getClass()); @Autowired private RolesUtils rolesUtils; @Autowired private StakeholderDAO stakeholderDAO; @Autowired private TopicDAO topicDAO; @Autowired private CategoryDAO categoryDAO; @Autowired private SubCategoryDAO subCategoryDAO; @Autowired private SubCategoryController subCategoryController; public Category buildCategory(Category categoryFull) { Category category = new Category<>(categoryFull); List subCategories = new ArrayList<>(); List subCategoriesFull = new ArrayList<>(); for (SubCategory> subCategory : categoryFull.getSubCategories()) { SubCategory> subcategoryFull = subCategoryController.buildSubCategory(subCategory); subCategoriesFull.add(subcategoryFull); subCategories.add(subcategoryFull.getId()); } categoryFull.setSubCategories(subCategoriesFull); category.setSubCategories(subCategories); Date date = new Date(); category.setCreationDate(date); category.setUpdateDate(date); categoryFull.setCreationDate(date); categoryFull.setUpdateDate(date); categoryDAO.save(category); categoryFull.setId(category.getId()); return categoryFull; } @PreAuthorize("isAuthenticated()") @RequestMapping(value = "/{stakeholderId}/{topicId}/save", method = RequestMethod.POST) public Category saveCategory(@PathVariable("stakeholderId") String stakeholderId, @PathVariable("topicId") String topicId, @RequestBody Category categoryFull) { log.debug("save category"); log.debug("Alias: " + categoryFull.getAlias() + " - Id: " + categoryFull.getId() + " - Stakeholder: " + stakeholderId + " - Topic: " + topicId); Stakeholder stakeholder = stakeholderDAO.findById(stakeholderId); if (stakeholder != null) { if (!rolesUtils.hasUpdateAuthority(stakeholder.getType(), stakeholder.getAlias())) { // EXCEPTION - Access denied throw new ForbiddenException("Save Category: You are not authorized to update stakeholder with id: " + stakeholderId); } Category oldCategory = null; if (categoryFull.getId() != null) { oldCategory = categoryDAO.findById(categoryFull.getId()); if (oldCategory == null) { // EXCEPTION - Category not found throw new EntityNotFoundException("save category: Category with id: " + categoryFull.getId() + " not found"); } } Topic topic = topicDAO.findById(topicId); if (topic != null) { if (stakeholder.getTopics().contains(topicId)) { Category category = new Category<>(categoryFull); Date date = new Date(); category.setUpdateDate(date); categoryFull.setUpdateDate(date); List subCategories = new ArrayList<>(); // if category not exists (no id), create a new default subcategory, identical to category if (categoryFull.getId() == null) { category.setCreationDate(date); categoryFull.setCreationDate(date); SubCategory subCategory = new SubCategory<>(); subCategory.createOverviewSubCategory(categoryFull); subCategoryDAO.save(subCategory); List subCategoriesFull = categoryFull.getSubCategories(); subCategoriesFull.add(subCategory); for (SubCategory oldSubCategory : subCategoriesFull) { subCategories.add(oldSubCategory.getId()); } } else { for (String subCategoryId : oldCategory.getSubCategories()) { SubCategory subCategory = subCategoryDAO.findById(subCategoryId); if (subCategory == null) { // EXCEPTION - SubCategory not found throw new EntityNotFoundException("Save category: SubCategory with id: " + subCategoryId + " not found (subcategory exists in category: " + category.getId() + ")"); } subCategories.add(subCategory.getId()); } } category.setSubCategories(subCategories); if (stakeholder.getDefaultId() == null) { if (categoryFull.getId() == null) { categoryDAO.save(category); onSaveDefaultCategory(category, topicId); } else { onUpdateDefaultCategory(category, oldCategory); categoryDAO.save(category); } } else { categoryDAO.save(category); } List categories = topic.getCategories(); int index = categories.indexOf(category.getId()); if (index == -1) { categories.add(category.getId()); topicDAO.save(topic); log.debug("Category saved!"); categoryFull.setId(category.getId()); } } else { // EXCEPTION - Topic not found in Stakeholder: stakeholder.getAlias(); throw new PathNotValidException("Save category: Topic with id: " + topicId + " not found in Stakeholder: " + stakeholderId); } } else { // EXCEPTION - Topic not found throw new EntityNotFoundException("Save category: Topic with id: " + topicId + " not found"); } } else { // EXCEPTION - Stakeholder not found throw new EntityNotFoundException("Save category: Stakeholder with id: " + stakeholderId + " not found"); } return categoryFull; } public void onSaveDefaultCategory(Category category, String topicId) { log.debug("On save default category"); List topics = topicDAO.findByDefaultId(topicId); for (Topic topic : topics) { Category categoryNew = new Category(); categoryNew.copyFromDefault(category); categoryDAO.save(categoryNew); List categories = topic.getCategories(); categories.add(categoryNew.getId()); topicDAO.save(topic); } String subCategoryOverviewId = category.getSubCategories().get(0); SubCategory subCategoryOverview = subCategoryDAO.findById(subCategoryOverviewId); subCategoryController.onSaveDefaultSubCategory(subCategoryOverview, category.getId()); } public void onUpdateDefaultCategory(Category category, Category oldCategory) { log.debug("On update default category"); List categories = categoryDAO.findByDefaultId(category.getId()); boolean changed = false; for (Category categoryBasedOnDefault : categories) { if (category.getName() != null && !category.getName().equals(categoryBasedOnDefault.getName()) && (oldCategory.getName() == null || oldCategory.getName().equals(categoryBasedOnDefault.getName()))) { categoryBasedOnDefault.setName(category.getName()); categoryBasedOnDefault.setAlias(category.getAlias()); changed = true; } if (category.getDescription() != null && !category.getDescription().equals(categoryBasedOnDefault.getDescription()) && (oldCategory.getDescription() == null || oldCategory.getDescription().equals(categoryBasedOnDefault.getDescription()))) { categoryBasedOnDefault.setDescription(category.getDescription()); changed = true; } if (!changed) { continue; } categoryBasedOnDefault.setUpdateDate(category.getUpdateDate()); categoryDAO.save(categoryBasedOnDefault); } } @PreAuthorize("isAuthenticated()") @RequestMapping(value = "/{stakeholderId}/{topicId}/{categoryId}/delete", method = RequestMethod.DELETE) public boolean deleteCategory(@PathVariable("stakeholderId") String stakeholderId, @PathVariable("topicId") String topicId, @PathVariable("categoryId") String categoryId, @RequestParam(required = false) String children) { log.debug("delete category"); log.debug("Id: " + categoryId + " - Stakeholder: " + stakeholderId + " - Topic: " + topicId); Stakeholder stakeholder = stakeholderDAO.findById(stakeholderId); if (stakeholder != null) { if (!rolesUtils.hasUpdateAuthority(stakeholder.getType(), stakeholder.getAlias())) { // EXCEPTION - Access denied throw new ForbiddenException("Delete category: You are not authorized to update stakeholder with id: " + stakeholderId); } Topic topic = topicDAO.findById(topicId); if (topic != null) { if (stakeholder.getTopics().contains(topicId)) { Category category = categoryDAO.findById(categoryId); if (category != null) { if (category.getDefaultId() != null && !rolesUtils.hasCreateAndDeleteAuthority(stakeholder.getType())) { // EXCEPTION - Access denied throw new ForbiddenException("Delete category: You are not authorized to delete a default Category in stakeholder with id: " + stakeholderId); } List categories = topic.getCategories(); int index = categories.indexOf(categoryId); if (index != -1) { // this category belongs in default profile if (topic.getDefaultId() == null && children != null) { onDeleteDefaultCategory(categoryId, topicId, children); } subCategoryController.deleteTree(category); category.setSubCategories(null); categories.remove(index); topicDAO.save(topic); categoryDAO.delete(categoryId); log.debug("Category deleted!"); } else { // EXCEPTION - Category not found in Stakeholder: stakeholder.getAlias(); -> Topic: topic.getAlias(); throw new PathNotValidException("Delete category: Category with id: " + categoryId + " not found in Topic: " + topicId); } } else { // EXCEPTION - Category not found throw new EntityNotFoundException("Delete category: Category with id: " + categoryId + " not found"); } } else { // EXCEPTION - Topic not found in Stakeholder: stakeholder.getAlias(); throw new PathNotValidException("Delete category: Topic with id: " + topicId + " not found in Stakeholder: " + stakeholderId); } } else { // EXCEPTION - Topic not found throw new EntityNotFoundException("Delete category: Topic with id: " + topicId + " not found"); } } else { // EXCEPTION - Stakeholder not found throw new EntityNotFoundException("Delete category: Stakeholder with id: " + stakeholderId + " not found"); } return true; } public boolean onDeleteDefaultCategory(String defaultCategoryId, String defaultTopicId, String children) { if (children.equals("delete")) { List topics = topicDAO.findByDefaultId(defaultTopicId); List categories = categoryDAO.findByDefaultId(defaultCategoryId); for (Topic topic : topics) { Iterator categoriesIterator = categories.iterator(); while (categoriesIterator.hasNext()) { Category category = categoriesIterator.next(); String categoryId = category.getId(); if (topic.getCategories() != null && topic.getCategories().contains(categoryId)) { categoriesIterator.remove(); topic.getCategories().remove(categoryId); topicDAO.save(topic); subCategoryController.deleteTree(category); categoryDAO.delete(categoryId); log.debug("Category with id: " + categoryId + " deleted!"); break; } } } } else if (children.equals("disconnect")) { List categories = categoryDAO.findByDefaultId(defaultCategoryId); for (Category category : categories) { subCategoryController.disConnectTree(category); category.setDefaultId(null); categoryDAO.save(category); log.debug("DefaultId for Category with id: " + category.getId() + " empty!"); } } return true; } @PreAuthorize("isAuthenticated()") @RequestMapping(value = "/{stakeholderId}/{topicId}/reorder", method = RequestMethod.POST) public List reorderCategories(@PathVariable("stakeholderId") String stakeholderId, @PathVariable("topicId") String topicId, @RequestBody List categories) { log.debug("reorder categories"); log.debug("Stakeholder: " + stakeholderId + " - Topic: " + topicId); Topic topic = checkForExceptions(stakeholderId, topicId); List oldCategories = topic.getCategories(); for (String categoryId : oldCategories) { if (!categories.contains(categoryId)) { categories.add(categoryId); } } topic.setCategories(categories); List categoriesFull = new ArrayList<>(); for (String categoryId : categories) { Category category = categoryDAO.findById(categoryId); if (category == null) { // EXCEPTION - Category not found throw new EntityNotFoundException("Reorder Categories: Category with id: " + categoryId + " not found"); } categoriesFull.add(category); } topicDAO.save(topic); log.debug("Categories reordered!"); return categoriesFull; } @PreAuthorize("isAuthenticated()") @RequestMapping(value = "/{stakeholderId}/{topicId}/{categoryId}/change-visibility", method = RequestMethod.POST) public Category changeCategoryVisibility(@PathVariable("stakeholderId") String stakeholderId, @PathVariable("topicId") String topicId, @PathVariable("categoryId") String categoryId, @RequestParam("visibility") Visibility visibility, @RequestParam(required = false) Boolean propagate) { log.debug("change category visibility: " + visibility + " - toggle propagate: " + ((propagate != null && propagate) ? "true" : "false")); log.debug("Stakeholder: " + stakeholderId + " - Topic: " + topicId + " - Category: " + categoryId); Stakeholder stakeholder = stakeholderDAO.findById(stakeholderId); if (stakeholder != null) { if (!rolesUtils.hasUpdateAuthority(stakeholder.getType(), stakeholder.getAlias())) { // EXCEPTION - Access denied throw new ForbiddenException("Toggle category: You are not authorized to update stakeholder with id: " + stakeholderId); } Topic topic = topicDAO.findById(topicId); if (topic != null) { if (stakeholder.getTopics().contains(topicId)) { if (topic.getCategories().contains(categoryId)) { return changeVisibilityTree(categoryId, visibility, propagate); } else { // EXCEPTION - Category not found in Stakeholder: stakeholder.getAlias(); -> Topic: topic.getAlias(); throw new PathNotValidException("Toggle category: Category with id: " + categoryId + " not found in Topic: " + topicId); } } else { // EXCEPTION - Topic not found in Stakeholder: stakeholder.getAlias(); throw new PathNotValidException("Toggle category: Topic with id: " + topicId + " not found in Stakeholder: " + stakeholderId); } } else { // EXCEPTION - Topic not found throw new EntityNotFoundException("Toggle category: Topic with id: " + topicId + " not found"); } } else { // EXCEPTION - Stakeholder not found throw new EntityNotFoundException("Toggle category: Stakeholder with id: " + stakeholderId + " not found"); } } public Category changeVisibilityTree(String categoryId, Visibility visibility, Boolean propagate) { Category category = categoryDAO.findById(categoryId); if (category == null) { // EXCEPTION - Category not found throw new EntityNotFoundException("Change category visibility: Category with id: " + categoryId + " not found"); } Category categoryFull = new Category(category); List subCategoriesFull = new ArrayList<>(); if (propagate != null && propagate) { for (String subCategoryId : category.getSubCategories()) { subCategoriesFull.add(subCategoryController.changeVisibilityTree(subCategoryId, visibility, propagate)); } } category.setVisibility(visibility); categoryDAO.save(category); log.debug("Category toggled!"); categoryFull.setVisibility(visibility); categoryFull.setSubCategories(subCategoriesFull); return categoryFull; } private Topic checkForExceptions(String stakeholderId, String topicId) { Stakeholder stakeholder = stakeholderDAO.findById(stakeholderId); if (stakeholder == null) { // EXCEPTION - Stakeholder not found throw new EntityNotFoundException("checkForExceptions category: Stakeholder with id: " + stakeholderId + " not found"); } if (!rolesUtils.hasUpdateAuthority(stakeholder.getType(), stakeholder.getAlias())) { // EXCEPTION - Access denied throw new ForbiddenException("checkForExceptions category: You are not authorized to update stakeholder with id: " + stakeholderId); } Topic topic = topicDAO.findById(topicId); if (topic == null) { // EXCEPTION - Topic not found throw new EntityNotFoundException("checkForExceptions category: Topic with id: " + topicId + " not found"); } if (!stakeholder.getTopics().contains(topicId)) { // EXCEPTION - Topic not found in Stakeholder: stakeholder.getAlias(); throw new PathNotValidException("checkForExceptions category: Topic with id: " + topicId + " not found in Stakeholder: " + stakeholderId); } return topic; } public void deleteTree(Topic topic) { List categories = topic.getCategories(); for (String categoryId : categories) { Category category = categoryDAO.findById(categoryId); if (category == null) { // EXCEPTION - Category not found throw new EntityNotFoundException("Category delete tree: Category with id: " + categoryId + " not found (category exists in topic: " + topic.getId() + ")"); } subCategoryController.deleteTree(category); categoryDAO.delete(categoryId); } } public void disConnectTree(Topic topic) { List categories = topic.getCategories(); for (String categoryId : categories) { Category category = categoryDAO.findById(categoryId); if (category == null) { // EXCEPTION - Category not found throw new EntityNotFoundException("Category disconnect tree: Category with id: " + categoryId + " not found (category exists in topic: " + topic.getId() + ")"); } subCategoryController.disConnectTree(category); category.setDefaultId(null); categoryDAO.save(category); } } }