Some code formattig, added function for fixing item and asset permissions (sometimes they are not correctly inherited from the folder.
parent
4251fd1df9
commit
7cea45560a
|
|
@ -580,16 +580,28 @@ public class PagesController {
|
||||||
|
|
||||||
final Page page = pageManager.findPageForCategory(category);
|
final Page page = pageManager.findPageForCategory(category);
|
||||||
pagePropertiesModel.setProperties(page.getProperties());
|
pagePropertiesModel.setProperties(page.getProperties());
|
||||||
if (itemName.equals("index") || itemName.isBlank()) {
|
try {
|
||||||
return themesMvc.getMvcTemplate(
|
final String result;
|
||||||
uriInfo, "pages", page.getDisplayName()
|
if (itemName.equals("index") || itemName.isBlank()) {
|
||||||
);
|
result = themesMvc.getMvcTemplate(
|
||||||
} else {
|
uriInfo, "pages", page.getDisplayName()
|
||||||
return themesMvc.getMvcTemplate(
|
);
|
||||||
uriInfo, "pages", "item-page"
|
|
||||||
|
} else {
|
||||||
|
result = themesMvc.getMvcTemplate(
|
||||||
|
uriInfo, "pages", "item-page"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new WebApplicationException(
|
||||||
|
"An error occured while rendering the page.",
|
||||||
|
ex,
|
||||||
|
Response.serverError().entity(
|
||||||
|
"An error occured while rendering the page."
|
||||||
|
).build()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initSiteInfoModel(
|
private void initSiteInfoModel(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.pages.models;
|
||||||
|
|
||||||
|
import org.librecms.contentsection.ContentItem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
public class ContentItemListItemModel extends AbstractContentItemListItemModel {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return ContentItem.class.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.pages.models;
|
||||||
|
|
||||||
|
import org.librecms.contentsection.ContentItem;
|
||||||
|
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@RequestScoped
|
||||||
|
public class ContentItemListModelBuilder
|
||||||
|
extends AbstractContentItemListItemModelBuilder<ContentItem, ContentItemListItemModel> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<ContentItem> buildsListItemModelFor() {
|
||||||
|
return ContentItem.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ContentItemListItemModel buildModel() {
|
||||||
|
return new ContentItemListItemModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -251,10 +251,11 @@ public class ItemListModel {
|
||||||
criteriaBuilder.isNull(catJoin.get("type")),
|
criteriaBuilder.isNull(catJoin.get("type")),
|
||||||
criteriaBuilder.equal(
|
criteriaBuilder.equal(
|
||||||
from.get("version"), ContentItemVersion.LIVE
|
from.get("version"), ContentItemVersion.LIVE
|
||||||
),
|
|
||||||
buildPermissionsCheck(
|
|
||||||
criteriaBuilder, from, permissionsJoin
|
|
||||||
)
|
)
|
||||||
|
// ,
|
||||||
|
// buildPermissionsCheck(
|
||||||
|
// criteriaBuilder, from, permissionsJoin
|
||||||
|
// )
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -265,7 +266,7 @@ public class ItemListModel {
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
);
|
);
|
||||||
|
|
||||||
return entityManager
|
final List<? extends AbstractContentItemListItemModel> result = entityManager
|
||||||
.createQuery(criteriaQuery)
|
.createQuery(criteriaQuery)
|
||||||
.getResultList()
|
.getResultList()
|
||||||
.stream()
|
.stream()
|
||||||
|
|
@ -278,6 +279,8 @@ public class ItemListModel {
|
||||||
.limit(pageSize)
|
.limit(pageSize)
|
||||||
.map(this::buildListItemModel)
|
.map(this::buildListItemModel)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Category> collectCategories(final Category category) {
|
private List<Category> collectCategories(final Category category) {
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,8 @@ public class ConfigurationController {
|
||||||
return "org/librecms/ui/contentsection/configuration/index.xhtml";
|
return "org/librecms/ui/contentsection/configuration/index.xhtml";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the current user is permitted to access the configurations page
|
* Checks if the current user is permitted to access the configurations page
|
||||||
* of the content section.
|
* of the content section.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections;
|
||||||
|
|
||||||
|
import org.libreccm.categorization.Categorization;
|
||||||
|
import org.libreccm.security.AuthorizationRequired;
|
||||||
|
import org.libreccm.security.PermissionManager;
|
||||||
|
import org.librecms.contentsection.Asset;
|
||||||
|
import org.librecms.contentsection.ContentItem;
|
||||||
|
import org.librecms.contentsection.ContentSection;
|
||||||
|
import org.librecms.contentsection.ContentSectionManager;
|
||||||
|
import org.librecms.contentsection.Folder;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.mvc.Controller;
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller for the fix item and asset permissions function.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@RequestScoped
|
||||||
|
@Controller
|
||||||
|
@Path("/{sectionIdentifier}/configuration/fix-item-and-asset-permissions")
|
||||||
|
public class ConfigurationFixItemPermissionsController {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to check the admin permissions of a content section.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private AdminPermissionsChecker adminPermissionsChecker;
|
||||||
|
|
||||||
|
// @Inject
|
||||||
|
// private ContentSectionManager sectionManager;
|
||||||
|
@Inject
|
||||||
|
private ContentSectionModel sectionModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common functions for views working with {@link ContentSection}s.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ContentSectionsUi sectionsUi;
|
||||||
|
|
||||||
|
// @Inject
|
||||||
|
// private PermissionManager permissionManager;
|
||||||
|
//
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private FixItemPermissionsTaskManager taskManager;
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/")
|
||||||
|
@AuthorizationRequired
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
public String fixItemAndAssetPermissions(
|
||||||
|
@PathParam("sectionIdentifier") final String sectionIdentifierParam
|
||||||
|
) {
|
||||||
|
final Optional<ContentSection> sectionResult = sectionsUi
|
||||||
|
.findContentSection(sectionIdentifierParam);
|
||||||
|
if (!sectionResult.isPresent()) {
|
||||||
|
return sectionsUi.showContentSectionNotFound(sectionIdentifierParam);
|
||||||
|
}
|
||||||
|
final ContentSection section = sectionResult.get();
|
||||||
|
sectionModel.setSection(section);
|
||||||
|
if (!adminPermissionsChecker.canAdministerContentTypes(section)) {
|
||||||
|
return sectionsUi.showAccessDenied(
|
||||||
|
"sectionIdentifier", sectionIdentifierParam
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fixContentItemPermissions(section.getRootDocumentsFolder());
|
||||||
|
// fixAssetPermissions(section.getRootAssetsFolder());
|
||||||
|
|
||||||
|
taskManager.fixItemPermissions(section);
|
||||||
|
|
||||||
|
return String.format(
|
||||||
|
"redirect:%s/configuration", sectionIdentifierParam
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// private void fixContentItemPermissions(final Folder folder) {
|
||||||
|
// final List<ContentItem> items = folder
|
||||||
|
// .getObjects()
|
||||||
|
// .stream()
|
||||||
|
// .map(Categorization::getCategorizedObject)
|
||||||
|
// .filter(obj -> obj instanceof ContentItem)
|
||||||
|
// .map(obj -> (ContentItem) obj)
|
||||||
|
// .collect(Collectors.toList());
|
||||||
|
//
|
||||||
|
// for(final ContentItem item : items) {
|
||||||
|
// permissionManager.copyPermissions(folder, item, true);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// for(final Folder subFolder : folder.getSubFolders()) {
|
||||||
|
// fixContentItemPermissions(subFolder);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private void fixAssetPermissions(final Folder folder) {
|
||||||
|
// final List<Asset> assets = folder
|
||||||
|
// .getObjects()
|
||||||
|
// .stream()
|
||||||
|
// .map(Categorization::getCategorizedObject)
|
||||||
|
// .filter(obj -> obj instanceof Asset)
|
||||||
|
// .map(obj -> (Asset) obj)
|
||||||
|
// .collect(Collectors.toList());
|
||||||
|
//
|
||||||
|
// for(final Asset asset : assets) {
|
||||||
|
// permissionManager.copyPermissions(folder, asset, true);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// for(final Folder subFolder : folder.getSubFolders()) {
|
||||||
|
// fixAssetPermissions(subFolder);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
@ -76,6 +76,7 @@ public class ContentSectionApplication extends Application {
|
||||||
classes.add(ConfigurationController.class);
|
classes.add(ConfigurationController.class);
|
||||||
classes.add(ConfigurationContactEntryKeysController.class);
|
classes.add(ConfigurationContactEntryKeysController.class);
|
||||||
classes.add(ConfigurationDocumentTypesController.class);
|
classes.add(ConfigurationDocumentTypesController.class);
|
||||||
|
classes.add(ConfigurationFixItemPermissionsController.class);
|
||||||
classes.add(ConfigurationLifecyclesController.class);
|
classes.add(ConfigurationLifecyclesController.class);
|
||||||
classes.add(ConfigurationRolesController.class);
|
classes.add(ConfigurationRolesController.class);
|
||||||
classes.add(ConfigurationWorkflowController.class);
|
classes.add(ConfigurationWorkflowController.class);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.libreccm.categorization.Categorization;
|
||||||
|
import org.libreccm.core.CcmObject;
|
||||||
|
import org.libreccm.security.PermissionManager;
|
||||||
|
import org.librecms.contentsection.Asset;
|
||||||
|
import org.librecms.contentsection.AssetManager;
|
||||||
|
import org.librecms.contentsection.ContentItem;
|
||||||
|
import org.librecms.contentsection.ContentItemManager;
|
||||||
|
import org.librecms.contentsection.ContentSection;
|
||||||
|
import org.librecms.contentsection.ContentSectionRepository;
|
||||||
|
import org.librecms.contentsection.Folder;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.enterprise.context.ApplicationScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@ApplicationScoped
|
||||||
|
public class FixItemPermissions {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(
|
||||||
|
FixItemPermissions.class
|
||||||
|
);
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private AssetManager assetManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ContentItemManager itemManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ContentSectionRepository sectionRepo;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private PermissionManager permissionManager;
|
||||||
|
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
public void fixItemPermissions(final ContentSection contentSection) {
|
||||||
|
final String sectionUuid = Optional
|
||||||
|
.ofNullable(contentSection)
|
||||||
|
.map(ContentSection::getUuid)
|
||||||
|
.orElseThrow(
|
||||||
|
() -> new IllegalArgumentException(
|
||||||
|
"Can't fix ItemPermissions for content section null"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
final ContentSection section = sectionRepo
|
||||||
|
.findByUuid(sectionUuid)
|
||||||
|
.orElseThrow(
|
||||||
|
() -> new IllegalArgumentException(
|
||||||
|
String.format(
|
||||||
|
"No ContentSection with UUID %s in the database.",
|
||||||
|
sectionUuid
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
fixContentItemPermissions(section.getRootDocumentsFolder());
|
||||||
|
fixAssetPermissions(section.getRootAssetsFolder());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fixContentItemPermissions(final Folder folder) {
|
||||||
|
final List<ContentItem> items = new ArrayList<>();
|
||||||
|
for (final Categorization categorization : folder.getObjects()) {
|
||||||
|
final CcmObject categorized = categorization.getCategorizedObject();
|
||||||
|
if (categorized instanceof ContentItem) {
|
||||||
|
items.add((ContentItem) categorized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// final List<ContentItem> items = folder
|
||||||
|
// .getObjects()
|
||||||
|
// .stream()
|
||||||
|
// .map(Categorization::getCategorizedObject)
|
||||||
|
// .filter(obj -> obj instanceof ContentItem)
|
||||||
|
// .map(obj -> (ContentItem) obj)
|
||||||
|
// .collect(Collectors.toList());
|
||||||
|
for (final ContentItem item : items) {
|
||||||
|
LOGGER.info(
|
||||||
|
"Fixing permissions for item {} {}",
|
||||||
|
item.getUuid(),
|
||||||
|
itemManager.getItemPath(item)
|
||||||
|
);
|
||||||
|
permissionManager.copyPermissions(folder, item, true);
|
||||||
|
|
||||||
|
if (itemManager.isLive(item)) {
|
||||||
|
permissionManager.copyPermissions(
|
||||||
|
folder,
|
||||||
|
itemManager.getLiveVersion(item, ContentItem.class).get(),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final Folder subFolder : folder.getSubFolders()) {
|
||||||
|
fixContentItemPermissions(subFolder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fixAssetPermissions(final Folder folder) {
|
||||||
|
final List<Asset> assets = folder
|
||||||
|
.getObjects()
|
||||||
|
.stream()
|
||||||
|
.map(Categorization::getCategorizedObject)
|
||||||
|
.filter(obj -> obj instanceof Asset)
|
||||||
|
.map(obj -> (Asset) obj)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
for (final Asset asset : assets) {
|
||||||
|
LOGGER.info(
|
||||||
|
"Fixing permissions for asset {} {}...",
|
||||||
|
asset.getUuid(),
|
||||||
|
assetManager.getAssetPath(asset)
|
||||||
|
);
|
||||||
|
permissionManager.copyPermissions(folder, asset, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final Folder subFolder : folder.getSubFolders()) {
|
||||||
|
fixAssetPermissions(subFolder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
public enum FixItemPermissionsStatus {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An error occured during the process.
|
||||||
|
*/
|
||||||
|
ERROR,
|
||||||
|
/**
|
||||||
|
* The import or export task is finished.
|
||||||
|
*/
|
||||||
|
FINISHED,
|
||||||
|
/**
|
||||||
|
* The task is still running.
|
||||||
|
*/
|
||||||
|
RUNNING,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections;
|
||||||
|
|
||||||
|
import org.apache.shiro.mgt.SecurityManager;
|
||||||
|
import org.librecms.contentsection.ContentSection;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
public class FixItemPermissionsTask {
|
||||||
|
|
||||||
|
private final ContentSection contentSection;
|
||||||
|
|
||||||
|
private final LocalDate started;
|
||||||
|
|
||||||
|
private final FixItemPermissionsTaskStatus status;
|
||||||
|
|
||||||
|
private final org.apache.shiro.mgt.SecurityManager securityManager;
|
||||||
|
|
||||||
|
public FixItemPermissionsTask(
|
||||||
|
final ContentSection contentSection,
|
||||||
|
final LocalDate started,
|
||||||
|
final FixItemPermissionsTaskStatus status,
|
||||||
|
final org.apache.shiro.mgt.SecurityManager securityManager
|
||||||
|
) {
|
||||||
|
this.contentSection = contentSection;
|
||||||
|
this.started = started;
|
||||||
|
this.status = status;
|
||||||
|
this.securityManager = securityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentSection getContentSection() {
|
||||||
|
return contentSection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDate getStarted() {
|
||||||
|
return started;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FixItemPermissionsTaskStatus getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SecurityManager getSecurityManager() {
|
||||||
|
return securityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,159 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.apache.shiro.SecurityUtils;
|
||||||
|
import org.librecms.contentsection.ContentSection;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.enterprise.context.ApplicationScoped;
|
||||||
|
import javax.enterprise.event.Event;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@ApplicationScoped
|
||||||
|
public class FixItemPermissionsTaskManager {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(
|
||||||
|
FixItemPermissionsTaskManager.class
|
||||||
|
);
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Event<FixItemPermissionsTask> taskSender;
|
||||||
|
|
||||||
|
private final SortedSet<FixItemPermissionsTaskStatus> tasks;
|
||||||
|
|
||||||
|
public SortedSet<FixItemPermissionsTaskStatus> getTasks() {
|
||||||
|
return Collections.unmodifiableSortedSet(tasks);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTaskActiveForContentSection(final ContentSection section) {
|
||||||
|
return isTaskActiveForContentSection(
|
||||||
|
Optional
|
||||||
|
.ofNullable(section)
|
||||||
|
.map(ContentSection::getLabel)
|
||||||
|
.orElseThrow(
|
||||||
|
() -> new IllegalArgumentException(
|
||||||
|
"Can't check task status for ContentSection null."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTaskActiveForContentSection(final String name) {
|
||||||
|
return tasks
|
||||||
|
.stream()
|
||||||
|
.anyMatch(
|
||||||
|
task -> task.getContentSection().equals(name)
|
||||||
|
&& task.getStatus()
|
||||||
|
== FixItemPermissionsStatus.RUNNING
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTaskFailedForContentSection(final String name) {
|
||||||
|
return tasks
|
||||||
|
.stream()
|
||||||
|
.anyMatch(
|
||||||
|
task -> task.getContentSection().equals(name)
|
||||||
|
&& task.getStatus()
|
||||||
|
== FixItemPermissionsStatus.ERROR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FixItemPermissionsTaskManager() {
|
||||||
|
tasks = new TreeSet<>(
|
||||||
|
Comparator
|
||||||
|
.comparing(FixItemPermissionsTaskStatus::getStarted)
|
||||||
|
.thenComparing(FixItemPermissionsTaskStatus::getContentSection)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
public void fixItemPermissions(final ContentSection section) {
|
||||||
|
if (isTaskActiveForContentSection(section)) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
String.format(
|
||||||
|
"A FixItemPermissionsTask is already active for content "
|
||||||
|
+ "section %s.",
|
||||||
|
section.getLabel()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.removeAll(
|
||||||
|
tasks
|
||||||
|
.stream()
|
||||||
|
.filter(task -> task.getStatus()
|
||||||
|
== FixItemPermissionsStatus.ERROR
|
||||||
|
|| task.getStatus()
|
||||||
|
== FixItemPermissionsStatus.FINISHED)
|
||||||
|
.collect(Collectors.toSet())
|
||||||
|
);
|
||||||
|
|
||||||
|
final FixItemPermissionsTaskStatus taskStatus
|
||||||
|
= new FixItemPermissionsTaskStatus();
|
||||||
|
taskStatus.setContentSection(section.getLabel());
|
||||||
|
taskStatus.setStarted(LocalDateTime.now());
|
||||||
|
taskSender.fireAsync(
|
||||||
|
new FixItemPermissionsTask(
|
||||||
|
section,
|
||||||
|
LocalDate.now(),
|
||||||
|
taskStatus,
|
||||||
|
SecurityUtils.getSecurityManager()
|
||||||
|
)
|
||||||
|
).handle((task, ex) -> handleTaskResult(task, ex, taskStatus));
|
||||||
|
|
||||||
|
taskStatus.setStatus(FixItemPermissionsStatus.RUNNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object handleTaskResult(
|
||||||
|
final FixItemPermissionsTask task,
|
||||||
|
final Throwable ex,
|
||||||
|
final FixItemPermissionsTaskStatus status
|
||||||
|
) {
|
||||||
|
if (ex == null) {
|
||||||
|
status.setStatus(FixItemPermissionsStatus.FINISHED);
|
||||||
|
} else {
|
||||||
|
status.setStatus(FixItemPermissionsStatus.ERROR);
|
||||||
|
status.setException(ex);
|
||||||
|
LOGGER.error(
|
||||||
|
"Fix Item Permissions for Content Section {} failed ",
|
||||||
|
status.getContentSection()
|
||||||
|
);
|
||||||
|
LOGGER.error("with exception:", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,152 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
public class FixItemPermissionsTaskStatus
|
||||||
|
implements Comparable<FixItemPermissionsTaskStatus> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The content section for which the task was started.
|
||||||
|
*/
|
||||||
|
private String contentSection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When was the task started?
|
||||||
|
*/
|
||||||
|
private LocalDateTime started;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The status of the task.
|
||||||
|
*/
|
||||||
|
private FixItemPermissionsStatus status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the proces throw an exception, it is stored here.
|
||||||
|
*/
|
||||||
|
private Throwable exception;
|
||||||
|
|
||||||
|
public String getContentSection() {
|
||||||
|
return contentSection;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setContentSection(final String contentSection) {
|
||||||
|
this.contentSection = contentSection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getStarted() {
|
||||||
|
return started;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setStarted(final LocalDateTime started) {
|
||||||
|
this.started = started;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FixItemPermissionsStatus getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setStatus(final FixItemPermissionsStatus status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Throwable getException() {
|
||||||
|
return exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setException(final Throwable exception) {
|
||||||
|
this.exception = exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 5;
|
||||||
|
hash = 17 * hash + Objects.hashCode(contentSection);
|
||||||
|
hash = 17 * hash + Objects.hashCode(started);
|
||||||
|
hash = 17 * hash + Objects.hashCode(status);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (obj instanceof FixItemPermissionsTaskStatus) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final FixItemPermissionsTaskStatus other
|
||||||
|
= (FixItemPermissionsTaskStatus) obj;
|
||||||
|
if (!other.canEqual(this)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(contentSection, other.getContentSection())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(started, other.getStarted())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return status == other.getStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canEqual(final Object obj) {
|
||||||
|
return obj instanceof FixItemPermissionsTaskStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(final FixItemPermissionsTaskStatus other) {
|
||||||
|
return Comparator
|
||||||
|
.nullsFirst(
|
||||||
|
Comparator
|
||||||
|
.comparing(FixItemPermissionsTaskStatus::getContentSection)
|
||||||
|
.thenComparing(FixItemPermissionsTaskStatus::getStarted)
|
||||||
|
)
|
||||||
|
.compare(this, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format(
|
||||||
|
"%s{"
|
||||||
|
+ "contentSection = %s, "
|
||||||
|
+ "started = %s, "
|
||||||
|
+ "status = %s"
|
||||||
|
+ "}",
|
||||||
|
super.toString(),
|
||||||
|
contentSection,
|
||||||
|
DateTimeFormatter.ISO_DATE_TIME
|
||||||
|
.withZone(ZoneId.systemDefault())
|
||||||
|
.format(started),
|
||||||
|
Objects.toString(status)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections;
|
||||||
|
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@RequestScoped
|
||||||
|
@Named("FixItemPermissionsTaskStatusModel")
|
||||||
|
public class FixItemPermissionsTaskStatusModel {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ContentSectionModel sectionModel;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private FixItemPermissionsTaskManager taskManager;
|
||||||
|
|
||||||
|
public boolean isTaskRunningForContentSection() {
|
||||||
|
return taskManager.isTaskActiveForContentSection(
|
||||||
|
sectionModel.getSectionName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTaskFailedForContentSection() {
|
||||||
|
return taskManager.isTaskFailedForContentSection(
|
||||||
|
sectionModel.getSectionName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.librecms.ui.contentsections;
|
||||||
|
|
||||||
|
import org.apache.shiro.util.ThreadContext;
|
||||||
|
import org.libreccm.security.Shiro;
|
||||||
|
|
||||||
|
import javax.enterprise.context.ApplicationScoped;
|
||||||
|
import javax.enterprise.event.ObservesAsync;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@ApplicationScoped
|
||||||
|
public class FixItemPermissionsTasks {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private FixItemPermissions fixItemPermissions;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Shiro shiro;
|
||||||
|
|
||||||
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
|
public void fixItemPermissions(
|
||||||
|
@ObservesAsync final FixItemPermissionsTask task
|
||||||
|
) {
|
||||||
|
ThreadContext.bind(task.getSecurityManager());
|
||||||
|
shiro.getSystemUser().execute(() -> executeFixItemPermissions(task));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void executeFixItemPermissions(final FixItemPermissionsTask task) {
|
||||||
|
fixItemPermissions.fixItemPermissions(task.getContentSection());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -136,6 +136,51 @@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col mb-4">
|
||||||
|
<div aria-describedby="configuration-fixitemandassetspermissions-body"
|
||||||
|
class="card pt-2"
|
||||||
|
id="configuration-fixitemandassetspermissions">
|
||||||
|
<svg aria-hidden="true"
|
||||||
|
class="card-img-top"
|
||||||
|
fill="currentColor">
|
||||||
|
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#screwdriver" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/configuration/fix-item-and-asset-permissions"
|
||||||
|
class="card-body"
|
||||||
|
id="configuration-fixitemandassetspermissions-body"
|
||||||
|
method="post">
|
||||||
|
<h2 class="card-title">
|
||||||
|
<c:choose>
|
||||||
|
<c:when test="#{FixItemPermissionsTaskStatusModel.taskRunningForContentSection}">
|
||||||
|
#{CmsAdminMessages['contentsection.configuration.fixitemandassetspermissions.title']}
|
||||||
|
</c:when>
|
||||||
|
<c:otherwise>
|
||||||
|
<button class="btn btn-link stretched-link"
|
||||||
|
type="submit">
|
||||||
|
#{CmsAdminMessages['contentsection.configuration.fixitemandassetspermissions.title']}
|
||||||
|
</button>
|
||||||
|
</c:otherwise>
|
||||||
|
|
||||||
|
</c:choose>
|
||||||
|
</h2>
|
||||||
|
<p class="card-text">
|
||||||
|
<c:if test="#{FixItemPermissionsTaskStatusModel.taskFailedForContentSection}">
|
||||||
|
<div class="alert alert-danger" role="alert">
|
||||||
|
#{CmsAdminMessages['contentsection.configuration.fixitemandassetspermissions.failed']}
|
||||||
|
</div>
|
||||||
|
</c:if>
|
||||||
|
<c:choose>
|
||||||
|
<c:when test="#{FixItemPermissionsTaskStatusModel.taskRunningForContentSection}">
|
||||||
|
#{CmsAdminMessages['contentsection.configuration.fixitemandassetspermissions.running']}
|
||||||
|
</c:when>
|
||||||
|
<c:otherwise>
|
||||||
|
#{CmsAdminMessages['contentsection.configuration.fixitemandassetspermissions.description']}
|
||||||
|
</c:otherwise>
|
||||||
|
</c:choose>
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ui:define>
|
</ui:define>
|
||||||
|
|
|
||||||
|
|
@ -1030,3 +1030,7 @@ pages.page.details.displayname.dialog.displayname.help=The display name of the p
|
||||||
pages.page.details.displayname.dialog.submit=Save
|
pages.page.details.displayname.dialog.submit=Save
|
||||||
pages.page.details.displayname.edit=Edit display name
|
pages.page.details.displayname.edit=Edit display name
|
||||||
pages.page.details.dialog.displayname.label=Display name
|
pages.page.details.dialog.displayname.label=Display name
|
||||||
|
contentsection.configuration.fixitemandassetspermissions.title=Fix permissions
|
||||||
|
contentsection.configuration.fixitemandassetspermissions.description=Repairs the permissions for items and assets
|
||||||
|
contentsection.configuration.fixitemandassetspermissions.running=Fixing permissions for item and assets...
|
||||||
|
contentsection.configuration.fixitemandassetspermissions.failed=Failed to repair permissions for items and assets. Check the log for details.
|
||||||
|
|
|
||||||
|
|
@ -1031,3 +1031,7 @@ pages.page.details.displayname.dialog.displayname.help=The display name of the p
|
||||||
pages.page.details.displayname.dialog.submit=Speichern
|
pages.page.details.displayname.dialog.submit=Speichern
|
||||||
pages.page.details.displayname.edit=Display Name bearbeiten
|
pages.page.details.displayname.edit=Display Name bearbeiten
|
||||||
pages.page.details.dialog.displayname.label=Display Name
|
pages.page.details.dialog.displayname.label=Display Name
|
||||||
|
contentsection.configuration.fixitemandassetspermissions.title=Berechtigungen reparieren
|
||||||
|
contentsection.configuration.fixitemandassetspermissions.description=Repariert die Berechtigungen f\u00fcr Dokumente und Assets
|
||||||
|
contentsection.configuration.fixitemandassetspermissions.running=Repariere Berechtigungen f\u00fcr Dokumente und Assets
|
||||||
|
contentsection.configuration.fixitemandassetspermissions.failed=Reparieren der Berechtigungen f\u00fcr Dokumente und Assets fehlgeschlagen. Weitere Informationen im Log.
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@
|
||||||
*/
|
*/
|
||||||
package org.libreccm.mvc.freemarker;
|
package org.libreccm.mvc.freemarker;
|
||||||
|
|
||||||
|
import com.arsdigita.kernel.KernelConfig;
|
||||||
|
|
||||||
import freemarker.cache.ClassTemplateLoader;
|
import freemarker.cache.ClassTemplateLoader;
|
||||||
import freemarker.cache.MultiTemplateLoader;
|
import freemarker.cache.MultiTemplateLoader;
|
||||||
import freemarker.cache.TemplateLoader;
|
import freemarker.cache.TemplateLoader;
|
||||||
|
|
@ -26,6 +28,7 @@ import freemarker.template.Configuration;
|
||||||
import freemarker.template.TemplateExceptionHandler;
|
import freemarker.template.TemplateExceptionHandler;
|
||||||
import org.eclipse.krazo.engine.ViewEngineConfig;
|
import org.eclipse.krazo.engine.ViewEngineConfig;
|
||||||
import org.eclipse.krazo.ext.freemarker.DefaultConfigurationProducer;
|
import org.eclipse.krazo.ext.freemarker.DefaultConfigurationProducer;
|
||||||
|
import org.libreccm.configuration.ConfigurationManager;
|
||||||
import org.libreccm.theming.Themes;
|
import org.libreccm.theming.Themes;
|
||||||
|
|
||||||
import javax.enterprise.inject.Produces;
|
import javax.enterprise.inject.Produces;
|
||||||
|
|
@ -43,6 +46,9 @@ import javax.servlet.ServletContext;
|
||||||
public class MvcFreemarkerConfigurationProducer
|
public class MvcFreemarkerConfigurationProducer
|
||||||
extends DefaultConfigurationProducer {
|
extends DefaultConfigurationProducer {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ConfigurationManager confManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private Models models;
|
private Models models;
|
||||||
|
|
||||||
|
|
@ -51,7 +57,7 @@ public class MvcFreemarkerConfigurationProducer
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private Themes themes;
|
private Themes themes;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ThemeTemplateUtil themeTemplateUtil;
|
private ThemeTemplateUtil themeTemplateUtil;
|
||||||
|
|
||||||
|
|
@ -60,15 +66,27 @@ public class MvcFreemarkerConfigurationProducer
|
||||||
@Specializes
|
@Specializes
|
||||||
@Override
|
@Override
|
||||||
public Configuration getConfiguration() {
|
public Configuration getConfiguration() {
|
||||||
|
final KernelConfig kernelConfig = confManager.findConfiguration(
|
||||||
|
KernelConfig.class
|
||||||
|
);
|
||||||
|
|
||||||
final Configuration configuration = new Configuration(
|
final Configuration configuration = new Configuration(
|
||||||
Configuration.VERSION_2_3_30
|
Configuration.VERSION_2_3_30
|
||||||
);
|
);
|
||||||
|
|
||||||
configuration.setDefaultEncoding("UTF-8");
|
configuration.setDefaultEncoding("UTF-8");
|
||||||
configuration.setTemplateExceptionHandler(
|
if (kernelConfig.isDebugEnabled()) {
|
||||||
TemplateExceptionHandler.RETHROW_HANDLER
|
configuration.setTemplateExceptionHandler(
|
||||||
);
|
TemplateExceptionHandler.DEBUG_HANDLER
|
||||||
configuration.setLogTemplateExceptions(false);
|
);
|
||||||
|
configuration.setLogTemplateExceptions(true);
|
||||||
|
} else {
|
||||||
|
configuration.setTemplateExceptionHandler(
|
||||||
|
TemplateExceptionHandler.RETHROW_HANDLER
|
||||||
|
);
|
||||||
|
configuration.setLogTemplateExceptions(false);
|
||||||
|
}
|
||||||
|
|
||||||
configuration.setWrapUncheckedExceptions(false);
|
configuration.setWrapUncheckedExceptions(false);
|
||||||
configuration.setLocalizedLookup(false);
|
configuration.setLocalizedLookup(false);
|
||||||
configuration.setTemplateLoader(
|
configuration.setTemplateLoader(
|
||||||
|
|
|
||||||
|
|
@ -57,8 +57,10 @@ public class PermissionManager implements Serializable {
|
||||||
|
|
||||||
@SuppressWarnings("PMD.LongVariable")
|
@SuppressWarnings("PMD.LongVariable")
|
||||||
private static final String QUERY_PARAM_OBJECT = "object";
|
private static final String QUERY_PARAM_OBJECT = "object";
|
||||||
|
|
||||||
@SuppressWarnings("PMD.LongVariable")
|
@SuppressWarnings("PMD.LongVariable")
|
||||||
private static final String QUERY_PARAM_GRANTEE = "grantee";
|
private static final String QUERY_PARAM_GRANTEE = "grantee";
|
||||||
|
|
||||||
@SuppressWarnings("PMD.LongVariable")
|
@SuppressWarnings("PMD.LongVariable")
|
||||||
private static final String QUERY_PARAM_PRIVILEGE = "privilege";
|
private static final String QUERY_PARAM_PRIVILEGE = "privilege";
|
||||||
|
|
||||||
|
|
@ -79,8 +81,12 @@ public class PermissionManager implements Serializable {
|
||||||
* @return The permission identified by the provided {@code permissionId).
|
* @return The permission identified by the provided {@code permissionId).
|
||||||
*/
|
*/
|
||||||
public Optional<Permission> findById(final long permissionId) {
|
public Optional<Permission> findById(final long permissionId) {
|
||||||
return Optional.ofNullable(entityManager.find(Permission.class,
|
return Optional.ofNullable(
|
||||||
permissionId));
|
entityManager.find(
|
||||||
|
Permission.class,
|
||||||
|
permissionId
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -93,7 +99,9 @@ public class PermissionManager implements Serializable {
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
public List<Permission> findPermissionsForRole(final Role role) {
|
public List<Permission> findPermissionsForRole(final Role role) {
|
||||||
final TypedQuery<Permission> query = entityManager.createNamedQuery(
|
final TypedQuery<Permission> query = entityManager.createNamedQuery(
|
||||||
"Permission.findPermissionsForRole", Permission.class);
|
"Permission.findPermissionsForRole",
|
||||||
|
Permission.class
|
||||||
|
);
|
||||||
query.setParameter("grantee", role);
|
query.setParameter("grantee", role);
|
||||||
|
|
||||||
return query.getResultList();
|
return query.getResultList();
|
||||||
|
|
@ -110,17 +118,22 @@ public class PermissionManager implements Serializable {
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
public List<Permission> findPermissionsForObject(final CcmObject object) {
|
public List<Permission> findPermissionsForObject(final CcmObject object) {
|
||||||
final TypedQuery<Permission> query = entityManager.createNamedQuery(
|
final TypedQuery<Permission> query = entityManager.createNamedQuery(
|
||||||
"Permission.findPermissionsForCcmObject", Permission.class);
|
"Permission.findPermissionsForCcmObject",
|
||||||
|
Permission.class
|
||||||
|
);
|
||||||
query.setParameter("object", object);
|
query.setParameter("object", object);
|
||||||
|
|
||||||
return query.getResultList();
|
return query.getResultList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Permission> findPermissionsForRoleAndObject(
|
public List<Permission> findPermissionsForRoleAndObject(
|
||||||
final Role role, final CcmObject object) {
|
final Role role,
|
||||||
|
final CcmObject object
|
||||||
|
) {
|
||||||
final TypedQuery<Permission> query = entityManager.createNamedQuery(
|
final TypedQuery<Permission> query = entityManager.createNamedQuery(
|
||||||
"Permission.findPermissionsForRoleAndObject", Permission.class);
|
"Permission.findPermissionsForRoleAndObject",
|
||||||
|
Permission.class
|
||||||
|
);
|
||||||
query.setParameter("object", object);
|
query.setParameter("object", object);
|
||||||
query.setParameter("grantee", role);
|
query.setParameter("grantee", role);
|
||||||
|
|
||||||
|
|
@ -148,9 +161,11 @@ public class PermissionManager implements Serializable {
|
||||||
@AuthorizationRequired
|
@AuthorizationRequired
|
||||||
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
public Permission grantPrivilege(final String privilege,
|
public Permission grantPrivilege(
|
||||||
final Role grantee,
|
final String privilege,
|
||||||
final CcmObject object) {
|
final Role grantee,
|
||||||
|
final CcmObject object
|
||||||
|
) {
|
||||||
if (privilege == null || privilege.isEmpty()) {
|
if (privilege == null || privilege.isEmpty()) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Can't grant a permission without a privilege.");
|
"Can't grant a permission without a privilege.");
|
||||||
|
|
@ -182,7 +197,13 @@ public class PermissionManager implements Serializable {
|
||||||
|
|
||||||
entityManager.persist(permission);
|
entityManager.persist(permission);
|
||||||
|
|
||||||
grantRecursive(privilege, grantee, object, object.getClass(), object);
|
grantRecursive(
|
||||||
|
privilege,
|
||||||
|
grantee,
|
||||||
|
object,
|
||||||
|
object.getClass(),
|
||||||
|
object
|
||||||
|
);
|
||||||
|
|
||||||
return permission;
|
return permission;
|
||||||
}
|
}
|
||||||
|
|
@ -202,32 +223,44 @@ public class PermissionManager implements Serializable {
|
||||||
* {@link #grantPrivilege(java.lang.String, org.libreccm.security.Role, org.libreccm.core.CcmObject)}
|
* {@link #grantPrivilege(java.lang.String, org.libreccm.security.Role, org.libreccm.core.CcmObject)}
|
||||||
* was invoked.
|
* was invoked.
|
||||||
*/
|
*/
|
||||||
private void grantRecursive(final String privilege,
|
private void grantRecursive(
|
||||||
final Role grantee,
|
final String privilege,
|
||||||
final CcmObject object,
|
final Role grantee,
|
||||||
final Class<?> clazz,
|
final CcmObject object,
|
||||||
final CcmObject inheritedFrom) {
|
final Class<?> clazz,
|
||||||
|
final CcmObject inheritedFrom
|
||||||
|
) {
|
||||||
final Field[] fields = clazz.getDeclaredFields();
|
final Field[] fields = clazz.getDeclaredFields();
|
||||||
Arrays.stream(fields)
|
Arrays.stream(fields)
|
||||||
.filter(field -> field.isAnnotationPresent(
|
.filter(field -> field.isAnnotationPresent(
|
||||||
RecursivePermissions.class))
|
RecursivePermissions.class))
|
||||||
.filter(field -> {
|
.filter(
|
||||||
return checkIfPrivilegeIsRecursive(
|
field -> checkIfPrivilegeIsRecursive(
|
||||||
field.getAnnotation(RecursivePermissions.class),
|
field.getAnnotation(RecursivePermissions.class),
|
||||||
privilege);
|
privilege
|
||||||
})
|
)
|
||||||
.forEach(field -> {
|
)
|
||||||
|
.forEach(
|
||||||
|
field -> {
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
grantRecursive(privilege, grantee, field, object, inheritedFrom);
|
grantRecursive(
|
||||||
|
privilege,
|
||||||
|
grantee,
|
||||||
|
field,
|
||||||
|
object,
|
||||||
|
inheritedFrom
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Repeat for superclass of the current class.
|
// Repeat for superclass of the current class.
|
||||||
if (clazz.getSuperclass() != null) {
|
if (clazz.getSuperclass() != null) {
|
||||||
grantRecursive(privilege,
|
grantRecursive(
|
||||||
grantee,
|
privilege,
|
||||||
object,
|
grantee,
|
||||||
clazz.getSuperclass(),
|
object,
|
||||||
inheritedFrom);
|
clazz.getSuperclass(),
|
||||||
|
inheritedFrom
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -246,13 +279,14 @@ public class PermissionManager implements Serializable {
|
||||||
*/
|
*/
|
||||||
private boolean checkIfPrivilegeIsRecursive(
|
private boolean checkIfPrivilegeIsRecursive(
|
||||||
final RecursivePermissions annotation,
|
final RecursivePermissions annotation,
|
||||||
final String privilege) {
|
final String privilege
|
||||||
|
) {
|
||||||
if (annotation.privileges() == null
|
if (annotation.privileges() == null
|
||||||
|| annotation.privileges().length == 0) {
|
|| annotation.privileges().length == 0) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return Arrays.stream(annotation.privileges())
|
return Arrays
|
||||||
|
.stream(annotation.privileges())
|
||||||
.anyMatch(privilege::equals);
|
.anyMatch(privilege::equals);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -266,24 +300,35 @@ public class PermissionManager implements Serializable {
|
||||||
* @param owner The object which own the provided {@code field}.
|
* @param owner The object which own the provided {@code field}.
|
||||||
* @param inheritedFrom The object from which the permission is inherited.
|
* @param inheritedFrom The object from which the permission is inherited.
|
||||||
*/
|
*/
|
||||||
private void grantRecursive(final String privilege,
|
private void grantRecursive(
|
||||||
final Role grantee,
|
final String privilege,
|
||||||
final Field field,
|
final Role grantee,
|
||||||
final CcmObject owner,
|
final Field field,
|
||||||
final CcmObject inheritedFrom) {
|
final CcmObject owner,
|
||||||
|
final CcmObject inheritedFrom
|
||||||
|
) {
|
||||||
final CcmObject ownerObject = ccmObjectRepo
|
final CcmObject ownerObject = ccmObjectRepo
|
||||||
.findObjectById(owner.getObjectId())
|
.findObjectById(owner.getObjectId())
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
.orElseThrow(
|
||||||
"No CcmObject with ID %d in the database. "
|
() -> new IllegalArgumentException(
|
||||||
+ "Where did that ID come from?",
|
String.format(
|
||||||
owner.getObjectId())));
|
"No CcmObject with ID %d in the database. "
|
||||||
|
+ "Where did that ID come from?",
|
||||||
|
owner.getObjectId()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
final CcmObject inheritedFromObject = ccmObjectRepo
|
final CcmObject inheritedFromObject = ccmObjectRepo
|
||||||
.findObjectById(inheritedFrom.getObjectId())
|
.findObjectById(inheritedFrom.getObjectId())
|
||||||
.orElseThrow(() -> new IllegalArgumentException(String.format(
|
.orElseThrow(
|
||||||
"No CcmObject with ID %d in the database. "
|
() -> new IllegalArgumentException(
|
||||||
+ "Where did that ID come from?",
|
String.format(
|
||||||
inheritedFrom.getObjectId())));
|
"No CcmObject with ID %d in the database. "
|
||||||
|
+ "Where did that ID come from?",
|
||||||
|
inheritedFrom.getObjectId()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
final Object value;
|
final Object value;
|
||||||
try {
|
try {
|
||||||
|
|
@ -303,10 +348,14 @@ public class PermissionManager implements Serializable {
|
||||||
collection.stream()
|
collection.stream()
|
||||||
.filter(obj -> obj instanceof CcmObject)
|
.filter(obj -> obj instanceof CcmObject)
|
||||||
.map(obj -> (CcmObject) obj)
|
.map(obj -> (CcmObject) obj)
|
||||||
.forEach(obj -> grantInherited(privilege,
|
.forEach(
|
||||||
grantee,
|
obj -> grantInherited(
|
||||||
obj,
|
privilege,
|
||||||
inheritedFromObject));
|
grantee,
|
||||||
|
obj,
|
||||||
|
inheritedFromObject
|
||||||
|
)
|
||||||
|
);
|
||||||
// Relations between two CcmObjects with attributes or n:m relations
|
// Relations between two CcmObjects with attributes or n:m relations
|
||||||
// use an object to represent the relation. The object must implement
|
// use an object to represent the relation. The object must implement
|
||||||
// the Relation interface. For each Relation object in the collection
|
// the Relation interface. For each Relation object in the collection
|
||||||
|
|
@ -316,33 +365,44 @@ public class PermissionManager implements Serializable {
|
||||||
.map(obj -> (Relation) obj)
|
.map(obj -> (Relation) obj)
|
||||||
.filter(relation -> relation.getRelatedObject() != null)
|
.filter(relation -> relation.getRelatedObject() != null)
|
||||||
.map(relation -> relation.getRelatedObject())
|
.map(relation -> relation.getRelatedObject())
|
||||||
.forEach(obj -> grantInherited(privilege,
|
.forEach(
|
||||||
grantee,
|
obj -> grantInherited(
|
||||||
obj,
|
privilege,
|
||||||
inheritedFromObject));
|
grantee,
|
||||||
|
obj,
|
||||||
|
inheritedFromObject
|
||||||
|
)
|
||||||
|
);
|
||||||
} else if (CcmObject.class.isAssignableFrom(field.getType())) {
|
} else if (CcmObject.class.isAssignableFrom(field.getType())) {
|
||||||
// If the provided object is a CcmObject create an inherited
|
// If the provided object is a CcmObject create an inherited
|
||||||
// permission for this object.
|
// permission for this object.
|
||||||
grantInherited(privilege,
|
grantInherited(
|
||||||
grantee,
|
privilege,
|
||||||
(CcmObject) value,
|
grantee,
|
||||||
inheritedFromObject);
|
(CcmObject) value,
|
||||||
|
inheritedFromObject
|
||||||
|
);
|
||||||
} else if (Relation.class.isAssignableFrom(field.getType())) {
|
} else if (Relation.class.isAssignableFrom(field.getType())) {
|
||||||
// If the provided field is a Relation object created an inherited
|
// If the provided field is a Relation object created an inherited
|
||||||
// permission on the related object.
|
// permission on the related object.
|
||||||
final Relation relation = (Relation) value;
|
final Relation relation = (Relation) value;
|
||||||
if (relation.getRelatedObject() != null) {
|
if (relation.getRelatedObject() != null) {
|
||||||
grantInherited(privilege,
|
grantInherited(
|
||||||
grantee,
|
privilege,
|
||||||
relation.getRelatedObject(),
|
grantee,
|
||||||
inheritedFromObject);
|
relation.getRelatedObject(),
|
||||||
|
inheritedFromObject
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException(String.format(
|
throw new IllegalArgumentException(
|
||||||
"Found a field annotated with \"%s\" but the field is not a "
|
String.format(
|
||||||
|
"Found a field annotated with \"%s\" but the field is not a "
|
||||||
+ "collection nor a CcmObject nore a Relation object. This "
|
+ "collection nor a CcmObject nore a Relation object. This "
|
||||||
+ "is not supported.",
|
+ "is not supported.",
|
||||||
RecursivePermissions.class));
|
RecursivePermissions.class
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -355,11 +415,12 @@ public class PermissionManager implements Serializable {
|
||||||
* granted.
|
* granted.
|
||||||
* @param inheritedFrom The object from which the permission is inherited.
|
* @param inheritedFrom The object from which the permission is inherited.
|
||||||
*/
|
*/
|
||||||
private void grantInherited(final String privilege,
|
private void grantInherited(
|
||||||
final Role grantee,
|
final String privilege,
|
||||||
final CcmObject object,
|
final Role grantee,
|
||||||
final CcmObject inheritedFrom) {
|
final CcmObject object,
|
||||||
|
final CcmObject inheritedFrom
|
||||||
|
) {
|
||||||
if (!existsPermission(privilege, grantee, object)) {
|
if (!existsPermission(privilege, grantee, object)) {
|
||||||
final Permission permission = new Permission();
|
final Permission permission = new Permission();
|
||||||
permission.setGrantee(grantee);
|
permission.setGrantee(grantee);
|
||||||
|
|
@ -371,11 +432,13 @@ public class PermissionManager implements Serializable {
|
||||||
|
|
||||||
entityManager.persist(permission);
|
entityManager.persist(permission);
|
||||||
|
|
||||||
grantRecursive(privilege,
|
grantRecursive(
|
||||||
grantee,
|
privilege,
|
||||||
object,
|
grantee,
|
||||||
object.getClass(),
|
object,
|
||||||
inheritedFrom);
|
object.getClass(),
|
||||||
|
inheritedFrom
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -389,16 +452,20 @@ public class PermissionManager implements Serializable {
|
||||||
@AuthorizationRequired
|
@AuthorizationRequired
|
||||||
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
public void grantPrivilege(final String privilege,
|
public void grantPrivilege(
|
||||||
final Role grantee) {
|
final String privilege,
|
||||||
|
final Role grantee
|
||||||
|
) {
|
||||||
if (privilege == null || privilege.isEmpty()) {
|
if (privilege == null || privilege.isEmpty()) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Can't grant a permission without a privilege.");
|
"Can't grant a permission without a privilege."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (grantee == null) {
|
if (grantee == null) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Can't grant a permission to grantee null.");
|
"Can't grant a permission to grantee null."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!existsPermission(privilege, grantee)) {
|
if (!existsPermission(privilege, grantee)) {
|
||||||
|
|
@ -423,42 +490,52 @@ public class PermissionManager implements Serializable {
|
||||||
@AuthorizationRequired
|
@AuthorizationRequired
|
||||||
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
public void revokePrivilege(final String privilege,
|
public void revokePrivilege(
|
||||||
final Role grantee,
|
final String privilege,
|
||||||
final CcmObject object) {
|
final Role grantee,
|
||||||
|
final CcmObject object
|
||||||
|
) {
|
||||||
|
|
||||||
if (privilege == null || privilege.isEmpty()) {
|
if (privilege == null || privilege.isEmpty()) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Can't revoke a permission without a privilege.");
|
"Can't revoke a permission without a privilege."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (grantee == null) {
|
if (grantee == null) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Can't revoke a permission from grantee null.");
|
"Can't revoke a permission from grantee null."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object == null) {
|
if (object == null) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Can't revoke a permission from object NULL.");
|
"Can't revoke a permission from object NULL."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.debug("Revoking permission granting privilege \"{}\" "
|
LOGGER.debug(
|
||||||
+ "on object \"{}\" to role \"{}\"...",
|
"Revoking permission granting privilege \"{}\" "
|
||||||
privilege,
|
+ "on object \"{}\" to role \"{}\"...",
|
||||||
grantee.getName(),
|
privilege,
|
||||||
object.getUuid());
|
grantee.getName(),
|
||||||
|
object.getUuid()
|
||||||
|
);
|
||||||
|
|
||||||
if (existsPermission(privilege, grantee, object)
|
if (existsPermission(privilege, grantee, object)
|
||||||
|| existsInheritedPermission(privilege, grantee, object)) {
|
|| existsInheritedPermission(privilege, grantee, object)) {
|
||||||
|
|
||||||
LOGGER.debug("There is a permission for the provided parameters, "
|
LOGGER.debug(
|
||||||
+ "revoking it...");
|
"There is a permission for the provided parameters, "
|
||||||
|
+ "revoking it..."
|
||||||
|
);
|
||||||
|
|
||||||
final Query deleteQuery = entityManager.createQuery(
|
final Query deleteQuery = entityManager.createQuery(
|
||||||
"DELETE FROM Permission p "
|
"DELETE FROM Permission p "
|
||||||
+ "WHERE p.grantedPrivilege = :privilege "
|
+ "WHERE p.grantedPrivilege = :privilege "
|
||||||
+ "AND p.grantee = :grantee "
|
+ "AND p.grantee = :grantee "
|
||||||
+ "AND p.object = :object");
|
+ "AND p.object = :object"
|
||||||
|
);
|
||||||
deleteQuery.setParameter(QUERY_PARAM_PRIVILEGE, privilege);
|
deleteQuery.setParameter(QUERY_PARAM_PRIVILEGE, privilege);
|
||||||
deleteQuery.setParameter(QUERY_PARAM_GRANTEE, grantee);
|
deleteQuery.setParameter(QUERY_PARAM_GRANTEE, grantee);
|
||||||
deleteQuery.setParameter(QUERY_PARAM_OBJECT, object);
|
deleteQuery.setParameter(QUERY_PARAM_OBJECT, object);
|
||||||
|
|
@ -470,18 +547,21 @@ public class PermissionManager implements Serializable {
|
||||||
+ "WHERE p.grantedPrivilege = :privilege "
|
+ "WHERE p.grantedPrivilege = :privilege "
|
||||||
+ "AND p.grantee = :grantee "
|
+ "AND p.grantee = :grantee "
|
||||||
+ "AND p.inheritedFrom = :object "
|
+ "AND p.inheritedFrom = :object "
|
||||||
+ "AND p.inherited = true");
|
+ "AND p.inherited = true"
|
||||||
|
);
|
||||||
deleteInheritedQuery.setParameter(QUERY_PARAM_PRIVILEGE, privilege);
|
deleteInheritedQuery.setParameter(QUERY_PARAM_PRIVILEGE, privilege);
|
||||||
deleteInheritedQuery.setParameter(QUERY_PARAM_GRANTEE, grantee);
|
deleteInheritedQuery.setParameter(QUERY_PARAM_GRANTEE, grantee);
|
||||||
deleteInheritedQuery.setParameter("object", object);
|
deleteInheritedQuery.setParameter("object", object);
|
||||||
final int deletedInherited = deleteInheritedQuery.executeUpdate();
|
final int deletedInherited = deleteInheritedQuery.executeUpdate();
|
||||||
LOGGER.debug("{} inherited permissions deleted.", deletedInherited);
|
LOGGER.debug("{} inherited permissions deleted.", deletedInherited);
|
||||||
} else {
|
} else {
|
||||||
LOGGER.warn("No permission granting privilege \"{}\" "
|
LOGGER.warn(
|
||||||
+ "on object \"{}\" to role \"{}\". Ignoring.",
|
"No permission granting privilege \"{}\" "
|
||||||
privilege,
|
+ "on object \"{}\" to role \"{}\". Ignoring.",
|
||||||
grantee.getName(),
|
privilege,
|
||||||
object.getUuid());
|
grantee.getName(),
|
||||||
|
object.getUuid()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -495,16 +575,20 @@ public class PermissionManager implements Serializable {
|
||||||
@AuthorizationRequired
|
@AuthorizationRequired
|
||||||
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
public void revokePrivilege(final String privilege,
|
public void revokePrivilege(
|
||||||
final Role grantee) {
|
final String privilege,
|
||||||
|
final Role grantee
|
||||||
|
) {
|
||||||
if (privilege == null || privilege.isEmpty()) {
|
if (privilege == null || privilege.isEmpty()) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Can't revoke a permission without a privilege.");
|
"Can't revoke a permission without a privilege."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (grantee == null) {
|
if (grantee == null) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Can't revoke a permission from grantee null.");
|
"Can't revoke a permission from grantee null."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existsPermission(privilege, grantee)) {
|
if (existsPermission(privilege, grantee)) {
|
||||||
|
|
@ -512,7 +596,8 @@ public class PermissionManager implements Serializable {
|
||||||
"DELETE FROM Permission p "
|
"DELETE FROM Permission p "
|
||||||
+ "WHERE p.grantedPrivilege = :privilege "
|
+ "WHERE p.grantedPrivilege = :privilege "
|
||||||
+ "AND p.grantee = :grantee "
|
+ "AND p.grantee = :grantee "
|
||||||
+ "AND p.object IS NULL");
|
+ "AND p.object IS NULL"
|
||||||
|
);
|
||||||
query.setParameter(QUERY_PARAM_PRIVILEGE, privilege);
|
query.setParameter(QUERY_PARAM_PRIVILEGE, privilege);
|
||||||
query.setParameter(QUERY_PARAM_GRANTEE, grantee);
|
query.setParameter(QUERY_PARAM_GRANTEE, grantee);
|
||||||
query.executeUpdate();
|
query.executeUpdate();
|
||||||
|
|
@ -532,8 +617,10 @@ public class PermissionManager implements Serializable {
|
||||||
@AuthorizationRequired
|
@AuthorizationRequired
|
||||||
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
public void copyPermissions(final CcmObject source,
|
public void copyPermissions(
|
||||||
final CcmObject target) {
|
final CcmObject source,
|
||||||
|
final CcmObject target
|
||||||
|
) {
|
||||||
copyPermissions(source, target, false);
|
copyPermissions(source, target, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -552,21 +639,27 @@ public class PermissionManager implements Serializable {
|
||||||
@AuthorizationRequired
|
@AuthorizationRequired
|
||||||
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
public void copyPermissions(final CcmObject source,
|
public void copyPermissions(
|
||||||
final CcmObject target,
|
final CcmObject source,
|
||||||
final boolean inherited) {
|
final CcmObject target,
|
||||||
|
final boolean inherited
|
||||||
|
) {
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Can't copy permissions from source NULL.");
|
"Can't copy permissions from source NULL."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Can't copy permissions to target NULL.");
|
"Can't copy permissions to target NULL."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final TypedQuery<Permission> query = entityManager.createNamedQuery(
|
final TypedQuery<Permission> query = entityManager.createNamedQuery(
|
||||||
"Permission.findPermissionsForCcmObject", Permission.class);
|
"Permission.findPermissionsForCcmObject",
|
||||||
|
Permission.class
|
||||||
|
);
|
||||||
query.setParameter(QUERY_PARAM_OBJECT, source);
|
query.setParameter(QUERY_PARAM_OBJECT, source);
|
||||||
final List<Permission> result = query.getResultList();
|
final List<Permission> result = query.getResultList();
|
||||||
|
|
||||||
|
|
@ -574,7 +667,11 @@ public class PermissionManager implements Serializable {
|
||||||
final Permission granted = grantPrivilege(
|
final Permission granted = grantPrivilege(
|
||||||
permission.getGrantedPrivilege(),
|
permission.getGrantedPrivilege(),
|
||||||
permission.getGrantee(),
|
permission.getGrantee(),
|
||||||
target);
|
target
|
||||||
|
);
|
||||||
|
if (granted == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
granted.setInherited(inherited);
|
granted.setInherited(inherited);
|
||||||
if (inherited) {
|
if (inherited) {
|
||||||
granted.setInheritedFrom(source);
|
granted.setInheritedFrom(source);
|
||||||
|
|
@ -598,12 +695,17 @@ public class PermissionManager implements Serializable {
|
||||||
* @return A list with all privileges defined by the provided class.
|
* @return A list with all privileges defined by the provided class.
|
||||||
*/
|
*/
|
||||||
public List<String> listDefiniedPrivileges(final Class<?> clazz) {
|
public List<String> listDefiniedPrivileges(final Class<?> clazz) {
|
||||||
return Arrays.stream(clazz.getDeclaredFields())
|
return Arrays
|
||||||
|
.stream(clazz.getDeclaredFields())
|
||||||
.filter(field -> field.getType().isAssignableFrom(String.class))
|
.filter(field -> field.getType().isAssignableFrom(String.class))
|
||||||
.filter(field -> Modifier.isStatic(field.getModifiers())
|
.filter(
|
||||||
&& Modifier.isFinal(field.getModifiers()))
|
field -> Modifier.isStatic(field.getModifiers())
|
||||||
.filter(field -> field.getName().startsWith("PRIVILEGE_")
|
&& Modifier.isFinal(field.getModifiers())
|
||||||
|| clazz.getSimpleName().endsWith("Privileges"))
|
)
|
||||||
|
.filter(
|
||||||
|
field -> field.getName().startsWith("PRIVILEGE_")
|
||||||
|
|| clazz.getSimpleName().endsWith("Privileges")
|
||||||
|
)
|
||||||
.map(field -> getPrivilegeString(field))
|
.map(field -> getPrivilegeString(field))
|
||||||
.sorted()
|
.sorted()
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
@ -629,11 +731,15 @@ public class PermissionManager implements Serializable {
|
||||||
* @return {@code true} if there is a matching permission, {@code false} if
|
* @return {@code true} if there is a matching permission, {@code false} if
|
||||||
* not.
|
* not.
|
||||||
*/
|
*/
|
||||||
private boolean existsPermission(final String privilege,
|
private boolean existsPermission(
|
||||||
final Role grantee,
|
final String privilege,
|
||||||
final CcmObject object) {
|
final Role grantee,
|
||||||
|
final CcmObject object
|
||||||
|
) {
|
||||||
final TypedQuery<Long> query = entityManager.createNamedQuery(
|
final TypedQuery<Long> query = entityManager.createNamedQuery(
|
||||||
"Permission.existsDirectForPrivilegeRoleObject", Long.class);
|
"Permission.existsDirectForPrivilegeRoleObject",
|
||||||
|
Long.class
|
||||||
|
);
|
||||||
query.setParameter(QUERY_PARAM_PRIVILEGE, privilege);
|
query.setParameter(QUERY_PARAM_PRIVILEGE, privilege);
|
||||||
query.setParameter(QUERY_PARAM_GRANTEE, grantee);
|
query.setParameter(QUERY_PARAM_GRANTEE, grantee);
|
||||||
query.setParameter(QUERY_PARAM_OBJECT, object);
|
query.setParameter(QUERY_PARAM_OBJECT, object);
|
||||||
|
|
@ -641,11 +747,15 @@ public class PermissionManager implements Serializable {
|
||||||
return query.getSingleResult() > 0;
|
return query.getSingleResult() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean existsInheritedPermission(final String privilege,
|
private boolean existsInheritedPermission(
|
||||||
final Role grantee,
|
final String privilege,
|
||||||
final CcmObject object) {
|
final Role grantee,
|
||||||
|
final CcmObject object
|
||||||
|
) {
|
||||||
final TypedQuery<Long> query = entityManager.createNamedQuery(
|
final TypedQuery<Long> query = entityManager.createNamedQuery(
|
||||||
"Permission.existsInheritedForPrivilegeRoleObject", Long.class);
|
"Permission.existsInheritedForPrivilegeRoleObject",
|
||||||
|
Long.class
|
||||||
|
);
|
||||||
query.setParameter(QUERY_PARAM_PRIVILEGE, privilege);
|
query.setParameter(QUERY_PARAM_PRIVILEGE, privilege);
|
||||||
query.setParameter(QUERY_PARAM_GRANTEE, grantee);
|
query.setParameter(QUERY_PARAM_GRANTEE, grantee);
|
||||||
query.setParameter(QUERY_PARAM_OBJECT, object);
|
query.setParameter(QUERY_PARAM_OBJECT, object);
|
||||||
|
|
@ -663,10 +773,14 @@ public class PermissionManager implements Serializable {
|
||||||
* @return {@code true} if there is a matching permission, {@code false} if
|
* @return {@code true} if there is a matching permission, {@code false} if
|
||||||
* not.
|
* not.
|
||||||
*/
|
*/
|
||||||
private boolean existsPermission(final String privilege,
|
private boolean existsPermission(
|
||||||
final Role grantee) {
|
final String privilege,
|
||||||
|
final Role grantee
|
||||||
|
) {
|
||||||
final TypedQuery<Long> query = entityManager.createNamedQuery(
|
final TypedQuery<Long> query = entityManager.createNamedQuery(
|
||||||
"Permission.existsForPrivilegeAndRole", Long.class);
|
"Permission.existsForPrivilegeAndRole",
|
||||||
|
Long.class
|
||||||
|
);
|
||||||
query.setParameter(QUERY_PARAM_PRIVILEGE, privilege);
|
query.setParameter(QUERY_PARAM_PRIVILEGE, privilege);
|
||||||
query.setParameter(QUERY_PARAM_GRANTEE, grantee);
|
query.setParameter(QUERY_PARAM_GRANTEE, grantee);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,32 +57,36 @@ class FreemarkerConfigurationProvider {
|
||||||
private final Map<ThemeInfo, Configuration> configurations = new HashMap<>();
|
private final Map<ThemeInfo, Configuration> configurations = new HashMap<>();
|
||||||
|
|
||||||
protected Configuration getConfiguration(final ThemeInfo forTheme) {
|
protected Configuration getConfiguration(final ThemeInfo forTheme) {
|
||||||
|
|
||||||
if (configurations.containsKey(forTheme)) {
|
if (configurations.containsKey(forTheme)) {
|
||||||
|
|
||||||
return configurations.get(forTheme);
|
return configurations.get(forTheme);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
final Configuration configuration = new Configuration(
|
final Configuration configuration = new Configuration(
|
||||||
Configuration.VERSION_2_3_27);
|
Configuration.VERSION_2_3_27
|
||||||
|
);
|
||||||
configuration.setDefaultEncoding("UTF-8");
|
configuration.setDefaultEncoding("UTF-8");
|
||||||
configuration
|
configuration
|
||||||
.setTemplateExceptionHandler(
|
.setTemplateExceptionHandler(
|
||||||
TemplateExceptionHandler.RETHROW_HANDLER);
|
TemplateExceptionHandler.DEBUG_HANDLER
|
||||||
configuration.setLogTemplateExceptions(false);
|
);
|
||||||
|
configuration.setLogTemplateExceptions(true);
|
||||||
configuration.setWrapUncheckedExceptions(false);
|
configuration.setWrapUncheckedExceptions(false);
|
||||||
configuration.setLocalizedLookup(false);
|
configuration.setLocalizedLookup(false);
|
||||||
|
|
||||||
configuration.setTemplateLoader(
|
configuration.setTemplateLoader(
|
||||||
new MultiTemplateLoader(new TemplateLoader[]{
|
new MultiTemplateLoader(
|
||||||
// For for files from themes
|
new TemplateLoader[]{
|
||||||
new CcmTemplateLoader(forTheme),
|
// For for files from themes
|
||||||
// Loader for MacroLibs provided by CCM modules
|
new CcmTemplateLoader(forTheme),
|
||||||
new WebappTemplateLoader(
|
// Loader for MacroLibs provided by CCM modules
|
||||||
servletContext, "/themes/freemarker"
|
new WebappTemplateLoader(
|
||||||
),
|
servletContext, "/themes/freemarker"
|
||||||
new ClassTemplateLoader(getClass(), "/themes/freemarker")
|
),
|
||||||
})
|
new ClassTemplateLoader(
|
||||||
|
getClass(),
|
||||||
|
"/themes/freemarker"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
configurations.put(forTheme, configuration);
|
configurations.put(forTheme, configuration);
|
||||||
|
|
@ -103,7 +107,8 @@ class FreemarkerConfigurationProvider {
|
||||||
public Object findTemplateSource(final String name) throws IOException {
|
public Object findTemplateSource(final String name) throws IOException {
|
||||||
|
|
||||||
final Optional<InputStream> source = themes.getFileFromTheme(
|
final Optional<InputStream> source = themes.getFileFromTheme(
|
||||||
fromTheme, name);
|
fromTheme, name
|
||||||
|
);
|
||||||
if (source.isPresent()) {
|
if (source.isPresent()) {
|
||||||
return source.get();
|
return source.get();
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -118,9 +123,10 @@ class FreemarkerConfigurationProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Reader getReader(final Object templateSource,
|
public Reader getReader(
|
||||||
final String encoding) throws IOException {
|
final Object templateSource,
|
||||||
|
final String encoding
|
||||||
|
) throws IOException {
|
||||||
final InputStream inputStream = (InputStream) templateSource;
|
final InputStream inputStream = (InputStream) templateSource;
|
||||||
return new InputStreamReader(inputStream, encoding);
|
return new InputStreamReader(inputStream, encoding);
|
||||||
}
|
}
|
||||||
|
|
@ -128,7 +134,6 @@ class FreemarkerConfigurationProvider {
|
||||||
@Override
|
@Override
|
||||||
public void closeTemplateSource(final Object templateSource)
|
public void closeTemplateSource(final Object templateSource)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
final InputStream inputStream = (InputStream) templateSource;
|
final InputStream inputStream = (InputStream) templateSource;
|
||||||
inputStream.close();
|
inputStream.close();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -217,7 +217,9 @@ public class ImportExportTaskManager {
|
||||||
* @see CompletionStage#handle(java.util.function.BiFunction)
|
* @see CompletionStage#handle(java.util.function.BiFunction)
|
||||||
*/
|
*/
|
||||||
private Object handleExportTaskResult(
|
private Object handleExportTaskResult(
|
||||||
final ExportTask task, final Throwable ex, final ExportTaskStatus status
|
final ExportTask task,
|
||||||
|
final Throwable ex,
|
||||||
|
final ExportTaskStatus status
|
||||||
) {
|
) {
|
||||||
if (ex == null) {
|
if (ex == null) {
|
||||||
status.setStatus(ImExportTaskStatus.FINISHED);
|
status.setStatus(ImExportTaskStatus.FINISHED);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue