AEM Cloud Service Version : 2021.1.4738.20210107T143101Z-201217 (Jan 7, 2021)
Goal
Adding the following extension would restrict users from uploading duplicates files (files with same name). The check is done repository wide /content/dam
For a server side validation, check this post
Demo | Package Install | Github
Solution
1) Create a service user configuration in repo init script ui.config\src\main\content\jcr_root\apps\eaem-cs-upload-unique-assets\osgiconfig\config.author\org.apache.sling.jcr.repoinit.RepositoryInitializer-eaem.config this is for querying and returning duplicates as JSON (in next steps).
scripts=[ " create service user eaem-service-user with path system/cq:services/experience-aem set principal ACL for eaem-service-user allow jcr:read on /apps allow jcr:read on /content/dam end " ]
2) Adding the above repo init script in code repo and installing on AEM CS creates a service user in /home/users/system/cq:services/experience-aem
3) Add the service user to bundle mapping in ui.config\src\main\content\jcr_root\apps\eaem-cs-upload-unique-assets\osgiconfig\config.author\org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-eaem.xml
<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" jcr:primaryType="sling:OsgiConfig" user.mapping="[eaem-cs-upload-unique-assets.core:eaem-service-user=[eaem-service-user]]"/>
4) Create a servlet apps.experienceaem.assets.core.servlets.FindAssetDuplicates to return the duplicates
package apps.experienceaem.assets.core.servlets; import com.day.cq.search.PredicateGroup; import com.day.cq.search.Query; import com.day.cq.search.QueryBuilder; import com.day.cq.search.result.Hit; import com.day.cq.search.result.SearchResult; import org.apache.commons.lang3.ArrayUtils; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.SlingHttpServletResponse; import org.apache.sling.api.resource.LoginException; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.ResourceResolverFactory; import org.apache.sling.api.servlets.SlingAllMethodsServlet; import org.apache.sling.commons.json.JSONArray; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.jcr.Session; import javax.servlet.Servlet; import javax.servlet.ServletException; import java.io.IOException; import java.util.HashMap; import java.util.Map; @Component( name = "Experience AEM find duplicates servlet", immediate = true, service = Servlet.class, property = { "sling.servlet.methods=GET", "sling.servlet.paths=/bin/experience-aem/duplicates" } ) public class FindAssetDuplicates extends SlingAllMethodsServlet { private static final Logger log = LoggerFactory.getLogger(FindAssetDuplicates.class); private static final String EAEM_SERVICE_USER = "eaem-service-user"; @Reference private ResourceResolverFactory factory; @Reference private QueryBuilder builder; @Override protected final void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException { try { String fileNames[] = request.getParameterValues("fileName"); JSONArray duplicates = new JSONArray(); response.setContentType("application/json"); if(ArrayUtils.isEmpty(fileNames)){ duplicates.write(response.getWriter()); return; } ResourceResolver resourceResolver = getServiceResourceResolver(factory); Query query = builder.createQuery(PredicateGroup.create(getQueryPredicateMap(fileNames)), resourceResolver.adaptTo(Session.class)); SearchResult result = query.getResult(); for (Hit hit : result.getHits()) { duplicates.put(hit.getPath()); } duplicates.write(response.getWriter()); } catch (Exception e) { log.error("Could not execute duplicates check", e); response.setStatus(SlingHttpServletResponse.SC_INTERNAL_SERVER_ERROR); } } public ResourceResolver getServiceResourceResolver(ResourceResolverFactory resourceResolverFactory) { Map<String, Object> subServiceUser = new HashMap<>(); subServiceUser.put(ResourceResolverFactory.SUBSERVICE, EAEM_SERVICE_USER); try { return resourceResolverFactory.getServiceResourceResolver(subServiceUser); } catch (LoginException ex) { log.error("Could not login as SubService user {}, exiting SearchService service.", "eaem-service-user", ex);
return null; } } private Map<String, String> getQueryPredicateMap(String[] fileNames) { Map<String, String> map = new HashMap<>(); map.put("path", "/content/dam"); map.put("group.p.or", "true"); for(int index = 0; index < fileNames.length; index++){ map.put("group." + index + "_nodename", fileNames[index]); } return map; } }
5) Create a client library /apps/eaem-cs-upload-unique-assets/clientlibs/unique-names with categories =dam.gui.coral.fileupload and dependencies=eaem.lodash and following script
(function ($, $document) { "use strict"; var _ = window._; var _origConfirmUpload = window.DamFileUpload.prototype._confirmUpload, _origOnInputChange = window.Dam.ChunkFileUpload.prototype._onInputChange; window.Dam.ChunkFileUpload.prototype._onInputChange = function(event){ var files = event.target.files; if(!files && event.dataTransfer && event.dataTransfer.files){ files = event.dataTransfer.files; } if(_.isEmpty(files)){ _origOnInputChange.call(this, event); return; } var validFiles = []; _.each(files, function(file) { validFiles.push(file.name); }); var existInDAMFiles = checkFilesExist(validFiles); if(!_.isEmpty(existInDAMFiles)){ showAlert("Following files exist : BR BR" + existInDAMFiles.join("BR") + "</b>");
return; } _origOnInputChange.call(this, event); }; window.DamFileUpload.prototype._confirmUpload = function (event) { var existInDAMFiles = checkFilesExist(this.fileUpload.uploadQueue.map(hit => hit.path)); if(!_.isEmpty(existInDAMFiles)){ showAlert("Following files exist : BR BR" + existInDAMFiles.join("BR") + "</b>");
return; } _origConfirmUpload.call(this, event); var uploadDialog = this.uploadDialog; _.defer(function(){ $(uploadDialog).find("input").attr("disabled", "disabled"); },0) }; function checkFilesExist(fileNames){ var existingFiles = [], url = "/bin/experience-aem/duplicates?"; _.each(fileNames, function(fileName, index){ url = url + "fileName=" + fileName + "&"; }); $.ajax( { url : url, async : false, contentType:"application/json" }).done(function(data){ existingFiles = data; }).fail(function() { showAlert("Error occured while checking for duplicates", "Error"); }); return existingFiles; } function showAlert(message, title, callback){ var fui = $(window).adaptTo("foundation-ui"), options = [{ id: "ok", text: "OK", primary: true }]; message = message || "Unknown Error"; title = title || "Error"; fui.prompt(title, message, "warning", options, callback); } }(jQuery, jQuery(document)));
No comments:
Post a Comment