diff --git a/Backend/alfresco/common/src/main/java/org/edu_sharing/repository/client/tools/CCConstants.java b/Backend/alfresco/common/src/main/java/org/edu_sharing/repository/client/tools/CCConstants.java index 8dbef0532..37cc20dda 100644 --- a/Backend/alfresco/common/src/main/java/org/edu_sharing/repository/client/tools/CCConstants.java +++ b/Backend/alfresco/common/src/main/java/org/edu_sharing/repository/client/tools/CCConstants.java @@ -2022,6 +2022,8 @@ public static synchronized Set getUsagePermissions(){ usagePermissions.add(PERMISSION_READ_PREVIEW); usagePermissions.add(PERMISSION_READ_ALL); usagePermissions.add(PERMISSION_CONSUMER); + usagePermissions.add(PERMISSION_DOWNLOAD_CONTENT); + usagePermissions.add(PERMISSION_EMBED); usagePermissions.add(PERMISSION_COMMENT); usagePermissions.add(PERMISSION_RATE); usagePermissions.add(PERMISSION_RATE_READ); diff --git a/Backend/services/core/src/main/java/org/edu_sharing/repository/server/jobs/quartz/MediacenterMonthlyReportsJob.java b/Backend/services/core/src/main/java/org/edu_sharing/repository/server/jobs/quartz/MediacenterMonthlyReportsJob.java index a92863218..14cccb48b 100644 --- a/Backend/services/core/src/main/java/org/edu_sharing/repository/server/jobs/quartz/MediacenterMonthlyReportsJob.java +++ b/Backend/services/core/src/main/java/org/edu_sharing/repository/server/jobs/quartz/MediacenterMonthlyReportsJob.java @@ -98,8 +98,8 @@ private enum ReportType { @JobFieldDescription(description = "When set to true, the job will generate a yearly report as well (only on 1st January)") private boolean generateYearly = false; - @JobFieldDescription(description = "When set to true, the job will generate a quaternary report as well (only on 1st of January, April, July and October)") - private boolean generateQuaternary = false; + @JobFieldDescription(description = "When set to true, the job will generate a quarterly report as well (only on 1st of January, April, July and October)") + private boolean generateQuarterly = false; @JobFieldDescription(description = "use a custom date (month) to run the job for. Note: The job will run the month BEFORE the given date!", sampleValue = "YYYY-MM-DD") private Date customDate = null; @@ -142,7 +142,7 @@ private Void createStats() { } LocalDate lastMonth = localDate.minusMonths(1); - LocalDate from = LocalDate.of(lastMonth.getYear(), lastMonth.getMonth(), 1); + LocalDate from = lastMonth.withDayOfMonth(1); YearMonth month = YearMonth.from(from); LocalDate to = month.atEndOfMonth(); @@ -158,13 +158,15 @@ private Void createStats() { generateSchoolReportByTimeRange(mediacenter, startDate, endDate, ReportType.Monthly); if (generateYearly && localDate.getMonthValue() == 1) { - from = localDate.minusYears(1); + from = localDate.minusYears(1).withDayOfMonth(1); startDate = Date.from(from.atStartOfDay().toInstant(ZoneOffset.UTC)); generateReportByTimeRange(mediacenter, startDate, endDate, ReportType.Yearly); } - if (generateQuaternary && List.of(1, 4, 7, 10).contains(localDate.getMonthValue())) { - from = localDate.minusMonths(3); + if (generateQuarterly && List.of(1, 4, 7, 10).contains(localDate.getMonthValue())) { + from = lastMonth.withMonth(lastMonth.getMonth().firstMonthOfQuarter().getValue()) + .withDayOfMonth(1); + startDate = Date.from(from.atStartOfDay().toInstant(ZoneOffset.UTC)); generateReportByTimeRange(mediacenter, startDate, endDate, ReportType.Quarterly); } diff --git a/Backend/services/core/src/main/java/org/edu_sharing/repository/server/jobs/quartz/NodeObjectReportJob.java b/Backend/services/core/src/main/java/org/edu_sharing/repository/server/jobs/quartz/NodeObjectReportJob.java index a857f221e..6ab6e974c 100644 --- a/Backend/services/core/src/main/java/org/edu_sharing/repository/server/jobs/quartz/NodeObjectReportJob.java +++ b/Backend/services/core/src/main/java/org/edu_sharing/repository/server/jobs/quartz/NodeObjectReportJob.java @@ -6,7 +6,6 @@ import lombok.extern.slf4j.Slf4j; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.service.cmr.repository.InvalidNodeRefException; -import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.StoreRef; import org.apache.commons.lang3.NotImplementedException; import org.apache.commons.lang3.StringUtils; @@ -30,9 +29,7 @@ import java.io.ByteArrayOutputStream; import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; -import java.time.LocalDate; -import java.time.ZoneId; -import java.time.ZoneOffset; +import java.time.*; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; @@ -62,11 +59,11 @@ enum TrackingMode { } public enum ReportType { - @JobFieldDescription(description = "The job will generate a monthly report (only on 1st of January, April, July and October)") + @JobFieldDescription(description = "The job will generate a monthly report (beginning from the 1st of the month)") Monthly, - @JobFieldDescription(description = "The job will generate a quaternary report (only on 1st of January, April, July and October)") + @JobFieldDescription(description = "The job will generate a quaternary report (beginning from the 1st day of the quartal)") Quarterly, - @JobFieldDescription(description = "The job will generate a yearly report (only on 1st of January)") + @JobFieldDescription(description = "The job will generate a yearly report (beginning from 1st of January)") Yearly, } @@ -89,7 +86,7 @@ public enum ReportType { @JobFieldDescription(description = "List of grouped (custom) fields to be fetched from the tracking data", sampleValue = "field1") private List groupFields = Collections.emptyList(); - @JobFieldDescription(description = "use a custom date (month) to run the job for. Note: The job will run the month BEFORE the given date!", sampleValue = "YYYY-MM-DD") + @JobFieldDescription(description = "use a custom date (month) to run the job for. Note: The job will run to the given date from the first of the given month, quartal or year!", sampleValue = "YYYY-MM-DD") private Date customDate = null; @JobFieldDescription(description = "Defines the reporting period", sampleValue = "Monthly") @@ -109,6 +106,9 @@ public enum ReportType { @JobFieldDescription(description = "List of aspects to filter by", sampleValue = "[]") private List aspectFilters = Collections.emptyList(); + @JobFieldDescription(description = "force run, even if the date is currently not the 1st") + private boolean force = false; + @Autowired private TrackingService trackingService; @@ -119,7 +119,7 @@ public enum ReportType { @Override protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { LocalDate now = LocalDate.now(); - if (customDate == null && now.getDayOfMonth() != 1) { + if (!force && now.getDayOfMonth() != 1) { logger.error("Job not running because of date: " + now.getDayOfMonth()); return; } @@ -128,22 +128,22 @@ protected void executeInternal(JobExecutionContext jobExecutionContext) throws J } private Void createStats() { - LocalDate to = LocalDate.now(); - if (this.customDate != null) { + LocalDate now = LocalDate.now(); + LocalDate to = now.minusDays(1); + + if (customDate != null) { to = customDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); } - to = to.minusDays(1); - LocalDate from; + LocalDate from = to.withDayOfMonth(1); switch (type) { case Monthly: - from = to.minusMonths(1).plusDays(1); break; case Yearly: - from = to.minusYears(1).minusMonths(1).plusDays(1); + from = from.withMonth(1); break; case Quarterly: - from = to.minusMonths(3).plusDays(1); + from = from.withMonth(from.getMonth().firstMonthOfQuarter().getValue()); break; default: throw new NotImplementedException(type.name()); @@ -154,7 +154,7 @@ private Void createStats() { List nodeStatisics = trackingService.getNodeStatisics( TrackingService.GroupingType.Node, Date.from(from.atStartOfDay().toInstant(ZoneOffset.UTC)), - Date.from(to.atStartOfDay().toInstant(ZoneOffset.UTC)), + Date.from(to.plusDays(1).atStartOfDay().toInstant(ZoneOffset.UTC)), "", additionalFields, groupFields, @@ -198,19 +198,29 @@ private String generateFilename(LocalDate from, LocalDate to) { switch (type) { case Yearly: sb.append(from.format(DateTimeFormatter.ofPattern(("yyyy")))); + if(to.getMonthValue() != 12 && to.getDayOfMonth() != to.lengthOfMonth()){ + sb.append("_interim"); + } break; case Quarterly: sb.append(from.format(DateTimeFormatter.ofPattern(("yyyy")))); sb.append("-Q"); - sb.append(to.getMonthValue()/3); + sb.append(to.getMonthValue() / 3); + if(to.getMonth().firstMonthOfQuarter().getValue() + 3 != to.getMonthValue() && to.getDayOfMonth() != to.lengthOfMonth()){ + sb.append("_interim"); + } break; case Monthly: sb.append(from.format(DateTimeFormatter.ofPattern(("yyyy-MM")))); + if(to.getDayOfMonth() != to.lengthOfMonth()){ + sb.append("_interim"); + } break; default: throw new NotImplementedException(type.name()); } } + sb.append(".csv"); return sb.toString(); } diff --git a/Backend/services/core/src/main/java/org/edu_sharing/repository/server/jobs/quartz/TimedPermissionJob.java b/Backend/services/core/src/main/java/org/edu_sharing/repository/server/jobs/quartz/TimedPermissionJob.java index c80f72d7e..7b7583cfa 100644 --- a/Backend/services/core/src/main/java/org/edu_sharing/repository/server/jobs/quartz/TimedPermissionJob.java +++ b/Backend/services/core/src/main/java/org/edu_sharing/repository/server/jobs/quartz/TimedPermissionJob.java @@ -1,71 +1,21 @@ package org.edu_sharing.repository.server.jobs.quartz; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.security.PermissionService; import org.edu_sharing.repository.server.jobs.quartz.annotation.JobDescription; -import org.edu_sharing.service.permission.TimedPermission; -import org.edu_sharing.service.permission.TimedPermissionMapper; +import org.edu_sharing.service.permission.PermissionService; import org.quartz.JobExecutionContext; import org.springframework.beans.factory.annotation.Autowired; -import java.util.Date; -import java.util.List; - -@JobDescription(description = "") +@JobDescription(description = "Updates permission of timed permissions") +@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") public class TimedPermissionJob extends AbstractInterruptableJob { - @Autowired - private TimedPermissionMapper timedPermissionMapper; - @Autowired private PermissionService permissionService; - @Autowired - private RetryingTransactionHelper retryingTransactionHelper; @Override protected void executeInterruptable(JobExecutionContext jobExecutionContext) { - - List permissionsToAdd = timedPermissionMapper.findAllByFromAfterAndNotActivated(new Date()); - List permissionsToRemove = timedPermissionMapper.findAllByToBefore(new Date()); - - - for (TimedPermission timedPermission : permissionsToAdd) { - retryingTransactionHelper.doInTransaction(() -> - AuthenticationUtil.runAsSystem(() -> { - permissionService.setPermission( - new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, timedPermission.getNode_id()), - timedPermission.getAuthority(), - timedPermission.getPermission(), - true); - - if(timedPermission.getTo() == null){ - timedPermissionMapper.delete(timedPermission); - }else { - timedPermission.setActivated(true); - timedPermissionMapper.save(timedPermission); - } - return null; - })); - } - - for (TimedPermission timedPermission : permissionsToRemove) { - retryingTransactionHelper.doInTransaction(() -> - AuthenticationUtil.runAsSystem(() -> { - permissionService.deletePermission( - new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, timedPermission.getNode_id()), - timedPermission.getAuthority(), - timedPermission.getPermission()); - - timedPermissionMapper.delete(timedPermission); - return null; - })); - } - - + permissionService.updateTimedPermissions(); } } diff --git a/Backend/services/core/src/main/java/org/edu_sharing/restservices/NodeDao.java b/Backend/services/core/src/main/java/org/edu_sharing/restservices/NodeDao.java index 27b37ddb4..381db63fc 100755 --- a/Backend/services/core/src/main/java/org/edu_sharing/restservices/NodeDao.java +++ b/Backend/services/core/src/main/java/org/edu_sharing/restservices/NodeDao.java @@ -28,7 +28,6 @@ import org.edu_sharing.repository.client.rpc.User; import org.edu_sharing.repository.client.tools.CCConstants; import org.edu_sharing.repository.client.tools.metadata.ValueTool; -import org.edu_sharing.repository.server.AuthenticationToolAPI; import org.edu_sharing.repository.server.MCAlfrescoAPIClient; import org.edu_sharing.repository.server.SearchResultNodeRef; import org.edu_sharing.repository.server.tools.*; @@ -40,8 +39,8 @@ import org.edu_sharing.restservices.shared.NodeRef; import org.edu_sharing.restservices.shared.*; import org.edu_sharing.restservices.shared.NodeSearch.Facet; -import org.edu_sharing.restservices.shared.NodeSearch.Facet.Value; import org.edu_sharing.restservices.shared.SearchResult; +import org.edu_sharing.restservices.shared.NodeSearch.Facet.Value; import org.edu_sharing.service.InsufficientPermissionException; import org.edu_sharing.service.authority.AuthorityService; import org.edu_sharing.service.authority.AuthorityServiceFactory; @@ -1083,7 +1082,7 @@ public NodeDao createChildByCopy(String sourceId, boolean withChildren) try { org.alfresco.service.cmr.repository.NodeRef newNode = nodeService.copyNode(sourceId, nodeId, withChildren); - permissionService.createNotifyObject(newNode.getId(), new AuthenticationToolAPI().getCurrentUser(), CCConstants.CCM_VALUE_NOTIFY_ACTION_PERMISSION_ADD); + permissionService.createNotifyObject(newNode.getId(),AuthenticationUtil.getFullyAuthenticatedUser(), CCConstants.CCM_VALUE_NOTIFY_ACTION_PERMISSION_ADD); return new NodeDao(repoDao, newNode.getId(), Filter.createShowAllFilter()); } catch (Throwable t) { @@ -1469,7 +1468,10 @@ public void fillNodeObject(T data, boolean fillOwner, boolean f data.setAccess(access); // set access effective for original elements only if (!(data instanceof CollectionReference) && Objects.equals(CallSourceHelper.CallSource.Render, CallSourceHelper.getCallSource())) { - List permissions = org.edu_sharing.service.nodeservice.NodeServiceInterceptor.getIndirectPermissions(getId(), List.of(DAO_PERMISSIONS)); + java.util.Collection permissions = org.edu_sharing.service.nodeservice.NodeServiceInterceptor.getIndirectPermissions(getId(), List.of(DAO_PERMISSIONS)); + // since it's an original: we join the permissions with the original ones + permissions = new HashSet<>(permissions); + permissions.addAll(access); data.setAccessEffective(permissions); } data.setPublic(isPublic); @@ -2711,7 +2713,7 @@ public NodeDao createFork(String sourceId) throws DAOException { RunAsWork work = () -> { try { org.alfresco.service.cmr.repository.NodeRef newNode = nodeService.copyNode(source[0], nodeId, false); - permissionService.createNotifyObject(newNode.getId(), new AuthenticationToolAPI().getCurrentUser(), CCConstants.CCM_VALUE_NOTIFY_ACTION_PERMISSION_ADD); + permissionService.createNotifyObject(newNode.getId(),AuthenticationUtil.getFullyAuthenticatedUser(), CCConstants.CCM_VALUE_NOTIFY_ACTION_PERMISSION_ADD); nodeService.addAspect(newNode.getId(), CCConstants.CCM_ASPECT_FORKED); nodeService.setProperty(newNode.getStoreRef().getProtocol(), newNode.getStoreRef().getIdentifier(), newNode.getId(), CCConstants.CCM_PROP_FORKED_ORIGIN, new org.alfresco.service.cmr.repository.NodeRef(storeProtocol, storeId, source[0]), false); diff --git a/Backend/services/core/src/main/java/org/edu_sharing/service/collection/CollectionServiceElastic.java b/Backend/services/core/src/main/java/org/edu_sharing/service/collection/CollectionServiceElastic.java index 3dd58a824..6c980ef03 100644 --- a/Backend/services/core/src/main/java/org/edu_sharing/service/collection/CollectionServiceElastic.java +++ b/Backend/services/core/src/main/java/org/edu_sharing/service/collection/CollectionServiceElastic.java @@ -13,6 +13,8 @@ import org.edu_sharing.metadataset.v2.tools.MetadataHelper; import org.edu_sharing.repository.client.tools.CCConstants; import org.edu_sharing.repository.server.SearchResultNodeRef; +import org.edu_sharing.restservices.CollectionDao; +import org.edu_sharing.service.authority.AuthorityServiceFactory; import org.edu_sharing.service.authority.AuthorityServiceHelper; import org.edu_sharing.service.search.SearchService; import org.edu_sharing.service.search.SearchServiceElastic; @@ -139,6 +141,12 @@ protected SearchResultNodeRef searchChildren(String scope, SortDefinition sortDe token.setSortDefinition(sortDefinition); token.setFrom(skipCount); token.setMaxResult(maxItems); + if(CollectionDao.SearchScope.valueOf(scope).equals(CollectionDao.SearchScope.EDU_GROUPS)) { + ArrayList authorities = new ArrayList<>(serviceRegistry.getAuthorityService().getAuthorities()); + authorities.add(serviceRegistry.getAuthenticationService().getCurrentUserName()); + authorities.remove(CCConstants.AUTHORITY_GROUP_EVERYONE); + token.setAuthorityScope(authorities); + } SearchResultNodeRef nodeRefs = SearchServiceFactory.getLocalService().search(mds, queryId, Collections.emptyMap(), token); for (org.edu_sharing.service.model.NodeRef nodeRef : nodeRefs.getData()) { if (isSubCollection(nodeRef)) { diff --git a/Backend/services/core/src/main/java/org/edu_sharing/service/config/ConfigServiceImpl.java b/Backend/services/core/src/main/java/org/edu_sharing/service/config/ConfigServiceImpl.java index 1cedc06e6..9fa1fa26c 100644 --- a/Backend/services/core/src/main/java/org/edu_sharing/service/config/ConfigServiceImpl.java +++ b/Backend/services/core/src/main/java/org/edu_sharing/service/config/ConfigServiceImpl.java @@ -126,6 +126,8 @@ public List getAvailableContext() throws Exception { private void buildContextCache() throws Exception { if (contextCache.getKeys().isEmpty()) { + // put an element so that next time, the cache is never empty! + contextCache.put("", null); Config config = getConfig(); if (config.contexts != null && config.contexts.context != null) { for (Context context : config.contexts.context) { diff --git a/Backend/services/core/src/main/java/org/edu_sharing/service/permission/PermissionService.java b/Backend/services/core/src/main/java/org/edu_sharing/service/permission/PermissionService.java index 324cb4a03..f66503b57 100644 --- a/Backend/services/core/src/main/java/org/edu_sharing/service/permission/PermissionService.java +++ b/Backend/services/core/src/main/java/org/edu_sharing/service/permission/PermissionService.java @@ -1,20 +1,21 @@ package org.edu_sharing.service.permission; -import java.util.*; - import org.alfresco.service.cmr.repository.NodeRef; -import org.edu_sharing.repository.client.rpc.ACE; -import org.edu_sharing.repository.client.rpc.ACL; -import org.edu_sharing.repository.client.rpc.Authority; -import org.edu_sharing.repository.client.rpc.Group; -import org.edu_sharing.repository.client.rpc.Notify; -import org.edu_sharing.repository.client.rpc.Result; -import org.edu_sharing.repository.client.rpc.User; +import org.edu_sharing.repository.client.rpc.*; import org.edu_sharing.repository.client.tools.CCConstants; import org.edu_sharing.service.InsufficientPermissionException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + public interface PermissionService { public static final String[] GUEST_PERMISSIONS = new String[]{ org.alfresco.service.cmr.security.PermissionService.READ,CCConstants.PERMISSION_READ_PREVIEW,CCConstants.PERMISSION_READ_ALL, CCConstants.PERMISSION_DOWNLOAD_CONTENT, CCConstants.PERMISSION_FEEDBACK}; + + + void updateTimedPermissions(); + /** * adds permissions to the current ACL * @param _nodeId diff --git a/Backend/services/core/src/main/java/org/edu_sharing/service/permission/PermissionServiceAdapter.java b/Backend/services/core/src/main/java/org/edu_sharing/service/permission/PermissionServiceAdapter.java index 32bc7f249..3a30a1125 100644 --- a/Backend/services/core/src/main/java/org/edu_sharing/service/permission/PermissionServiceAdapter.java +++ b/Backend/services/core/src/main/java/org/edu_sharing/service/permission/PermissionServiceAdapter.java @@ -1,21 +1,21 @@ package org.edu_sharing.service.permission; -import java.util.*; - import org.alfresco.service.cmr.repository.NodeRef; -import org.edu_sharing.repository.client.rpc.ACE; -import org.edu_sharing.repository.client.rpc.ACL; -import org.edu_sharing.repository.client.rpc.Authority; -import org.edu_sharing.repository.client.rpc.Group; -import org.edu_sharing.repository.client.rpc.Notify; -import org.edu_sharing.repository.client.rpc.Result; -import org.edu_sharing.repository.client.rpc.User; +import org.edu_sharing.repository.client.rpc.*; import org.edu_sharing.service.InsufficientPermissionException; +import java.util.Collection; +import java.util.*; + public class PermissionServiceAdapter implements PermissionService { protected List ALLOWED_PERMISSIONS=new ArrayList<>(); - + + @Override + public void updateTimedPermissions() { + + } + @Override public void addPermissions(String _nodeId, Map _authPerm, Boolean _inheritPermissions, String _mailText, Boolean _sendMail, Boolean _sendCopy) throws Throwable { 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 6613fa6a0..08f5c452d 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 @@ -9,6 +9,7 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.permissions.impl.acegi.FilteringResultSet; +import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.ChildAssociationRef; @@ -88,6 +89,7 @@ public class PermissionServiceImpl implements org.edu_sharing.service.permission MCAlfrescoAPIClient repoClient = new MCAlfrescoAPIClient(); private GuestService guestService = applicationContext.getBean(GuestService.class); private PermissionService permissionService; + private final RetryingTransactionHelper retryingTransactionHelper = serviceRegistry.getRetryingTransactionHelper(); public PermissionServiceImpl( ToolPermissionService toolPermissionService, @@ -252,7 +254,7 @@ public void setPermissions(String nodeId, List aces, Boolean inheritPermiss } if (createNotify) { - createNotifyObject(nodeId, new AuthenticationToolAPI().getCurrentUser(), + createNotifyObject(nodeId, AuthenticationUtil.getFullyAuthenticatedUser(), CCConstants.CCM_VALUE_NOTIFY_ACTION_PERMISSION_CHANGE); } @@ -298,11 +300,62 @@ public void setPermissions(String nodeId, List aces, Boolean inheritPermiss } + @Override + public void updateTimedPermissions() { + List permissionsToAdd = timedPermissionMapper.findAllByFromAfterAndNotActivated(new Date()); + List permissionsToRemove = timedPermissionMapper.findAllByToBefore(new Date()); + + for (TimedPermission timedPermission : permissionsToAdd) { + retryingTransactionHelper.doInTransaction(() -> + AuthenticationUtil.runAs(() -> { + NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, timedPermission.getNode_id()); + if(!nodeService.exists(nodeRef)) { + timedPermissionMapper.delete(timedPermission); + return null; + } + + try { + addPermissions(timedPermission.getNode_id(), + Map.of(timedPermission.getAuthority(), new String[]{timedPermission.getPermission()}), false, null, false, timedPermission.getUser()); + if (timedPermission.getTo() == null) { + timedPermissionMapper.delete(timedPermission); + } else { + timedPermission.setActivated(true); + timedPermissionMapper.save(timedPermission); + } + } catch (Throwable e) { + log.error(e.getMessage(), e); + } + return null; + }, timedPermission.getUser())); + } + + for (TimedPermission timedPermission : permissionsToRemove) { + retryingTransactionHelper.doInTransaction(() -> + AuthenticationUtil.runAs(() -> { + NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, timedPermission.getNode_id()); + if(nodeService.exists(nodeRef)) { + permissionService.deletePermission( + nodeRef, + timedPermission.getAuthority(), + timedPermission.getPermission()); + createNotifyObject(timedPermission.getNode_id(), timedPermission.getUser(), CCConstants.CCM_VALUE_NOTIFY_ACTION_PERMISSION_CHANGE); + } + timedPermissionMapper.delete(timedPermission); + return null; + }, timedPermission.getUser())); + } + } + @Override public void addPermissions(String _nodeId, Map _authPerm, Boolean _inheritPermissions, String _mailText, Boolean _sendMail, Boolean _sendCopy) throws Throwable { + String user = AuthenticationUtil.getFullyAuthenticatedUser(); + addPermissions(_nodeId, _authPerm, _inheritPermissions, _mailText, _sendMail, user); + } + + private void addPermissions(String _nodeId, Map _authPerm, Boolean _inheritPermissions, String _mailText, Boolean _sendMail, String user) throws Throwable { - String user = new AuthenticationToolAPI().getCurrentUser(); for (String authority : _authPerm.keySet()) { String[] permissions = _authPerm.get(authority); setPermissions(_nodeId, authority, permissions, _inheritPermissions); @@ -317,7 +370,12 @@ public void addPermissions(String _nodeId, Map _authPerm, Bool if (AuthorityType.GROUP.equals(authorityType)) { addToRecent(authorityService.getAuthorityNodeRef(authority)); } + } + + createNotifyObject(_nodeId, user, CCConstants.CCM_VALUE_NOTIFY_ACTION_PERMISSION_ADD); + for (String authority : _authPerm.keySet()) { + String[] permissions = _authPerm.get(authority); if (_sendMail) { String nodeType = eduNodeService.getType(StoreRef.PROTOCOL_WORKSPACE, StoreRef.STORE_REF_WORKSPACE_SPACESSTORE.getIdentifier(), _nodeId); Map props = eduNodeService.getProperties(StoreRef.PROTOCOL_WORKSPACE, StoreRef.STORE_REF_WORKSPACE_SPACESSTORE.getIdentifier(), _nodeId); @@ -326,11 +384,6 @@ public void addPermissions(String _nodeId, Map _authPerm, Bool .notifyPermissionChanged(user, authority, _nodeId, nodeType, aspects, props, permissions, _mailText); } } - - org.edu_sharing.service.permission.PermissionService permissionService = PermissionServiceFactory - .getPermissionService(ApplicationInfoList.getHomeRepository().getAppId()); - - permissionService.createNotifyObject(_nodeId, user, CCConstants.CCM_VALUE_NOTIFY_ACTION_PERMISSION_ADD); } @@ -803,6 +856,7 @@ private TimedPermission createTimedPermission(String nodeId, ACE ace, boolean ac permission.setAuthority(ace.getAuthority()); permission.setPermission(ace.getPermission()); permission.setActivated(activated); + permission.setUser(AuthenticationUtil.getFullyAuthenticatedUser()); return permission; } diff --git a/Backend/services/core/src/main/java/org/edu_sharing/service/permission/TimedPermission.java b/Backend/services/core/src/main/java/org/edu_sharing/service/permission/TimedPermission.java index 9cecbde0c..005f9874b 100644 --- a/Backend/services/core/src/main/java/org/edu_sharing/service/permission/TimedPermission.java +++ b/Backend/services/core/src/main/java/org/edu_sharing/service/permission/TimedPermission.java @@ -7,6 +7,7 @@ @Data public class TimedPermission { private String node_id; + private String user; private String permission; private String authority; private Date from; diff --git a/Backend/services/core/src/main/java/org/edu_sharing/service/permission/TimedPermissionMapper.java b/Backend/services/core/src/main/java/org/edu_sharing/service/permission/TimedPermissionMapper.java index fceb7cbc8..fdecbe5b5 100644 --- a/Backend/services/core/src/main/java/org/edu_sharing/service/permission/TimedPermissionMapper.java +++ b/Backend/services/core/src/main/java/org/edu_sharing/service/permission/TimedPermissionMapper.java @@ -22,7 +22,7 @@ public interface TimedPermissionMapper { @Select("SELECT * FROM edu_timed_node_permission WHERE \"to\" < #{date}") List findAllByToBefore(@Param("date") Date date); - @Insert("INSERT INTO edu_timed_node_permission(node_id,authority,permission,\"from\",\"to\", activated)VALUES(#{node_id},#{authority},#{permission},#{from},#{to}, #{activated}) ON CONFLICT (node_id, authority, permission) DO UPDATE SET \"from\" = #{from}, \"to\" = #{to}, activated = #{activated};") + @Insert("INSERT INTO edu_timed_node_permission(node_id,authority,\"user\",permission,\"from\",\"to\", activated)VALUES(#{node_id},#{authority},#{user},#{permission},#{from},#{to}, #{activated}) ON CONFLICT (node_id, authority, permission) DO UPDATE SET \"from\" = #{from}, \"to\" = #{to}, \"user\" = #{user}, activated = #{activated};") void save(TimedPermission timedPermission); @Delete("DELETE FROM edu_timed_node_permission WHERE node_id = #{node_id} AND authority = #{authority} AND permission = #{permission}") diff --git a/Backend/services/core/src/main/java/org/edu_sharing/service/search/SearchServiceElastic.java b/Backend/services/core/src/main/java/org/edu_sharing/service/search/SearchServiceElastic.java index 052417c98..3d26d61a9 100644 --- a/Backend/services/core/src/main/java/org/edu_sharing/service/search/SearchServiceElastic.java +++ b/Backend/services/core/src/main/java/org/edu_sharing/service/search/SearchServiceElastic.java @@ -503,8 +503,13 @@ public SearchResultNodeRef search(MetadataSet mds, String query, Map authorities = getUserAuthorities(); + Set authorities; + if(searchToken.getAuthorityScope() != null && !searchToken.getAuthorityScope().isEmpty()) { + logger.debug("Searching elastic with authority scope: " + StringUtils.join(searchToken.getAuthorityScope())); + authorities = new HashSet<>(searchToken.getAuthorityScope()); + } else { + authorities = getUserAuthorities(); + } String user = serviceRegistry.getAuthenticationService().getCurrentUserName(); diff --git a/Frontend/src/app/core-module b/Frontend/src/app/core-module index 9a86835e1..2bff78121 160000 --- a/Frontend/src/app/core-module +++ b/Frontend/src/app/core-module @@ -1 +1 @@ -Subproject commit 9a86835e1920cae6f1ed03a96f914cb716e079ee +Subproject commit 2bff78121609ada923ed98bc9a52b6ac1a06f013 diff --git a/Frontend/src/app/features/dialogs/dialog-modules/checkbox-dialog/checkbox-dialog-data.ts b/Frontend/src/app/features/dialogs/dialog-modules/checkbox-dialog/checkbox-dialog-data.ts new file mode 100644 index 000000000..f2faefb6d --- /dev/null +++ b/Frontend/src/app/features/dialogs/dialog-modules/checkbox-dialog/checkbox-dialog-data.ts @@ -0,0 +1,16 @@ +import { CardDialogConfig } from '../../card-dialog/card-dialog-config'; +import { Node } from 'ngx-edu-sharing-api'; + +export class CheckboxDialogData

extends CardDialogConfig { + nodes: Node[]; + /** Message to show in the dialog body. Will be translated. */ + message: string; + /** Translation parameters for the given message text. */ + messageParameters?: { [key in P]: string }; + /** Label of the checkbox field. Will be translated. */ + label: string; + /** state of the checkbox **/ + state?: boolean; +} + +export type CheckboxDialogResult = boolean | null; diff --git a/Frontend/src/app/features/dialogs/dialog-modules/checkbox-dialog/checkbox-dialog.component.html b/Frontend/src/app/features/dialogs/dialog-modules/checkbox-dialog/checkbox-dialog.component.html new file mode 100644 index 000000000..35e684533 --- /dev/null +++ b/Frontend/src/app/features/dialogs/dialog-modules/checkbox-dialog/checkbox-dialog.component.html @@ -0,0 +1,4 @@ +

+ {{ line }} +

+{{ data.label | translate }} diff --git a/Frontend/src/app/features/dialogs/dialog-modules/checkbox-dialog/checkbox-dialog.component.scss b/Frontend/src/app/features/dialogs/dialog-modules/checkbox-dialog/checkbox-dialog.component.scss new file mode 100644 index 000000000..13232c33f --- /dev/null +++ b/Frontend/src/app/features/dialogs/dialog-modules/checkbox-dialog/checkbox-dialog.component.scss @@ -0,0 +1,8 @@ +p { + margin: 0; + margin-bottom: 1.5em; +} + +mat-checkbox { + margin-top: 1.5em; +} diff --git a/Frontend/src/app/features/dialogs/dialog-modules/checkbox-dialog/checkbox-dialog.component.ts b/Frontend/src/app/features/dialogs/dialog-modules/checkbox-dialog/checkbox-dialog.component.ts new file mode 100644 index 000000000..320249a20 --- /dev/null +++ b/Frontend/src/app/features/dialogs/dialog-modules/checkbox-dialog/checkbox-dialog.component.ts @@ -0,0 +1,26 @@ +import { Component, Inject } from '@angular/core'; +import { FormControl } from '@angular/forms'; +import { CARD_DIALOG_DATA } from '../../card-dialog/card-dialog-config'; +import { CardDialogRef } from '../../card-dialog/card-dialog-ref'; +import { CheckboxDialogData, CheckboxDialogResult } from './checkbox-dialog-data'; +import { SharedModule } from '../../../../shared/shared.module'; + +/** + * A generic dialog with an input form field and configurable title, message, label and icon. + */ +@Component({ + standalone: true, + imports: [SharedModule], + templateUrl: './checkbox-dialog.component.html', + styleUrls: ['./checkbox-dialog.component.scss'], +}) +export class CheckboxDialogComponent { + control = new FormControl(false); + + constructor( + @Inject(CARD_DIALOG_DATA) public data: CheckboxDialogData, + private dialogRef: CardDialogRef, + ) { + this.control.valueChanges.subscribe((value) => (this.data.state = value)); + } +} diff --git a/Frontend/src/app/features/dialogs/dialogs.service.ts b/Frontend/src/app/features/dialogs/dialogs.service.ts index 6788b7876..6d214f725 100644 --- a/Frontend/src/app/features/dialogs/dialogs.service.ts +++ b/Frontend/src/app/features/dialogs/dialogs.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; -import { DialogButton, RestConnectorService, UIConstants } from '../../core-module/core.module'; +import { DialogButton, RestConnectorService } from '../../core-module/core.module'; import { Closable } from './card-dialog/card-dialog-config'; import { CardDialogRef } from './card-dialog/card-dialog-ref'; import { CardDialogUtilsService } from './card-dialog/card-dialog-utils.service'; @@ -128,13 +128,16 @@ import { XmlAppPropertiesDialogResult, } from './dialog-modules/xml-app-properties-dialog/xml-app-properties-dialog-data'; import { NotificationDialogComponent } from '../../main/navigation/top-bar/notification-dialog/notification-dialog.component'; -import { CardComponent } from '../../shared/components/card/card.component'; import { Node } from 'ngx-edu-sharing-api'; import { DropSource, DropTarget, NodeRoot, NodeTitlePipe } from 'ngx-edu-sharing-ui'; import { RevocationDialogData, RevocationDialogResult, } from './dialog-modules/revocation-dialog/revocation-dialog-data'; +import { + CheckboxDialogData, + CheckboxDialogResult, +} from './dialog-modules/checkbox-dialog/checkbox-dialog-data'; @Injectable({ providedIn: 'root', @@ -205,6 +208,27 @@ export class DialogsService { }); } + async openCheckboxConfirmDialog( + config: CheckboxDialogData, + ): Promise> { + const { title, subtitle, avatar, buttons, ...data } = { + ...new CheckboxDialogData(), + ...config, + }; + const { CheckboxDialogComponent } = await import( + './dialog-modules/checkbox-dialog/checkbox-dialog.component' + ); + return this.cardDialog.open(CheckboxDialogComponent, { + title, + ...(await this.cardDialogUtils.configForNodes(data.nodes)), + avatar, + buttons, + width: 600, + closable: Closable.Casual, + data, + }); + } + async openQrDialog(data: QrDialogData): Promise> { const { QrDialogComponent } = await import('./dialog-modules/qr-dialog/qr-dialog.module'); return this.cardDialog.open(QrDialogComponent, { diff --git a/Frontend/src/app/pages/workspace-page/workspace-page.component.ts b/Frontend/src/app/pages/workspace-page/workspace-page.component.ts index 7266b0d38..eab8eca5e 100644 --- a/Frontend/src/app/pages/workspace-page/workspace-page.component.ts +++ b/Frontend/src/app/pages/workspace-page/workspace-page.component.ts @@ -505,6 +505,7 @@ export class WorkspacePageComponent implements EventListener, OnInit, OnDestroy await this.prepareActionbar(); await this.initUser(); this.loadFolders(this.user); + this.initMainNav(); this.connector.scope = this.isSafe ? RestConstants.SAFE_SCOPE : null; this.isLoggedIn = true; @@ -560,8 +561,6 @@ export class WorkspacePageComponent implements EventListener, OnInit, OnDestroy } this.mainnav = params.mainnav === 'false' ? false : true; - this.initMainNav(); - if (params.file && params.file !== this.oldParams?.file) { void this.showNodeInCurrentFolder(params.file); } diff --git a/Frontend/src/app/services/node-helper.service.ts b/Frontend/src/app/services/node-helper.service.ts index 954726326..282e3e5bc 100644 --- a/Frontend/src/app/services/node-helper.service.ts +++ b/Frontend/src/app/services/node-helper.service.ts @@ -1,5 +1,5 @@ import { TranslateService } from '@ngx-translate/core'; -import { forkJoin, Observable, Observer } from 'rxjs'; +import { forkJoin, Observable } from 'rxjs'; import { Params, Router } from '@angular/router'; import { Location } from '@angular/common'; import { @@ -31,7 +31,6 @@ import { AuthorityProfile, CollectionReference, DeepLinkResponse, - Permission, Repository, User, } from '../core-module/rest/data-object'; @@ -39,18 +38,21 @@ import { RestConstants } from '../core-module/rest/rest-constants'; import { RestHelper } from '../core-module/rest/rest-helper'; import { RestConnectorService } from '../core-module/rest/services/rest-connector.service'; import { UniversalNode } from '../core-module/rest/definitions'; -import { SessionStorageService } from '../core-module/rest/services/session-storage.service'; +import { SessionStorageService, Store } from '../core-module/rest/services/session-storage.service'; import { map } from 'rxjs/operators'; import { RestNodeService } from '../core-module/rest/services/rest-node.service'; import { Ace, ApiHelpersService, + AuthenticationService, ConfigService, HOME_REPOSITORY, NetworkService, Node, TrackingV1Service, } from 'ngx-edu-sharing-api'; +import { DialogsService } from '../features/dialogs/dialogs.service'; +import { DialogButton } from '../util/dialog-button'; export interface ConfigEntry { name: string; @@ -90,7 +92,9 @@ export class NodeHelperService extends NodeHelperServiceBase { repoUrlService: RepoUrlService, @Optional() @Inject(ASSETS_BASE_PATH) assetsBasePath: string, private componentFactoryResolver: ComponentFactoryResolver, + private authenticationService: AuthenticationService, private config: ConfigService, + private dialogsService: DialogsService, private rest: RestConnectorService, private bridge: BridgeService, private http: HttpClient, @@ -492,9 +496,49 @@ export class NodeHelperService extends NodeHelperServiceBase { /** * Download one or multiple nodes - * @param node */ - async downloadNodes(nodes: Node[], fileName = 'download.zip') { + async downloadNodes(nodes: Node[], fileName = 'download.zip', confirmed = false) { + const safe = nodes.some((n) => + n.properties?.[RestConstants.CCM_PROP_EDUSCOPENAME]?.includes(RestConstants.SAFE_SCOPE), + ); + if ( + safe && + !confirmed && + !(await this.sessionStorage + .get( + SessionStorageService.KEY_WORKSPACE_SAFE_DOWNLOAD_CONFIRM, + false, + Store.Session, + ) + .toPromise()) + ) { + const buttons = [ + new DialogButton('CANCEL', DialogButton.TYPE_CANCEL, null), + new DialogButton('DOWNLOAD', DialogButton.TYPE_PRIMARY, null), + ]; + const dialog = await this.dialogsService.openCheckboxConfirmDialog({ + nodes, + buttons, + title: 'WORKSPACE.SAFE_CONFIRM_DOWNLOAD_TITLE', + label: 'WORKSPACE.SAFE_CONFIRM_DOWNLOAD_CHECKBOX', + message: 'WORKSPACE.SAFE_CONFIRM_DOWNLOAD_MESSAGE', + }); + buttons[0].callback = () => dialog.close(); + buttons[1].callback = () => { + if (dialog.config.data.state) { + this.sessionStorage + .set( + SessionStorageService.KEY_WORKSPACE_SAFE_DOWNLOAD_CONFIRM, + true, + Store.Session, + ) + .then(() => {}); + } + this.downloadNodes(nodes, fileName, true); + dialog.close(); + }; + return; + } if (nodes.length === 1) return await this.downloadNode(nodes[0]); const nodesString = RestHelper.getNodeIds(nodes).join(','); diff --git a/Frontend/src/app/services/options-helper.service.ts b/Frontend/src/app/services/options-helper.service.ts index b696a953d..2f0107d2b 100644 --- a/Frontend/src/app/services/options-helper.service.ts +++ b/Frontend/src/app/services/options-helper.service.ts @@ -1004,48 +1004,8 @@ export class OptionsHelperService extends OptionsHelperServiceAbstract implement } return isAllowed; */ - const downloadNode = new OptionItem('OPTIONS.DOWNLOAD', 'cloud_download', (object) => - this.nodeHelper.downloadNodes(this.getObjects(object, data)), - ); - downloadNode.elementType = OptionsHelperService.DownloadElementTypes; - downloadNode.constrains = [Constrain.Files]; - downloadNode.group = DefaultGroups.View; - // downloadNode.key = 'D'; - downloadNode.priority = 40; - downloadNode.customEnabledCallback = async (nodes) => { - if (!nodes) { - return false; - } - - if ( - nodes.some((n) => - n.properties?.[RestConstants.CCM_PROP_EDUSCOPENAME]?.includes( - RestConstants.SAFE_SCOPE, - ), - ) - ) { - downloadNode.name = 'OPTIONS.DOWNLOAD_SAFE'; - } else { - downloadNode.name = 'OPTIONS.DOWNLOAD'; - } - for (const item of nodes) { - // if at least one is allowed -> allow download (download servlet will later filter invalid files) - if ( - item.downloadUrl != null && - item.properties && - (!item.properties[RestConstants.CCM_PROP_IO_WWWURL] || - !RestNetworkService.isFromHomeRepo(item)) && - this.nodeHelper.referenceOriginalExists(item) - ) { - // bulk upload is not supported for remote nodes - if (!RestNetworkService.isFromHomeRepo(item) && nodes.length !== 1) { - continue; - } - return true; - } - } - return false; - }; + const downloadNode = this.getDownloadOption(data, false); + const downloadNodeSafe = this.getDownloadOption(data, true); const downloadMetadataNode = new OptionItem( 'OPTIONS.DOWNLOAD_METADATA', 'format_align_left', @@ -1528,6 +1488,7 @@ export class OptionsHelperService extends OptionsHelperServiceAbstract implement options.push(contributorNode); options.push(workflowNode); options.push(downloadNode); + options.push(downloadNodeSafe); options.push(downloadMetadataNode); options.push(qrCodeNode); options.push(relationNode); @@ -1554,6 +1515,52 @@ export class OptionsHelperService extends OptionsHelperServiceAbstract implement return options; } + private getDownloadOption(data: OptionData, safe = false) { + const downloadNode = new OptionItem( + 'OPTIONS.DOWNLOAD' + (safe ? '_SAFE' : ''), + 'cloud_download', + (object) => this.nodeHelper.downloadNodes(this.getObjects(object, data)), + ); + downloadNode.elementType = OptionsHelperService.DownloadElementTypes; + downloadNode.constrains = [Constrain.Files]; + downloadNode.group = DefaultGroups.View; + // downloadNode.key = 'D'; + downloadNode.priority = 40; + downloadNode.customShowCallback = async (nodes) => { + return ( + nodes.some((n) => + n.properties?.[RestConstants.CCM_PROP_EDUSCOPENAME]?.includes( + RestConstants.SAFE_SCOPE, + ), + ) === safe + ); + }; + downloadNode.customEnabledCallback = async (nodes) => { + if (!nodes) { + return false; + } + + for (const item of nodes) { + // if at least one is allowed -> allow download (download servlet will later filter invalid files) + if ( + item.downloadUrl != null && + item.properties && + (!item.properties[RestConstants.CCM_PROP_IO_WWWURL] || + !RestNetworkService.isFromHomeRepo(item)) && + this.nodeHelper.referenceOriginalExists(item) + ) { + // bulk upload is not supported for remote nodes + if (!RestNetworkService.isFromHomeRepo(item) && nodes.length !== 1) { + continue; + } + return true; + } + } + return false; + }; + return downloadNode; + } + private async revokeNode(object: any, data: OptionData) { const dialogRef = await this.dialogs.openRevocationDialog({ node: this.getObjects(object, data)[0], diff --git a/Frontend/src/assets/i18n/workspace/de.json b/Frontend/src/assets/i18n/workspace/de.json index 034d14619..76db02ee1 100644 --- a/Frontend/src/assets/i18n/workspace/de.json +++ b/Frontend/src/assets/i18n/workspace/de.json @@ -453,6 +453,9 @@ "DRAG_DROP_COPY": "Kopieren", "DRAG_DROP_MOVE": "Verschieben", "FEATURE_NOT_IMPLEMENTED": "Die Funktion ist derzeit leider noch nicht verfügbar", + "SAFE_CONFIRM_DOWNLOAD_TITLE": "Hinweis", + "SAFE_CONFIRM_DOWNLOAD_CHECKBOX": "In dieser Sitzung nicht erneut anzeigen", + "SAFE_CONFIRM_DOWNLOAD_MESSAGE": "Bitte beachten Sie, dass lokal gespeicherte Dateien aus dem Datensafe wieder gelöscht werden sollten. Wir empfehlen die Synchronisation mit eigenen Cloudservices zusätzlich zu deaktivieren.", "LICENSE": { "TITLE": "Lizenz festlegen", "TYPE": "Lizenz wählen", diff --git a/Frontend/src/assets/i18n/workspace/en.json b/Frontend/src/assets/i18n/workspace/en.json index 343494be8..2be429fc7 100644 --- a/Frontend/src/assets/i18n/workspace/en.json +++ b/Frontend/src/assets/i18n/workspace/en.json @@ -455,6 +455,9 @@ "DRAG_DROP_COPY": "copy", "DRAG_DROP_MOVE": "move", "FEATURE_NOT_IMPLEMENTED": "This feature is currently not available", + "SAFE_CONFIRM_DOWNLOAD_TITLE": "Notice", + "SAFE_CONFIRM_DOWNLOAD_CHECKBOX": "Don't show again in this session", + "SAFE_CONFIRM_DOWNLOAD_MESSAGE": "Please note that locally stored files fron the data safe should be deleted afterwards. We also recommend to disable any synchronisations with cloud services.", "LICENSE": { "TITLE": "Define license", "TYPE": "Choose license", diff --git a/config/defaults/src/main/resources/database/timed-permission.u1.sql b/config/defaults/src/main/resources/database/timed-permission.u1.sql new file mode 100644 index 000000000..dd753d3de --- /dev/null +++ b/config/defaults/src/main/resources/database/timed-permission.u1.sql @@ -0,0 +1,2 @@ +ALTER TABLE edu_timed_node_permission + ADD "user" varchar(100) NOT NULL DEFAULT 'admin' diff --git a/config/defaults/src/main/resources/edu-sharing.reference.conf b/config/defaults/src/main/resources/edu-sharing.reference.conf index 872b6d10e..cc9468005 100644 --- a/config/defaults/src/main/resources/edu-sharing.reference.conf +++ b/config/defaults/src/main/resources/edu-sharing.reference.conf @@ -223,7 +223,8 @@ repository: { "tracking.u4.sql", "tracking.u5.sql", "factualterm.sql", - "timed-permission.sql" + "timed-permission.sql", + "timed-permission.u1.sql" ], custom:[] // any custom scripts (this can be safely overriden) } diff --git a/config/defaults/src/main/resources/metadatasets/xml/mds.xml b/config/defaults/src/main/resources/metadatasets/xml/mds.xml index 195239bb8..5d82ee3bb 100644 --- a/config/defaults/src/main/resources/metadatasets/xml/mds.xml +++ b/config/defaults/src/main/resources/metadatasets/xml/mds.xml @@ -1329,7 +1329,6 @@ {"match":{"properties.ccm:collectionlevel0.keyword":"true"}} ], "must_not":[ - {"match":{"permissions.Read":"GROUP_EVERYONE"}}, {"match":{"properties.cm:owner.keyword":"${authority}"}}, {"match":{"properties.ccm:collectiontype.keyword":"EDITORIAL"}}, {"match":{"properties.ccm:collectiontype.keyword":"MEDIA_CENTER"}}