From 6c18304cd268fc54cb4157d51e3800a6588c6ff3 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Mon, 18 Oct 2021 21:22:59 +0200 Subject: [PATCH] Additional service/endpoint for retrieving file content from a binary asset. --- .../java/org/librecms/assets/BinaryAsset.java | 77 +++- .../assets/BinaryAssetRepository.java | 387 ++++++++++++++++++ .../org/librecms/contentsection/PathUtil.java | 2 +- .../librecms/contentsection/rs/Assets.java | 36 +- .../rs/ContentSectionsApplication.java | 1 + .../org/librecms/contentsection/rs/Files.java | 150 +++++++ .../librecms/contentsection/rs/Images.java | 81 ++-- .../assets/FileAssetEditStepDownload.java | 4 +- .../assets/VideoAssetEditStep.java | 3 +- .../components/librecms/cmsEditor.xhtml | 2 +- .../cms-editor/video-node/video-node.ts | 2 +- 11 files changed, 681 insertions(+), 64 deletions(-) create mode 100644 ccm-cms/src/main/java/org/librecms/assets/BinaryAssetRepository.java create mode 100644 ccm-cms/src/main/java/org/librecms/contentsection/rs/Files.java diff --git a/ccm-cms/src/main/java/org/librecms/assets/BinaryAsset.java b/ccm-cms/src/main/java/org/librecms/assets/BinaryAsset.java index 306dd770a..6e9562a20 100644 --- a/ccm-cms/src/main/java/org/librecms/assets/BinaryAsset.java +++ b/ccm-cms/src/main/java/org/librecms/assets/BinaryAsset.java @@ -38,6 +38,7 @@ import org.hibernate.envers.NotAudited; import org.libreccm.core.UnexpectedErrorException; import org.libreccm.jpa.utils.MimeTypeConverter; import org.libreccm.l10n.LocalizedString; +import org.librecms.contentsection.privileges.AssetPrivileges; import java.io.InputStream; import java.io.OutputStream; @@ -47,7 +48,8 @@ import java.sql.SQLException; import javax.persistence.Basic; import javax.persistence.Convert; import javax.persistence.FetchType; -import javax.transaction.Transactional; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; import static org.librecms.CmsConstants.*; @@ -59,6 +61,73 @@ import static org.librecms.CmsConstants.*; @Entity @Table(name = "BINARY_ASSETS", schema = DB_SCHEMA) @Audited +@NamedQueries({ + @NamedQuery( + name = "BinaryAsset.findById", + query = "SELECT DISTINCT a " + + "FROM BinaryAsset a " + + "LEFT JOIN a.permissions p " + + "WHERE a.objectId = :assetId " + + "LEFT JOIN a.permissions p " + + "AND (" + + " (" + + " p.grantee IN :roles " + + " AND p.grantedPrivilege = " + + " '" + AssetPrivileges.VIEW + "' " + + " ) " + + " OR true = :isSystemUser OR true = :isAdmin" + + ")" + ), + @NamedQuery( + name = "BinaryAsset.findByUuid", + query = "SELECT DISTINCT a " + + "FROM BinaryAsset a " + + "LEFT JOIN a.permissions p " + + "WHERE a.uuid = :uuid " + + "AND (" + + " (" + + " p.grantee IN :roles " + + " AND p.grantedPrivilege = " + + " '" + AssetPrivileges.VIEW + "' " + + " ) " + + " OR true = :isSystemUser OR true = :isAdmin" + + ")" + ), + @NamedQuery( + name = "BinaryAsset.findByContentSection", + query = "SELECT DISTINCT a " + + "FROM BinaryAsset a " + + "JOIN a.categories c " + + "LEFT JOIN a.permissions p " + + "WHERE c.category.section = :section " + + "AND (" + + " (" + + " p.grantee IN :roles " + + " AND p.grantedPrivilege = " + + " '" + AssetPrivileges.VIEW + "' " + + " ) " + + " OR true = :isSystemUser OR true = :isAdmin" + + ")" + ), + @NamedQuery( + name = "BinaryAsset.findByNameInFolder", + query = "SELECT DISTINCT a " + + "FROM BinaryAsset a " + + "JOIN a.categories c " + + "LEFT JOIN a.permissions p " + + "WHERE c.category = :folder " + + "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER + "' " + + "AND a.displayName = :name " + + "AND (" + + " (" + + " p.grantee IN :roles " + + " AND p.grantedPrivilege = '" + + AssetPrivileges.VIEW + "'" + + " ) " + + " OR true = :isSystemUser OR true = :isAdmin" + + " )" + ) +}) public class BinaryAsset extends Asset implements Serializable { private static final long serialVersionUID = -8540922051232103527L; @@ -126,11 +195,11 @@ public class BinaryAsset extends Asset implements Serializable { public Blob getData() { return data; } - + public long getDataSize() { try { - return data.length(); - } catch(SQLException ex) { + return data.length(); + } catch (SQLException ex) { throw new UnexpectedErrorException(ex); } } diff --git a/ccm-cms/src/main/java/org/librecms/assets/BinaryAssetRepository.java b/ccm-cms/src/main/java/org/librecms/assets/BinaryAssetRepository.java new file mode 100644 index 000000000..93483f8ef --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/assets/BinaryAssetRepository.java @@ -0,0 +1,387 @@ +/* + * Copyright (C) 2021 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.assets; + +import com.arsdigita.kernel.KernelConfig; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.libreccm.auditing.AbstractAuditedEntityRepository; +import org.libreccm.categorization.Categorization; +import org.libreccm.categorization.Category; +import org.libreccm.categorization.CategoryManager; +import org.libreccm.categorization.ObjectNotAssignedToCategoryException; +import org.libreccm.configuration.ConfigurationManager; +import org.libreccm.core.CcmObjectRepository; +import org.libreccm.core.UnexpectedErrorException; +import org.libreccm.security.AuthorizationRequired; +import org.libreccm.security.Permission; +import org.libreccm.security.PermissionChecker; +import org.libreccm.security.PermissionManager; +import org.libreccm.security.RequiresPrivilege; +import org.libreccm.security.Role; +import org.libreccm.security.RoleManager; +import org.libreccm.security.Shiro; +import org.libreccm.security.User; +import org.libreccm.security.UserRepository; +import org.librecms.contentsection.Asset; +import org.librecms.contentsection.AssetInUseException; +import org.librecms.contentsection.AssetManager; +import org.librecms.contentsection.ContentSection; +import org.librecms.contentsection.Folder; +import org.librecms.contentsection.FolderRepository; +import org.librecms.contentsection.FolderType; +import org.librecms.contentsection.PathUtil; +import org.librecms.contentsection.privileges.AssetPrivileges; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.persistence.EntityManager; +import javax.persistence.NoResultException; +import javax.persistence.TypedQuery; +import javax.transaction.Transactional; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +public class BinaryAssetRepository + extends AbstractAuditedEntityRepository { + + private static final long serialVersionUID = 1L; + + private static final Logger LOGGER = LogManager + .getLogger(BinaryAssetRepository.class); + + @Inject + private AssetManager assetManager; + + @Inject + private CategoryManager categoryManager; + + @Inject + private CcmObjectRepository ccmObjectRepo; + + @Inject + private ConfigurationManager confManager; + + @Inject + private EntityManager entityManager; + + @Inject + private FolderRepository folderRepo; + + @Inject + private PermissionChecker permissionChecker; + + @Inject + private PermissionManager permissionManager; + + @Inject + private RoleManager roleManager; + + @Inject + private Shiro shiro; + + @Inject + private UserRepository userRepository; + + @Override + public Long getEntityId(final BinaryAsset entity) { + return entity.getObjectId(); + } + + @Override + public Class getEntityClass() { + return BinaryAsset.class; + } + + @Override + public String getIdAttributeName() { + return "objectId"; + } + + @Override + public Long getIdOfEntity(final BinaryAsset entity) { + return entity.getObjectId(); + } + + @Override + public boolean isNew(final BinaryAsset asset) { + return asset.getObjectId() == 0; + } + + /** + * Set the UUID of a new asset. + * + * @param asset + */ + @Override + public void initNewEntity(final BinaryAsset asset) { + super.initNewEntity(asset); + if (asset.getUuid() == null) { + final String uuid = UUID.randomUUID().toString(); + asset.setUuid(uuid); + } + } + + @Transactional(Transactional.TxType.REQUIRED) + public Optional findById(final long assetId) { + + final TypedQuery query = getEntityManager() + .createNamedQuery("BinaryAsset.findById", BinaryAsset.class) + .setParameter("assetId", assetId); + setAuthorizationParameters(query); + + try { + return Optional.of(query.getSingleResult()); + } catch (NoResultException ex) { + return Optional.empty(); + } + } + + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + @Override + public void save( + @RequiresPrivilege(AssetPrivileges.EDIT) + final BinaryAsset asset) { + + super.save(asset); + } + + /** + * Deletes an unused Asset. If the {@link Asset} is in use + * (linked to at least one ContentItem) an {@link AssetInUseException} is + * thrown. Use {@link AssetManager#isAssetInUse} to check if an + * {@link Asset} is used. + * + * @param asset The {@link Asset} to delete. + * + * @throws AssetInUseException if the {@link Asset} to delete is in use. + */ + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + @Override + public void delete( + @RequiresPrivilege(AssetPrivileges.DELETE) + final BinaryAsset asset + ) { + + if (assetManager.isAssetInUse(asset)) { + throw new AssetInUseException( + String.format( + "BinaryAsset %s is in use.", + asset.getUuid() + ) + ); + } else { + final List categories = asset.getCategories() + .stream() + .map(categorization -> categorization.getCategory()) + .collect(Collectors.toList()); + + for (final Category category : categories) { + try { + categoryManager.removeObjectFromCategory(asset, category); + } catch (ObjectNotAssignedToCategoryException ex) { + throw new UnexpectedErrorException(ex); + } + } + + final List permissions = asset.getPermissions(); + for (final Permission permission : permissions) { + permissionManager.revokePrivilege(permission + .getGrantedPrivilege(), + permission.getGrantee(), + asset); + } + + ccmObjectRepo.delete(asset); + } + } + + /** + * Find an {@link Asset} by its UUID. This method does not distinguish + * between shared and non shared assets. + * + * @param uuid The UUID of the {@link Asset}. + * + * @return An {@link Optional} containing the {@link Asset} with the + * provided {@code uuid} if there is an asset with that + * {@code uuid}. Otherwise an empty {@link Optional} is returned. + */ + @Transactional(Transactional.TxType.REQUIRED) + public Optional findByUuid(final String uuid) { + + final TypedQuery query = entityManager + .createNamedQuery("BinaryAsset.findByUuid", BinaryAsset.class); + query.setParameter("uuid", uuid); + setAuthorizationParameters(query); + + try { + return Optional.of(query.getSingleResult()); + } catch (NoResultException ex) { + return Optional.empty(); + } + } + + @Transactional(Transactional.TxType.REQUIRED) + public List findByContentSection(final ContentSection section) { + + final TypedQuery query = entityManager + .createNamedQuery( + "BinaryAsset.findByContentSection", BinaryAsset.class + ); + query.setParameter("section", section); + setAuthorizationParameters(query); + + return query.getResultList(); + } + + @Transactional(Transactional.TxType.REQUIRED) + public Optional findByNameInFolder( + final Folder folder, final String name + ) { + final TypedQuery query = getEntityManager() + .createNamedQuery( + "BinaryAsset.findByNameInFolder", BinaryAsset.class + ) + .setParameter("folder", folder) + .setParameter("name", name); + setAuthorizationParameters(query); + + try { + return Optional.of(query.getSingleResult()); + } catch (NoResultException ex) { + return Optional.empty(); + } + } + + @Transactional(Transactional.TxType.REQUIRED) + public Optional findByPath(final String path) { + + //The last token is the name of the asset itself. Remove this part and + //get the folder containing the asset using the FolderRepository. + final String normalizedPath = PathUtil.normalizePath(path); + final int lastTokenStart = normalizedPath.lastIndexOf('/'); + final String folderPath = normalizedPath.substring(0, lastTokenStart); + final String assetName = normalizedPath.substring(lastTokenStart + 1); + + final Optional folder = folderRepo.findByPath( + folderPath, FolderType.ASSETS_FOLDER); + + if (folder.isPresent()) { + return findByNameInFolder(folder.get(), assetName); + } else { + return Optional.empty(); + } + } + + @Transactional(Transactional.TxType.REQUIRED) + public Optional findByPath( + final ContentSection section, final String path + ) { + //The last token is the name of the asset itself. Remove this part an get + //the folder containing the asset using the FolderRepository. + final String normalizedPath = PathUtil.normalizePath(path); + final int lastTokenStart = normalizedPath.lastIndexOf('/'); + final String assetName; + final Optional folder; + if (lastTokenStart < 0) { + assetName = normalizedPath; + folder = folderRepo + .findById(section.getRootAssetsFolder().getObjectId()); + } else { + final String folderPath = normalizedPath + .substring(0, lastTokenStart); + assetName = normalizedPath.substring(lastTokenStart + 1); + folder = folderRepo + .findByPath(section, folderPath, FolderType.ASSETS_FOLDER); + } + + if (folder.isPresent()) { + LOGGER.debug("transaction is active? {}", + entityManager.isJoinedToTransaction()); + LOGGER.debug("Folder for path {} found...", path); +// LOGGER.debug("Assets in the folder:"); +// final Folder theFolder = folderRepo +// .findById(folder.get().getObjectId()) +// .orElseThrow(() -> new IllegalArgumentException()); + for (final Categorization categorization : folder.get().getObjects()) { + LOGGER.debug(" {}", + categorization.getCategorizedObject() + .getDisplayName()); + } + + return findByNameInFolder(folder.get(), assetName); + } else { + return Optional.empty(); + } + } + + private void setAuthorizationParameters(final TypedQuery query) { + + final Optional user = shiro.getUser(); + final List roles; + if (user.isPresent()) { + roles = user + .get() + .getRoleMemberships() + .stream() + .map(membership -> membership.getRole()) + .collect(Collectors.toList()); + } else { + + final Optional publicUser; + + final KernelConfig kernelConfig = confManager + .findConfiguration(KernelConfig.class); + final String principal = (String) shiro + .getPublicUser() + .getPrincipal(); + if (kernelConfig.emailIsPrimaryIdentifier()) { + publicUser = userRepository.findByEmailAddress(principal); + } else { + publicUser = userRepository.findByName(principal); + } + + if (publicUser.isPresent()) { + roles = roleManager.findAllRolesForUser(publicUser.get()); + } else { + roles = Collections.emptyList(); + } + } + + final boolean isSystemUser = shiro.isSystemUser(); + final boolean isAdmin = permissionChecker.isPermitted("*"); + + query.setParameter("roles", roles); + query.setParameter("isSystemUser", isSystemUser); + query.setParameter("isAdmin", isAdmin); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/PathUtil.java b/ccm-cms/src/main/java/org/librecms/contentsection/PathUtil.java index a756bf79d..a1045553a 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/PathUtil.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/PathUtil.java @@ -41,7 +41,7 @@ public final class PathUtil { * @param path The path to normalise. * @return The normalised path */ - protected static final String normalizePath(final String path) { + public static final String normalizePath(final String path) { String normalizedPath = path; if (normalizedPath.charAt(0) == '/') { normalizedPath = normalizedPath.substring(1); diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Assets.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Assets.java index ef5f0c255..3b1d87df1 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Assets.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Assets.java @@ -163,7 +163,7 @@ public class Assets { assets .stream() - .map(this::assetToJson) + .map(asset -> assetToJson(asset, contentSection)) .forEach(arrayBuilder::add); final StringWriter writer = new StringWriter(); @@ -189,7 +189,7 @@ public class Assets { final Folder folder = contentSection.getRootAssetsFolder(); - return findAssetsInFolder(folder, query, type); + return findAssetsInFolder(contentSection, folder, query, type); } @GET @@ -215,13 +215,15 @@ public class Assets { folderPath, section))); - return findAssetsInFolder(folder, query, type); + return findAssetsInFolder(contentSection, folder, query, type); } - private String findAssetsInFolder(final Folder folder, - final String query, - final String type) { - + private String findAssetsInFolder( + final ContentSection section, + final Folder folder, + final String query, + final String type + ) { final List assets; if ((query == null || query.trim().isEmpty()) && ((type == null) || type.trim().isEmpty())) { @@ -245,12 +247,12 @@ public class Assets { folder .getSubFolders() .stream() - .map(this::assetToJson) + .map(subFolder -> assetToJson(subFolder, section)) .forEach(arrayBuilder::add); assets .stream() - .map(this::assetToJson) + .map(asset -> assetToJson(asset, section)) .forEach(arrayBuilder::add); final StringWriter writer = new StringWriter(); @@ -283,19 +285,25 @@ public class Assets { } } - private JsonObject assetToJson(final Folder folder) { - + private JsonObject assetToJson( + final Folder folder, + final ContentSection section + ) { return Json .createObjectBuilder() .add("title", folder.getTitle().getValue(defaultLocale)) .add("type", Folder.class.getName()) + .add("section", section.getLabel()) + .add("path", folderManager.getFolderPath(folder)) .add("place", "") .build(); } - private JsonObject assetToJson(final Asset asset) { - + private JsonObject assetToJson( + final Asset asset, + final ContentSection section + ) { final AssetTypeInfo typeInfo = assetTypesManager .getAssetTypeInfo(asset.getClass()); final ResourceBundle bundle = ResourceBundle @@ -318,6 +326,8 @@ public class Assets { asset.getTitle())) .add("type", asset.getClass().getName()) .add("typeLabel", bundle.getString(typeInfo.getLabelKey())) + .add("contentsection", section.getLabel()) + .add("path", assetManager.getAssetPath(asset)) .add("place", place) .add("properties", getAssetProperties(asset)) .build(); diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/ContentSectionsApplication.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/ContentSectionsApplication.java index efe43a9bd..bff1be942 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/rs/ContentSectionsApplication.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/ContentSectionsApplication.java @@ -39,6 +39,7 @@ public class ContentSectionsApplication extends Application{ classes.add(Assets.class); classes.add(ContentItems.class); classes.add(ContentSections.class); + classes.add(Files.class); classes.add(Images.class); return classes; diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Files.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Files.java new file mode 100644 index 000000000..fb22f47e0 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Files.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2021 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.contentsection.rs; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.librecms.assets.BinaryAsset; +import org.librecms.assets.BinaryAssetDataService; +import org.librecms.assets.BinaryAssetRepository; +import org.librecms.contentsection.Asset; +import org.librecms.contentsection.AssetRepository; +import org.librecms.contentsection.ContentSection; +import org.librecms.contentsection.ContentSectionRepository; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Optional; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.StreamingOutput; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Path("/{content-section}/files") +public class Files { + + private static final Logger LOGGER = LogManager.getLogger(Files.class); + +// @Inject +// private AssetRepository assetRepo; + @Inject + private BinaryAssetRepository binaryAssetRepo; + + @Inject + private BinaryAssetDataService dataService; + + @Inject + private ContentSectionRepository sectionRepo; + + @GET + @Path("/uuid-{uuid}") + public Response getFileByUuid( + @PathParam("content-section") final String sectionName, + @PathParam("uuid") final String uuid + ) { + final Optional asset = binaryAssetRepo.findByUuid(uuid); + + if (asset.isPresent()) { + return loadFile(asset.get()); + } else { + return Response + .status(Response.Status.NOT_FOUND) + .entity( + String.format( + "The requested file \"%s\" does not exist.", + uuid + ) + ) + .build(); + } + } + + @GET + @Path("/{path:^(?!uuid).+$}") + public Response getFile( + @PathParam("content-section") final String sectionName, + @PathParam("path") final String path + ) { + final Optional section = sectionRepo + .findByLabel(sectionName); + if (!section.isPresent()) { + return Response + .status(Response.Status.NOT_FOUND) + .entity(String.format("No content section \"%s\" available.", + sectionName)) + .build(); + } + + final Optional asset = binaryAssetRepo.findByPath( + section.get(), path + ); + + if (asset.isPresent()) { + + return loadFile(asset.get()); + + } else { + return Response + .status(Response.Status.NOT_FOUND) + .entity( + String.format( + "The requested file \"%s\" does not exist.", + path + ) + ) + .build(); + } + } + + private Response loadFile(final BinaryAsset asset) { + return Response + .ok() + .entity( + new StreamingOutput() { + + @Override + public void write(final OutputStream outputStream) + throws IOException, WebApplicationException { + dataService.copyDataToOutputStream(asset, outputStream); + } + + }) + .header("ContentType", asset.getMimeType()) + .header( + "Content-Disposition", + String.format( + "attachment; filename=\"%s\"", + asset.getFileName() + ) + ) + .build(); + + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Images.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Images.java index b2558039c..0f17d0e37 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Images.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Images.java @@ -27,7 +27,6 @@ import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSectionRepository; import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -65,17 +64,12 @@ public class Images { @GET @Path("/uuid-{uuid}") public Response getImageByUuid( - @PathParam("content-section") - final String sectionName, - @PathParam("uuid") - final String uuid, - @QueryParam("width") - @DefaultValue("-1") - final String widthParam, - @QueryParam("height") - @DefaultValue("-1") - final String heightParam) { - + @PathParam("content-section") final String sectionName, + @PathParam("uuid") final String uuid, + @QueryParam("width") @DefaultValue("-1") + final String widthParam, @QueryParam("height") + @DefaultValue("-1") final String heightParam + ) { final Optional asset = assetRepo .findByUuidAndType(uuid, Image.class); @@ -84,9 +78,12 @@ public class Images { } else { return Response .status(Response.Status.NOT_FOUND) - .entity(String - .format("The requested image \"%s\" does not exist.", - uuid)) + .entity( + String.format( + "The requested image \"%s\" does not exist.", + uuid + ) + ) .build(); } } @@ -95,8 +92,8 @@ public class Images { @Path("/uuid-{uuid}/properties") public Response getImagePropertiesByUuid( @PathParam("content-section") final String sectionName, - @PathParam("uuid") final String uuid) { - + @PathParam("uuid") final String uuid + ) { final Optional asset = assetRepo.findByUuidAndType( uuid, Image.class ); @@ -144,17 +141,11 @@ public class Images { @GET @Path("/{path:^(?!uuid).+$}") public Response getImage( - @PathParam("content-section") - final String sectionName, - @PathParam("path") - final String path, - @QueryParam("width") - @DefaultValue("-1") - final String widthParam, - @QueryParam("height") - @DefaultValue("-1") - final String heightParam) { - + @PathParam("content-section") final String sectionName, + @PathParam("path") final String path, + @QueryParam("width") @DefaultValue("-1") final String widthParam, + @QueryParam("height") @DefaultValue("-1") final String heightParam + ) { final Optional section = sectionRepo .findByLabel(sectionName); if (!section.isPresent()) { @@ -165,8 +156,9 @@ public class Images { .build(); } - final Optional asset = assetRepo.findByPath(section.get(), - path); + final Optional asset = assetRepo.findByPath( + section.get(), path + ); if (asset.isPresent()) { if (asset.get() instanceof Image) { @@ -174,18 +166,24 @@ public class Images { } else { return Response .status(Response.Status.NOT_FOUND) - .entity(String - .format("The asset found at the requested path \"%s\" " - + "is not an image.", - path)) + .entity( + String.format( + "The asset found at the requested path \"%s\" " + + "is not an image.", + path + ) + ) .build(); } } else { return Response .status(Response.Status.NOT_FOUND) - .entity(String - .format("The requested image \"%s\" does not exist.", - path)) + .entity( + String.format( + "The requested image \"%s\" does not exist.", + path + ) + ) .build(); } } @@ -253,10 +251,11 @@ public class Images { * @return The {@link Response} for sending the (scaled) image to the * requesting user agent. */ - private Response loadImage(final Image image, - final String widthParam, - final String heightParam) { - + private Response loadImage( + final Image image, + final String widthParam, + final String heightParam + ) { //final byte[] data = image.getData(); final String mimeType = image.getMimeType().toString(); diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/FileAssetEditStepDownload.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/FileAssetEditStepDownload.java index de35092fc..6a7f2e1aa 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/FileAssetEditStepDownload.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/FileAssetEditStepDownload.java @@ -119,7 +119,9 @@ public class FileAssetEditStepDownload { @Override public void write(final OutputStream outputStream) throws IOException, WebApplicationException { - dataService.copyDataToOutputStream(fileAsset, outputStream); + dataService.copyDataToOutputStream( + fileAsset, outputStream + ); } }) diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/VideoAssetEditStep.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/VideoAssetEditStep.java index 385d00907..0dd8b7044 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/VideoAssetEditStep.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/assets/VideoAssetEditStep.java @@ -28,7 +28,6 @@ import org.libreccm.core.UnexpectedErrorException; import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.security.AuthorizationRequired; import org.librecms.assets.BinaryAssetDataService; -import org.librecms.assets.FileAsset; import org.librecms.assets.VideoAsset; import org.librecms.assets.LegalMetadata; import org.librecms.contentsection.AssetRepository; @@ -72,7 +71,7 @@ import javax.ws.rs.core.MultivaluedMap; bundle = MvcAssetStepsConstants.BUNDLE, descriptionKey = "videoasset.editstep.description", labelKey = "videoasset.editstep.lable", - supportedAssetType = FileAsset.class + supportedAssetType = VideoAsset.class ) public class VideoAssetEditStep extends AbstractMvcAssetEditStep { diff --git a/ccm-cms/src/main/resources/META-INF/resources/components/librecms/cmsEditor.xhtml b/ccm-cms/src/main/resources/META-INF/resources/components/librecms/cmsEditor.xhtml index c0ff9f7be..1070575d0 100644 --- a/ccm-cms/src/main/resources/META-INF/resources/components/librecms/cmsEditor.xhtml +++ b/ccm-cms/src/main/resources/META-INF/resources/components/librecms/cmsEditor.xhtml @@ -872,7 +872,7 @@
diff --git a/ccm-cms/src/main/typescript/content-sections/cms-editor/video-node/video-node.ts b/ccm-cms/src/main/typescript/content-sections/cms-editor/video-node/video-node.ts index 43a807f01..879357b8a 100644 --- a/ccm-cms/src/main/typescript/content-sections/cms-editor/video-node/video-node.ts +++ b/ccm-cms/src/main/typescript/content-sections/cms-editor/video-node/video-node.ts @@ -462,7 +462,7 @@ function loadVideos( selectButton.addEventListener( "click", (event) => { - const videoUrl = `/content-sections/info/videos/uuid-${video["uuid"]}`; + const videoUrl = `/@contentsections/info/videos/uuid-${video["uuid"]}`; node.attrs.videoSrc = videoUrl; if (videoElem) { videoElem.src = videoUrl;