Additional service/endpoint for retrieving file content from a binary asset.
parent
618893a41f
commit
6c18304cd2
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
@RequestScoped
|
||||
public class BinaryAssetRepository
|
||||
extends AbstractAuditedEntityRepository<Long, BinaryAsset> {
|
||||
|
||||
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<BinaryAsset> 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<BinaryAsset> findById(final long assetId) {
|
||||
|
||||
final TypedQuery<BinaryAsset> 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 <strong>unused</strong> 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<Category> 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<Permission> 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<BinaryAsset> findByUuid(final String uuid) {
|
||||
|
||||
final TypedQuery<BinaryAsset> 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<BinaryAsset> findByContentSection(final ContentSection section) {
|
||||
|
||||
final TypedQuery<BinaryAsset> query = entityManager
|
||||
.createNamedQuery(
|
||||
"BinaryAsset.findByContentSection", BinaryAsset.class
|
||||
);
|
||||
query.setParameter("section", section);
|
||||
setAuthorizationParameters(query);
|
||||
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public Optional<BinaryAsset> findByNameInFolder(
|
||||
final Folder folder, final String name
|
||||
) {
|
||||
final TypedQuery<BinaryAsset> 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<BinaryAsset> 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> 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<BinaryAsset> 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> 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> user = shiro.getUser();
|
||||
final List<Role> roles;
|
||||
if (user.isPresent()) {
|
||||
roles = user
|
||||
.get()
|
||||
.getRoleMemberships()
|
||||
.stream()
|
||||
.map(membership -> membership.getRole())
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
|
||||
final Optional<User> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
private String findAssetsInFolder(
|
||||
final ContentSection section,
|
||||
final Folder folder,
|
||||
final String query,
|
||||
final String type) {
|
||||
|
||||
final String type
|
||||
) {
|
||||
final List<Asset> 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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
@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<BinaryAsset> 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<ContentSection> 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<BinaryAsset> 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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<Image> 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<Image> 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<ContentSection> section = sectionRepo
|
||||
.findByLabel(sectionName);
|
||||
if (!section.isPresent()) {
|
||||
|
|
@ -165,8 +156,9 @@ public class Images {
|
|||
.build();
|
||||
}
|
||||
|
||||
final Optional<Asset> asset = assetRepo.findByPath(section.get(),
|
||||
path);
|
||||
final Optional<Asset> 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\" "
|
||||
.entity(
|
||||
String.format(
|
||||
"The asset found at the requested path \"%s\" "
|
||||
+ "is not an image.",
|
||||
path))
|
||||
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,
|
||||
private Response loadImage(
|
||||
final Image image,
|
||||
final String widthParam,
|
||||
final String heightParam) {
|
||||
|
||||
final String heightParam
|
||||
) {
|
||||
//final byte[] data = image.getData();
|
||||
final String mimeType = image.getMimeType().toString();
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -872,7 +872,7 @@
|
|||
<figure>
|
||||
<video controls="controls"
|
||||
src=""
|
||||
style="min-heigth: 4em;">
|
||||
style="min-height: 4em;">
|
||||
#{CmsAdminMessages['cms_editor.video_node_view.video.none']}
|
||||
</video>
|
||||
<div class="border-light librecms-video-node-view-buttons">
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue