From e95100e429e7ba2d3f51d1e3afefcb32f18f2296 Mon Sep 17 00:00:00 2001 From: Sara Date: Tue, 3 Aug 2021 14:16:24 +0100 Subject: [PATCH] Acs 1865 impl configs for da us (#634) * ACS-1781 Config set up and validation * ACS-1781 Unit tests for config validation * ACS-1865 Code tidy up * ACS-1865 Updates from PR review * ACS-1865 Updates from review --- .../directurl/RestApiDirectUrlConfig.java | 93 + .../org/alfresco/AppContext04TestSuite.java | 3 +- .../impl/RestApiDirectUrlConfigUnitTest.java | 132 + .../directurl/AbstractDirectUrlConfig.java | 81 + .../ContentStoreDirectUrlConfig.java | 134 + .../content/directurl/DirectUrlConfig.java | 41 + ...InvalidDirectAccessUrlConfigException.java | 44 + .../directurl/SystemWideDirectUrlConfig.java | 124 + .../alfresco/content-services-context.xml | 732 ++--- .../resources/alfresco/repository.properties | 2557 +++++++++-------- .../java/org/alfresco/AllUnitTestsSuite.java | 2 + .../ContentStoreDirectUrlConfigUnitTest.java | 234 ++ .../SystemWideDirectUrlConfigUnitTest.java | 153 + 13 files changed, 2723 insertions(+), 1607 deletions(-) create mode 100644 remote-api/src/main/java/org/alfresco/rest/api/impl/directurl/RestApiDirectUrlConfig.java create mode 100644 remote-api/src/test/java/org/alfresco/rest/api/impl/RestApiDirectUrlConfigUnitTest.java create mode 100644 repository/src/main/java/org/alfresco/repo/content/directurl/AbstractDirectUrlConfig.java create mode 100644 repository/src/main/java/org/alfresco/repo/content/directurl/ContentStoreDirectUrlConfig.java create mode 100644 repository/src/main/java/org/alfresco/repo/content/directurl/DirectUrlConfig.java create mode 100644 repository/src/main/java/org/alfresco/repo/content/directurl/InvalidDirectAccessUrlConfigException.java create mode 100644 repository/src/main/java/org/alfresco/repo/content/directurl/SystemWideDirectUrlConfig.java create mode 100644 repository/src/test/java/org/alfresco/repo/content/directurl/ContentStoreDirectUrlConfigUnitTest.java create mode 100644 repository/src/test/java/org/alfresco/repo/content/directurl/SystemWideDirectUrlConfigUnitTest.java diff --git a/remote-api/src/main/java/org/alfresco/rest/api/impl/directurl/RestApiDirectUrlConfig.java b/remote-api/src/main/java/org/alfresco/rest/api/impl/directurl/RestApiDirectUrlConfig.java new file mode 100644 index 0000000000..3b231ae7e1 --- /dev/null +++ b/remote-api/src/main/java/org/alfresco/rest/api/impl/directurl/RestApiDirectUrlConfig.java @@ -0,0 +1,93 @@ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2021 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco 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 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + * #L% + */ +package org.alfresco.rest.api.impl.directurl; + +import org.alfresco.repo.content.directurl.AbstractDirectUrlConfig; +import org.alfresco.repo.content.directurl.InvalidDirectAccessUrlConfigException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * REST API direct access URL configuration settings. + * + * @author Sara Aspery + */ +public class RestApiDirectUrlConfig extends AbstractDirectUrlConfig +{ + private static final Log logger = LogFactory.getLog(RestApiDirectUrlConfig.class); + + /** + * Configuration initialise + */ + public void init() + { + validate(); + } + + /** + * {@inheritDoc} + */ + @Override + public void validate() + { + // Disable direct access URLs for the REST API if any error found in the REST API direct access URL config + try + { + validateDirectAccessUrlConfig(); + } + catch (InvalidDirectAccessUrlConfigException ex) + { + logger.error("Disabling REST API direct access URLs due to configuration error: " + ex.getMessage()); + setEnabled(false); + } + } + + /* Helper method to validate the REST API direct access url configuration settings */ + private void validateDirectAccessUrlConfig() throws InvalidDirectAccessUrlConfigException + { + if (isEnabled()) + { + if (getDefaultExpiryTimeInSec() == null) + { + logger.warn(String.format("Default expiry time property is missing: setting to system-wide default [%s].", getSysWideDefaultExpiryTimeInSec())); + setDefaultExpiryTimeInSec(getSysWideDefaultExpiryTimeInSec()); + } + + if (getDefaultExpiryTimeInSec() < 1) + { + String errorMsg = String.format("REST API direct access URL default expiry time [%s] is invalid.", getDefaultExpiryTimeInSec()); + throw new InvalidDirectAccessUrlConfigException(errorMsg); + } + + if (getDefaultExpiryTimeInSec() > getSysWideMaxExpiryTimeInSec()) + { + String errorMsg = String.format("REST API direct access URL default expiry time [%s] exceeds system-wide maximum expiry time [%s].", + getDefaultExpiryTimeInSec(), getSysWideMaxExpiryTimeInSec()); + throw new InvalidDirectAccessUrlConfigException(errorMsg); + } + } + } +} diff --git a/remote-api/src/test/java/org/alfresco/AppContext04TestSuite.java b/remote-api/src/test/java/org/alfresco/AppContext04TestSuite.java index 9545280e76..4548e38d4c 100644 --- a/remote-api/src/test/java/org/alfresco/AppContext04TestSuite.java +++ b/remote-api/src/test/java/org/alfresco/AppContext04TestSuite.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2017 Alfresco Software Limited + * Copyright (C) 2005 - 2021 Alfresco Software Limited * %% * This file is part of the Alfresco software. * If the software was purchased under a paid Alfresco license, the terms of @@ -76,6 +76,7 @@ import org.junit.runners.Suite; org.alfresco.repo.web.scripts.site.SurfConfigTest.class, org.alfresco.repo.web.scripts.node.NodeWebScripTest.class, org.alfresco.rest.api.impl.CommentsImplUnitTest.class, + org.alfresco.rest.api.impl.RestApiDirectUrlConfigUnitTest.class }) public class AppContext04TestSuite { diff --git a/remote-api/src/test/java/org/alfresco/rest/api/impl/RestApiDirectUrlConfigUnitTest.java b/remote-api/src/test/java/org/alfresco/rest/api/impl/RestApiDirectUrlConfigUnitTest.java new file mode 100644 index 0000000000..e04c07338f --- /dev/null +++ b/remote-api/src/test/java/org/alfresco/rest/api/impl/RestApiDirectUrlConfigUnitTest.java @@ -0,0 +1,132 @@ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2021 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco 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 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + * #L% + */ +package org.alfresco.rest.api.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import org.alfresco.repo.content.directurl.SystemWideDirectUrlConfig; +import org.alfresco.rest.api.impl.directurl.RestApiDirectUrlConfig; +import org.junit.Before; +import org.junit.Test; + +/** + * Tests for REST API direct access URL configuration settings. + * + * @author Sara Aspery + */ +public class RestApiDirectUrlConfigUnitTest +{ + private static final Boolean ENABLED = Boolean.TRUE; + private static final Boolean DISABLED = Boolean.FALSE; + + private static final Long DEFAULT_EXPIRY_TIME_IN_SECS = 20L; + + private RestApiDirectUrlConfig restApiDirectUrlConfig; + + @Before + public void setup() + { + this.restApiDirectUrlConfig = new RestApiDirectUrlConfig(); + SystemWideDirectUrlConfig sysConfig = new SystemWideDirectUrlConfig(); + sysConfig.setEnabled(ENABLED); + sysConfig.setDefaultExpiryTimeInSec(30L); + sysConfig.setMaxExpiryTimeInSec(300L); + restApiDirectUrlConfig.setSystemWideDirectUrlConfig(sysConfig); + } + + @Test + public void testValidConfig_RemainsEnabled() + { + setupDirectAccessConfig(ENABLED, DEFAULT_EXPIRY_TIME_IN_SECS); + + assertTrue("Expected REST API direct URLs to be enabled", restApiDirectUrlConfig.isEnabled()); + restApiDirectUrlConfig.validate(); + assertTrue("Expected REST API direct URLs to be enabled", restApiDirectUrlConfig.isEnabled()); + } + + @Test + public void testValidConfig_RemainsDisabled() + { + setupDirectAccessConfig(DISABLED, DEFAULT_EXPIRY_TIME_IN_SECS); + + assertFalse("Expected REST API direct URLs to be disabled", restApiDirectUrlConfig.isEnabled()); + restApiDirectUrlConfig.validate(); + assertFalse("Expected REST API direct URLs to be disabled", restApiDirectUrlConfig.isEnabled()); + } + + @Test + public void testValidConfig_DefaultExpiryTimeMissing() + { + setupDirectAccessConfig(ENABLED, null); + + assertNull("Expected REST API default expiry time to be null", restApiDirectUrlConfig.getDefaultExpiryTimeInSec()); + restApiDirectUrlConfig.validate(); + Long expectedDefaultExpiryTime = restApiDirectUrlConfig.getSysWideDefaultExpiryTimeInSec(); + assertEquals("Expected REST API default expiry time to be set to the system-wide default", expectedDefaultExpiryTime, restApiDirectUrlConfig.getDefaultExpiryTimeInSec()); + assertTrue("Expected REST API direct URLs to be enabled", restApiDirectUrlConfig.isEnabled()); + } + + @Test + public void testInvalidConfig_DefaultExpiryTimeZero() + { + setupDirectAccessConfig(ENABLED, 0L); + + assertTrue("Expected REST API direct URLs to be enabled", restApiDirectUrlConfig.isEnabled()); + restApiDirectUrlConfig.validate(); + assertFalse("Expected REST API direct URLs to be disabled", restApiDirectUrlConfig.isEnabled()); + } + + @Test + public void testInvalidConfig_DefaultExpiryTimeNegative() + { + setupDirectAccessConfig(ENABLED, -1L); + + assertTrue("Expected REST API direct URLs to be enabled", restApiDirectUrlConfig.isEnabled()); + restApiDirectUrlConfig.validate(); + assertFalse("Expected REST API direct URLs to be disabled", restApiDirectUrlConfig.isEnabled()); + } + + @Test + public void testInvalidConfig_DefaultExpiryTimeExceedsSystemMax() + { + Long systemMax = restApiDirectUrlConfig.getSysWideMaxExpiryTimeInSec(); + setupDirectAccessConfig(ENABLED, systemMax + 1); + + assertTrue("Expected REST API direct URLs to be enabled", restApiDirectUrlConfig.isEnabled()); + restApiDirectUrlConfig.validate(); + assertFalse("Expected REST API direct URLs to be disabled", restApiDirectUrlConfig.isEnabled()); + } + + /* Helper method to set system-wide direct access url configuration settings */ + private void setupDirectAccessConfig(Boolean isEnabled, Long defaultExpiryTime) + { + restApiDirectUrlConfig.setEnabled(isEnabled); + restApiDirectUrlConfig.setDefaultExpiryTimeInSec(defaultExpiryTime); + } +} diff --git a/repository/src/main/java/org/alfresco/repo/content/directurl/AbstractDirectUrlConfig.java b/repository/src/main/java/org/alfresco/repo/content/directurl/AbstractDirectUrlConfig.java new file mode 100644 index 0000000000..db6ebef9e6 --- /dev/null +++ b/repository/src/main/java/org/alfresco/repo/content/directurl/AbstractDirectUrlConfig.java @@ -0,0 +1,81 @@ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2021 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco 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 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.content.directurl; + +/** + * Direct Access Url configuration settings. + * + * @author Sara Aspery + */ +public abstract class AbstractDirectUrlConfig implements DirectUrlConfig +{ + /** System-wide direct access URL configuration */ + private SystemWideDirectUrlConfig systemWideDirectUrlConfig; + + /** Direct access URL configuration settings */ + private Boolean enabled; + private Long defaultExpiryTimeInSec; + + public void setSystemWideDirectUrlConfig(SystemWideDirectUrlConfig systemWideDirectUrlConfig) + { + this.systemWideDirectUrlConfig = systemWideDirectUrlConfig; + } + + public void setEnabled(Boolean enabled) + { + this.enabled = enabled; + } + + public void setDefaultExpiryTimeInSec(Long defaultExpiryTimeInSec) + { + this.defaultExpiryTimeInSec = defaultExpiryTimeInSec; + } + + protected Boolean isSysWideEnabled() + { + return systemWideDirectUrlConfig.isEnabled(); + } + + public Long getSysWideDefaultExpiryTimeInSec() + { + return systemWideDirectUrlConfig.getDefaultExpiryTimeInSec(); + } + + public Long getSysWideMaxExpiryTimeInSec() + { + return systemWideDirectUrlConfig.getMaxExpiryTimeInSec(); + } + + public Boolean isEnabled() + { + return enabled; + } + + public Long getDefaultExpiryTimeInSec() + { + return defaultExpiryTimeInSec; + } +} diff --git a/repository/src/main/java/org/alfresco/repo/content/directurl/ContentStoreDirectUrlConfig.java b/repository/src/main/java/org/alfresco/repo/content/directurl/ContentStoreDirectUrlConfig.java new file mode 100644 index 0000000000..79494718bf --- /dev/null +++ b/repository/src/main/java/org/alfresco/repo/content/directurl/ContentStoreDirectUrlConfig.java @@ -0,0 +1,134 @@ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2021 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco 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 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.content.directurl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Content store direct access URL configuration settings. + * + * @author Sara Aspery + */ +public class ContentStoreDirectUrlConfig extends AbstractDirectUrlConfig +{ + private static final Log logger = LogFactory.getLog(ContentStoreDirectUrlConfig.class); + + private Long maxExpiryTimeInSec; + + public void setMaxExpiryTimeInSec(Long maxExpiryTimeInSec) + { + this.maxExpiryTimeInSec = maxExpiryTimeInSec; + } + + public Long getMaxExpiryTimeInSec() + { + return maxExpiryTimeInSec; + } + + /** + * Configuration initialise + */ + public void init() + { + validate(); + } + + /** + * {@inheritDoc} + */ + @Override + public void validate() + { + // Disable direct access URLs for the content store if any error found in the content store direct access URL config + try + { + validateDirectAccessUrlConfig(); + } + catch (InvalidDirectAccessUrlConfigException ex) + { + logger.error("Disabling content store direct access URLs due to configuration error: " + ex.getMessage()); + setEnabled(false); + } + } + + /* Helper method to validate the content direct access url configuration settings */ + private void validateDirectAccessUrlConfig() throws InvalidDirectAccessUrlConfigException + { + if (isEnabled()) + { + if (getMaxExpiryTimeInSec() == null) + { + logger.warn(String.format("Maximum expiry time property is missing: setting to system-wide maximum [%s].", getSysWideMaxExpiryTimeInSec())); + setMaxExpiryTimeInSec(getSysWideMaxExpiryTimeInSec()); + } + else if (getMaxExpiryTimeInSec() > getSysWideMaxExpiryTimeInSec()) + { + String errorMsg = String.format("Content store direct access URL maximum expiry time [%s] exceeds system-wide maximum expiry time [%s].", + getMaxExpiryTimeInSec(), getSysWideMaxExpiryTimeInSec()); + throw new InvalidDirectAccessUrlConfigException(errorMsg); + } + + if (getDefaultExpiryTimeInSec() == null) + { + logger.warn(String.format("Default expiry time property is missing: setting to system-wide default [%s].", getSysWideDefaultExpiryTimeInSec())); + setDefaultExpiryTimeInSec(getSysWideDefaultExpiryTimeInSec()); + } + else if (getDefaultExpiryTimeInSec() > getMaxExpiryTimeInSec()) + { + logger.warn(String.format("Default expiry time property [%s] exceeds maximum expiry time for content store [%s]: setting to system-wide default [%s].", + getDefaultExpiryTimeInSec(), getMaxExpiryTimeInSec(), getSysWideDefaultExpiryTimeInSec())); + setDefaultExpiryTimeInSec(getSysWideDefaultExpiryTimeInSec()); + } + else if (getDefaultExpiryTimeInSec() > getSysWideDefaultExpiryTimeInSec()) + { + logger.warn(String.format("Default expiry time property [%s] exceeds system-wide default expiry time [%s]: setting to system-wide default.", + getDefaultExpiryTimeInSec(), getSysWideDefaultExpiryTimeInSec())); + setDefaultExpiryTimeInSec(getSysWideDefaultExpiryTimeInSec()); + } + + if (getDefaultExpiryTimeInSec() < 1) + { + String errorMsg = String.format("Content store direct access URL default expiry time [%s] is invalid.", getDefaultExpiryTimeInSec()); + throw new InvalidDirectAccessUrlConfigException(errorMsg); + } + + if (getDefaultExpiryTimeInSec() > getSysWideMaxExpiryTimeInSec()) + { + String errorMsg = String.format("Content store direct access URL default expiry time [%s] exceeds system-wide maximum expiry time [%s].", + getDefaultExpiryTimeInSec(), getSysWideMaxExpiryTimeInSec()); + throw new InvalidDirectAccessUrlConfigException(errorMsg); + } + + if (getDefaultExpiryTimeInSec() > getMaxExpiryTimeInSec()) + { + String errorMsg = String.format("Content store direct access URL default expiry time [%s] exceeds content store maximum expiry time [%s].", + getDefaultExpiryTimeInSec(), getMaxExpiryTimeInSec()); + throw new InvalidDirectAccessUrlConfigException(errorMsg); + } + } + } +} diff --git a/repository/src/main/java/org/alfresco/repo/content/directurl/DirectUrlConfig.java b/repository/src/main/java/org/alfresco/repo/content/directurl/DirectUrlConfig.java new file mode 100644 index 0000000000..68ed3a84da --- /dev/null +++ b/repository/src/main/java/org/alfresco/repo/content/directurl/DirectUrlConfig.java @@ -0,0 +1,41 @@ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2021 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco 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 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.content.directurl; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Direct Access Url configuration settings interface. + * + * @author Sara Aspery + */ +@AlfrescoPublicApi +public interface DirectUrlConfig +{ + Boolean isEnabled(); + Long getDefaultExpiryTimeInSec(); + void validate(); +} diff --git a/repository/src/main/java/org/alfresco/repo/content/directurl/InvalidDirectAccessUrlConfigException.java b/repository/src/main/java/org/alfresco/repo/content/directurl/InvalidDirectAccessUrlConfigException.java new file mode 100644 index 0000000000..5c6445ed5f --- /dev/null +++ b/repository/src/main/java/org/alfresco/repo/content/directurl/InvalidDirectAccessUrlConfigException.java @@ -0,0 +1,44 @@ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2021 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco 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 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.content.directurl; + +import org.alfresco.error.AlfrescoRuntimeException; + +/** + * Runtime exception thrown when the direct access URL configuration settings are invalid. + * + * @author Sara Aspery + */ +public class InvalidDirectAccessUrlConfigException extends AlfrescoRuntimeException +{ + private static final long serialVersionUID = -6318313836484979887L; + + public InvalidDirectAccessUrlConfigException(String msg) + { + super(msg); + } +} + diff --git a/repository/src/main/java/org/alfresco/repo/content/directurl/SystemWideDirectUrlConfig.java b/repository/src/main/java/org/alfresco/repo/content/directurl/SystemWideDirectUrlConfig.java new file mode 100644 index 0000000000..ecfa769e38 --- /dev/null +++ b/repository/src/main/java/org/alfresco/repo/content/directurl/SystemWideDirectUrlConfig.java @@ -0,0 +1,124 @@ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2021 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco 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 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.content.directurl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * System-wide direct access URL configuration settings. + * + * @author Sara Aspery + */ +public class SystemWideDirectUrlConfig implements DirectUrlConfig +{ + private static final Log logger = LogFactory.getLog(SystemWideDirectUrlConfig.class); + + /** Direct access url configuration settings */ + private Boolean enabled; + private Long defaultExpiryTimeInSec; + private Long maxExpiryTimeInSec; + + public void setEnabled(Boolean enabled) + { + this.enabled = enabled; + } + + public void setDefaultExpiryTimeInSec(Long defaultExpiryTimeInSec) + { + this.defaultExpiryTimeInSec = defaultExpiryTimeInSec; + } + + public void setMaxExpiryTimeInSec(Long maxExpiryTimeInSec) + { + this.maxExpiryTimeInSec = maxExpiryTimeInSec; + } + + public Boolean isEnabled() + { + return enabled; + } + + public Long getDefaultExpiryTimeInSec() + { + return defaultExpiryTimeInSec; + } + + public Long getMaxExpiryTimeInSec() + { + return maxExpiryTimeInSec; + } + + /** + * Configuration initialise + */ + public void init() + { + validate(); + } + + /** + * {@inheritDoc} + */ + @Override + public void validate() + { + // Disable direct access URLs system-wide if any error found in the system-wide direct access URL config + try + { + validateSystemDirectAccessUrlConfig(); + } + catch (InvalidDirectAccessUrlConfigException ex) + { + logger.error("Disabling system-wide direct access URLs due to configuration error: " + ex.getMessage()); + setEnabled(false); + } + } + + /* Helper method to validate the system-wide direct access url configuration settings */ + private void validateSystemDirectAccessUrlConfig() throws InvalidDirectAccessUrlConfigException + { + if (isEnabled()) + { + if (getDefaultExpiryTimeInSec() == null || getDefaultExpiryTimeInSec() < 1) + { + throw new InvalidDirectAccessUrlConfigException("System-wide direct access URL default expiry time is missing or invalid."); + } + + if (getMaxExpiryTimeInSec() == null || getMaxExpiryTimeInSec() < 1) + { + throw new InvalidDirectAccessUrlConfigException("System-wide direct access URL maximum expiry time is missing or invalid."); + } + + if (getDefaultExpiryTimeInSec() > getMaxExpiryTimeInSec()) + { + String errorMsg = String.format("System-wide direct access URL default expiry time [%s] exceeds maximum expiry time [%s].", + getDefaultExpiryTimeInSec(), getMaxExpiryTimeInSec()); + throw new InvalidDirectAccessUrlConfigException(errorMsg); + } + } + } +} diff --git a/repository/src/main/resources/alfresco/content-services-context.xml b/repository/src/main/resources/alfresco/content-services-context.xml index aed14cdd9e..ab02159381 100644 --- a/repository/src/main/resources/alfresco/content-services-context.xml +++ b/repository/src/main/resources/alfresco/content-services-context.xml @@ -1,359 +1,373 @@ - - - - - - - false - - - ContentStore - - - - ${filecontentstore.subsystem.name} - - - - manager - - - - - - - - true - - - ContentStore - - - unencrypted - - - - managed - unencrypted - - - - - - - - - - - fileContentStore - - - - org.alfresco.repo.content.ContentStore - org.alfresco.repo.content.ContentStoreCaps - - - - - - - - - - - - - - - - ${dir.contentstore.deleted} - - - - - - - - - - - - - - - - - - - - - - ${system.content.orphanProtectDays} - - - ${system.content.deletionFailureAction} - - - - - - - - - - - - - - - - - - - - - ${system.content.cleanerBatchSize} - - - - - - ${system.content.eagerOrphanCleanup} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${policy.content.update.ignoreEmpty} - - - - - - - - - - - - - - - - - - UTF-8 - - - - - - - - - - - - - - - - - - - - - - - classpath:alfresco/mimetype/mimetype-map.xml - classpath:alfresco/mimetype/mimetype-map-openoffice.xml - classpath*:alfresco/module/*/mimetype-map*.xml - classpath*:alfresco/extension/mimetype/*-map.xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - classpath:alfresco/ml/content-filter-lang.xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - EEE, d MMM yyyy HH:mm:ss Z - EEE, d MMM yy HH:mm:ss Z - d MMM yyyy HH:mm:ss Z - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - org.alfresco.repo.content.transform.TransformerConfigMBean - - - - - - - - - - - transformerDebugLog - - - - org.apache.commons.logging.Log - - - - - - - - - - - transformerLog - - - - org.apache.commons.logging.Log - - - - - - + + + + + + + false + + + ContentStore + + + + ${filecontentstore.subsystem.name} + + + + manager + + + + + + + + true + + + ContentStore + + + unencrypted + + + + managed + unencrypted + + + + + + + + + + + fileContentStore + + + + org.alfresco.repo.content.ContentStore + org.alfresco.repo.content.ContentStoreCaps + + + + + + + + + + + + + + + + ${dir.contentstore.deleted} + + + + + + + + + + + + + + + + + + + + + + ${system.content.orphanProtectDays} + + + ${system.content.deletionFailureAction} + + + + + + + + + + + + + + + + + + + + + ${system.content.cleanerBatchSize} + + + + + + ${system.content.eagerOrphanCleanup} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${policy.content.update.ignoreEmpty} + + + + + + + + + + + + + + + + + + UTF-8 + + + + + + + + + + + + + + + + + + + + + + + classpath:alfresco/mimetype/mimetype-map.xml + classpath:alfresco/mimetype/mimetype-map-openoffice.xml + classpath*:alfresco/module/*/mimetype-map*.xml + classpath*:alfresco/extension/mimetype/*-map.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + classpath:alfresco/ml/content-filter-lang.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + EEE, d MMM yyyy HH:mm:ss Z + EEE, d MMM yy HH:mm:ss Z + d MMM yyyy HH:mm:ss Z + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.alfresco.repo.content.transform.TransformerConfigMBean + + + + + + + + + + + transformerDebugLog + + + + org.apache.commons.logging.Log + + + + + + + + + + + transformerLog + + + + org.apache.commons.logging.Log + + + + + + + + + + + + + + + + + + + + diff --git a/repository/src/main/resources/alfresco/repository.properties b/repository/src/main/resources/alfresco/repository.properties index ef6bade8a1..4979b06b90 100644 --- a/repository/src/main/resources/alfresco/repository.properties +++ b/repository/src/main/resources/alfresco/repository.properties @@ -1,1247 +1,1310 @@ -# Repository configuration - -repository.name=Main Repository - -# Schema number -version.schema=15001 - -# Directory configuration - -dir.root=./alf_data - -dir.contentstore=${dir.root}/contentstore -dir.contentstore.deleted=${dir.root}/contentstore.deleted -dir.contentstore.bucketsPerMinute=0 - -# ContentStore subsystem: default choice -filecontentstore.subsystem.name=unencryptedContentStore - -# The location of cached content -dir.cachedcontent=${dir.root}/cachedcontent - -# The value for the maximum permitted size in bytes of all content. -# No value (or a negative long) will be taken to mean that no limit should be applied. -# See content-services-context.xml -system.content.maximumFileSizeLimit= - -# -# The server mode. Set value in alfresco-global.properties -# UNKNOWN | TEST | BACKUP | PRODUCTION -# -system.serverMode=UNKNOWN - -# The location for lucene index files -dir.indexes=${dir.root}/lucene-indexes - -# The location for index backups -dir.indexes.backup=${dir.root}/backup-lucene-indexes - -# The location for lucene index locks -dir.indexes.lock=${dir.indexes}/locks - -#Directory to find external license -dir.license.external=. -# Spring resource location of external license files -location.license.external=file://${dir.license.external}/*.lic -# Spring resource location of embedded license files -location.license.embedded=/WEB-INF/alfresco/license/*.lic -# Spring resource location of license files on shared classpath -location.license.shared=classpath*:/alfresco/extension/license/*.lic - -# WebDAV initialization properties -system.webdav.servlet.enabled=true -system.webdav.url.path.prefix= -system.webdav.storeName=${protocols.storeName} -system.webdav.rootPath=${protocols.rootPath} -# File name patterns that trigger rename shuffle detection -# pattern is used by move - tested against full path after it has been lower cased. -system.webdav.renameShufflePattern=(.*/\\..*)|(.*[a-f0-9]{8}+$)|(.*\\.tmp$)|(.*atmp[0-9]+$)|(.*\\.wbk$)|(.*\\.bak$)|(.*\\~$)|(.*backup.*\\.do[ct]{1}[x]?[m]?$)|(.*\\.sb\\-\\w{8}\\-\\w{6}$) -system.webdav.activities.enabled=false - - -system.workflow.jbpm.comment.property.max.length=-1 -system.workflow.comment.property.max.length=4000 - -#Determines if Activiti definitions are visible -system.workflow.engine.activiti.definitions.visible=true - - -# Determines if the Activiti engine is enabled -system.workflow.engine.activiti.enabled=true -system.workflow.engine.activiti.idblocksize=100 -system.workflow.engine.activiti.taskvariableslimit=20000 - -# Determines if the workflows that are deployed to the activiti engine should -# be deployed in the tenant-context of the thread IF the tenant-service is enabled -# If set to false, all workflows deployed will be shared among tenants. Recommended -# setting is true unless there is a good reason to not allow deploy tenant-specific -# worklfows when a MT-environment is set up. -system.workflow.deployWorkflowsInTenant=true -#Determines if historic process instance are retained in case of canceling a process instance -system.workflow.engine.activiti.retentionHistoricProcessInstance=false - -# The maximum number of groups to check for pooled tasks. For performance -# reasons, this is limited to 500 by default. -system.workflow.maxAuthoritiesForPooledTasks=500 - -# The maximum number of pooled tasks to return in a query. It may be necessary -# to limit this depending on UI limitations. -system.workflow.maxPooledTasks=-1 - -# The maximum number of reviewers for "Group Review and Approve" workflow. -# Use '0' for unlimited. -system.workflow.maxGroupReviewers=0 - -index.subsystem.name=noindex - -# ######################################### # -# Index Tracking Configuration # -# ######################################### # -# -# Index tracking information of a certain age is cleaned out by a scheduled job. -# Any clustered system that has been offline for longer than this period will need to be seeded -# with a more recent backup of the Lucene indexes or the indexes will have to be fully rebuilt. -# Use -1 to disable purging. This can be switched on at any stage. -index.tracking.minRecordPurgeAgeDays=30 -# Unused transactions will be purged in chunks determined by commit time boundaries. 'index.tracking.purgeSize' specifies the size -# of the chunk (in ms). Default is a couple of hours. -index.tracking.purgeSize=7200000 - -# Change the failure behaviour of the configuration checker -system.bootstrap.config_check.strict=true - - -# -# How long should shutdown wait to complete normally before -# taking stronger action and calling System.exit() -# in ms, 10,000 is 10 seconds -# -shutdown.backstop.timeout=10000 -shutdown.backstop.enabled=false - -# Server Single User Mode -# note: -# only allow named user (note: if blank or not set then will allow all users) -# assuming maxusers is not set to 0 -#server.singleuseronly.name=admin - -# Server Max Users - limit number of users with non-expired tickets -# note: -# -1 allows any number of users, assuming not in single-user mode -# 0 prevents further logins, including the ability to enter single-user mode -server.maxusers=-1 - -# -# Disable all shared caches (mutable and immutable) -# These properties are used for diagnostic purposes -system.cache.disableMutableSharedCaches=false -system.cache.disableImmutableSharedCaches=false - -# The maximum capacity of the parent assocs cache (the number of nodes whose parents can be cached) -system.cache.parentAssocs.maxSize=130000 - -# The average number of parents expected per cache entry. This parameter is multiplied by the above -# value to compute a limit on the total number of cached parents, which will be proportional to the -# cache's memory usage. The cache will be pruned when this limit is exceeded to avoid excessive -# memory usage. -system.cache.parentAssocs.limitFactor=8 - -# -# Properties to limit resources spent on individual searches -# -# The maximum time spent pruning results -system.acl.maxPermissionCheckTimeMillis=10000 -# The maximum number of search results to perform permission checks against -system.acl.maxPermissionChecks=1000 -system.acl.maxPermissionCheckEnabled=false - -# The maximum number of filefolder list results -system.filefolderservice.defaultListMaxResults=5000 -# DEPRECATED: Use 'system.auditableData.preserve' -system.preserve.modificationData=false -# The default to preserve all cm:auditable data on a node when the process is not directly driven by a user action -system.auditableData.preserve=${system.preserve.modificationData} -# Specific control of how the FileFolderService treats cm:auditable data when performing moves -system.auditableData.FileFolderService=${system.auditableData.preserve} -# Specific control of whether ACL changes on a node trigger the cm:auditable aspect -system.auditableData.ACLs=${system.auditableData.preserve} - -# Properties to control read permission evaluation for acegi -system.readpermissions.optimise=true -system.readpermissions.bulkfetchsize=1000 - -# -# Manually control how the system handles maximum string lengths. -# Any zero or negative value is ignored. -# Only change this after consulting support or reading the appropriate Javadocs for -# org.alfresco.repo.domain.schema.SchemaBootstrap for V2.1.2. -# Before database migration, the string value storage may need to be adjusted using the scheduled job -system.maximumStringLength=-1 -system.maximumStringLength.jobCronExpression=* * * * * ? 2099 -system.maximumStringLength.jobQueryRange=10000 -system.maximumStringLength.jobThreadCount=4 - -# -# Limit hibernate session size by trying to amalgamate events for the L2 session invalidation -# - hibernate works as is up to this size -# - after the limit is hit events that can be grouped invalidate the L2 cache by type and not instance -# events may not group if there are post action listener registered (this is not the case with the default distribution) -system.hibernateMaxExecutions=20000 - -# -# Determine if modification timestamp propagation from child to parent nodes is respected or not. -# Even if 'true', the functionality is only supported for child associations that declare the -# 'propagateTimestamps' element in the dictionary definition. -system.enableTimestampPropagation=true - -# -# Enable system model integrity checking. -# WARNING: Changing this is unsupported; bugs may corrupt data -system.integrity.enabled=true -# Do integrity violations fail transactions -# WARNING: Changing this is unsupported; bugs may corrupt data -system.integrity.failOnViolation=true -# The number of errors to report when violations are detected -system.integrity.maxErrorsPerTransaction=5 -# Add call stacks to integrity events so that errors are logged with possible causes -# WARNING: This is expensive and should only be switched on for diagnostic purposes -system.integrity.trace=false - -# -# Decide if content should be removed from the system immediately after being orphaned. -# Do not change this unless you have examined the impact it has on your backup procedures. -system.content.eagerOrphanCleanup=false -# The number of days to keep orphaned content in the content stores. -# This has no effect on the 'deleted' content stores, which are not automatically emptied. -system.content.orphanProtectDays=14 -# The action to take when a store or stores fails to delete orphaned content -# IGNORE: Just log a warning. The binary remains and the record is expunged -# KEEP_URL: Log a warning and create a URL entry with orphan time 0. It won't be processed or removed. -system.content.deletionFailureAction=IGNORE -# The CRON expression to trigger the deletion of resources associated with orphaned content. -system.content.orphanCleanup.cronExpression=0 0 4 * * ? -# The batch size user by the content store cleaner -system.content.cleanerBatchSize=1000 - -# The CRON expression to trigger the cleanup of deleted nodes and dangling transactions that are old enough -system.nodeServiceCleanup.cronExpression=0 0 21 * * ? - -# When transforming archive files (.zip etc) into text representations (such as -# for full text indexing), should the files within the archive be processed too? -# If enabled, transformation takes longer, but searches of the files find more. -transformer.Archive.includeContents=false - -# Database configuration -db.schema.name= -db.schema.stopAfterSchemaBootstrap=false -db.schema.update=true -db.schema.update.lockRetryCount=24 -db.schema.update.lockRetryWaitSeconds=5 -db.driver=org.gjt.mm.mysql.Driver -db.name=alfresco -db.url=jdbc:mysql:///${db.name} -db.username=alfresco -db.password=alfresco -db.pool.initial=10 -db.pool.max=275 -db.txn.isolation=-1 -db.pool.statements.enable=true -db.pool.statements.max=40 -db.pool.min=10 -db.pool.idle=10 -db.pool.wait.max=5000 - -db.pool.validate.query= -db.pool.evict.interval=600000 -db.pool.evict.idle.min=1800000 -# -# note: for 'db.pool.evict.num.tests' see http://commons.apache.org/dbcp/configuration.html (numTestsPerEvictionRun) -# and also following extract from "org.apache.commons.pool.impl.GenericKeyedObjectPool" (1.5.5) -# -# * The number of objects to examine during each run of the idle object evictor thread (if any). -# * When a negative value is supplied, ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun}) -# * tests will be run. I.e., when the value is -n, roughly one nth of the -# * idle objects will be tested per run. -# -db.pool.evict.num.tests=-1 - -db.pool.evict.validate=false -db.pool.validate.borrow=true -db.pool.validate.return=false - -db.pool.abandoned.detect=false -db.pool.abandoned.time=300 -# -# db.pool.abandoned.log=true (logAbandoned) adds overhead (http://commons.apache.org/dbcp/configuration.html) -# and also requires db.pool.abandoned.detect=true (removeAbandoned) -# -db.pool.abandoned.log=false - - -# Audit configuration -audit.enabled=true -audit.tagging.enabled=true -audit.alfresco-access.enabled=false -audit.alfresco-access.sub-actions.enabled=false -audit.cmischangelog.enabled=false -audit.dod5015.enabled=false -# Setting this flag to true will force startup failure when invalid audit configurations are detected -audit.config.strict=false -# Audit map filter for AccessAuditor - restricts recorded events to user driven events -audit.filter.alfresco-access.default.enabled=false -audit.filter.alfresco-access.transaction.user=~System;~null;.* -audit.filter.alfresco-access.transaction.type=cm:folder;cm:content;st:site -audit.filter.alfresco-access.transaction.path=~/sys:archivedItem;~/ver:;.* - - -# System Configuration -system.store=system://system -system.descriptor.childname=sys:descriptor -system.descriptor.current.childname=sys:descriptor-current - -# User config -alfresco_user_store.store=user://alfrescoUserStore -alfresco_user_store.system_container.childname=sys:system -alfresco_user_store.user_container.childname=sys:people - -# note: default admin username - should not be changed after installation -alfresco_user_store.adminusername=admin - -# Initial password - editing this will not have any effect once the repository is installed -alfresco_user_store.adminpassword=209c6174da490caeb422f3fa5a7ae634 - -# note: default guest username - should not be changed after installation -alfresco_user_store.guestusername=guest - -# Used to move home folders to a new location -home_folder_provider_synchronizer.enabled=false -home_folder_provider_synchronizer.override_provider= -home_folder_provider_synchronizer.keep_empty_parents=false - -# Spaces Archive Configuration -spaces.archive.store=archive://SpacesStore - -# Spaces Configuration -spaces.store=workspace://SpacesStore -spaces.company_home.childname=app:company_home -spaces.guest_home.childname=app:guest_home -spaces.dictionary.childname=app:dictionary -spaces.templates.childname=app:space_templates -spaces.imap_attachments.childname=cm:Imap Attachments -spaces.imap_home.childname=cm:Imap Home -spaces.imapConfig.childname=app:imap_configs -spaces.imap_templates.childname=app:imap_templates -spaces.scheduled_actions.childname=cm:Scheduled Actions -spaces.emailActions.childname=app:email_actions -spaces.searchAction.childname=cm:search -spaces.templates.content.childname=app:content_templates -spaces.templates.email.childname=app:email_templates -spaces.templates.email.invite1.childname=app:invite_email_templates -spaces.templates.email.notify.childname=app:notify_email_templates -spaces.templates.email.following.childname=app:following -spaces.templates.rss.childname=app:rss_templates -spaces.savedsearches.childname=app:saved_searches -spaces.scripts.childname=app:scripts -spaces.content_forms.childname=app:forms -spaces.user_homes.childname=app:user_homes -spaces.user_homes.regex.key=userName -spaces.user_homes.regex.pattern= -spaces.user_homes.regex.group_order= -spaces.sites.childname=st:sites -spaces.templates.email.invite.childname=cm:invite -spaces.templates.email.activities.childname=cm:activities -spaces.rendition.rendering_actions.childname=app:rendering_actions -spaces.replication.replication_actions.childname=app:replication_actions -spaces.transfers.childname=app:transfers -spaces.transfer_groups.childname=app:transfer_groups -spaces.transfer_temp.childname=app:temp -spaces.inbound_transfer_records.childname=app:inbound_transfer_records -spaces.webscripts.childname=cm:webscripts -spaces.extension_webscripts.childname=cm:extensionwebscripts -spaces.models.childname=app:models -spaces.workflow.definitions.childname=app:workflow_defs -spaces.templates.email.workflowemailnotification.childname=cm:workflownotification -spaces.nodetemplates.childname=app:node_templates -spaces.shared.childname=app:shared -spaces.solr_facets.root.childname=srft:facets -spaces.smartfolders.childname=app:smart_folders -spaces.smartdownloads.childname=app:smart_downloads -spaces.transfer_summary_report.location=/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}/${spaces.inbound_transfer_records.childname} -spaces.quickshare.link_expiry_actions.childname=app:quick_share_link_expiry_actions - - -# ADM VersionStore Configuration -version.store.initialVersion=true -version.store.enableAutoVersioning=true -version.store.enableAutoVersionOnUpdateProps=false -version.store.deprecated.lightWeightVersionStore=workspace://lightWeightVersionStore -version.store.version2Store=workspace://version2Store - -# Optional Comparator class name to sort versions. -# Set to: org.alfresco.repo.version.common.VersionLabelComparator -# if upgrading from a version that used unordered sequences in a cluster. -version.store.versionComparatorClass= - -# Folders for storing people -system.system_container.childname=sys:system -system.people_container.childname=sys:people -system.authorities_container.childname=sys:authorities -system.zones_container.childname=sys:zones - -# Folders for storing workflow related info -system.workflow_container.childname=sys:workflow - -# Folder for storing shared remote credentials -system.remote_credentials_container.childname=sys:remote_credentials - -# Folder for storing syncset definitions -system.syncset_definition_container.childname=sys:syncset_definitions - -# Folder for storing download archives -system.downloads_container.childname=sys:downloads - -# Folder for storing IdP's certificate definitions -system.certificate_container.childname=sys:samlcertificate - -# Are user names case sensitive? -user.name.caseSensitive=false -domain.name.caseSensitive=false -domain.separator= - -#Format caption extracted from the XML Schema. -xforms.formatCaption=true - -# ECM content usages/quotas -system.usages.enabled=false -system.usages.clearBatchSize=0 -system.usages.updateBatchSize=50 - -# Repository endpoint - used by Activity Service -repo.remote.endpoint=/service - -# Some authentication mechanisms may need to create people -# in the repository on demand. This enables that feature. -# If disabled an error will be generated for missing -# people. If enabled then a person will be created and -# persisted. -create.missing.people=${server.transaction.allow-writes} - -# Create home folders (unless disabled, see next property) as people are created (true) or create them lazily (false) -home.folder.creation.eager=true -# Disable home folder creation - if true then home folders are not created (neither eagerly nor lazily) -home.folder.creation.disabled=false - -# Should we consider zero byte content to be the same as no content when firing -# content update policies? Prevents 'premature' firing of inbound content rules -# for some clients such as Mac OS X Finder -policy.content.update.ignoreEmpty=true - -# Default value of alfresco.rmi.services.host is 0.0.0.0 which means 'listen on all adapters'. -# This allows connections to JMX both remotely and locally. -# -alfresco.rmi.services.port=50500 -alfresco.rmi.services.external.host=localhost -alfresco.rmi.services.host=0.0.0.0 - -# If the RMI address is in-use, how many retries should be done before aborting -# Default value of alfresco.rmi.services.retries is 0 which means 'Don't retry if the address is in-use' -alfresco.rmi.services.retries=4 -# How long in milliseconds to wait after a failed server socket bind, before retrying -alfresco.rmi.services.retryInterval=250 - -# RMI service ports for the individual services. -# These eight services are available remotely. -# -# Assign individual ports for each service for best performance -# or run several services on the same port, you can even run everything on 50500 if -# running through a firewall. -# -# Specify 0 to use a random unused port. -# -monitor.rmi.service.port=50508 - -# -# enable or disable individual RMI services -# -monitor.rmi.service.enabled=false - - -# Should the Mbean server bind to an existing server. Set to true for most application servers. -# false for WebSphere clusters. -mbean.server.locateExistingServerIfPossible=true - -# Rendition Service 2 -renditionService2.enabled=true - -# Thumbnail Service -system.thumbnail.generate=true - -# when creating doc via CMIS - optionally configure set of renditions names to request async -cmis.create.doc.request.renditions.set= - -# Default thumbnail limits -# When creating thumbnails, only use the first pageLimit pages -system.thumbnail.definition.default.timeoutMs=-1 -system.thumbnail.definition.default.readLimitTimeMs=-1 -system.thumbnail.definition.default.maxSourceSizeKBytes=-1 -system.thumbnail.definition.default.readLimitKBytes=-1 -system.thumbnail.definition.default.pageLimit=-1 -system.thumbnail.definition.default.maxPages=-1 - -# Max mimetype sizes to create thumbnail icons -system.thumbnail.mimetype.maxSourceSizeKBytes.pdf=-1 -system.thumbnail.mimetype.maxSourceSizeKBytes.txt=-1 -system.thumbnail.mimetype.maxSourceSizeKBytes.docx=-1 -system.thumbnail.mimetype.maxSourceSizeKBytes.xlsx=-1 -system.thumbnail.mimetype.maxSourceSizeKBytes.pptx=-1 -system.thumbnail.mimetype.maxSourceSizeKBytes.odt=-1 -system.thumbnail.mimetype.maxSourceSizeKBytes.ods=-1 -system.thumbnail.mimetype.maxSourceSizeKBytes.odp=-1 - -# Configuration for handling of failing thumbnails. -# See NodeEligibleForRethumbnailingEvaluator's javadoc for details. -# -# Retry periods limit the frequency with which the repository will attempt to create Share thumbnails -# for content nodes which have previously failed in their thumbnail attempts. -# These periods are in seconds. -# -# 604800s = 60s * 60m * 24h * 7d = 1 week -system.thumbnail.retryPeriod=60 -system.thumbnail.retryCount=2 -system.thumbnail.quietPeriod=604800 -system.thumbnail.quietPeriodRetriesEnabled=true -system.thumbnail.redeployStaticDefsOnStartup=true - -content.metadata.async.extract.enabled=true -content.metadata.async.embed.enabled=true - -# The default timeout for metadata mapping extracters -content.metadataExtracter.default.timeoutMs=20000 - -# Local transformer urls to T-engines to service transform requests via http. Enabled by default. -localTransform.core-aio.url=http://localhost:8090/ - -# When a local transformer .url is set, this value indicates the amount of time to wait after a connection failure -# before retrying the connection to allow a docker container to (re)start. -localTransform.core-aio.startupRetryPeriodSeconds=60 - -# Property to enable upgrade from 2.1-A -V2.1-A.fixes.to.schema=0 -#V2.1-A.fixes.to.schema=82 - -# The default authentication chain -authentication.chain=alfrescoNtlm1:alfrescoNtlm - -# Do authentication tickets expire or live for ever? -authentication.ticket.ticketsExpire=true - -# If ticketsEpire is true then how they should expire? -# Valid values are: AFTER_INACTIVITY, AFTER_FIXED_TIME, DO_NOT_EXPIRE -# The default is AFTER_FIXED_TIME -authentication.ticket.expiryMode=AFTER_INACTIVITY - -# If authentication.ticket.ticketsExpire is true and -# authentication.ticket.expiryMode is AFTER_FIXED_TIME or AFTER_INACTIVITY, -# this controls the minimum period for which tickets are valid. -# The default is PT1H for one hour. -authentication.ticket.validDuration=PT1H - -# Use one ticket for all user sessions -# For the pre 4.2 behaviour of one ticket per session set this to false. -authentication.ticket.useSingleTicketPerUser=true - -authentication.alwaysAllowBasicAuthForAdminConsole.enabled=true -authentication.getRemoteUserTimeoutMilliseconds=10000 - -# FTP access -ftp.enabled=false - -# Default root path for protocols -protocols.storeName=${spaces.store} -protocols.rootPath=/${spaces.company_home.childname} - -# OpenCMIS -opencmis.connector.default.store=${spaces.store} -opencmis.connector.default.rootPath=/${spaces.company_home.childname} -opencmis.connector.default.typesDefaultMaxItems=500 -opencmis.connector.default.typesDefaultDepth=-1 -opencmis.connector.default.objectsDefaultMaxItems=10000 -opencmis.connector.default.objectsDefaultDepth=100 -opencmis.connector.default.contentChangesDefaultMaxItems=10000 -opencmis.connector.default.openHttpSession=false -opencmis.activities.enabled=true -opencmis.bulkUpdateProperties.maxItemsSize=1000 -opencmis.bulkUpdateProperties.batchSize=20 -opencmis.bulkUpdateProperties.workerThreads=2 -opencmis.maxContentSizeMB=4096 -opencmis.memoryThresholdKB=4096 - -# URL generation overrides - -# if true, the context path of OpenCMIS generated urls will be set to "opencmis.context.value", otherwise it will be taken from the request url -opencmis.context.override=false -opencmis.context.value= -# if true, the servlet path of OpenCMIS generated urls will be set to "opencmis.servletpath.value", otherwise it will be taken from the request url -opencmis.servletpath.override=false -opencmis.servletpath.value= -opencmis.server.override=false -opencmis.server.value= - -# IMAP -imap.server.enabled=false -imap.server.port=143 -imap.server.attachments.extraction.enabled=true - -# Default IMAP mount points -imap.config.home.store=${spaces.store} -imap.config.home.rootPath=/${spaces.company_home.childname} -imap.config.home.folderPath=${spaces.imap_home.childname} -imap.config.server.mountPoints=AlfrescoIMAP -imap.config.server.mountPoints.default.mountPointName=IMAP -imap.config.server.mountPoints.default.modeName=ARCHIVE -imap.config.server.mountPoints.default.store=${spaces.store} -imap.config.server.mountPoints.default.rootPath=${protocols.rootPath} -imap.config.server.mountPoints.value.AlfrescoIMAP.mountPointName=Alfresco IMAP -imap.config.server.mountPoints.value.AlfrescoIMAP.modeName=MIXED - -#Imap extraction settings -#imap.attachments.mode: -# SEPARATE -- All attachments for each email will be extracted to separate folder. -# COMMON -- All attachments for all emails will be extracted to one folder. -# SAME -- Attachments will be extracted to the same folder where email lies. -imap.attachments.mode=SEPARATE -imap.attachments.folder.store=${spaces.store} -imap.attachments.folder.rootPath=/${spaces.company_home.childname} -imap.attachments.folder.folderPath=${spaces.imap_attachments.childname} - -# Activities Feed - refer to subsystem - -# Feed max ID range to limit maximum number of entries -activities.feed.max.idRange=1000000 -# Feed max size (number of entries) -activities.feed.max.size=200 -# Feed max age (eg. 44640 mins => 31 days) -activities.feed.max.ageMins=44640 - -activities.feed.generator.jsonFormatOnly=true -activities.feed.fetchBatchSize=250 -activities.feedNotifier.batchSize=200 -activities.feedNotifier.numThreads=2 - -# Subsystem unit test values. Will not have any effect on production servers -subsystems.test.beanProp.default.longProperty=123456789123456789 -subsystems.test.beanProp.default.anotherStringProperty=Global Default -subsystems.test.beanProp=inst1,inst2,inst3 -subsystems.test.beanProp.value.inst2.boolProperty=true -subsystems.test.beanProp.value.inst3.anotherStringProperty=Global Instance Default -subsystems.test.simpleProp2=true -subsystems.test.simpleProp3=Global Default3 - -# Default Async Action Thread Pool -default.async.action.threadPriority=1 -default.async.action.corePoolSize=8 -default.async.action.maximumPoolSize=20 - -# Deployment Service -deployment.service.numberOfSendingThreads=5 -deployment.service.corePoolSize=2 -deployment.service.maximumPoolSize=3 -deployment.service.threadPriority=5 -# How long to wait in mS before refreshing a target lock - detects shutdown servers -deployment.service.targetLockRefreshTime=60000 -# How long to wait in mS from the last communication before deciding that deployment has failed, possibly -# the destination is no longer available? -deployment.service.targetLockTimeout=3600000 -# Deployment method used to deploy this Alfresco instance (DEFAULT, INSTALLER, DOCKER_COMPOSE, HELM_CHART, ANSIBLE, ZIP, QUICK_START) -deployment.method=DEFAULT - -#Invitation Service -# Should send emails as part of invitation process. -notification.email.siteinvite=true -# Moderated invite Activiti workflow -site.invite.moderated.workflowId=activiti$activitiInvitationModerated -# Add intneral users Activiti workflow (use activiti$activitiInvitationNominated to revert to requiring accept of invite for internal users) -site.invite.nominated.workflowId=activiti$activitiInvitationNominatedAddDirect -# Add external users Activiti workflow -site.invite.nominatedExternal.workflowId=activiti$activitiInvitationNominated - -# Replication Service -replication.enabled=false - -# Transfer Service -transferservice.receiver.enabled=false -transferservice.receiver.stagingDir=${java.io.tmpdir}/alfresco-transfer-staging -# -# How long to wait in mS before refreshing a transfer lock - detects shutdown servers -# Default 1 minute. -transferservice.receiver.lockRefreshTime=60000 -# -# How many times to attempt retry the transfer lock -transferservice.receiver.lockRetryCount=3 -# How long to wait, in mS, before retrying the transfer lock -transferservice.receiver.lockRetryWait=100 -# -# How long to wait, in mS, since the last contact with from the client before -# timing out a transfer. Needs to be long enough to cope with network delays and "thinking -# time" for both source and destination. Default 5 minutes. -transferservice.receiver.lockTimeOut=300000 - -# OrphanReaper -orphanReaper.lockRefreshTime=60000 -orphanReaper.lockTimeOut=3600000 - - -# security -security.anyDenyDenies=true -# Whether to post-process denies. Only applies to solr4+ when anyDenyDenies is true. -security.postProcessDenies=false - -# -# Encryption properties -# -# default keystores location -dir.keystore=classpath:alfresco/keystore - -# general encryption parameters -encryption.keySpec.class=org.alfresco.encryption.DESEDEKeyGenerator -encryption.keyAlgorithm=AES -encryption.cipherAlgorithm=AES/CBC/PKCS5Padding - -# secret key keystore configuration -encryption.keystore.location=${dir.keystore}/keystore -# configuration via metadata is deprecated -encryption.keystore.keyMetaData.location= -encryption.keystore.provider= -encryption.keystore.type=pkcs12 - -# backup secret key keystore configuration -encryption.keystore.backup.location=${dir.keystore}/backup-keystore -# configuration via metadata is deprecated -encryption.keystore.backup.keyMetaData.location= -encryption.keystore.backup.provider= -encryption.keystore.backup.type=pkcs12 - -# Should encryptable properties be re-encrypted with new encryption keys on botstrap? -encryption.bootstrap.reencrypt=false - -# mac/md5 encryption -encryption.mac.messageTimeout=30000 -encryption.mac.algorithm=HmacSHA1 - -# ssl encryption -encryption.ssl.keystore.location=${dir.keystore}/ssl.keystore -encryption.ssl.keystore.provider= -encryption.ssl.keystore.type=JCEKS -# configuration via metadata is deprecated -encryption.ssl.keystore.keyMetaData.location= -encryption.ssl.truststore.location=${dir.keystore}/ssl.truststore -encryption.ssl.truststore.provider= -encryption.ssl.truststore.type=JCEKS -# configuration via metadata is deprecated -encryption.ssl.truststore.keyMetaData.location= - -# Re-encryptor properties -encryption.reencryptor.chunkSize=100 -encryption.reencryptor.numThreads=2 - -# SOLR connection details (e.g. for JMX) -solr.host=localhost -solr.port=8983 -solr.port.ssl=8984 -solr.solrUser=solr -solr.solrPassword=solr -# none, https -solr.secureComms=https -solr.sharedSecret= -solr.sharedSecret.header=X-Alfresco-Search-Secret -solr.cmis.alternativeDictionary=DEFAULT_DICTIONARY - -solr.max.total.connections=40 -solr.max.host.connections=40 - -# Solr connection timeouts -# solr connect timeout in ms -solr.solrConnectTimeout=5000 - -# cron expression defining how often the Solr Admin client (used by JMX) pings Solr if it goes away -solr.solrPingCronExpression=0 0/5 * * * ? * - - -#Default SOLR store mappings mappings -solr.store.mappings=solrMappingAlfresco,solrMappingArchive -solr.store.mappings.value.solrMappingAlfresco.httpClientFactory=solrHttpClientFactory -solr.store.mappings.value.solrMappingAlfresco.baseUrl=/solr/alfresco -solr.store.mappings.value.solrMappingAlfresco.protocol=workspace -solr.store.mappings.value.solrMappingAlfresco.identifier=SpacesStore -solr.store.mappings.value.solrMappingArchive.httpClientFactory=solrHttpClientFactory -solr.store.mappings.value.solrMappingArchive.baseUrl=/solr/archive -solr.store.mappings.value.solrMappingArchive.protocol=archive -solr.store.mappings.value.solrMappingArchive.identifier=SpacesStore - -#Default SOLR 4 store mappings mappings -solr4.store.mappings=solrMappingAlfresco,solrMappingArchive -solr4.store.mappings.value.solrMappingAlfresco.httpClientFactory=solrHttpClientFactory -solr4.store.mappings.value.solrMappingAlfresco.baseUrl=/solr4/alfresco -solr4.store.mappings.value.solrMappingAlfresco.protocol=workspace -solr4.store.mappings.value.solrMappingAlfresco.identifier=SpacesStore -solr4.store.mappings.value.solrMappingArchive.httpClientFactory=solrHttpClientFactory -solr4.store.mappings.value.solrMappingArchive.baseUrl=/solr4/archive -solr4.store.mappings.value.solrMappingArchive.protocol=archive -solr4.store.mappings.value.solrMappingArchive.identifier=SpacesStore - -#Default SOLR 6 store mappings mappings -solr6.store.mappings=solrMappingAlfresco,solrMappingArchive,solrMappingHistory -solr6.store.mappings.value.solrMappingAlfresco.httpClientFactory=solrHttpClientFactory -solr6.store.mappings.value.solrMappingAlfresco.baseUrl=/solr/alfresco -solr6.store.mappings.value.solrMappingAlfresco.protocol=workspace -solr6.store.mappings.value.solrMappingAlfresco.identifier=SpacesStore -solr6.store.mappings.value.solrMappingArchive.httpClientFactory=solrHttpClientFactory -solr6.store.mappings.value.solrMappingArchive.baseUrl=/solr/archive -solr6.store.mappings.value.solrMappingArchive.protocol=archive -solr6.store.mappings.value.solrMappingArchive.identifier=SpacesStore -solr6.store.mappings.value.solrMappingHistory.httpClientFactory=solrHttpClientFactory -solr6.store.mappings.value.solrMappingHistory.baseUrl=/solr/history -solr6.store.mappings.value.solrMappingHistory.protocol=workspace -solr6.store.mappings.value.solrMappingHistory.identifier=history - -# -# URL Shortening Properties -# -urlshortening.bitly.username=brianalfresco -urlshortening.bitly.api.key=R_ca15c6c89e9b25ccd170bafd209a0d4f -urlshortening.bitly.url.length=20 - -# -# Bulk Filesystem Importer -# - -# The number of threads to employ in a batch import -bulkImport.batch.numThreads=4 - -# The size of a batch in a batch import i.e. the number of files to import in a -# transaction/thread -bulkImport.batch.batchSize=20 - - -# -# Caching Content Store -# -system.content.caching.cacheOnInbound=true -system.content.caching.maxDeleteWatchCount=1 -# Clean up every day at 3 am -system.content.caching.contentCleanup.cronExpression=0 0 3 * * ? -system.content.caching.minFileAgeMillis=60000 -system.content.caching.maxUsageMB=4096 -# maxFileSizeMB - 0 means no max file size. -system.content.caching.maxFileSizeMB=0 -# When the CachingContentStore is about to write a cache file but the disk usage is in excess of panicThresholdPct -# (default 90%) then the cache file is not written and the cleaner is started (if not already running) in a new thread. -system.content.caching.panicThresholdPct=90 -# When a cache file has been written that results in cleanThresholdPct (default 80%) of maxUsageBytes -# being exceeded then the cached content cleaner is invoked (if not already running) in a new thread. -system.content.caching.cleanThresholdPct=80 -# An aggressive cleaner is run till the targetUsagePct (default 70%) of maxUsageBytes is achieved -system.content.caching.targetUsagePct=70 -# Threshold in seconds indicating a minimal gap between normal cleanup starts -system.content.caching.normalCleanThresholdSec=0 - -mybatis.useLocalCaches=false - -fileFolderService.checkHidden.enabled=true - - -ticket.cleanup.cronExpression=0 0 * * * ? - -# -# Download Service Cleanup -# -download.cleaner.startDelayMilliseconds=3600000 -# 1 hour -download.cleaner.repeatIntervalMilliseconds=3600000 -download.cleaner.maxAgeMins=60 -# -1 or 0 for not using batches -download.cleaner.batchSize=1000 - -# you could set this to false for new installations greater then ACS 6.2 -# see MNT-20212 -download.cleaner.cleanAllSysDownloadFolders=true - -# -# Download Service Limits, in bytes -# -download.maxContentSize=2152852358 - -# Max size of view trashcan files -# -trashcan.MaxSize=1000 - -# -# Use bridge tables for caching authority evaluation. -# -authority.useBridgeTable=true - -# Limit the number of results from findAuthority query -authority.findAuthorityLimit=10000 - -# enable QuickShare - if false then the QuickShare-specific REST APIs will return 403 Forbidden -system.quickshare.enabled=true -system.quickshare.email.from.default=noreply@alfresco.com -# By default the difference between the quick share expiry date and the current time must be at least 1 day (24 hours). -# However, this can be changed to at least 1 hour or 1 minute for testing purposes. For example, -# setting the value to MINUTES, means the service will calculate the difference between NOW and the given expiry date -# in terms of minutes and checks for the difference to be greater than 1 minute. -# DAYS | HOURS | MINUTES -system.quickshare.expiry_date.enforce.minimum.period=DAYS - -# Oubound Mail -mail.service.corePoolSize=8 -mail.service.maximumPoolSize=20 - -nodes.bulkLoad.cachingThreshold=10 - -# Multi-Tenancy - -# if "dir.contentstore.tenants" is set then -# tenants are not co-mingled and all content roots will appear below this container (in sub-folder) -# and when creating a tenant the "contentRootPath" (root content store directory for a given tenant) will be ignored -dir.contentstore.tenants= - -# Gateway Authentication -# gateway authentication is disabled if empty host is specified -alfresco.authentication.gateway.host= -alfresco.authentication.gateway.protocol=https -alfresco.authentication.gateway.port=443 -alfresco.authentication.gateway.outboundHeaders=Authorization,key -alfresco.authentication.gateway.inboundHeaders=X-Alfresco-Authenticator-Key,X-Alfresco-Remote-User -alfresco.authentication.gateway.prefixUrl=/publicapi -alfresco.authentication.gateway.bufferSize=2048 -alfresco.authentication.gateway.connectTimeout=10000 -alfresco.authentication.gateway.readTimeout=120000 -alfresco.authentication.gateway.httpTcpNodelay=true -alfresco.authentication.gateway.httpConnectionStalecheck=true - -# webscripts config -webscripts.encryptTempFiles=false -webscripts.tempDirectoryName=Alfresco-WebScripts -# 4mb -webscripts.memoryThreshold=4194304 -# 4gb -webscripts.setMaxContentSize=5368709120 - -# Property to enable index upgrade for metadata query (MDQ) -# -# The indexes are not added unless this value is changed -# Adding each the supporting indexes may take several hours depending on the size of the database. -# The required indexes may be added in stages. -# See: classpath:alfresco/dbscripts/upgrade/4.2/${db.script.dialect}/metadata-query-indexes.sql -# See: classpath:alfresco/dbscripts/upgrade/5.1/${db.script.dialect}/metadata-query-indexes-2.sql -system.metadata-query-indexes.ignored=true -system.metadata-query-indexes-more.ignored=true - -# -# Do we defer running the shared folder patch? -# -system.patch.sharedFolder.deferred=false -# Default value is run new years day 2030 i.e. not run. -system.patch.sharedFolder.cronExpression=0 0 0 ? 1 1 2030 - -# -# Default values for deferring the running of the addUnmovableAspect patch -# -system.patch.addUnmovableAspect.deferred=false -system.patch.addUnmovableAspect.cronExpression=0 0 0 ? 1 1 2030 - -# Property to enable removal of all JBPM related data from the database -# -# The tables are not removed from the databasen unless explicitly requested by setting this property to false. -# See: classpath:alfresco/dbscripts/upgrade/5.2/${db.script.dialect}/remove-jbpm-tables-from-db.sql -system.remove-jbpm-tables-from-db.ignored=true - -# -# Use a canned query when requested to search for people if " [hint:useCQ]" is provided in search term -# -people.search.honor.hint.useCQ=true - -# Delays cron jobs after bootstrap to allow server to fully come up before jobs start -system.cronJob.startDelayMilliseconds=60000 - -# Schedule for reading mimetype config definitions dynamically. Initially checks every 10 seconds and then switches to -# every hour after the configuration is read successfully. If there is a error later reading the config, the -# checks return to every 10 seconds. -mimetype.config.cronExpression=0 30 0/1 * * ? -mimetype.config.initialAndOnError.cronExpression=0/10 * * * * ? - -# Optional property to specify an external file or directory that will be read for mimetype definitions from YAML -# files (possibly added to a volume via k8 ConfigMaps). -mimetype.config.dir=shared/classes/alfresco/extension/mimetypes - -# Schedule for reading rendition config definitions dynamically. Initially checks every 10 seconds and then switches to -# every hour after the configuration is read successfully. If there is a error later reading the config, the -# checks return to every 10 seconds. -rendition.config.cronExpression=2 30 0/1 * * ? -rendition.config.initialAndOnError.cronExpression=0/10 * * * * ? - -# Optional property to specify an external file or directory that will be read for rendition definitions from YAML -# files (possibly added to a volume via k8 ConfigMaps). -rendition.config.dir=shared/classes/alfresco/extension/transform/renditions - -# Optional property to specify an external file or directory that will be read for transformer json config. -local.transform.pipeline.config.dir=shared/classes/alfresco/extension/transform/pipelines - -# Used to disable transforms locally. -local.transform.service.enabled=true - -# Schedule for reading local transform config, so that T-Engines and local pipeline config is dynamically -# picked up, or reintegrated after an outage. Initially checks every 10 seconds and then switches to every hour -# after the configuration is read successfully. If there is a error later reading the config, the checks return to -# every 10 seconds. -local.transform.service.cronExpression=4 30 0/1 * * ? -local.transform.service.initialAndOnError.cronExpression=0/10 * * * * ? - -# -# Check that the declared mimetype (of the Node) is the same as the derived -# mimetype of the content (via Tika) before a transformation takes place. -# Only files in the repository (not intermediate files in a transformer -# pipeline) are checked. This property provides a trade off between a -# security check and a relatively expensive (Tika) operation. -# -# There are a few issues with the Tika mimetype detection. So that transformations -# still take place where the detected mimetype is not the same as the declared mimetype, -# another property (transformer.strict.mimetype.check.whitelist.mimetypes) contains pairs -# of declared and detected mimetypes that should be allowed. This parameter value is a -# sequence of ; separated pairs. The declared and derived mimetypes are also ; separated. -# -transformer.strict.mimetype.check=true - -# A white list of declared and detected mimetypes, that don't match, but should still be transformed. -transformer.strict.mimetype.check.whitelist.mimetypes=application/eps;application/postscript;application/illustrator;application/pdf;application/x-tar;application/x-gtar;application/acp;application/zip;application/vnd.stardivision.math;application/x-tika-msoffice - -# -# Enable transformation retrying if the file has MIME type differ than file extension. -# Ignored if transformer.strict.mimetype.check is true as these transformations -# will not take place. -# -content.transformer.retryOn.different.mimetype=true - -# Debug and Log buffer sizes -transformer.debug.entries=0 -transformer.log.entries=50 - -# -# Lock timeout configuration -# -system.lockTryTimeout=100 -system.lockTryTimeout.DictionaryDAOImpl=10000 -system.lockTryTimeout.MessageServiceImpl=${system.lockTryTimeout} -system.lockTryTimeout.PolicyComponentImpl=${system.lockTryTimeout} - - -# Scheduled job to clean up unused properties from the alf_prop_xxx tables. -# Default setting of "0 0 3 ? * SAT" is to run every Saturday at 3am. -attributes.propcleaner.cronExpression=0 0 3 ? * SAT - -# Control Alfresco JMX connectivity -alfresco.jmx.connector.enabled=false - -# Dissallow Attribute Service Entries with "Serializable" objects in key Segments -# Please, see MNT-11895 for details. -system.propval.uniquenessCheck.enabled=true - -# Requests for ephemeral (in-memory) locks with expiry times (in seconds) greater -# than this value will result in persistent locks being created instead. By default -# this value is equal to the maximum allowed expiry for ephemeral locks, therefore -# this feature is disabled by default. Setting this to -1 would mean that ALL -# requests for ephemeral locks would result in persistent locks being created. -alfresco.ephemeralLock.expiryThresh=172800 - -# SurfConfigFolder Patch -# -# Do we defer running the surf-config folder patch? -# -system.patch.surfConfigFolder.deferred=false -# Default value. i.e. never run. It can be triggered using JMX -system.patch.surfConfigFolder.cronExpression=* * * * * ? 2099 - -# -# Solr Facets Config Properties -# -solr_facets.root.path=/app:company_home/app:dictionary -solr_facets.root=${solr_facets.root.path}/${spaces.solr_facets.root.childname} -solr_facets.inheritanceHierarchy=default,custom - -models.enforceTenantInNamespace=false - -# Allowed protocols for links -links.protocosl.white.list=http,https,ftp,mailto - -# Fixed ACLs -# Required for fixing MNT-15368 - Time Consumed for Updating Folder Permission -# ADMAccessControlListDAO.setFixedAcls called on a large folder hierarchy will take a long time for its execution. -# For this reason now method can also be called asynchronously if transaction reaches system.fixedACLs.maxTransactionTime. -# In this case setFixedAcls method recursion will be stopped and unfinished nodes will be marked with ASPECT_PENDING_FIX_ACL. -# Pending nodes will be processed by FixedAclUpdater, programmatically called but also configured as a scheduled job. -system.fixedACLs.maxTransactionTime=10000 -# fixedACLsUpdater - lock time to live -system.fixedACLsUpdater.lockTTL=10000 -# fixedACLsUpdater - maximum number of nodes to process per execution -system.fixedACLsUpdater.maxItemBatchSize=100 -# fixedACLsUpdater - the number of threads to use -system.fixedACLsUpdater.numThreads=4 -# fixedACLsUpdater - Force shared ACL to propagate through children even if there is an unexpected ACL -system.fixedACLsUpdater.forceSharedACL=false -# fixedACLsUpdater cron expression - fire at midnight every day -system.fixedACLsUpdater.cronExpression=0 0 0 * * ? - -cmis.disable.hidden.leading.period.files=false - -#Smart Folders Config Properties -smart.folders.enabled=false - -#Smart reference config -smart.reference.classpath.hash=${smart.folders.config.vanilla.processor.classpath}->1,${smart.folders.config.system.templates.classpath}->2 - -#Smart store config - -#Company home relative download associations of smart entries -smart.download.associations.folder=${spaces.dictionary.childname}/${spaces.smartdownloads.childname} - -#Generic virtualization methods config - -#Vanilla JSON templates javascript processor classpath. A java script processor used to -#covert JSON templates to internal smart folder definitions. - -smart.folders.config.vanilla.processor.classpath=/org/alfresco/repo/virtual/node/vanilla.js - -#System virtualization method config - -#System virtualization method aspect. -smart.folders.config.system.aspect=smf:systemConfigSmartFolder -#System virtualization method aspect defined template location property. -smart.folders.config.system.aspect.template.location.property=smf:system-template-location -#Classpath to be explored for *.json entries defining system templates. -smart.folders.config.system.templates.classpath=/org/alfresco/repo/virtual/node -#A company home relative name or qname path location of repository system templates. -smart.folders.config.system.templates.path=${spaces.dictionary.childname}/${spaces.smartfolders.childname} -#Content sub type of repository system templates. -smart.folders.config.system.templates.template.type=smf:smartFolderTemplate - -#Custom virtualization method config - -#Custom virtualization method aspect. -smart.folders.config.custom.aspect=smf:customConfigSmartFolder -#Custom virtualization method aspect template content association. -smart.folders.config.custom.aspect.template.association=smf:custom-template-association - - -#Type virtualization method config - -#A company home relative name or qname path location of the type mapped templates. -smart.folders.config.type.templates.path=${spaces.dictionary.childname}/${spaces.smartfolders.childname} -#Type and aspect qname regular expression filter. -smart.folders.config.type.templates.qname.filter=none - -# Preferred password encoding, md4, sha256, bcrypt10 -system.preferred.password.encoding=md4 - -# Upgrade Password Hash Job -system.upgradePasswordHash.jobBatchSize=100 -system.upgradePasswordHash.jobQueryRange=10000 -system.upgradePasswordHash.jobThreadCount=4 -system.upgradePasswordHash.jobCronExpression=* * * * * ? 2099 - -system.api.discovery.enabled=true - -# Maximum query size for category/tag fetch when not explicitly set by paging parameters -category.queryFetchSize=5000 - -# Brute force protection -authentication.protection.enabled=true -authentication.protection.limit=10 -authentication.protection.periodSeconds=6 - -system.email.sender.default=noreply@alfresco.com -# reset password workflow will expire in an hour -system.reset-password.endTimer=PT1H -system.reset-password.sendEmailAsynchronously=true - -# HeartBeat -heartbeat.target.url= -heartbeat.enabled=true - -# CSRF filter overrides -csrf.filter.enabled=true -csrf.filter.referer= -csrf.filter.referer.always=false -csrf.filter.origin= -csrf.filter.origin.always=false - -# CORS settings -cors.enabled=false -cors.allowed.origins= -cors.allowed.methods=GET,POST,HEAD,OPTIONS,PUT,DELETE -cors.allowed.headers=Authorization,Content-Type,Cache-Control,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,X-CSRF-Token -cors.exposed.headers=Access-Control-Allow-Origin,Access-Control-Allow-Credentials -cors.support.credentials=true -cors.preflight.maxage=10 - -# Alfresco Rest Api-Explorer -api-explorer.url= - -# Events subsystem -events.subsystem.autoStart=false -# Messaging subsystem -messaging.subsystem.autoStart=true - - -# Raw events -acs.repo.rendition.events.endpoint=jms:acs-repo-rendition-events?jmsMessageType=Text - -# Transform request events -acs.repo.transform.request.endpoint=jms:acs-repo-transform-request?jmsMessageType=Text - -# If enabled doesn't allow to set content properties via NodeService -contentPropertyRestrictions.enabled=true -contentPropertyRestrictions.whitelist= - -# Repo events2 -# Type and aspect filters which should be excluded -# Note: System folders node types are added by default -repo.event2.filter.nodeTypes=sys:*, fm:*, cm:thumbnail, cm:failedThumbnail, cm:rating, rma:rmsite include_subtypes -repo.event2.filter.nodeAspects=sys:* -repo.event2.filter.childAssocTypes=rn:rendition -# Comma separated list of users which should be excluded -# Note: username's case-sensitivity depends on the {user.name.caseSensitive} setting -repo.event2.filter.users= -# Topic name -repo.event2.topic.endpoint=amqp:topic:alfresco.repo.event2 -# Thread pool for async enqueue of repo events -repo.event2.queue.enqueueThreadPool.priority=1 -repo.event2.queue.enqueueThreadPool.coreSize=8 -repo.event2.queue.enqueueThreadPool.maximumSize=10 -# Thread pool for async dequeue and delivery of repo events -repo.event2.queue.dequeueThreadPool.priority=1 -repo.event2.queue.dequeueThreadPool.coreSize=1 -repo.event2.queue.dequeueThreadPool.maximumSize=1 - - -# MNT-21083 -# --DELETE_NOT_EXISTS - default settings -system.delete_not_exists.batchsize=100000 -system.delete_not_exists.delete_batchsize=1000 -system.delete_not_exists.read_only=false -system.delete_not_exists.timeout_seconds=-1 -system.prop_table_cleaner.algorithm=V2 - -# Configure the expiration time of the direct access url. This is the length of time in seconds that the link is valid for. -# Note: It is up to the actual ContentStore implementation if it can fulfil this request or not. -alfresco.content.directAccessUrl.lifetimeInSec=300 - -# Creates additional indexes on alf_node and alf_transaction. Recommended for large repositories. -system.new-node-transaction-indexes.ignored=true - -# Allows the configuration of maximum limits of the temp files to be deleted or the maximum time allowed to run for the job -system.tempFileCleaner.maxFilesToDelete= -system.tempFileCleaner.maxTimeToRun= - -# Property to long running migration to remove alf_server in v7+ patch.db-V7.1.0-remove-alf_server-table -system.remove-alf_server-table-from-db.ignored=true +# Repository configuration + +repository.name=Main Repository + +# Schema number +version.schema=15001 + +# Directory configuration + +dir.root=./alf_data + +dir.contentstore=${dir.root}/contentstore +dir.contentstore.deleted=${dir.root}/contentstore.deleted +dir.contentstore.bucketsPerMinute=0 + +# ContentStore subsystem: default choice +filecontentstore.subsystem.name=unencryptedContentStore + +# The location of cached content +dir.cachedcontent=${dir.root}/cachedcontent + +# The value for the maximum permitted size in bytes of all content. +# No value (or a negative long) will be taken to mean that no limit should be applied. +# See content-services-context.xml +system.content.maximumFileSizeLimit= + +# +# The server mode. Set value in alfresco-global.properties +# UNKNOWN | TEST | BACKUP | PRODUCTION +# +system.serverMode=UNKNOWN + +# The location for lucene index files +dir.indexes=${dir.root}/lucene-indexes + +# The location for index backups +dir.indexes.backup=${dir.root}/backup-lucene-indexes + +# The location for lucene index locks +dir.indexes.lock=${dir.indexes}/locks + +#Directory to find external license +dir.license.external=. +# Spring resource location of external license files +location.license.external=file://${dir.license.external}/*.lic +# Spring resource location of embedded license files +location.license.embedded=/WEB-INF/alfresco/license/*.lic +# Spring resource location of license files on shared classpath +location.license.shared=classpath*:/alfresco/extension/license/*.lic + +# WebDAV initialization properties +system.webdav.servlet.enabled=true +system.webdav.url.path.prefix= +system.webdav.storeName=${protocols.storeName} +system.webdav.rootPath=${protocols.rootPath} +# File name patterns that trigger rename shuffle detection +# pattern is used by move - tested against full path after it has been lower cased. +system.webdav.renameShufflePattern=(.*/\\..*)|(.*[a-f0-9]{8}+$)|(.*\\.tmp$)|(.*atmp[0-9]+$)|(.*\\.wbk$)|(.*\\.bak$)|(.*\\~$)|(.*backup.*\\.do[ct]{1}[x]?[m]?$)|(.*\\.sb\\-\\w{8}\\-\\w{6}$) +system.webdav.activities.enabled=false + + +system.workflow.jbpm.comment.property.max.length=-1 +system.workflow.comment.property.max.length=4000 + +#Determines if Activiti definitions are visible +system.workflow.engine.activiti.definitions.visible=true + + +# Determines if the Activiti engine is enabled +system.workflow.engine.activiti.enabled=true +system.workflow.engine.activiti.idblocksize=100 +system.workflow.engine.activiti.taskvariableslimit=20000 + +# Determines if the workflows that are deployed to the activiti engine should +# be deployed in the tenant-context of the thread IF the tenant-service is enabled +# If set to false, all workflows deployed will be shared among tenants. Recommended +# setting is true unless there is a good reason to not allow deploy tenant-specific +# worklfows when a MT-environment is set up. +system.workflow.deployWorkflowsInTenant=true +#Determines if historic process instance are retained in case of canceling a process instance +system.workflow.engine.activiti.retentionHistoricProcessInstance=false + +# The maximum number of groups to check for pooled tasks. For performance +# reasons, this is limited to 500 by default. +system.workflow.maxAuthoritiesForPooledTasks=500 + +# The maximum number of pooled tasks to return in a query. It may be necessary +# to limit this depending on UI limitations. +system.workflow.maxPooledTasks=-1 + +# The maximum number of reviewers for "Group Review and Approve" workflow. +# Use '0' for unlimited. +system.workflow.maxGroupReviewers=0 + +index.subsystem.name=noindex + +# ######################################### # +# Index Tracking Configuration # +# ######################################### # +# +# Index tracking information of a certain age is cleaned out by a scheduled job. +# Any clustered system that has been offline for longer than this period will need to be seeded +# with a more recent backup of the Lucene indexes or the indexes will have to be fully rebuilt. +# Use -1 to disable purging. This can be switched on at any stage. +index.tracking.minRecordPurgeAgeDays=30 +# Unused transactions will be purged in chunks determined by commit time boundaries. 'index.tracking.purgeSize' specifies the size +# of the chunk (in ms). Default is a couple of hours. +index.tracking.purgeSize=7200000 + +# Change the failure behaviour of the configuration checker +system.bootstrap.config_check.strict=true + + +# +# How long should shutdown wait to complete normally before +# taking stronger action and calling System.exit() +# in ms, 10,000 is 10 seconds +# +shutdown.backstop.timeout=10000 +shutdown.backstop.enabled=false + +# Server Single User Mode +# note: +# only allow named user (note: if blank or not set then will allow all users) +# assuming maxusers is not set to 0 +#server.singleuseronly.name=admin + +# Server Max Users - limit number of users with non-expired tickets +# note: +# -1 allows any number of users, assuming not in single-user mode +# 0 prevents further logins, including the ability to enter single-user mode +server.maxusers=-1 + +# +# Disable all shared caches (mutable and immutable) +# These properties are used for diagnostic purposes +system.cache.disableMutableSharedCaches=false +system.cache.disableImmutableSharedCaches=false + +# The maximum capacity of the parent assocs cache (the number of nodes whose parents can be cached) +system.cache.parentAssocs.maxSize=130000 + +# The average number of parents expected per cache entry. This parameter is multiplied by the above +# value to compute a limit on the total number of cached parents, which will be proportional to the +# cache's memory usage. The cache will be pruned when this limit is exceeded to avoid excessive +# memory usage. +system.cache.parentAssocs.limitFactor=8 + +# +# Properties to limit resources spent on individual searches +# +# The maximum time spent pruning results +system.acl.maxPermissionCheckTimeMillis=10000 +# The maximum number of search results to perform permission checks against +system.acl.maxPermissionChecks=1000 +system.acl.maxPermissionCheckEnabled=false + +# The maximum number of filefolder list results +system.filefolderservice.defaultListMaxResults=5000 +# DEPRECATED: Use 'system.auditableData.preserve' +system.preserve.modificationData=false +# The default to preserve all cm:auditable data on a node when the process is not directly driven by a user action +system.auditableData.preserve=${system.preserve.modificationData} +# Specific control of how the FileFolderService treats cm:auditable data when performing moves +system.auditableData.FileFolderService=${system.auditableData.preserve} +# Specific control of whether ACL changes on a node trigger the cm:auditable aspect +system.auditableData.ACLs=${system.auditableData.preserve} + +# Properties to control read permission evaluation for acegi +system.readpermissions.optimise=true +system.readpermissions.bulkfetchsize=1000 + +# +# Manually control how the system handles maximum string lengths. +# Any zero or negative value is ignored. +# Only change this after consulting support or reading the appropriate Javadocs for +# org.alfresco.repo.domain.schema.SchemaBootstrap for V2.1.2. +# Before database migration, the string value storage may need to be adjusted using the scheduled job +system.maximumStringLength=-1 +system.maximumStringLength.jobCronExpression=* * * * * ? 2099 +system.maximumStringLength.jobQueryRange=10000 +system.maximumStringLength.jobThreadCount=4 + +# +# Limit hibernate session size by trying to amalgamate events for the L2 session invalidation +# - hibernate works as is up to this size +# - after the limit is hit events that can be grouped invalidate the L2 cache by type and not instance +# events may not group if there are post action listener registered (this is not the case with the default distribution) +system.hibernateMaxExecutions=20000 + +# +# Determine if modification timestamp propagation from child to parent nodes is respected or not. +# Even if 'true', the functionality is only supported for child associations that declare the +# 'propagateTimestamps' element in the dictionary definition. +system.enableTimestampPropagation=true + +# +# Enable system model integrity checking. +# WARNING: Changing this is unsupported; bugs may corrupt data +system.integrity.enabled=true +# Do integrity violations fail transactions +# WARNING: Changing this is unsupported; bugs may corrupt data +system.integrity.failOnViolation=true +# The number of errors to report when violations are detected +system.integrity.maxErrorsPerTransaction=5 +# Add call stacks to integrity events so that errors are logged with possible causes +# WARNING: This is expensive and should only be switched on for diagnostic purposes +system.integrity.trace=false + +# +# Decide if content should be removed from the system immediately after being orphaned. +# Do not change this unless you have examined the impact it has on your backup procedures. +system.content.eagerOrphanCleanup=false +# The number of days to keep orphaned content in the content stores. +# This has no effect on the 'deleted' content stores, which are not automatically emptied. +system.content.orphanProtectDays=14 +# The action to take when a store or stores fails to delete orphaned content +# IGNORE: Just log a warning. The binary remains and the record is expunged +# KEEP_URL: Log a warning and create a URL entry with orphan time 0. It won't be processed or removed. +system.content.deletionFailureAction=IGNORE +# The CRON expression to trigger the deletion of resources associated with orphaned content. +system.content.orphanCleanup.cronExpression=0 0 4 * * ? +# The batch size user by the content store cleaner +system.content.cleanerBatchSize=1000 + +# The CRON expression to trigger the cleanup of deleted nodes and dangling transactions that are old enough +system.nodeServiceCleanup.cronExpression=0 0 21 * * ? + +# When transforming archive files (.zip etc) into text representations (such as +# for full text indexing), should the files within the archive be processed too? +# If enabled, transformation takes longer, but searches of the files find more. +transformer.Archive.includeContents=false + +# Database configuration +db.schema.name= +db.schema.stopAfterSchemaBootstrap=false +db.schema.update=true +db.schema.update.lockRetryCount=24 +db.schema.update.lockRetryWaitSeconds=5 +db.driver=org.gjt.mm.mysql.Driver +db.name=alfresco +db.url=jdbc:mysql:///${db.name} +db.username=alfresco +db.password=alfresco +db.pool.initial=10 +db.pool.max=275 +db.txn.isolation=-1 +db.pool.statements.enable=true +db.pool.statements.max=40 +db.pool.min=10 +db.pool.idle=10 +db.pool.wait.max=5000 + +db.pool.validate.query= +db.pool.evict.interval=600000 +db.pool.evict.idle.min=1800000 +# +# note: for 'db.pool.evict.num.tests' see http://commons.apache.org/dbcp/configuration.html (numTestsPerEvictionRun) +# and also following extract from "org.apache.commons.pool.impl.GenericKeyedObjectPool" (1.5.5) +# +# * The number of objects to examine during each run of the idle object evictor thread (if any). +# * When a negative value is supplied, ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun}) +# * tests will be run. I.e., when the value is -n, roughly one nth of the +# * idle objects will be tested per run. +# +db.pool.evict.num.tests=-1 + +db.pool.evict.validate=false +db.pool.validate.borrow=true +db.pool.validate.return=false + +db.pool.abandoned.detect=false +db.pool.abandoned.time=300 +# +# db.pool.abandoned.log=true (logAbandoned) adds overhead (http://commons.apache.org/dbcp/configuration.html) +# and also requires db.pool.abandoned.detect=true (removeAbandoned) +# +db.pool.abandoned.log=false + + +# Audit configuration +audit.enabled=true +audit.tagging.enabled=true +audit.alfresco-access.enabled=false +audit.alfresco-access.sub-actions.enabled=false +audit.cmischangelog.enabled=false +audit.dod5015.enabled=false +# Setting this flag to true will force startup failure when invalid audit configurations are detected +audit.config.strict=false +# Audit map filter for AccessAuditor - restricts recorded events to user driven events +audit.filter.alfresco-access.default.enabled=false +audit.filter.alfresco-access.transaction.user=~System;~null;.* +audit.filter.alfresco-access.transaction.type=cm:folder;cm:content;st:site +audit.filter.alfresco-access.transaction.path=~/sys:archivedItem;~/ver:;.* + + +# System Configuration +system.store=system://system +system.descriptor.childname=sys:descriptor +system.descriptor.current.childname=sys:descriptor-current + +# User config +alfresco_user_store.store=user://alfrescoUserStore +alfresco_user_store.system_container.childname=sys:system +alfresco_user_store.user_container.childname=sys:people + +# note: default admin username - should not be changed after installation +alfresco_user_store.adminusername=admin + +# Initial password - editing this will not have any effect once the repository is installed +alfresco_user_store.adminpassword=209c6174da490caeb422f3fa5a7ae634 + +# note: default guest username - should not be changed after installation +alfresco_user_store.guestusername=guest + +# Used to move home folders to a new location +home_folder_provider_synchronizer.enabled=false +home_folder_provider_synchronizer.override_provider= +home_folder_provider_synchronizer.keep_empty_parents=false + +# Spaces Archive Configuration +spaces.archive.store=archive://SpacesStore + +# Spaces Configuration +spaces.store=workspace://SpacesStore +spaces.company_home.childname=app:company_home +spaces.guest_home.childname=app:guest_home +spaces.dictionary.childname=app:dictionary +spaces.templates.childname=app:space_templates +spaces.imap_attachments.childname=cm:Imap Attachments +spaces.imap_home.childname=cm:Imap Home +spaces.imapConfig.childname=app:imap_configs +spaces.imap_templates.childname=app:imap_templates +spaces.scheduled_actions.childname=cm:Scheduled Actions +spaces.emailActions.childname=app:email_actions +spaces.searchAction.childname=cm:search +spaces.templates.content.childname=app:content_templates +spaces.templates.email.childname=app:email_templates +spaces.templates.email.invite1.childname=app:invite_email_templates +spaces.templates.email.notify.childname=app:notify_email_templates +spaces.templates.email.following.childname=app:following +spaces.templates.rss.childname=app:rss_templates +spaces.savedsearches.childname=app:saved_searches +spaces.scripts.childname=app:scripts +spaces.content_forms.childname=app:forms +spaces.user_homes.childname=app:user_homes +spaces.user_homes.regex.key=userName +spaces.user_homes.regex.pattern= +spaces.user_homes.regex.group_order= +spaces.sites.childname=st:sites +spaces.templates.email.invite.childname=cm:invite +spaces.templates.email.activities.childname=cm:activities +spaces.rendition.rendering_actions.childname=app:rendering_actions +spaces.replication.replication_actions.childname=app:replication_actions +spaces.transfers.childname=app:transfers +spaces.transfer_groups.childname=app:transfer_groups +spaces.transfer_temp.childname=app:temp +spaces.inbound_transfer_records.childname=app:inbound_transfer_records +spaces.webscripts.childname=cm:webscripts +spaces.extension_webscripts.childname=cm:extensionwebscripts +spaces.models.childname=app:models +spaces.workflow.definitions.childname=app:workflow_defs +spaces.templates.email.workflowemailnotification.childname=cm:workflownotification +spaces.nodetemplates.childname=app:node_templates +spaces.shared.childname=app:shared +spaces.solr_facets.root.childname=srft:facets +spaces.smartfolders.childname=app:smart_folders +spaces.smartdownloads.childname=app:smart_downloads +spaces.transfer_summary_report.location=/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}/${spaces.inbound_transfer_records.childname} +spaces.quickshare.link_expiry_actions.childname=app:quick_share_link_expiry_actions + + +# ADM VersionStore Configuration +version.store.initialVersion=true +version.store.enableAutoVersioning=true +version.store.enableAutoVersionOnUpdateProps=false +version.store.deprecated.lightWeightVersionStore=workspace://lightWeightVersionStore +version.store.version2Store=workspace://version2Store + +# Optional Comparator class name to sort versions. +# Set to: org.alfresco.repo.version.common.VersionLabelComparator +# if upgrading from a version that used unordered sequences in a cluster. +version.store.versionComparatorClass= + +# Folders for storing people +system.system_container.childname=sys:system +system.people_container.childname=sys:people +system.authorities_container.childname=sys:authorities +system.zones_container.childname=sys:zones + +# Folders for storing workflow related info +system.workflow_container.childname=sys:workflow + +# Folder for storing shared remote credentials +system.remote_credentials_container.childname=sys:remote_credentials + +# Folder for storing syncset definitions +system.syncset_definition_container.childname=sys:syncset_definitions + +# Folder for storing download archives +system.downloads_container.childname=sys:downloads + +# Folder for storing IdP's certificate definitions +system.certificate_container.childname=sys:samlcertificate + +# Are user names case sensitive? +user.name.caseSensitive=false +domain.name.caseSensitive=false +domain.separator= + +#Format caption extracted from the XML Schema. +xforms.formatCaption=true + +# ECM content usages/quotas +system.usages.enabled=false +system.usages.clearBatchSize=0 +system.usages.updateBatchSize=50 + +# Repository endpoint - used by Activity Service +repo.remote.endpoint=/service + +# Some authentication mechanisms may need to create people +# in the repository on demand. This enables that feature. +# If disabled an error will be generated for missing +# people. If enabled then a person will be created and +# persisted. +create.missing.people=${server.transaction.allow-writes} + +# Create home folders (unless disabled, see next property) as people are created (true) or create them lazily (false) +home.folder.creation.eager=true +# Disable home folder creation - if true then home folders are not created (neither eagerly nor lazily) +home.folder.creation.disabled=false + +# Should we consider zero byte content to be the same as no content when firing +# content update policies? Prevents 'premature' firing of inbound content rules +# for some clients such as Mac OS X Finder +policy.content.update.ignoreEmpty=true + +# Default value of alfresco.rmi.services.host is 0.0.0.0 which means 'listen on all adapters'. +# This allows connections to JMX both remotely and locally. +# +alfresco.rmi.services.port=50500 +alfresco.rmi.services.external.host=localhost +alfresco.rmi.services.host=0.0.0.0 + +# If the RMI address is in-use, how many retries should be done before aborting +# Default value of alfresco.rmi.services.retries is 0 which means 'Don't retry if the address is in-use' +alfresco.rmi.services.retries=4 +# How long in milliseconds to wait after a failed server socket bind, before retrying +alfresco.rmi.services.retryInterval=250 + +# RMI service ports for the individual services. +# These eight services are available remotely. +# +# Assign individual ports for each service for best performance +# or run several services on the same port, you can even run everything on 50500 if +# running through a firewall. +# +# Specify 0 to use a random unused port. +# +monitor.rmi.service.port=50508 + +# +# enable or disable individual RMI services +# +monitor.rmi.service.enabled=false + + +# Should the Mbean server bind to an existing server. Set to true for most application servers. +# false for WebSphere clusters. +mbean.server.locateExistingServerIfPossible=true + +# Rendition Service 2 +renditionService2.enabled=true + +# Thumbnail Service +system.thumbnail.generate=true + +# when creating doc via CMIS - optionally configure set of renditions names to request async +cmis.create.doc.request.renditions.set= + +# Default thumbnail limits +# When creating thumbnails, only use the first pageLimit pages +system.thumbnail.definition.default.timeoutMs=-1 +system.thumbnail.definition.default.readLimitTimeMs=-1 +system.thumbnail.definition.default.maxSourceSizeKBytes=-1 +system.thumbnail.definition.default.readLimitKBytes=-1 +system.thumbnail.definition.default.pageLimit=-1 +system.thumbnail.definition.default.maxPages=-1 + +# Max mimetype sizes to create thumbnail icons +system.thumbnail.mimetype.maxSourceSizeKBytes.pdf=-1 +system.thumbnail.mimetype.maxSourceSizeKBytes.txt=-1 +system.thumbnail.mimetype.maxSourceSizeKBytes.docx=-1 +system.thumbnail.mimetype.maxSourceSizeKBytes.xlsx=-1 +system.thumbnail.mimetype.maxSourceSizeKBytes.pptx=-1 +system.thumbnail.mimetype.maxSourceSizeKBytes.odt=-1 +system.thumbnail.mimetype.maxSourceSizeKBytes.ods=-1 +system.thumbnail.mimetype.maxSourceSizeKBytes.odp=-1 + +# Configuration for handling of failing thumbnails. +# See NodeEligibleForRethumbnailingEvaluator's javadoc for details. +# +# Retry periods limit the frequency with which the repository will attempt to create Share thumbnails +# for content nodes which have previously failed in their thumbnail attempts. +# These periods are in seconds. +# +# 604800s = 60s * 60m * 24h * 7d = 1 week +system.thumbnail.retryPeriod=60 +system.thumbnail.retryCount=2 +system.thumbnail.quietPeriod=604800 +system.thumbnail.quietPeriodRetriesEnabled=true +system.thumbnail.redeployStaticDefsOnStartup=true + +content.metadata.async.extract.enabled=true +content.metadata.async.embed.enabled=true + +# The default timeout for metadata mapping extracters +content.metadataExtracter.default.timeoutMs=20000 + +# Local transformer urls to T-engines to service transform requests via http. Enabled by default. +localTransform.core-aio.url=http://localhost:8090/ + +# When a local transformer .url is set, this value indicates the amount of time to wait after a connection failure +# before retrying the connection to allow a docker container to (re)start. +localTransform.core-aio.startupRetryPeriodSeconds=60 + +# Property to enable upgrade from 2.1-A +V2.1-A.fixes.to.schema=0 +#V2.1-A.fixes.to.schema=82 + +# The default authentication chain +authentication.chain=alfrescoNtlm1:alfrescoNtlm + +# Do authentication tickets expire or live for ever? +authentication.ticket.ticketsExpire=true + +# If ticketsEpire is true then how they should expire? +# Valid values are: AFTER_INACTIVITY, AFTER_FIXED_TIME, DO_NOT_EXPIRE +# The default is AFTER_FIXED_TIME +authentication.ticket.expiryMode=AFTER_INACTIVITY + +# If authentication.ticket.ticketsExpire is true and +# authentication.ticket.expiryMode is AFTER_FIXED_TIME or AFTER_INACTIVITY, +# this controls the minimum period for which tickets are valid. +# The default is PT1H for one hour. +authentication.ticket.validDuration=PT1H + +# Use one ticket for all user sessions +# For the pre 4.2 behaviour of one ticket per session set this to false. +authentication.ticket.useSingleTicketPerUser=true + +authentication.alwaysAllowBasicAuthForAdminConsole.enabled=true +authentication.getRemoteUserTimeoutMilliseconds=10000 + +# FTP access +ftp.enabled=false + +# Default root path for protocols +protocols.storeName=${spaces.store} +protocols.rootPath=/${spaces.company_home.childname} + +# OpenCMIS +opencmis.connector.default.store=${spaces.store} +opencmis.connector.default.rootPath=/${spaces.company_home.childname} +opencmis.connector.default.typesDefaultMaxItems=500 +opencmis.connector.default.typesDefaultDepth=-1 +opencmis.connector.default.objectsDefaultMaxItems=10000 +opencmis.connector.default.objectsDefaultDepth=100 +opencmis.connector.default.contentChangesDefaultMaxItems=10000 +opencmis.connector.default.openHttpSession=false +opencmis.activities.enabled=true +opencmis.bulkUpdateProperties.maxItemsSize=1000 +opencmis.bulkUpdateProperties.batchSize=20 +opencmis.bulkUpdateProperties.workerThreads=2 +opencmis.maxContentSizeMB=4096 +opencmis.memoryThresholdKB=4096 + +# URL generation overrides + +# if true, the context path of OpenCMIS generated urls will be set to "opencmis.context.value", otherwise it will be taken from the request url +opencmis.context.override=false +opencmis.context.value= +# if true, the servlet path of OpenCMIS generated urls will be set to "opencmis.servletpath.value", otherwise it will be taken from the request url +opencmis.servletpath.override=false +opencmis.servletpath.value= +opencmis.server.override=false +opencmis.server.value= + +# IMAP +imap.server.enabled=false +imap.server.port=143 +imap.server.attachments.extraction.enabled=true + +# Default IMAP mount points +imap.config.home.store=${spaces.store} +imap.config.home.rootPath=/${spaces.company_home.childname} +imap.config.home.folderPath=${spaces.imap_home.childname} +imap.config.server.mountPoints=AlfrescoIMAP +imap.config.server.mountPoints.default.mountPointName=IMAP +imap.config.server.mountPoints.default.modeName=ARCHIVE +imap.config.server.mountPoints.default.store=${spaces.store} +imap.config.server.mountPoints.default.rootPath=${protocols.rootPath} +imap.config.server.mountPoints.value.AlfrescoIMAP.mountPointName=Alfresco IMAP +imap.config.server.mountPoints.value.AlfrescoIMAP.modeName=MIXED + +#Imap extraction settings +#imap.attachments.mode: +# SEPARATE -- All attachments for each email will be extracted to separate folder. +# COMMON -- All attachments for all emails will be extracted to one folder. +# SAME -- Attachments will be extracted to the same folder where email lies. +imap.attachments.mode=SEPARATE +imap.attachments.folder.store=${spaces.store} +imap.attachments.folder.rootPath=/${spaces.company_home.childname} +imap.attachments.folder.folderPath=${spaces.imap_attachments.childname} + +# Activities Feed - refer to subsystem + +# Feed max ID range to limit maximum number of entries +activities.feed.max.idRange=1000000 +# Feed max size (number of entries) +activities.feed.max.size=200 +# Feed max age (eg. 44640 mins => 31 days) +activities.feed.max.ageMins=44640 + +activities.feed.generator.jsonFormatOnly=true +activities.feed.fetchBatchSize=250 +activities.feedNotifier.batchSize=200 +activities.feedNotifier.numThreads=2 + +# Subsystem unit test values. Will not have any effect on production servers +subsystems.test.beanProp.default.longProperty=123456789123456789 +subsystems.test.beanProp.default.anotherStringProperty=Global Default +subsystems.test.beanProp=inst1,inst2,inst3 +subsystems.test.beanProp.value.inst2.boolProperty=true +subsystems.test.beanProp.value.inst3.anotherStringProperty=Global Instance Default +subsystems.test.simpleProp2=true +subsystems.test.simpleProp3=Global Default3 + +# Default Async Action Thread Pool +default.async.action.threadPriority=1 +default.async.action.corePoolSize=8 +default.async.action.maximumPoolSize=20 + +# Deployment Service +deployment.service.numberOfSendingThreads=5 +deployment.service.corePoolSize=2 +deployment.service.maximumPoolSize=3 +deployment.service.threadPriority=5 +# How long to wait in mS before refreshing a target lock - detects shutdown servers +deployment.service.targetLockRefreshTime=60000 +# How long to wait in mS from the last communication before deciding that deployment has failed, possibly +# the destination is no longer available? +deployment.service.targetLockTimeout=3600000 +# Deployment method used to deploy this Alfresco instance (DEFAULT, INSTALLER, DOCKER_COMPOSE, HELM_CHART, ANSIBLE, ZIP, QUICK_START) +deployment.method=DEFAULT + +#Invitation Service +# Should send emails as part of invitation process. +notification.email.siteinvite=true +# Moderated invite Activiti workflow +site.invite.moderated.workflowId=activiti$activitiInvitationModerated +# Add intneral users Activiti workflow (use activiti$activitiInvitationNominated to revert to requiring accept of invite for internal users) +site.invite.nominated.workflowId=activiti$activitiInvitationNominatedAddDirect +# Add external users Activiti workflow +site.invite.nominatedExternal.workflowId=activiti$activitiInvitationNominated + +# Replication Service +replication.enabled=false + +# Transfer Service +transferservice.receiver.enabled=false +transferservice.receiver.stagingDir=${java.io.tmpdir}/alfresco-transfer-staging +# +# How long to wait in mS before refreshing a transfer lock - detects shutdown servers +# Default 1 minute. +transferservice.receiver.lockRefreshTime=60000 +# +# How many times to attempt retry the transfer lock +transferservice.receiver.lockRetryCount=3 +# How long to wait, in mS, before retrying the transfer lock +transferservice.receiver.lockRetryWait=100 +# +# How long to wait, in mS, since the last contact with from the client before +# timing out a transfer. Needs to be long enough to cope with network delays and "thinking +# time" for both source and destination. Default 5 minutes. +transferservice.receiver.lockTimeOut=300000 + +# OrphanReaper +orphanReaper.lockRefreshTime=60000 +orphanReaper.lockTimeOut=3600000 + + +# security +security.anyDenyDenies=true +# Whether to post-process denies. Only applies to solr4+ when anyDenyDenies is true. +security.postProcessDenies=false + +# +# Encryption properties +# +# default keystores location +dir.keystore=classpath:alfresco/keystore + +# general encryption parameters +encryption.keySpec.class=org.alfresco.encryption.DESEDEKeyGenerator +encryption.keyAlgorithm=AES +encryption.cipherAlgorithm=AES/CBC/PKCS5Padding + +# secret key keystore configuration +encryption.keystore.location=${dir.keystore}/keystore +# configuration via metadata is deprecated +encryption.keystore.keyMetaData.location= +encryption.keystore.provider= +encryption.keystore.type=pkcs12 + +# backup secret key keystore configuration +encryption.keystore.backup.location=${dir.keystore}/backup-keystore +# configuration via metadata is deprecated +encryption.keystore.backup.keyMetaData.location= +encryption.keystore.backup.provider= +encryption.keystore.backup.type=pkcs12 + +# Should encryptable properties be re-encrypted with new encryption keys on botstrap? +encryption.bootstrap.reencrypt=false + +# mac/md5 encryption +encryption.mac.messageTimeout=30000 +encryption.mac.algorithm=HmacSHA1 + +# ssl encryption +encryption.ssl.keystore.location=${dir.keystore}/ssl.keystore +encryption.ssl.keystore.provider= +encryption.ssl.keystore.type=JCEKS +# configuration via metadata is deprecated +encryption.ssl.keystore.keyMetaData.location= +encryption.ssl.truststore.location=${dir.keystore}/ssl.truststore +encryption.ssl.truststore.provider= +encryption.ssl.truststore.type=JCEKS +# configuration via metadata is deprecated +encryption.ssl.truststore.keyMetaData.location= + +# Re-encryptor properties +encryption.reencryptor.chunkSize=100 +encryption.reencryptor.numThreads=2 + +# SOLR connection details (e.g. for JMX) +solr.host=localhost +solr.port=8983 +solr.port.ssl=8984 +solr.solrUser=solr +solr.solrPassword=solr +# none, https +solr.secureComms=https +solr.sharedSecret= +solr.sharedSecret.header=X-Alfresco-Search-Secret +solr.cmis.alternativeDictionary=DEFAULT_DICTIONARY + +solr.max.total.connections=40 +solr.max.host.connections=40 + +# Solr connection timeouts +# solr connect timeout in ms +solr.solrConnectTimeout=5000 + +# cron expression defining how often the Solr Admin client (used by JMX) pings Solr if it goes away +solr.solrPingCronExpression=0 0/5 * * * ? * + + +#Default SOLR store mappings mappings +solr.store.mappings=solrMappingAlfresco,solrMappingArchive +solr.store.mappings.value.solrMappingAlfresco.httpClientFactory=solrHttpClientFactory +solr.store.mappings.value.solrMappingAlfresco.baseUrl=/solr/alfresco +solr.store.mappings.value.solrMappingAlfresco.protocol=workspace +solr.store.mappings.value.solrMappingAlfresco.identifier=SpacesStore +solr.store.mappings.value.solrMappingArchive.httpClientFactory=solrHttpClientFactory +solr.store.mappings.value.solrMappingArchive.baseUrl=/solr/archive +solr.store.mappings.value.solrMappingArchive.protocol=archive +solr.store.mappings.value.solrMappingArchive.identifier=SpacesStore + +#Default SOLR 4 store mappings mappings +solr4.store.mappings=solrMappingAlfresco,solrMappingArchive +solr4.store.mappings.value.solrMappingAlfresco.httpClientFactory=solrHttpClientFactory +solr4.store.mappings.value.solrMappingAlfresco.baseUrl=/solr4/alfresco +solr4.store.mappings.value.solrMappingAlfresco.protocol=workspace +solr4.store.mappings.value.solrMappingAlfresco.identifier=SpacesStore +solr4.store.mappings.value.solrMappingArchive.httpClientFactory=solrHttpClientFactory +solr4.store.mappings.value.solrMappingArchive.baseUrl=/solr4/archive +solr4.store.mappings.value.solrMappingArchive.protocol=archive +solr4.store.mappings.value.solrMappingArchive.identifier=SpacesStore + +#Default SOLR 6 store mappings mappings +solr6.store.mappings=solrMappingAlfresco,solrMappingArchive,solrMappingHistory +solr6.store.mappings.value.solrMappingAlfresco.httpClientFactory=solrHttpClientFactory +solr6.store.mappings.value.solrMappingAlfresco.baseUrl=/solr/alfresco +solr6.store.mappings.value.solrMappingAlfresco.protocol=workspace +solr6.store.mappings.value.solrMappingAlfresco.identifier=SpacesStore +solr6.store.mappings.value.solrMappingArchive.httpClientFactory=solrHttpClientFactory +solr6.store.mappings.value.solrMappingArchive.baseUrl=/solr/archive +solr6.store.mappings.value.solrMappingArchive.protocol=archive +solr6.store.mappings.value.solrMappingArchive.identifier=SpacesStore +solr6.store.mappings.value.solrMappingHistory.httpClientFactory=solrHttpClientFactory +solr6.store.mappings.value.solrMappingHistory.baseUrl=/solr/history +solr6.store.mappings.value.solrMappingHistory.protocol=workspace +solr6.store.mappings.value.solrMappingHistory.identifier=history + +# +# URL Shortening Properties +# +urlshortening.bitly.username=brianalfresco +urlshortening.bitly.api.key=R_ca15c6c89e9b25ccd170bafd209a0d4f +urlshortening.bitly.url.length=20 + +# +# Bulk Filesystem Importer +# + +# The number of threads to employ in a batch import +bulkImport.batch.numThreads=4 + +# The size of a batch in a batch import i.e. the number of files to import in a +# transaction/thread +bulkImport.batch.batchSize=20 + + +# +# Caching Content Store +# +system.content.caching.cacheOnInbound=true +system.content.caching.maxDeleteWatchCount=1 +# Clean up every day at 3 am +system.content.caching.contentCleanup.cronExpression=0 0 3 * * ? +system.content.caching.minFileAgeMillis=60000 +system.content.caching.maxUsageMB=4096 +# maxFileSizeMB - 0 means no max file size. +system.content.caching.maxFileSizeMB=0 +# When the CachingContentStore is about to write a cache file but the disk usage is in excess of panicThresholdPct +# (default 90%) then the cache file is not written and the cleaner is started (if not already running) in a new thread. +system.content.caching.panicThresholdPct=90 +# When a cache file has been written that results in cleanThresholdPct (default 80%) of maxUsageBytes +# being exceeded then the cached content cleaner is invoked (if not already running) in a new thread. +system.content.caching.cleanThresholdPct=80 +# An aggressive cleaner is run till the targetUsagePct (default 70%) of maxUsageBytes is achieved +system.content.caching.targetUsagePct=70 +# Threshold in seconds indicating a minimal gap between normal cleanup starts +system.content.caching.normalCleanThresholdSec=0 + +mybatis.useLocalCaches=false + +fileFolderService.checkHidden.enabled=true + + +ticket.cleanup.cronExpression=0 0 * * * ? + +# +# Download Service Cleanup +# +download.cleaner.startDelayMilliseconds=3600000 +# 1 hour +download.cleaner.repeatIntervalMilliseconds=3600000 +download.cleaner.maxAgeMins=60 +# -1 or 0 for not using batches +download.cleaner.batchSize=1000 + +# you could set this to false for new installations greater then ACS 6.2 +# see MNT-20212 +download.cleaner.cleanAllSysDownloadFolders=true + +# +# Download Service Limits, in bytes +# +download.maxContentSize=2152852358 + +# Max size of view trashcan files +# +trashcan.MaxSize=1000 + +# +# Use bridge tables for caching authority evaluation. +# +authority.useBridgeTable=true + +# Limit the number of results from findAuthority query +authority.findAuthorityLimit=10000 + +# enable QuickShare - if false then the QuickShare-specific REST APIs will return 403 Forbidden +system.quickshare.enabled=true +system.quickshare.email.from.default=noreply@alfresco.com +# By default the difference between the quick share expiry date and the current time must be at least 1 day (24 hours). +# However, this can be changed to at least 1 hour or 1 minute for testing purposes. For example, +# setting the value to MINUTES, means the service will calculate the difference between NOW and the given expiry date +# in terms of minutes and checks for the difference to be greater than 1 minute. +# DAYS | HOURS | MINUTES +system.quickshare.expiry_date.enforce.minimum.period=DAYS + +# Oubound Mail +mail.service.corePoolSize=8 +mail.service.maximumPoolSize=20 + +nodes.bulkLoad.cachingThreshold=10 + +# Multi-Tenancy + +# if "dir.contentstore.tenants" is set then +# tenants are not co-mingled and all content roots will appear below this container (in sub-folder) +# and when creating a tenant the "contentRootPath" (root content store directory for a given tenant) will be ignored +dir.contentstore.tenants= + +# Gateway Authentication +# gateway authentication is disabled if empty host is specified +alfresco.authentication.gateway.host= +alfresco.authentication.gateway.protocol=https +alfresco.authentication.gateway.port=443 +alfresco.authentication.gateway.outboundHeaders=Authorization,key +alfresco.authentication.gateway.inboundHeaders=X-Alfresco-Authenticator-Key,X-Alfresco-Remote-User +alfresco.authentication.gateway.prefixUrl=/publicapi +alfresco.authentication.gateway.bufferSize=2048 +alfresco.authentication.gateway.connectTimeout=10000 +alfresco.authentication.gateway.readTimeout=120000 +alfresco.authentication.gateway.httpTcpNodelay=true +alfresco.authentication.gateway.httpConnectionStalecheck=true + +# webscripts config +webscripts.encryptTempFiles=false +webscripts.tempDirectoryName=Alfresco-WebScripts +# 4mb +webscripts.memoryThreshold=4194304 +# 4gb +webscripts.setMaxContentSize=5368709120 + +# Property to enable index upgrade for metadata query (MDQ) +# +# The indexes are not added unless this value is changed +# Adding each the supporting indexes may take several hours depending on the size of the database. +# The required indexes may be added in stages. +# See: classpath:alfresco/dbscripts/upgrade/4.2/${db.script.dialect}/metadata-query-indexes.sql +# See: classpath:alfresco/dbscripts/upgrade/5.1/${db.script.dialect}/metadata-query-indexes-2.sql +system.metadata-query-indexes.ignored=true +system.metadata-query-indexes-more.ignored=true + +# +# Do we defer running the shared folder patch? +# +system.patch.sharedFolder.deferred=false +# Default value is run new years day 2030 i.e. not run. +system.patch.sharedFolder.cronExpression=0 0 0 ? 1 1 2030 + +# +# Default values for deferring the running of the addUnmovableAspect patch +# +system.patch.addUnmovableAspect.deferred=false +system.patch.addUnmovableAspect.cronExpression=0 0 0 ? 1 1 2030 + +# Property to enable removal of all JBPM related data from the database +# +# The tables are not removed from the databasen unless explicitly requested by setting this property to false. +# See: classpath:alfresco/dbscripts/upgrade/5.2/${db.script.dialect}/remove-jbpm-tables-from-db.sql +system.remove-jbpm-tables-from-db.ignored=true + +# +# Use a canned query when requested to search for people if " [hint:useCQ]" is provided in search term +# +people.search.honor.hint.useCQ=true + +# Delays cron jobs after bootstrap to allow server to fully come up before jobs start +system.cronJob.startDelayMilliseconds=60000 + +# Schedule for reading mimetype config definitions dynamically. Initially checks every 10 seconds and then switches to +# every hour after the configuration is read successfully. If there is a error later reading the config, the +# checks return to every 10 seconds. +mimetype.config.cronExpression=0 30 0/1 * * ? +mimetype.config.initialAndOnError.cronExpression=0/10 * * * * ? + +# Optional property to specify an external file or directory that will be read for mimetype definitions from YAML +# files (possibly added to a volume via k8 ConfigMaps). +mimetype.config.dir=shared/classes/alfresco/extension/mimetypes + +# Schedule for reading rendition config definitions dynamically. Initially checks every 10 seconds and then switches to +# every hour after the configuration is read successfully. If there is a error later reading the config, the +# checks return to every 10 seconds. +rendition.config.cronExpression=2 30 0/1 * * ? +rendition.config.initialAndOnError.cronExpression=0/10 * * * * ? + +# Optional property to specify an external file or directory that will be read for rendition definitions from YAML +# files (possibly added to a volume via k8 ConfigMaps). +rendition.config.dir=shared/classes/alfresco/extension/transform/renditions + +# Optional property to specify an external file or directory that will be read for transformer json config. +local.transform.pipeline.config.dir=shared/classes/alfresco/extension/transform/pipelines + +# Used to disable transforms locally. +local.transform.service.enabled=true + +# Schedule for reading local transform config, so that T-Engines and local pipeline config is dynamically +# picked up, or reintegrated after an outage. Initially checks every 10 seconds and then switches to every hour +# after the configuration is read successfully. If there is a error later reading the config, the checks return to +# every 10 seconds. +local.transform.service.cronExpression=4 30 0/1 * * ? +local.transform.service.initialAndOnError.cronExpression=0/10 * * * * ? + +# +# Check that the declared mimetype (of the Node) is the same as the derived +# mimetype of the content (via Tika) before a transformation takes place. +# Only files in the repository (not intermediate files in a transformer +# pipeline) are checked. This property provides a trade off between a +# security check and a relatively expensive (Tika) operation. +# +# There are a few issues with the Tika mimetype detection. So that transformations +# still take place where the detected mimetype is not the same as the declared mimetype, +# another property (transformer.strict.mimetype.check.whitelist.mimetypes) contains pairs +# of declared and detected mimetypes that should be allowed. This parameter value is a +# sequence of ; separated pairs. The declared and derived mimetypes are also ; separated. +# +transformer.strict.mimetype.check=true + +# A white list of declared and detected mimetypes, that don't match, but should still be transformed. +transformer.strict.mimetype.check.whitelist.mimetypes=application/eps;application/postscript;application/illustrator;application/pdf;application/x-tar;application/x-gtar;application/acp;application/zip;application/vnd.stardivision.math;application/x-tika-msoffice + +# +# Enable transformation retrying if the file has MIME type differ than file extension. +# Ignored if transformer.strict.mimetype.check is true as these transformations +# will not take place. +# +content.transformer.retryOn.different.mimetype=true + +# Debug and Log buffer sizes +transformer.debug.entries=0 +transformer.log.entries=50 + +# +# Lock timeout configuration +# +system.lockTryTimeout=100 +system.lockTryTimeout.DictionaryDAOImpl=10000 +system.lockTryTimeout.MessageServiceImpl=${system.lockTryTimeout} +system.lockTryTimeout.PolicyComponentImpl=${system.lockTryTimeout} + + +# Scheduled job to clean up unused properties from the alf_prop_xxx tables. +# Default setting of "0 0 3 ? * SAT" is to run every Saturday at 3am. +attributes.propcleaner.cronExpression=0 0 3 ? * SAT + +# Control Alfresco JMX connectivity +alfresco.jmx.connector.enabled=false + +# Dissallow Attribute Service Entries with "Serializable" objects in key Segments +# Please, see MNT-11895 for details. +system.propval.uniquenessCheck.enabled=true + +# Requests for ephemeral (in-memory) locks with expiry times (in seconds) greater +# than this value will result in persistent locks being created instead. By default +# this value is equal to the maximum allowed expiry for ephemeral locks, therefore +# this feature is disabled by default. Setting this to -1 would mean that ALL +# requests for ephemeral locks would result in persistent locks being created. +alfresco.ephemeralLock.expiryThresh=172800 + +# SurfConfigFolder Patch +# +# Do we defer running the surf-config folder patch? +# +system.patch.surfConfigFolder.deferred=false +# Default value. i.e. never run. It can be triggered using JMX +system.patch.surfConfigFolder.cronExpression=* * * * * ? 2099 + +# +# Solr Facets Config Properties +# +solr_facets.root.path=/app:company_home/app:dictionary +solr_facets.root=${solr_facets.root.path}/${spaces.solr_facets.root.childname} +solr_facets.inheritanceHierarchy=default,custom + +models.enforceTenantInNamespace=false + +# Allowed protocols for links +links.protocosl.white.list=http,https,ftp,mailto + +# Fixed ACLs +# Required for fixing MNT-15368 - Time Consumed for Updating Folder Permission +# ADMAccessControlListDAO.setFixedAcls called on a large folder hierarchy will take a long time for its execution. +# For this reason now method can also be called asynchronously if transaction reaches system.fixedACLs.maxTransactionTime. +# In this case setFixedAcls method recursion will be stopped and unfinished nodes will be marked with ASPECT_PENDING_FIX_ACL. +# Pending nodes will be processed by FixedAclUpdater, programmatically called but also configured as a scheduled job. +system.fixedACLs.maxTransactionTime=10000 +# fixedACLsUpdater - lock time to live +system.fixedACLsUpdater.lockTTL=10000 +# fixedACLsUpdater - maximum number of nodes to process per execution +system.fixedACLsUpdater.maxItemBatchSize=100 +# fixedACLsUpdater - the number of threads to use +system.fixedACLsUpdater.numThreads=4 +# fixedACLsUpdater - Force shared ACL to propagate through children even if there is an unexpected ACL +system.fixedACLsUpdater.forceSharedACL=false +# fixedACLsUpdater cron expression - fire at midnight every day +system.fixedACLsUpdater.cronExpression=0 0 0 * * ? + +cmis.disable.hidden.leading.period.files=false + +#Smart Folders Config Properties +smart.folders.enabled=false + +#Smart reference config +smart.reference.classpath.hash=${smart.folders.config.vanilla.processor.classpath}->1,${smart.folders.config.system.templates.classpath}->2 + +#Smart store config + +#Company home relative download associations of smart entries +smart.download.associations.folder=${spaces.dictionary.childname}/${spaces.smartdownloads.childname} + +#Generic virtualization methods config + +#Vanilla JSON templates javascript processor classpath. A java script processor used to +#covert JSON templates to internal smart folder definitions. + +smart.folders.config.vanilla.processor.classpath=/org/alfresco/repo/virtual/node/vanilla.js + +#System virtualization method config + +#System virtualization method aspect. +smart.folders.config.system.aspect=smf:systemConfigSmartFolder +#System virtualization method aspect defined template location property. +smart.folders.config.system.aspect.template.location.property=smf:system-template-location +#Classpath to be explored for *.json entries defining system templates. +smart.folders.config.system.templates.classpath=/org/alfresco/repo/virtual/node +#A company home relative name or qname path location of repository system templates. +smart.folders.config.system.templates.path=${spaces.dictionary.childname}/${spaces.smartfolders.childname} +#Content sub type of repository system templates. +smart.folders.config.system.templates.template.type=smf:smartFolderTemplate + +#Custom virtualization method config + +#Custom virtualization method aspect. +smart.folders.config.custom.aspect=smf:customConfigSmartFolder +#Custom virtualization method aspect template content association. +smart.folders.config.custom.aspect.template.association=smf:custom-template-association + + +#Type virtualization method config + +#A company home relative name or qname path location of the type mapped templates. +smart.folders.config.type.templates.path=${spaces.dictionary.childname}/${spaces.smartfolders.childname} +#Type and aspect qname regular expression filter. +smart.folders.config.type.templates.qname.filter=none + +# Preferred password encoding, md4, sha256, bcrypt10 +system.preferred.password.encoding=md4 + +# Upgrade Password Hash Job +system.upgradePasswordHash.jobBatchSize=100 +system.upgradePasswordHash.jobQueryRange=10000 +system.upgradePasswordHash.jobThreadCount=4 +system.upgradePasswordHash.jobCronExpression=* * * * * ? 2099 + +system.api.discovery.enabled=true + +# Maximum query size for category/tag fetch when not explicitly set by paging parameters +category.queryFetchSize=5000 + +# Brute force protection +authentication.protection.enabled=true +authentication.protection.limit=10 +authentication.protection.periodSeconds=6 + +system.email.sender.default=noreply@alfresco.com +# reset password workflow will expire in an hour +system.reset-password.endTimer=PT1H +system.reset-password.sendEmailAsynchronously=true + +# HeartBeat +heartbeat.target.url= +heartbeat.enabled=true + +# CSRF filter overrides +csrf.filter.enabled=true +csrf.filter.referer= +csrf.filter.referer.always=false +csrf.filter.origin= +csrf.filter.origin.always=false + +# CORS settings +cors.enabled=false +cors.allowed.origins= +cors.allowed.methods=GET,POST,HEAD,OPTIONS,PUT,DELETE +cors.allowed.headers=Authorization,Content-Type,Cache-Control,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,X-CSRF-Token +cors.exposed.headers=Access-Control-Allow-Origin,Access-Control-Allow-Credentials +cors.support.credentials=true +cors.preflight.maxage=10 + +# Alfresco Rest Api-Explorer +api-explorer.url= + +# Events subsystem +events.subsystem.autoStart=false +# Messaging subsystem +messaging.subsystem.autoStart=true + + +# Raw events +acs.repo.rendition.events.endpoint=jms:acs-repo-rendition-events?jmsMessageType=Text + +# Transform request events +acs.repo.transform.request.endpoint=jms:acs-repo-transform-request?jmsMessageType=Text + +# If enabled doesn't allow to set content properties via NodeService +contentPropertyRestrictions.enabled=true +contentPropertyRestrictions.whitelist= + +# Repo events2 +# Type and aspect filters which should be excluded +# Note: System folders node types are added by default +repo.event2.filter.nodeTypes=sys:*, fm:*, cm:thumbnail, cm:failedThumbnail, cm:rating, rma:rmsite include_subtypes +repo.event2.filter.nodeAspects=sys:* +repo.event2.filter.childAssocTypes=rn:rendition +# Comma separated list of users which should be excluded +# Note: username's case-sensitivity depends on the {user.name.caseSensitive} setting +repo.event2.filter.users= +# Topic name +repo.event2.topic.endpoint=amqp:topic:alfresco.repo.event2 +# Thread pool for async enqueue of repo events +repo.event2.queue.enqueueThreadPool.priority=1 +repo.event2.queue.enqueueThreadPool.coreSize=8 +repo.event2.queue.enqueueThreadPool.maximumSize=10 +# Thread pool for async dequeue and delivery of repo events +repo.event2.queue.dequeueThreadPool.priority=1 +repo.event2.queue.dequeueThreadPool.coreSize=1 +repo.event2.queue.dequeueThreadPool.maximumSize=1 + + +# MNT-21083 +# --DELETE_NOT_EXISTS - default settings +system.delete_not_exists.batchsize=100000 +system.delete_not_exists.delete_batchsize=1000 +system.delete_not_exists.read_only=false +system.delete_not_exists.timeout_seconds=-1 +system.prop_table_cleaner.algorithm=V2 + +# Configure the system-wide (ACS) settings for direct access urls. +# +# For Direct Access URLs to be usable on the service-layer, the feature must be enabled both system-wide and on the +# content-store(s). For the feature to be usable through REST (outside the JVM) the rest-api configuration must also be +# enabled. +# +# The system.directAccessUrl.enabled property is the main switch of the feature. If this is set to false ALL +# Direct Access URLs are disabled. +# +# The next configuration that controls specific Direct Access URLs is the content store one. +# The connector.s3.directAccessUrl.enabled property controls whether Direct Access URLs are enabled for that specific store. +# +# Whether or not a client can request a Direct Access URL by using a REST endpoint is controlled by the +# restApi.directAccessUrl.enabled property. If the REST endpoint is disabled, but the feature is enabled +# system-wide and on the content-store, then the direct access URLs will only be usable by Java clients (only +# service-level requests will be possible). + +# Controls whether this feature is available, system wide. +# For direct access urls to work, the feature needs to be enabled both system-wide and on the individual content-store. +system.directAccessUrl.enabled=false +# Sets the default expiry time for the direct access url across all Content Stores. +# Its value cannot exceed the system-wide max expiry time, it can only be equal or lower (all DAUs disabled otherwise). +# This property is mandatory if direct access urls are enabled system-wide - (all DAUs disabled otherwise). +system.directAccessUrl.defaultExpiryTimeInSec=30 +# Sets the upper limit for the direct access urls expiry time, meaning a Content Store will be able to override this +# value but not exceed it, and the same goes for the clients. +# A service (Java Interface) client will be able to request a direct access url for a custom expiry time but that time +# can’t exceed this value. +# If the requested time exceeds the max value, the expiry time reverts to the default configured one. +# This property is mandatory if direct access urls are enabled system-wide - (all DAUs disabled otherwise). +system.directAccessUrl.maxExpiryTimeInSec=300 + +# Configure the common S3 storage connector content store settings for direct access urls. +# +# Note: When multiple S3 buckets are used for storage in Alfresco, each S3 Content Stores can be configured with either +# the default (common) S3 Connector-specific properties (i.e. connector.s3.directAccessUrl.enabled etc.) OR new separate +# properties could be defined for each and every store (e.g. +# connector.s3store1.directAccessUrl.enabled, +# connector.s3store2.directAccessUrl.enabled etc.). + +# Controls whether DAUs are enabled on this specific content store. +# For direct access urls to work, the feature needs to be enabled both system-wide and on the individual content-store. +connector.s3.directAccessUrl.enabled=false +# Sets the expiry time for the direct access url in this store, by overriding the system-wide config. +# If this value exceeds the content store upper limit or the system-wide default it will fallback to the system-wide +# default configuration. +# Its value cannot exceed the system-wide max expiry time, it can only be equal or lower (DAUs for the specific content +# store disabled otherwise). +# If not set, the default system-wide setting will be used. +connector.s3.directAccessUrl.defaultExpiryTimeInSec=30 +# The maximum expiry time interval that can be requested by clients - content-store specific setting. +# Its value cannot exceed the system-wide configuration, it can only be equal or lower (DAUs for the specific content +# store disabled otherwise). +# If not set, the default system-wide setting will be used. +connector.s3.directAccessUrl.maxExpiryTimeInSec=300 + +# Configure the REST API configuration settings for direct access urls. +# +# Controls whether direct access url requests via the REST API are enabled. +restApi.directAccessUrl.enabled=true +# Sets the expiry time for all the direct access urls requested via a REST call. +# Its value cannot exceed the system-wide max expiry time configuration, it can only be equal or lower (REST API DAUs +# disabled otherwise). +# If not set, the default system-wide setting will be used. +# Direct Access Url REST API calls cannot request an explicit expiry time. +restApi.directAccessUrl.defaultExpiryTimeInSec=30 + +# Creates additional indexes on alf_node and alf_transaction. Recommended for large repositories. +system.new-node-transaction-indexes.ignored=true + +# Allows the configuration of maximum limits of the temp files to be deleted or the maximum time allowed to run for the job +system.tempFileCleaner.maxFilesToDelete= +system.tempFileCleaner.maxTimeToRun= + +# Property to long running migration to remove alf_server in v7+ patch.db-V7.1.0-remove-alf_server-table +system.remove-alf_server-table-from-db.ignored=true diff --git a/repository/src/test/java/org/alfresco/AllUnitTestsSuite.java b/repository/src/test/java/org/alfresco/AllUnitTestsSuite.java index 75a8e4c9c7..2d8cc48e74 100644 --- a/repository/src/test/java/org/alfresco/AllUnitTestsSuite.java +++ b/repository/src/test/java/org/alfresco/AllUnitTestsSuite.java @@ -180,6 +180,8 @@ import org.junit.runners.Suite; org.alfresco.repo.audit.AuditableAnnotationTest.class, org.alfresco.repo.audit.PropertyAuditFilterTest.class, org.alfresco.repo.audit.access.NodeChangeTest.class, + org.alfresco.repo.content.directurl.SystemWideDirectUrlConfigUnitTest.class, + org.alfresco.repo.content.directurl.ContentStoreDirectUrlConfigUnitTest.class, org.alfresco.repo.content.LimitedStreamCopierTest.class, org.alfresco.repo.content.filestore.FileIOTest.class, org.alfresco.repo.content.filestore.SpoofedTextContentReaderTest.class, diff --git a/repository/src/test/java/org/alfresco/repo/content/directurl/ContentStoreDirectUrlConfigUnitTest.java b/repository/src/test/java/org/alfresco/repo/content/directurl/ContentStoreDirectUrlConfigUnitTest.java new file mode 100644 index 0000000000..b32ed63be8 --- /dev/null +++ b/repository/src/test/java/org/alfresco/repo/content/directurl/ContentStoreDirectUrlConfigUnitTest.java @@ -0,0 +1,234 @@ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2021 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco 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 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.content.directurl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; + +/** + * Tests for content store direct access URL configuration settings. + * + * @author Sara Aspery + */ +public class ContentStoreDirectUrlConfigUnitTest +{ + private static final Boolean ENABLED = Boolean.TRUE; + private static final Boolean DISABLED = Boolean.FALSE; + + private static final Long DEFAULT_EXPIRY_TIME_IN_SECS = 10L; + private static final Long MAX_EXPIRY_TIME_IN_SECS = 20L; + + private static final Long SYS_DEFAULT_EXPIRY_TIME_IN_SECS = 30L; + private static final Long SYS_MAX_EXPIRY_TIME_IN_SECS = 300L; + + private ContentStoreDirectUrlConfig contentStoreDirectUrlConfig; + + @Before + public void setup() + { + this.contentStoreDirectUrlConfig = new ContentStoreDirectUrlConfig(); + setupSystemWideDirectAccessConfig(); + } + + @Test + public void testValidConfig_RemainsEnabled() + { + setupDirectAccessConfig(ENABLED, DEFAULT_EXPIRY_TIME_IN_SECS, MAX_EXPIRY_TIME_IN_SECS); + + assertTrue("Expected content store direct URLs to be enabled", contentStoreDirectUrlConfig.isEnabled()); + contentStoreDirectUrlConfig.validate(); + assertTrue("Expected REST API direct URLs to be enabled", contentStoreDirectUrlConfig.isEnabled()); + } + + @Test + public void testValidConfig_RemainsDisabled() + { + setupDirectAccessConfig(DISABLED, DEFAULT_EXPIRY_TIME_IN_SECS, MAX_EXPIRY_TIME_IN_SECS); + + assertFalse("Expected content store direct URLs to be disabled", contentStoreDirectUrlConfig.isEnabled()); + contentStoreDirectUrlConfig.validate(); + assertFalse("Expected content store direct URLs to be disabled", contentStoreDirectUrlConfig.isEnabled()); + } + + @Test + public void testInvalidConfig_DefaultExpiryTimeMissing_ValidReplacement() + { + Long maxExpiryTimeInSecs = SYS_DEFAULT_EXPIRY_TIME_IN_SECS + 1; + setupDirectAccessConfig(ENABLED, null, maxExpiryTimeInSecs); + + verifyDirectAccessConfig(ENABLED, null, maxExpiryTimeInSecs); + contentStoreDirectUrlConfig.validate(); + verifyDirectAccessConfig(ENABLED, SYS_DEFAULT_EXPIRY_TIME_IN_SECS, maxExpiryTimeInSecs); + } + + @Test + public void testInvalidConfig_DefaultExpiryTimeMissing_ReplacementExceedsMax() + { + setupDirectAccessConfig(ENABLED, null, MAX_EXPIRY_TIME_IN_SECS); + + verifyDirectAccessConfig(ENABLED, null, MAX_EXPIRY_TIME_IN_SECS); + contentStoreDirectUrlConfig.validate(); + verifyDirectAccessConfig(DISABLED, SYS_DEFAULT_EXPIRY_TIME_IN_SECS, MAX_EXPIRY_TIME_IN_SECS); + } + + @Test + public void testInvalidConfig_DefaultExpiryTimeZero() + { + setupDirectAccessConfig(ENABLED, 0L, MAX_EXPIRY_TIME_IN_SECS); + + assertTrue("Expected content store direct URLs to be enabled", contentStoreDirectUrlConfig.isEnabled()); + contentStoreDirectUrlConfig.validate(); + assertFalse("Expected content store direct URLs to be disabled", contentStoreDirectUrlConfig.isEnabled()); + } + + @Test + public void testInvalidConfig_DefaultExpiryTimeNegative() + { + setupDirectAccessConfig(ENABLED, -1L, MAX_EXPIRY_TIME_IN_SECS); + + assertTrue("Expected content store direct URLs to be enabled", contentStoreDirectUrlConfig.isEnabled()); + contentStoreDirectUrlConfig.validate(); + assertFalse("Expected content store direct URLs to be disabled", contentStoreDirectUrlConfig.isEnabled()); + } + + @Test + public void testInvalidConfig_DefaultExpiryTimeExceedsSystemMax() + { + Long defaultExpiryTimeInSecs = SYS_MAX_EXPIRY_TIME_IN_SECS + 1; + setupDirectAccessConfig(ENABLED, defaultExpiryTimeInSecs, MAX_EXPIRY_TIME_IN_SECS); + + assertTrue("Expected content store direct URLs to be enabled", contentStoreDirectUrlConfig.isEnabled()); + contentStoreDirectUrlConfig.validate(); + assertFalse("Expected content store direct URLs to be disabled", contentStoreDirectUrlConfig.isEnabled()); + } + + @Test + public void testInvalidConfig_DefaultExpiryTimeExceedsStoreMax_ValidReplacement() + { + Long maxExpiryTimeInSecs = SYS_DEFAULT_EXPIRY_TIME_IN_SECS + 1; + Long defaultExpiryTimeInSecs = maxExpiryTimeInSecs + 1; + setupDirectAccessConfig(ENABLED, defaultExpiryTimeInSecs, maxExpiryTimeInSecs); + + verifyDirectAccessConfig(ENABLED, defaultExpiryTimeInSecs, maxExpiryTimeInSecs); + contentStoreDirectUrlConfig.validate(); + verifyDirectAccessConfig(ENABLED, SYS_DEFAULT_EXPIRY_TIME_IN_SECS, maxExpiryTimeInSecs); + } + + @Test + public void testInvalidConfig_DefaultExpiryTimeExceedsStoreMax_ReplacementExceedsStoreMax() + { + Long defaultExpiryTimeInSecs = MAX_EXPIRY_TIME_IN_SECS + 1; + setupDirectAccessConfig(ENABLED, defaultExpiryTimeInSecs, MAX_EXPIRY_TIME_IN_SECS); + + verifyDirectAccessConfig(ENABLED, defaultExpiryTimeInSecs, MAX_EXPIRY_TIME_IN_SECS); + contentStoreDirectUrlConfig.validate(); + verifyDirectAccessConfig(DISABLED, SYS_DEFAULT_EXPIRY_TIME_IN_SECS, MAX_EXPIRY_TIME_IN_SECS); + } + @Test + public void testInvalidConfig_DefaultExpiryTimeExceedsSystemDefault_ValidReplacement() + { + Long defaultExpiryTimeInSecs = SYS_DEFAULT_EXPIRY_TIME_IN_SECS + 1; + Long maxExpiryTimeInSecs = SYS_MAX_EXPIRY_TIME_IN_SECS; + setupDirectAccessConfig(ENABLED, defaultExpiryTimeInSecs, maxExpiryTimeInSecs); + + verifyDirectAccessConfig(ENABLED, defaultExpiryTimeInSecs, maxExpiryTimeInSecs); + contentStoreDirectUrlConfig.validate(); + verifyDirectAccessConfig(ENABLED, SYS_DEFAULT_EXPIRY_TIME_IN_SECS, maxExpiryTimeInSecs); + } + + @Test + public void testInvalidConfig_DefaultExpiryTimeExceedsSystemDefault_ReplacementExceedsStoreMax() + { + Long defaultExpiryTimeInSecs = SYS_DEFAULT_EXPIRY_TIME_IN_SECS + 1; + setupDirectAccessConfig(ENABLED, defaultExpiryTimeInSecs, MAX_EXPIRY_TIME_IN_SECS); + + verifyDirectAccessConfig(ENABLED, defaultExpiryTimeInSecs, MAX_EXPIRY_TIME_IN_SECS); + contentStoreDirectUrlConfig.validate(); + verifyDirectAccessConfig(DISABLED, SYS_DEFAULT_EXPIRY_TIME_IN_SECS, MAX_EXPIRY_TIME_IN_SECS); + } + + @Test + public void testInvalidConfig_MaxExpiryTimeZero() + { + setupDirectAccessConfig(ENABLED, DEFAULT_EXPIRY_TIME_IN_SECS, 0L); + + assertTrue("Expected content store direct URLs to be enabled", contentStoreDirectUrlConfig.isEnabled()); + contentStoreDirectUrlConfig.validate(); + assertFalse("Expected content store direct URLs to be disabled", contentStoreDirectUrlConfig.isEnabled()); + } + + @Test + public void testInvalidConfig_MaxExpiryTimeNegative() + { + setupDirectAccessConfig(ENABLED, DEFAULT_EXPIRY_TIME_IN_SECS, -1L); + + assertTrue("Expected content store direct URLs to be enabled", contentStoreDirectUrlConfig.isEnabled()); + contentStoreDirectUrlConfig.validate(); + assertFalse("Expected content store direct URLs to be disabled", contentStoreDirectUrlConfig.isEnabled()); + } + + @Test + public void testInvalidConfig_MaxExpiryTimeExceedsSystemMax() + { + Long maxExpiryTimeInSec = contentStoreDirectUrlConfig.getSysWideMaxExpiryTimeInSec() + 1; + setupDirectAccessConfig(ENABLED, DEFAULT_EXPIRY_TIME_IN_SECS, maxExpiryTimeInSec); + + assertTrue("Expected content store direct URLs to be enabled", contentStoreDirectUrlConfig.isEnabled()); + contentStoreDirectUrlConfig.validate(); + assertFalse("Expected content store direct URLs to be disabled", contentStoreDirectUrlConfig.isEnabled()); + } + + /* Helper method to set content store direct access url configuration settings */ + private void setupDirectAccessConfig(Boolean isEnabled, Long defaultExpiryTime, Long maxExpiryTime) + { + contentStoreDirectUrlConfig.setEnabled(isEnabled); + contentStoreDirectUrlConfig.setDefaultExpiryTimeInSec(defaultExpiryTime); + contentStoreDirectUrlConfig.setMaxExpiryTimeInSec(maxExpiryTime); + } + + /* Helper method to verify content store direct access url configuration settings */ + private void verifyDirectAccessConfig(Boolean isEnabled, Long defaultExpiryTime, Long maxExpiryTime) + { + assertEquals("Expected content store direct URLs to be enabled = " + isEnabled, isEnabled, contentStoreDirectUrlConfig.isEnabled()); + assertEquals("Expected default expiry time to match " + defaultExpiryTime, defaultExpiryTime, contentStoreDirectUrlConfig.getDefaultExpiryTimeInSec()); + assertEquals("Expected maximum expiry time to match " + maxExpiryTime, maxExpiryTime, contentStoreDirectUrlConfig.getMaxExpiryTimeInSec()); + } + + /* Helper method to set system-wide direct access url configuration settings */ + private void setupSystemWideDirectAccessConfig() + { + SystemWideDirectUrlConfig sysConfig = new SystemWideDirectUrlConfig(); + sysConfig.setEnabled(ENABLED); + sysConfig.setDefaultExpiryTimeInSec(SYS_DEFAULT_EXPIRY_TIME_IN_SECS); + sysConfig.setMaxExpiryTimeInSec(SYS_MAX_EXPIRY_TIME_IN_SECS); + sysConfig.validate(); + contentStoreDirectUrlConfig.setSystemWideDirectUrlConfig(sysConfig); + } +} diff --git a/repository/src/test/java/org/alfresco/repo/content/directurl/SystemWideDirectUrlConfigUnitTest.java b/repository/src/test/java/org/alfresco/repo/content/directurl/SystemWideDirectUrlConfigUnitTest.java new file mode 100644 index 0000000000..d498fac30b --- /dev/null +++ b/repository/src/test/java/org/alfresco/repo/content/directurl/SystemWideDirectUrlConfigUnitTest.java @@ -0,0 +1,153 @@ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2021 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco 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 3 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.content.directurl; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; + +/** + * Tests for system-wide direct access URL configuration settings. + * + * @author Sara Aspery + */ +public class SystemWideDirectUrlConfigUnitTest +{ + private static final Boolean ENABLED = Boolean.TRUE; + private static final Boolean DISABLED = Boolean.FALSE; + + private static final Long DEFAULT_EXPIRY_TIME_IN_SECS = 30L; + private static final Long MAX_EXPIRY_TIME_IN_SECS = 300L; + + private SystemWideDirectUrlConfig systemWideDirectUrlConfig; + + @Before + public void setup() + { + this.systemWideDirectUrlConfig = new SystemWideDirectUrlConfig(); + } + + @Test + public void testValidConfig_RemainsEnabled() + { + setupDirectAccessConfig(ENABLED, DEFAULT_EXPIRY_TIME_IN_SECS, MAX_EXPIRY_TIME_IN_SECS); + + assertTrue("Expected system-wide direct URLs to be enabled", systemWideDirectUrlConfig.isEnabled()); + systemWideDirectUrlConfig.validate(); + assertTrue("Expected system-wide direct URLs to be enabled", systemWideDirectUrlConfig.isEnabled()); + } + + @Test + public void testValidConfig_RemainsDisabled() + { + setupDirectAccessConfig(DISABLED, DEFAULT_EXPIRY_TIME_IN_SECS, MAX_EXPIRY_TIME_IN_SECS); + + assertFalse("Expected system-wide direct URLs to be disabled", systemWideDirectUrlConfig.isEnabled()); + systemWideDirectUrlConfig.validate(); + assertFalse("Expected system-wide direct URLs to be disabled", systemWideDirectUrlConfig.isEnabled()); + } + + @Test + public void testInvalidConfig_DefaultExpiryTimeMissing() + { + setupDirectAccessConfig(ENABLED, null, MAX_EXPIRY_TIME_IN_SECS); + + assertTrue("Expected system-wide direct URLs to be enabled", systemWideDirectUrlConfig.isEnabled()); + systemWideDirectUrlConfig.validate(); + assertFalse("Expected system-wide direct URLs to be disabled", systemWideDirectUrlConfig.isEnabled()); + } + + @Test + public void testInvalidConfig_DefaultExpiryTimeZero() + { + setupDirectAccessConfig(ENABLED, 0L, MAX_EXPIRY_TIME_IN_SECS); + + assertTrue("Expected system-wide direct URLs to be enabled", systemWideDirectUrlConfig.isEnabled()); + systemWideDirectUrlConfig.validate(); + assertFalse("Expected system-wide direct URLs to be disabled", systemWideDirectUrlConfig.isEnabled()); + } + + @Test + public void testInvalidConfig_DefaultExpiryTimeNegative() + { + setupDirectAccessConfig(ENABLED, -1L, MAX_EXPIRY_TIME_IN_SECS); + + assertTrue("Expected system-wide direct URLs to be enabled", systemWideDirectUrlConfig.isEnabled()); + systemWideDirectUrlConfig.validate(); + assertFalse("Expected system-wide direct URLs to be disabled", systemWideDirectUrlConfig.isEnabled()); + } + + @Test + public void testInvalidConfig_MaxExpiryTimeMissing() + { + setupDirectAccessConfig(ENABLED, DEFAULT_EXPIRY_TIME_IN_SECS, null); + + assertTrue("Expected system-wide direct URLs to be enabled", systemWideDirectUrlConfig.isEnabled()); + systemWideDirectUrlConfig.validate(); + assertFalse("Expected system-wide direct URLs to be disabled", systemWideDirectUrlConfig.isEnabled()); + } + + @Test + public void testInvalidConfig_MaxExpiryTimeZero() + { + setupDirectAccessConfig(ENABLED, DEFAULT_EXPIRY_TIME_IN_SECS, 0L); + + assertTrue("Expected system-wide direct URLs to be enabled", systemWideDirectUrlConfig.isEnabled()); + systemWideDirectUrlConfig.validate(); + assertFalse("Expected system-wide direct URLs to be disabled", systemWideDirectUrlConfig.isEnabled()); + } + + @Test + public void testInvalidConfig_MaxExpiryTimeNegative() + { + setupDirectAccessConfig(ENABLED, DEFAULT_EXPIRY_TIME_IN_SECS, -1L); + + assertTrue("Expected system-wide direct URLs to be enabled", systemWideDirectUrlConfig.isEnabled()); + systemWideDirectUrlConfig.validate(); + assertFalse("Expected system-wide direct URLs to be disabled", systemWideDirectUrlConfig.isEnabled()); + } + + @Test + public void testInvalidConfig_DefaultExpiryTimeExceedsMax() + { + setupDirectAccessConfig(ENABLED, MAX_EXPIRY_TIME_IN_SECS + 1, MAX_EXPIRY_TIME_IN_SECS); + + assertTrue("Expected system-wide direct URLs to be enabled", systemWideDirectUrlConfig.isEnabled()); + systemWideDirectUrlConfig.validate(); + assertFalse("Expected system-wide direct URLs to be disabled", systemWideDirectUrlConfig.isEnabled()); + } + + /* Helper method to set system-wide direct access url configuration settings */ + private void setupDirectAccessConfig(Boolean isEnabled, Long defaultExpiryTime, Long maxExpiryTime) + { + systemWideDirectUrlConfig.setEnabled(isEnabled); + systemWideDirectUrlConfig.setDefaultExpiryTimeInSec(defaultExpiryTime); + systemWideDirectUrlConfig.setMaxExpiryTimeInSec(maxExpiryTime); + } +} +