diff --git a/Backend/alfresco/module/src/main/amp/config/alfresco/extension/es_models/ccmodel.xml b/Backend/alfresco/module/src/main/amp/config/alfresco/extension/es_models/ccmodel.xml index 0f968ae1a..8a69f7e5a 100644 --- a/Backend/alfresco/module/src/main/amp/config/alfresco/extension/es_models/ccmodel.xml +++ b/Backend/alfresco/module/src/main/amp/config/alfresco/extension/es_models/ccmodel.xml @@ -1834,7 +1834,8 @@ true false - both + + false diff --git a/Backend/services/core/src/main/java/org/edu_sharing/repository/server/rendering/RenderingServlet.java b/Backend/services/core/src/main/java/org/edu_sharing/repository/server/rendering/RenderingServlet.java index 52a05bed9..f86d5efd2 100644 --- a/Backend/services/core/src/main/java/org/edu_sharing/repository/server/rendering/RenderingServlet.java +++ b/Backend/services/core/src/main/java/org/edu_sharing/repository/server/rendering/RenderingServlet.java @@ -4,22 +4,28 @@ import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.StoreRef; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; +import org.edu_sharing.alfresco.RestrictedAccessException; import org.edu_sharing.repository.client.tools.CCConstants; import org.edu_sharing.repository.server.SecurityHeadersFilter; import org.edu_sharing.repository.server.tools.ApplicationInfoList; import org.edu_sharing.repository.tools.URLHelper; +import org.edu_sharing.service.InsufficientPermissionException; import org.edu_sharing.service.config.ConfigServiceFactory; +import org.edu_sharing.service.nodeservice.NodeServiceHelper; +import org.edu_sharing.service.permission.PermissionChecking; import org.edu_sharing.service.permission.PermissionServiceFactory; import org.edu_sharing.service.rendering.RenderingService; import org.edu_sharing.service.rendering.RenderingServiceFactory; import org.edu_sharing.service.rendering.RenderingTool; import org.edu_sharing.service.tracking.TrackingService; import org.edu_sharing.service.tracking.TrackingServiceFactory; +import org.springframework.web.servlet.support.RequestContextUtils; import java.io.IOException; import java.util.HashMap; @@ -32,6 +38,7 @@ public class RenderingServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + // new, preferred parameter String node_id = req.getParameter("nodeId"); if(node_id == null) { @@ -66,12 +73,22 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) resp.getWriter().write(""); String response; try { - if(!PermissionServiceFactory.getLocalService().hasPermission(StoreRef.PROTOCOL_WORKSPACE, - StoreRef.STORE_REF_WORKSPACE_SPACESSTORE.getIdentifier(), - node_id, - CCConstants.PERMISSION_EMBED)){ - throw new AccessDeniedException(CCConstants.PERMISSION_EMBED); + NodeRef ref = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, node_id); + if(NodeServiceHelper.hasAspect(ref,CCConstants.CCM_ASPECT_COLLECTION_IO_REFERENCE)){ + try { + NodeServiceHelper.validatePermissionRestrictedAccess(ref, CCConstants.PERMISSION_READ_ALL, CCConstants.PERMISSION_EMBED); + } catch (RestrictedAccessException e) { + throw new AccessDeniedException(CCConstants.PERMISSION_EMBED); + } + }else{ + if(!PermissionServiceFactory.getLocalService().hasPermission(ref.getStoreRef().getProtocol(), + ref.getStoreRef().getIdentifier(), + node_id, + CCConstants.PERMISSION_EMBED)) { + throw new AccessDeniedException(CCConstants.PERMISSION_EMBED); + } } + response = renderingService.getDetails(ApplicationInfoList.getHomeRepository().getAppId(), node_id, version,DEFAULT_DISPLAY_MODE, params).getDetails(); response = response.replace("{{{LMS_INLINE_HELPER_SCRIPT}}}", URLHelper.getNgRenderNodeUrl(node_id,version)+"?"); // add nonce to render styles diff --git a/Backend/services/core/src/main/java/org/edu_sharing/service/collection/CollectionServiceImpl.java b/Backend/services/core/src/main/java/org/edu_sharing/service/collection/CollectionServiceImpl.java index 23f22d189..d93fffebd 100644 --- a/Backend/services/core/src/main/java/org/edu_sharing/service/collection/CollectionServiceImpl.java +++ b/Backend/services/core/src/main/java/org/edu_sharing/service/collection/CollectionServiceImpl.java @@ -7,10 +7,7 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.repository.AssociationRef; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.repository.*; import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.security.PermissionService; @@ -629,9 +626,6 @@ public void updateAndSetScope(Collection collection) throws Exception { public Map asProps(Collection collection) { Map props = new HashMap<>(); - if (collection.getNodeId() != null) { - props.put(CCConstants.SYS_PROP_NODE_UID, collection.getNodeId()); - } props.put(CCConstants.CM_PROP_TITLE, collection.getTitle()); props.put(CCConstants.CM_NAME, NodeServiceHelper.cleanupCmName(collection.getTitle())); props.put(CCConstants.CM_PROP_DESCRIPTION, collection.getDescription()); @@ -846,10 +840,16 @@ protected MCAlfrescoAPIClient.ContextSearchMode getContextModeForScope(String sc } protected boolean isSubCollection(org.edu_sharing.service.model.NodeRef nodeRef) { - return AuthenticationUtil.runAsSystem(() -> { - NodeRef parent = NodeServiceHelper.getPrimaryParent(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeRef.getNodeId())); - return NodeServiceHelper.hasAspect(parent, CCConstants.CCM_ASPECT_COLLECTION); - }); + try { + return AuthenticationUtil.runAsSystem(() -> { + NodeRef parent = NodeServiceHelper.getPrimaryParent(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeRef.getNodeId())); + return NodeServiceHelper.hasAspect(parent, CCConstants.CCM_ASPECT_COLLECTION); + }); + } catch(InvalidNodeRefException e) { + // node from elastic index might already deleted, ignore to prevent full fail of query + logger.info("isSubCollection failed", e); + return true; + } } @Override diff --git a/Backend/services/core/src/main/java/org/edu_sharing/service/permission/PermissionServiceHelper.java b/Backend/services/core/src/main/java/org/edu_sharing/service/permission/PermissionServiceHelper.java index aa1ce242d..0fd5d26b5 100644 --- a/Backend/services/core/src/main/java/org/edu_sharing/service/permission/PermissionServiceHelper.java +++ b/Backend/services/core/src/main/java/org/edu_sharing/service/permission/PermissionServiceHelper.java @@ -44,10 +44,12 @@ public PermissionServiceHelper(PermissionService permissionService){ } public static HashSet getExplicitAuthoritiesFromACL(ACL acl) { - return Arrays.stream(acl.getAces()). - filter((ace) -> !ace.isInherited()). - map(ACE::getAuthority). - collect(Collectors.toCollection(HashSet::new)); + return Arrays.stream(acl.getAces()) + .filter((ace) -> !ace.isInherited()) + .filter((ace -> ace.getFrom() == null)) + .filter((ace -> ace.getTo() == null)) + .map(ACE::getAuthority) + .collect(Collectors.toCollection(HashSet::new)); } public static Boolean isNodePublic(NodeRef nodeRef) { diff --git a/Backend/services/core/src/main/java/org/edu_sharing/service/permission/PermissionServiceImpl.java b/Backend/services/core/src/main/java/org/edu_sharing/service/permission/PermissionServiceImpl.java index 8ae4db6ee..6613fa6a0 100644 --- a/Backend/services/core/src/main/java/org/edu_sharing/service/permission/PermissionServiceImpl.java +++ b/Backend/services/core/src/main/java/org/edu_sharing/service/permission/PermissionServiceImpl.java @@ -1108,7 +1108,7 @@ public StringBuffer getFindGroupsSearchString(String searchWord, boolean globalC } if (!token.isEmpty()) { - subQuery.append("=@cm:authorityDisplayName:").append("\"").append(token).append("\""); + subQuery.append(LightbendConfigLoader.get().getString("repository.search.groups.nonFuzzyField")).append(":\"").append(token).append("\""); } // if not fuzzy and no value for email return empty result diff --git a/Frontend/src/app/pages/collections-page/collection-info-bar/collection-info-bar.component.html b/Frontend/src/app/pages/collections-page/collection-info-bar/collection-info-bar.component.html index dd82db2b7..49f8784f5 100644 --- a/Frontend/src/app/pages/collections-page/collection-info-bar/collection-info-bar.component.html +++ b/Frontend/src/app/pages/collections-page/collection-info-bar/collection-info-bar.component.html @@ -8,12 +8,8 @@
-
+
-

+

{{ collection?.title }}

diff --git a/Frontend/src/app/pages/collections-page/collection-info-bar/collection-info-bar.component.scss b/Frontend/src/app/pages/collections-page/collection-info-bar/collection-info-bar.component.scss index 2ebbe1c4a..2059795bc 100644 --- a/Frontend/src/app/pages/collections-page/collection-info-bar/collection-info-bar.component.scss +++ b/Frontend/src/app/pages/collections-page/collection-info-bar/collection-info-bar.component.scss @@ -36,6 +36,7 @@ overflow-wrap: break-word; line-height: normal; margin: 0; + overflow: hidden; } .collection-new-preview-infoarea { min-height: 120px; @@ -80,6 +81,13 @@ text-align: center; vertical-align: middle; height: 200px; + width: 100%; + .card-collection-image-icon-wrapper { + width: 250px; + height: 200px; + margin-left: auto; + margin-right: auto; + } } .card-image-icon-container { diff --git a/Frontend/src/app/pages/collections-page/collections-page.component.html b/Frontend/src/app/pages/collections-page/collections-page.component.html index df1b79ff1..1ff4266a7 100644 --- a/Frontend/src/app/pages/collections-page/collections-page.component.html +++ b/Frontend/src/app/pages/collections-page/collections-page.component.html @@ -83,11 +83,7 @@ >
-
+

diff --git a/Frontend/src/app/pages/collections-page/collections-page.component.scss b/Frontend/src/app/pages/collections-page/collections-page.component.scss index 1b953480d..15ad75514 100644 --- a/Frontend/src/app/pages/collections-page/collections-page.component.scss +++ b/Frontend/src/app/pages/collections-page/collections-page.component.scss @@ -117,6 +117,12 @@ section { .button-area { text-align: right; } +.collections-right { + .collections-loading-div { + padding-top: 24px; + text-align: center; + } +} .dialog-input { width: 90%; diff --git a/Frontend/src/app/pages/user-management-page/authorities/authorities.component.scss b/Frontend/src/app/pages/user-management-page/authorities/authorities.component.scss index d91ba0e5d..44ef14f7b 100644 --- a/Frontend/src/app/pages/user-management-page/authorities/authorities.component.scss +++ b/Frontend/src/app/pages/user-management-page/authorities/authorities.component.scss @@ -163,7 +163,7 @@ color: $primary; } -$addToWidth: 400px; +$addToWidth: 450px; .list { overflow-y: auto; position: fixed; @@ -177,11 +177,6 @@ $addToWidth: 400px; width: 100%; } } -.listEmbedded { - top: 270px; - height: calc(100% - 330px); - width: $addToWidth; -} .formEmbedded { width: $addToWidth; } @@ -198,8 +193,8 @@ label.search { position: fixed; right: 0; width: $addToWidth; - top: calc(115px + var(--mainnavHeight)); - height: calc(100% - 115px - var(--mainnavHeight)); + top: calc(105px + var(--mainnavHeight)); + height: calc(100% - 105px - var(--mainnavHeight)); z-index: 2; padding-bottom: 20px; background-color: #fff; @@ -212,7 +207,27 @@ label.search { } .addToList { height: calc(100% - 37px); - overflow-y: auto; + // overflow-y: auto; + ::ng-deep es-permissions-authorities { + height: calc(100% - 7px); + display: flex; + flex-direction: column; + .topFrame { + display: none; + } + .searchEmbedded { + .mat-mdc-form-field-subscript-wrapper { + display: none; + } + } + .list { + position: relative; + top: 0; + height: auto; + flex-grow: 1; + overflow-y: auto; + } + } } #groupType { margin-bottom: 20px; diff --git a/Frontend/src/assets/i18n/workspace/en.json b/Frontend/src/assets/i18n/workspace/en.json index 1f5bc23a9..343494be8 100644 --- a/Frontend/src/assets/i18n/workspace/en.json +++ b/Frontend/src/assets/i18n/workspace/en.json @@ -514,6 +514,13 @@ "VIRTUAL": "You're inside a folder where inserting elements is not possible.", "GENERAL": "Navigate to a different folder and create your elements there." }, + "COPY_MOVE": { + "TITLE": "Move/copy element(s)", + "MESSAGE_SINGLE": "Do you want to move/copy \"{{element}}\" from \"{{source}}\" to \"{{target}}\"?", + "MESSAGE_MULTIPLE": "Do you want to move/copy {{count}} elements from \"{{source}}\" to \"{{target}}\"?", + "MOVE": "Move", + "COPY": "Copy" + }, "TOAST": { "FOLDER_ADDED": "Folder added", "NODE_EXISTS_IN_COLLECTION": "The collection already contains the element {{name}}", diff --git a/config/defaults/src/main/resources/edu-sharing.reference.conf b/config/defaults/src/main/resources/edu-sharing.reference.conf index 08b318a0a..872b6d10e 100644 --- a/config/defaults/src/main/resources/edu-sharing.reference.conf +++ b/config/defaults/src/main/resources/edu-sharing.reference.conf @@ -539,6 +539,16 @@ repository: { ] } + // search related configs for queries which are not handled by the mds + search { + // groups related search configs + groups: { + // field/solr key to match when non fuzzy group search is enabled + // examples: "=@cm:authorityDisplayName", "=@ccm:groupEmail" + nonFuzzyField: "=@cm:authorityDisplayName" + } + } + webdav: { enabled: true authentication: {