mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-09-24 14:32:01 +00:00
Compare commits
23 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
17eef66f5c | ||
|
1d1f269a70 | ||
|
2ccf6044b8 | ||
|
bdd09784e1 | ||
|
de5d70be46 | ||
|
8cacba0988 | ||
|
60187bf9a2 | ||
|
ff4634be19 | ||
|
9c64b45908 | ||
|
d97d8fba04 | ||
|
368b571d9c | ||
|
e9da7d222b | ||
|
8c059460f9 | ||
|
bd0aaa08b3 | ||
|
93d678dc30 | ||
|
9648189827 | ||
|
9bfd274127 | ||
|
dcf9f65f6b | ||
|
784fae5834 | ||
|
eddd8a1065 | ||
|
0941746518 | ||
|
a1f0f35f60 | ||
|
25d96a50cd |
@@ -1273,7 +1273,7 @@
|
||||
"filename": "repository/src/main/resources/alfresco/repository.properties",
|
||||
"hashed_secret": "84551ae5442affc9f1a2d3b4c86ae8b24860149d",
|
||||
"is_verified": false,
|
||||
"line_number": 770,
|
||||
"line_number": 771,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -4,7 +4,7 @@
|
||||
|
||||
# Version label
|
||||
version.major=23
|
||||
version.minor=5
|
||||
version.minor=6
|
||||
version.revision=0
|
||||
version.label=
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -9,6 +9,6 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
</project>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<organization>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -26,6 +26,13 @@
|
||||
package org.alfresco.rest.rules;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
import static org.springframework.http.HttpStatus.CREATED;
|
||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
||||
import static org.springframework.http.HttpStatus.NOT_FOUND;
|
||||
|
||||
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.ERROR_MESSAGE_ACCESS_RESTRICTED;
|
||||
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.MAIL_ACTION;
|
||||
import static org.alfresco.rest.rules.RulesTestsUtils.CHECKIN_ACTION;
|
||||
@@ -45,11 +52,6 @@ import static org.alfresco.utility.model.FileModel.getRandomFileModel;
|
||||
import static org.alfresco.utility.model.FileType.TEXT_PLAIN;
|
||||
import static org.alfresco.utility.model.UserModel.getRandomUserModel;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
import static org.springframework.http.HttpStatus.CREATED;
|
||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
||||
import static org.springframework.http.HttpStatus.NOT_FOUND;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
@@ -61,10 +63,13 @@ import java.util.stream.IntStream;
|
||||
import jakarta.json.Json;
|
||||
import jakarta.json.JsonObject;
|
||||
|
||||
import org.apache.chemistry.opencmis.client.api.CmisObject;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import org.alfresco.rest.model.RestActionBodyExecTemplateModel;
|
||||
import org.alfresco.rest.model.RestActionConstraintModel;
|
||||
import org.alfresco.rest.model.RestCompositeConditionDefinitionModel;
|
||||
import org.alfresco.rest.model.RestPaginationModel;
|
||||
import org.alfresco.rest.model.RestRuleModel;
|
||||
import org.alfresco.rest.model.RestRuleModelsCollection;
|
||||
import org.alfresco.utility.constants.UserRole;
|
||||
@@ -74,9 +79,6 @@ import org.alfresco.utility.model.FolderModel;
|
||||
import org.alfresco.utility.model.SiteModel;
|
||||
import org.alfresco.utility.model.TestGroup;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.apache.chemistry.opencmis.client.api.CmisObject;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Tests for POST /nodes/{nodeId}/rule-sets/{ruleSetId}/rules.
|
||||
@@ -101,7 +103,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
* <p>
|
||||
* Also check that the isShared field is not returned when not requested.
|
||||
*/
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY})
|
||||
public void createRule()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModelWithModifiedValues();
|
||||
@@ -117,7 +119,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check creating a rule in a non-existent folder returns an error. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleInNonExistentFolder()
|
||||
{
|
||||
STEP("Try to create a rule in non-existent folder.");
|
||||
@@ -134,7 +136,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check creating a rule in a non-existent rule set returns an error. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleInNonExistentRuleSet()
|
||||
{
|
||||
STEP("Try to create a rule in non-existent rule set.");
|
||||
@@ -148,7 +150,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Try to create a rule without a name and check the error. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleWithEmptyName()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModel("");
|
||||
@@ -160,7 +162,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check we can create two rules with the same name. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void duplicateRuleNameIsAcceptable()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModel("duplicateRuleName");
|
||||
@@ -175,7 +177,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that a user without permission to view the folder cannot create a rule in it. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void requireReadPermissionToCreateRule()
|
||||
{
|
||||
STEP("Create a user and use them to create a private site containing a folder");
|
||||
@@ -194,7 +196,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that a Collaborator cannot create a rule in a folder in a private site. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void siteCollaboratorCannotCreateRule()
|
||||
{
|
||||
testRolePermissionsWith(SiteCollaborator);
|
||||
@@ -204,7 +206,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that a Contributor cannot create a rule in a private folder. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void siteContributorCannotCreateRule()
|
||||
{
|
||||
testRolePermissionsWith(SiteContributor);
|
||||
@@ -214,7 +216,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that a Consumer cannot create a rule in a folder in a private site. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void siteConsumerCannotCreateRule()
|
||||
{
|
||||
testRolePermissionsWith(SiteConsumer);
|
||||
@@ -224,7 +226,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that a siteManager can create a rule in a folder in a private site. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void siteManagerCanCreateRule()
|
||||
{
|
||||
testRolePermissionsWith(SiteManager)
|
||||
@@ -234,7 +236,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check we can't create a rule under a document node. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void tryToCreateRuleUnderDocument()
|
||||
{
|
||||
STEP("Create a document.");
|
||||
@@ -250,7 +252,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check we can create several rules. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRules()
|
||||
{
|
||||
STEP("Create a list of rules in one POST request");
|
||||
@@ -263,14 +265,13 @@ public class CreateRulesTests extends RulesRestTest
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
|
||||
assertEquals("Unexpected number of rules received in response.", ruleNames.size(), rules.getEntries().size());
|
||||
IntStream.range(0, ruleModels.size()).forEach(i ->
|
||||
rules.getEntries().get(i).onModel()
|
||||
IntStream.range(0, ruleModels.size()).forEach(i -> rules.getEntries().get(i).onModel()
|
||||
.assertThat().field("id").isNotNull()
|
||||
.assertThat().field("name").is(ruleNames.get(i)));
|
||||
}
|
||||
|
||||
/** Check we can create over 100 rules and get them all back in response. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createOver100Rules()
|
||||
{
|
||||
STEP("Create a list of 120 rules in one POST request");
|
||||
@@ -287,8 +288,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
|
||||
assertEquals("Unexpected number of rules received in response.", ruleCount, rules.getEntries().size());
|
||||
IntStream.range(0, ruleModels.size()).forEach(i ->
|
||||
rules.getEntries().get(i).onModel()
|
||||
IntStream.range(0, ruleModels.size()).forEach(i -> rules.getEntries().get(i).onModel()
|
||||
.assertThat().field("id").isNotNull()
|
||||
.assertThat().field("name").is(ruleNamePrefix + (i + 1)));
|
||||
|
||||
@@ -302,7 +302,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Try to create several rules with an error in one of them. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRulesWithOneError()
|
||||
{
|
||||
STEP("Try to create a three rules but the middle one has an error.");
|
||||
@@ -319,7 +319,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check we can create a rule without description. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleWithoutDescription()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
@@ -335,7 +335,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check we can create a rule without specifying triggers but with the default "inbound" value. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleWithoutTriggers()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
@@ -351,7 +351,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check we can create a rule without error script. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleWithoutErrorScript()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
@@ -367,7 +367,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check we can create a rule with irrelevant isShared flag, and it doesn't have impact to the process. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleWithSharedFlag()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
@@ -384,7 +384,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check we can create a rule. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY})
|
||||
public void createRuleAndIncludeFieldsInResponse()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModel("ruleName");
|
||||
@@ -412,7 +412,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that the folder's owner can create rules, even if it is in a private site they aren't a member of. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void checkOwnerCanCreateRule()
|
||||
{
|
||||
STEP("Use admin to create a private site.");
|
||||
@@ -431,7 +431,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that an administrator can create a rule in a private site even if they aren't a member. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void checkAdminCanCreateRule()
|
||||
{
|
||||
STEP("Use a user to create a private site with a folder.");
|
||||
@@ -446,7 +446,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that a coordinator can create rules in folders outside sites. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void checkCoordinatorCanCreateRule()
|
||||
{
|
||||
STEP("Create a folder in the user's file space.");
|
||||
@@ -454,11 +454,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
|
||||
STEP("Create another user as a coordinator for this folder.");
|
||||
UserModel coordinator = dataUser.createRandomTestUser("Rules");
|
||||
/*
|
||||
Update folder node properties to add a coordinator
|
||||
{ "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "coordinator.getUsername()",
|
||||
"name": "Coordinator", "accessStatus":"ALLOWED" } } }
|
||||
*/
|
||||
/* Update folder node properties to add a coordinator { "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "coordinator.getUsername()", "name": "Coordinator", "accessStatus":"ALLOWED" } } } */
|
||||
String putBody = getAddPermissionsBody(coordinator.getUsername(), "Coordinator");
|
||||
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).updateNode(putBody);
|
||||
|
||||
@@ -470,7 +466,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that an editor cannot create rules in folders outside sites. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void checkEditorCannotCreateRule()
|
||||
{
|
||||
STEP("Create a folder in the user's file space.");
|
||||
@@ -478,11 +474,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
|
||||
STEP("Create another user as a editor for this folder.");
|
||||
UserModel editor = dataUser.createRandomTestUser();
|
||||
/*
|
||||
Update folder node properties to add an editor
|
||||
{ "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "editor.getUsername()",
|
||||
"name": "Coordinator", "accessStatus":"ALLOWED" } } }
|
||||
*/
|
||||
/* Update folder node properties to add an editor { "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "editor.getUsername()", "name": "Coordinator", "accessStatus":"ALLOWED" } } } */
|
||||
String putBody = getAddPermissionsBody(editor.getUsername(), "Editor");
|
||||
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).updateNode(putBody);
|
||||
|
||||
@@ -494,7 +486,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
}
|
||||
|
||||
/** Check that a collaborator cannot create rules in folders outside sites. */
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void checkCollaboratorCannotCreateRule()
|
||||
{
|
||||
STEP("Create a folder in the user's file space.");
|
||||
@@ -502,11 +494,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
|
||||
STEP("Create another user as a collaborator for this folder.");
|
||||
UserModel collaborator = dataUser.createRandomTestUser();
|
||||
/*
|
||||
Update folder node properties to add a collaborator
|
||||
{ "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "collaborator.getUsername()",
|
||||
"name": "Coordinator", "accessStatus":"ALLOWED" } } }
|
||||
*/
|
||||
/* Update folder node properties to add a collaborator { "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "collaborator.getUsername()", "name": "Coordinator", "accessStatus":"ALLOWED" } } } */
|
||||
String putBody = getAddPermissionsBody(collaborator.getUsername(), "Collaborator");
|
||||
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).updateNode(putBody);
|
||||
|
||||
@@ -656,8 +644,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
public void createRuleWithNotApplicableActionShouldFail()
|
||||
{
|
||||
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
final RestActionBodyExecTemplateModel invalidAction =
|
||||
rulesUtils.createCustomActionModel(RulesTestsUtils.DELETE_RENDITION_ACTION, Map.of("dummy-key", "dummy-value"));
|
||||
final RestActionBodyExecTemplateModel invalidAction = rulesUtils.createCustomActionModel(RulesTestsUtils.DELETE_RENDITION_ACTION, Map.of("dummy-key", "dummy-value"));
|
||||
ruleModel.setActions(List.of(invalidAction));
|
||||
|
||||
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
|
||||
@@ -673,8 +660,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
public void createRuleWithMissingActionParametersShouldFail()
|
||||
{
|
||||
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
final RestActionBodyExecTemplateModel invalidAction =
|
||||
rulesUtils.createCustomActionModel(RulesTestsUtils.COPY_ACTION, Collections.emptyMap());
|
||||
final RestActionBodyExecTemplateModel invalidAction = rulesUtils.createCustomActionModel(RulesTestsUtils.COPY_ACTION, Collections.emptyMap());
|
||||
ruleModel.setActions(List.of(invalidAction));
|
||||
|
||||
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
@@ -736,7 +722,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
public void createRuleWithoutMandatoryActionParametersShouldFail()
|
||||
{
|
||||
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
final RestActionBodyExecTemplateModel invalidAction = rulesUtils.createCustomActionModel(COPY_ACTION, Map.of("deep-copy",false));
|
||||
final RestActionBodyExecTemplateModel invalidAction = rulesUtils.createCustomActionModel(COPY_ACTION, Map.of("deep-copy", false));
|
||||
ruleModel.setActions(List.of(invalidAction));
|
||||
|
||||
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
|
||||
@@ -749,7 +735,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
/**
|
||||
* Check we get error when attempting to create a rule that copies files to a non-existent folder.
|
||||
*/
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleThatUsesNonExistentNode()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
@@ -761,13 +747,13 @@ public class CreateRulesTests extends RulesRestTest
|
||||
.createSingleRule(ruleModel);
|
||||
|
||||
restClient.assertStatusCodeIs(NOT_FOUND);
|
||||
restClient.assertLastError().containsSummary("The entity with id: non-existent-node was not found");
|
||||
restClient.assertLastError().containsSummary("Destination folder having Id: non-existent-node no longer exists. Please update your rule definition.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check we get error when attempting to create a rule that references a folder that the user does not have read permission for.
|
||||
*/
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleThatUsesNodeWithoutReadPermission()
|
||||
{
|
||||
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
|
||||
@@ -788,7 +774,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
/**
|
||||
* Check we get error when attempting to create a rule that copies files to a folder that a user only has read permission for.
|
||||
*/
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void createRuleThatWritesToNodeWithoutPermission()
|
||||
{
|
||||
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
|
||||
@@ -828,7 +814,6 @@ public class CreateRulesTests extends RulesRestTest
|
||||
restClient.assertLastError().containsSummary("Node is not a folder " + fileModel.getNodeRef());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check we get error when attempting to create a rule with mail action defined with non-existing mail template.
|
||||
*/
|
||||
@@ -860,7 +845,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
/**
|
||||
* Check the user can create a rule with a script.
|
||||
*/
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void checkCanUseScriptInRule()
|
||||
{
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
@@ -877,7 +862,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
/**
|
||||
* Check the script has to be stored in the scripts directory in the data dictionary.
|
||||
*/
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void checkCantUseNodeOutsideScriptsDirectory()
|
||||
{
|
||||
STEP("Copy script to location outside data dictionary.");
|
||||
@@ -907,7 +892,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
/**
|
||||
* Check a real category needs to be supplied when linking to a category.
|
||||
*/
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
|
||||
public void checkLinkToCategoryNeedsRealCategory()
|
||||
{
|
||||
STEP("Attempt to link to a category with a folder node, rather than a category node.");
|
||||
@@ -970,9 +955,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
String fakeCategoryId = "bdba5f9f-fake-id22-803b-349bcfd06fd1";
|
||||
RestCompositeConditionDefinitionModel conditions = rulesUtils.createCompositeCondition(List.of(
|
||||
rulesUtils.createCompositeCondition(!INVERTED, List.of(
|
||||
rulesUtils.createSimpleCondition("category", "equals", fakeCategoryId)
|
||||
))
|
||||
));
|
||||
rulesUtils.createSimpleCondition("category", "equals", fakeCategoryId)))));
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
ruleModel.setConditions(conditions);
|
||||
|
||||
@@ -992,9 +975,7 @@ public class CreateRulesTests extends RulesRestTest
|
||||
final String comparator = "greaterthan";
|
||||
RestCompositeConditionDefinitionModel conditions = rulesUtils.createCompositeCondition(List.of(
|
||||
rulesUtils.createCompositeCondition(!INVERTED, List.of(
|
||||
rulesUtils.createSimpleCondition("size", comparator, "500")
|
||||
))
|
||||
));
|
||||
rulesUtils.createSimpleCondition("size", comparator, "500")))));
|
||||
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
|
||||
ruleModel.setConditions(conditions);
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
18
pom.xml
18
pom.xml
@@ -2,7 +2,7 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Alfresco Community Repo Parent</name>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
<properties>
|
||||
<acs.version.major>23</acs.version.major>
|
||||
<acs.version.minor>5</acs.version.minor>
|
||||
<acs.version.minor>6</acs.version.minor>
|
||||
<acs.version.revision>0</acs.version.revision>
|
||||
<acs.version.label />
|
||||
<amp.min.version>${acs.version.major}.0.0</amp.min.version>
|
||||
@@ -57,13 +57,13 @@
|
||||
<dependency.acs-event-model.version>0.0.33</dependency.acs-event-model.version>
|
||||
|
||||
<dependency.aspectj.version>1.9.22.1</dependency.aspectj.version>
|
||||
<dependency.spring.version>6.1.14</dependency.spring.version>
|
||||
<dependency.spring-security.version>6.3.8</dependency.spring-security.version>
|
||||
<dependency.spring.version>6.2.8</dependency.spring.version>
|
||||
<dependency.spring-security.version>6.3.9</dependency.spring-security.version>
|
||||
<dependency.antlr.version>3.5.3</dependency.antlr.version>
|
||||
<dependency.jackson.version>2.17.2</dependency.jackson.version>
|
||||
<dependency.cxf.version>4.1.0</dependency.cxf.version>
|
||||
<dependency.opencmis.version>1.0.0-jakarta-1</dependency.opencmis.version>
|
||||
<dependency.webscripts.version>9.4</dependency.webscripts.version>
|
||||
<dependency.webscripts.version>10.2</dependency.webscripts.version>
|
||||
<dependency.bouncycastle.version>1.78.1</dependency.bouncycastle.version>
|
||||
<dependency.mockito-core.version>5.14.1</dependency.mockito-core.version>
|
||||
<dependency.assertj.version>3.26.3</dependency.assertj.version>
|
||||
@@ -154,7 +154,7 @@
|
||||
<connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
|
||||
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
|
||||
<url>https://github.com/Alfresco/alfresco-community-repo</url>
|
||||
<tag>23.5.0.19</tag>
|
||||
<tag>23.6.0.7</tag>
|
||||
</scm>
|
||||
|
||||
<distributionManagement>
|
||||
@@ -409,7 +409,7 @@
|
||||
<dependency>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
<version>1.9.4</version>
|
||||
<version>1.11.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
@@ -439,8 +439,8 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-fileupload2-jakarta</artifactId>
|
||||
<version>2.0.0-M1</version>
|
||||
<artifactId>commons-fileupload2-jakarta-servlet6</artifactId>
|
||||
<version>2.0.0-M4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-net</groupId>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -34,7 +34,7 @@ import org.alfresco.repo.management.subsystems.ActivateableBean;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.external.AdminConsoleAuthenticator;
|
||||
import org.alfresco.repo.security.authentication.external.ExternalUserAuthenticator;
|
||||
import org.alfresco.repo.security.authentication.external.RemoteUserMapper;
|
||||
import org.alfresco.repo.web.auth.AuthenticationListener;
|
||||
import org.alfresco.repo.web.auth.TicketCredentials;
|
||||
@@ -73,9 +73,11 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor
|
||||
|
||||
protected RemoteUserMapper remoteUserMapper;
|
||||
protected AuthenticationComponent authenticationComponent;
|
||||
protected AdminConsoleAuthenticator adminConsoleAuthenticator;
|
||||
protected ExternalUserAuthenticator adminConsoleAuthenticator;
|
||||
protected ExternalUserAuthenticator webScriptsHomeAuthenticator;
|
||||
|
||||
private boolean alwaysAllowBasicAuthForAdminConsole = true;
|
||||
private boolean alwaysAllowBasicAuthForWebScriptsHome = true;
|
||||
List<String> adminConsoleScriptFamilies;
|
||||
long getRemoteUserTimeoutMilliseconds = GET_REMOTE_USER_TIMEOUT_MILLISECONDS_DEFAULT;
|
||||
|
||||
@@ -100,6 +102,16 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor
|
||||
this.alwaysAllowBasicAuthForAdminConsole = alwaysAllowBasicAuthForAdminConsole;
|
||||
}
|
||||
|
||||
public boolean isAlwaysAllowBasicAuthForWebScriptsHome()
|
||||
{
|
||||
return alwaysAllowBasicAuthForWebScriptsHome;
|
||||
}
|
||||
|
||||
public void setAlwaysAllowBasicAuthForWebScriptsHome(boolean alwaysAllowBasicAuthForWebScriptsHome)
|
||||
{
|
||||
this.alwaysAllowBasicAuthForWebScriptsHome = alwaysAllowBasicAuthForWebScriptsHome;
|
||||
}
|
||||
|
||||
public List<String> getAdminConsoleScriptFamilies()
|
||||
{
|
||||
return adminConsoleScriptFamilies;
|
||||
@@ -121,11 +133,17 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor
|
||||
}
|
||||
|
||||
public void setAdminConsoleAuthenticator(
|
||||
AdminConsoleAuthenticator adminConsoleAuthenticator)
|
||||
ExternalUserAuthenticator adminConsoleAuthenticator)
|
||||
{
|
||||
this.adminConsoleAuthenticator = adminConsoleAuthenticator;
|
||||
}
|
||||
|
||||
public void setWebScriptsHomeAuthenticator(
|
||||
ExternalUserAuthenticator webScriptsHomeAuthenticator)
|
||||
{
|
||||
this.webScriptsHomeAuthenticator = webScriptsHomeAuthenticator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authenticator create(WebScriptServletRequest req, WebScriptServletResponse res)
|
||||
{
|
||||
@@ -139,6 +157,8 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor
|
||||
*/
|
||||
public class RemoteUserAuthenticator extends BasicHttpAuthenticator
|
||||
{
|
||||
private static final String WEB_SCRIPTS_BASE_PATH = "org/springframework/extensions/webscripts";
|
||||
|
||||
public RemoteUserAuthenticator(WebScriptServletRequest req, WebScriptServletResponse res, AuthenticationListener listener)
|
||||
{
|
||||
super(req, res, listener);
|
||||
@@ -159,24 +179,47 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor
|
||||
{
|
||||
|
||||
if (servletReq.getServiceMatch() != null &&
|
||||
isAdminConsoleWebScript(servletReq.getServiceMatch().getWebScript()) && isAdminConsoleAuthenticatorActive())
|
||||
isAdminConsole(servletReq.getServiceMatch().getWebScript()) && isAdminConsoleAuthenticatorActive())
|
||||
{
|
||||
userId = getAdminConsoleUser();
|
||||
}
|
||||
else if (servletReq.getServiceMatch() != null &&
|
||||
isWebScriptsHome(servletReq.getServiceMatch().getWebScript()) && isWebScriptsHomeAuthenticatorActive())
|
||||
{
|
||||
userId = getWebScriptsHomeUser();
|
||||
}
|
||||
|
||||
if (userId == null)
|
||||
{
|
||||
if (isAlwaysAllowBasicAuthForAdminConsole())
|
||||
{
|
||||
final boolean useTimeoutForAdminAccessingAdminConsole = shouldUseTimeoutForAdminAccessingAdminConsole(required, isGuest);
|
||||
boolean shouldUseTimeout = shouldUseTimeoutForAdminAccessingAdminConsole(required, isGuest);
|
||||
|
||||
if (useTimeoutForAdminAccessingAdminConsole && isBasicAuthHeaderPresentForAdmin())
|
||||
if (shouldUseTimeout && isBasicAuthHeaderPresentForAdmin())
|
||||
{
|
||||
return callBasicAuthForAdminConsoleAccess(required, isGuest);
|
||||
return callBasicAuthForAdminConsoleOrWebScriptsHomeAccess(required, isGuest);
|
||||
}
|
||||
try
|
||||
{
|
||||
userId = getRemoteUserWithTimeout(useTimeoutForAdminAccessingAdminConsole);
|
||||
userId = getRemoteUserWithTimeout(shouldUseTimeout);
|
||||
}
|
||||
catch (AuthenticationTimeoutException e)
|
||||
{
|
||||
// return basic auth challenge
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (isAlwaysAllowBasicAuthForWebScriptsHome())
|
||||
{
|
||||
boolean shouldUseTimeout = shouldUseTimeoutForAdminAccessingWebScriptsHome(required, isGuest);
|
||||
|
||||
if (shouldUseTimeout && isBasicAuthHeaderPresentForAdmin())
|
||||
{
|
||||
return callBasicAuthForAdminConsoleOrWebScriptsHomeAccess(required, isGuest);
|
||||
}
|
||||
try
|
||||
{
|
||||
userId = getRemoteUserWithTimeout(shouldUseTimeout);
|
||||
}
|
||||
catch (AuthenticationTimeoutException e)
|
||||
{
|
||||
@@ -255,38 +298,63 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor
|
||||
authenticated = super.authenticate(required, isGuest);
|
||||
}
|
||||
}
|
||||
if(!authenticated && servletReq.getServiceMatch() != null &&
|
||||
isAdminConsoleWebScript(servletReq.getServiceMatch().getWebScript()) && isAdminConsoleAuthenticatorActive())
|
||||
if (!authenticated && servletReq.getServiceMatch() != null)
|
||||
{
|
||||
adminConsoleAuthenticator.requestAuthentication(this.servletReq.getHttpServletRequest(), this.servletRes.getHttpServletResponse());
|
||||
WebScript webScript = servletReq.getServiceMatch().getWebScript();
|
||||
|
||||
if (isAdminConsole(webScript) && isAdminConsoleAuthenticatorActive())
|
||||
{
|
||||
adminConsoleAuthenticator.requestAuthentication(
|
||||
this.servletReq.getHttpServletRequest(),
|
||||
this.servletRes.getHttpServletResponse());
|
||||
}
|
||||
else if (isWebScriptsHome(webScript)
|
||||
&& isWebScriptsHomeAuthenticatorActive())
|
||||
{
|
||||
webScriptsHomeAuthenticator.requestAuthentication(
|
||||
this.servletReq.getHttpServletRequest(),
|
||||
this.servletRes.getHttpServletResponse());
|
||||
}
|
||||
}
|
||||
return authenticated;
|
||||
}
|
||||
|
||||
private boolean callBasicAuthForAdminConsoleAccess(RequiredAuthentication required, boolean isGuest)
|
||||
private boolean callBasicAuthForAdminConsoleOrWebScriptsHomeAccess(RequiredAuthentication required, boolean isGuest)
|
||||
{
|
||||
// return REST call, after a timeout/basic auth challenge
|
||||
if (LOGGER.isTraceEnabled())
|
||||
{
|
||||
LOGGER.trace("An Admin Console request has come in with Basic Auth headers present for an admin user.");
|
||||
LOGGER.trace("An Admin Console or WebScripts Home request has come in with Basic Auth headers present for an admin user.");
|
||||
}
|
||||
// In order to prompt for another password, in case it was not entered correctly,
|
||||
// the output of this method should be returned by the calling "authenticate" method;
|
||||
// This would also mean, that once the admin basic auth header is present,
|
||||
// the authentication chain will not be used for the admin console access
|
||||
// the authentication chain will not be used for access
|
||||
return super.authenticate(required, isGuest);
|
||||
}
|
||||
|
||||
private boolean shouldUseTimeoutForAdminAccessingAdminConsole(RequiredAuthentication required, boolean isGuest)
|
||||
{
|
||||
boolean useTimeoutForAdminAccessingAdminConsole = RequiredAuthentication.admin.equals(required) && !isGuest &&
|
||||
servletReq.getServiceMatch() != null && isAdminConsoleWebScript(servletReq.getServiceMatch().getWebScript());
|
||||
boolean adminConsoleTimeout = RequiredAuthentication.admin.equals(required) && !isGuest &&
|
||||
servletReq.getServiceMatch() != null && isAdminConsole(servletReq.getServiceMatch().getWebScript());
|
||||
|
||||
if (LOGGER.isTraceEnabled())
|
||||
{
|
||||
LOGGER.trace("Should ensure that the admins can login with basic auth: " + useTimeoutForAdminAccessingAdminConsole);
|
||||
LOGGER.trace("Should ensure that the admins can login with basic auth: " + adminConsoleTimeout);
|
||||
}
|
||||
return useTimeoutForAdminAccessingAdminConsole;
|
||||
return adminConsoleTimeout;
|
||||
}
|
||||
|
||||
private boolean shouldUseTimeoutForAdminAccessingWebScriptsHome(RequiredAuthentication required, boolean isGuest)
|
||||
{
|
||||
boolean adminWebScriptsHomeTimeout = RequiredAuthentication.admin.equals(required) && !isGuest &&
|
||||
servletReq.getServiceMatch() != null && isWebScriptsHome(servletReq.getServiceMatch().getWebScript());
|
||||
|
||||
if (LOGGER.isTraceEnabled())
|
||||
{
|
||||
LOGGER.trace("Should ensure that the admins can login with basic auth: " + adminWebScriptsHomeTimeout);
|
||||
}
|
||||
return adminWebScriptsHomeTimeout;
|
||||
}
|
||||
|
||||
private boolean isRemoteUserMapperActive()
|
||||
@@ -299,7 +367,12 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor
|
||||
return adminConsoleAuthenticator != null && (!(adminConsoleAuthenticator instanceof ActivateableBean) || ((ActivateableBean) adminConsoleAuthenticator).isActive());
|
||||
}
|
||||
|
||||
protected boolean isAdminConsoleWebScript(WebScript webScript)
|
||||
private boolean isWebScriptsHomeAuthenticatorActive()
|
||||
{
|
||||
return webScriptsHomeAuthenticator != null && (!(webScriptsHomeAuthenticator instanceof ActivateableBean) || ((ActivateableBean) webScriptsHomeAuthenticator).isActive());
|
||||
}
|
||||
|
||||
protected boolean isAdminConsole(WebScript webScript)
|
||||
{
|
||||
if (webScript == null || adminConsoleScriptFamilies == null || webScript.getDescription() == null
|
||||
|| webScript.getDescription().getFamilys() == null)
|
||||
@@ -313,7 +386,7 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor
|
||||
}
|
||||
|
||||
// intersect the "family" sets defined
|
||||
Set<String> families = new HashSet<String>(webScript.getDescription().getFamilys());
|
||||
Set<String> families = new HashSet<>(webScript.getDescription().getFamilys());
|
||||
families.retainAll(adminConsoleScriptFamilies);
|
||||
final boolean isAdminConsole = !families.isEmpty();
|
||||
|
||||
@@ -325,6 +398,23 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor
|
||||
return isAdminConsole;
|
||||
}
|
||||
|
||||
protected boolean isWebScriptsHome(WebScript webScript)
|
||||
{
|
||||
if (webScript == null || webScript.toString() == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isWebScriptsHome = webScript.toString().startsWith(WEB_SCRIPTS_BASE_PATH);
|
||||
|
||||
if (LOGGER.isTraceEnabled() && isWebScriptsHome)
|
||||
{
|
||||
LOGGER.trace("Detected a WebScripts Home webscript: " + webScript);
|
||||
}
|
||||
|
||||
return isWebScriptsHome;
|
||||
}
|
||||
|
||||
protected String getRemoteUserWithTimeout(boolean useTimeout) throws AuthenticationTimeoutException
|
||||
{
|
||||
if (!useTimeout)
|
||||
@@ -423,7 +513,21 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor
|
||||
|
||||
if (isRemoteUserMapperActive())
|
||||
{
|
||||
userId = adminConsoleAuthenticator.getAdminConsoleUser(this.servletReq.getHttpServletRequest(), this.servletRes.getHttpServletResponse());
|
||||
userId = adminConsoleAuthenticator.getUserId(this.servletReq.getHttpServletRequest(), this.servletRes.getHttpServletResponse());
|
||||
}
|
||||
|
||||
logRemoteUserID(userId);
|
||||
|
||||
return userId;
|
||||
}
|
||||
|
||||
protected String getWebScriptsHomeUser()
|
||||
{
|
||||
String userId = null;
|
||||
|
||||
if (isRemoteUserMapperActive())
|
||||
{
|
||||
userId = webScriptsHomeAuthenticator.getUserId(this.servletReq.getHttpServletRequest(), this.servletRes.getHttpServletResponse());
|
||||
}
|
||||
|
||||
logRemoteUserID(userId);
|
||||
|
@@ -28,11 +28,9 @@ package org.alfresco.repo.web.scripts.transfer;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.alfresco.service.cmr.transfer.TransferException;
|
||||
import org.alfresco.service.cmr.transfer.TransferReceiver;
|
||||
import org.apache.commons.fileupload2.core.FileItemInput;
|
||||
import org.apache.commons.fileupload2.core.FileItemInputIterator;
|
||||
import org.apache.commons.fileupload2.jakarta.JakartaServletFileUpload;
|
||||
import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletFileUpload;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
@@ -41,6 +39,9 @@ import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||
import org.springframework.extensions.webscripts.WrappingWebScriptRequest;
|
||||
import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest;
|
||||
|
||||
import org.alfresco.service.cmr.transfer.TransferException;
|
||||
import org.alfresco.service.cmr.transfer.TransferReceiver;
|
||||
|
||||
/**
|
||||
* This command processor is used to receive one or more content files for a given transfer.
|
||||
*
|
||||
@@ -64,12 +65,9 @@ public class PostContentCommandProcessor implements CommandProcessor
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
/* (non-Javadoc)
|
||||
*
|
||||
* @see org.alfresco.repo.web.scripts.transfer.CommandProcessor#process(org.alfresco.web.scripts.WebScriptRequest,
|
||||
* org.alfresco.web.scripts.WebScriptResponse)
|
||||
*/
|
||||
* @see org.alfresco.repo.web.scripts.transfer.CommandProcessor#process(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) */
|
||||
public int process(WebScriptRequest req, WebScriptResponse resp)
|
||||
{
|
||||
logger.debug("post content start");
|
||||
@@ -91,8 +89,7 @@ public class PostContentCommandProcessor implements CommandProcessor
|
||||
{
|
||||
current = null;
|
||||
}
|
||||
}
|
||||
while (current != null);
|
||||
} while (current != null);
|
||||
if (webScriptServletRequest == null)
|
||||
{
|
||||
resp.setStatus(Status.STATUS_BAD_REQUEST);
|
||||
@@ -101,7 +98,7 @@ public class PostContentCommandProcessor implements CommandProcessor
|
||||
|
||||
HttpServletRequest servletRequest = webScriptServletRequest.getHttpServletRequest();
|
||||
|
||||
//Read the transfer id from the request
|
||||
// Read the transfer id from the request
|
||||
String transferId = servletRequest.getParameter("transferId");
|
||||
|
||||
if ((transferId == null) || !JakartaServletFileUpload.isMultipartContent(servletRequest))
|
||||
@@ -126,23 +123,23 @@ public class PostContentCommandProcessor implements CommandProcessor
|
||||
}
|
||||
}
|
||||
|
||||
// WebScriptServletRequest alfRequest = (WebScriptServletRequest)req;
|
||||
// String[] names = alfRequest.getParameterNames();
|
||||
// for(String name : names)
|
||||
// {
|
||||
// FormField item = alfRequest.getFileField(name);
|
||||
//
|
||||
// if(item != null)
|
||||
// {
|
||||
// logger.debug("got content Mime Part : " + name);
|
||||
// receiver.saveContent(transferId, item.getName(), item.getInputStream());
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// //TODO - should this be an exception?
|
||||
// logger.debug("Unable to get content for Mime Part : " + name);
|
||||
// }
|
||||
// }
|
||||
// WebScriptServletRequest alfRequest = (WebScriptServletRequest)req;
|
||||
// String[] names = alfRequest.getParameterNames();
|
||||
// for(String name : names)
|
||||
// {
|
||||
// FormField item = alfRequest.getFileField(name);
|
||||
//
|
||||
// if(item != null)
|
||||
// {
|
||||
// logger.debug("got content Mime Part : " + name);
|
||||
// receiver.saveContent(transferId, item.getName(), item.getInputStream());
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// //TODO - should this be an exception?
|
||||
// logger.debug("Unable to get content for Mime Part : " + name);
|
||||
// }
|
||||
// }
|
||||
|
||||
logger.debug("success");
|
||||
|
||||
@@ -151,7 +148,7 @@ public class PostContentCommandProcessor implements CommandProcessor
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.debug("exception caught", ex);
|
||||
if(transferId != null)
|
||||
if (transferId != null)
|
||||
{
|
||||
logger.debug("ending transfer", ex);
|
||||
receiver.end(transferId);
|
||||
|
@@ -27,15 +27,11 @@
|
||||
package org.alfresco.repo.web.scripts.transfer;
|
||||
|
||||
import java.io.OutputStream;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.alfresco.repo.transfer.TransferCommons;
|
||||
import org.alfresco.service.cmr.transfer.TransferException;
|
||||
import org.alfresco.service.cmr.transfer.TransferReceiver;
|
||||
import org.apache.commons.fileupload2.core.FileItemInput;
|
||||
import org.apache.commons.fileupload2.core.FileItemInputIterator;
|
||||
import org.apache.commons.fileupload2.jakarta.JakartaServletFileUpload;
|
||||
import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletFileUpload;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
@@ -44,6 +40,10 @@ import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||
import org.springframework.extensions.webscripts.WrappingWebScriptRequest;
|
||||
import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest;
|
||||
|
||||
import org.alfresco.repo.transfer.TransferCommons;
|
||||
import org.alfresco.service.cmr.transfer.TransferException;
|
||||
import org.alfresco.service.cmr.transfer.TransferReceiver;
|
||||
|
||||
/**
|
||||
* This command processor is used to receive the snapshot for a given transfer.
|
||||
*
|
||||
@@ -59,8 +59,8 @@ public class PostSnapshotCommandProcessor implements CommandProcessor
|
||||
private static final String MSG_CAUGHT_UNEXPECTED_EXCEPTION = "transfer_service.receiver.caught_unexpected_exception";
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.web.scripts.transfer.CommandProcessor#process(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
|
||||
*/
|
||||
*
|
||||
* @see org.alfresco.repo.web.scripts.transfer.CommandProcessor#process(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse) */
|
||||
public int process(WebScriptRequest req, WebScriptResponse resp)
|
||||
{
|
||||
|
||||
@@ -83,8 +83,7 @@ public class PostSnapshotCommandProcessor implements CommandProcessor
|
||||
{
|
||||
current = null;
|
||||
}
|
||||
}
|
||||
while (current != null);
|
||||
} while (current != null);
|
||||
if (webScriptServletRequest == null)
|
||||
{
|
||||
logger.debug("bad request, not assignable from");
|
||||
@@ -92,11 +91,11 @@ public class PostSnapshotCommandProcessor implements CommandProcessor
|
||||
return Status.STATUS_BAD_REQUEST;
|
||||
}
|
||||
|
||||
//We can't use the WebScriptRequest version of getParameter, since that may cause the content stream
|
||||
//to be parsed. Get hold of the raw HttpServletRequest and work with that.
|
||||
// We can't use the WebScriptRequest version of getParameter, since that may cause the content stream
|
||||
// to be parsed. Get hold of the raw HttpServletRequest and work with that.
|
||||
HttpServletRequest servletRequest = webScriptServletRequest.getHttpServletRequest();
|
||||
|
||||
//Read the transfer id from the request
|
||||
// Read the transfer id from the request
|
||||
String transferId = servletRequest.getParameter("transferId");
|
||||
|
||||
if ((transferId == null) || !JakartaServletFileUpload.isMultipartContent(servletRequest))
|
||||
@@ -136,7 +135,7 @@ public class PostSnapshotCommandProcessor implements CommandProcessor
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.debug("exception caught", ex);
|
||||
if(transferId != null)
|
||||
if (transferId != null)
|
||||
{
|
||||
logger.debug("ending transfer", ex);
|
||||
receiver.end(transferId);
|
||||
@@ -151,7 +150,8 @@ public class PostSnapshotCommandProcessor implements CommandProcessor
|
||||
}
|
||||
|
||||
/**
|
||||
* @param receiver the receiver to set
|
||||
* @param receiver
|
||||
* the receiver to set
|
||||
*/
|
||||
public void setReceiver(TransferReceiver receiver)
|
||||
{
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -38,11 +38,19 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.repo.site.SiteModel;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.People;
|
||||
@@ -77,8 +85,6 @@ import org.alfresco.util.AlfrescoCollator;
|
||||
import org.alfresco.util.ISO9075;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
import org.alfresco.util.SearchLanguageConversion;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
|
||||
/**
|
||||
* Queries implementation
|
||||
@@ -88,7 +94,8 @@ import org.springframework.extensions.surf.util.I18NUtil;
|
||||
*/
|
||||
public class QueriesImpl implements Queries, InitializingBean
|
||||
{
|
||||
private final static Map<String,QName> NODE_SORT_PARAMS_TO_QNAMES = sortParamsToQNames(
|
||||
private static final Log LOGGER = LogFactory.getLog(QueriesImpl.class);
|
||||
private final static Map<String, QName> NODE_SORT_PARAMS_TO_QNAMES = sortParamsToQNames(
|
||||
PARAM_NAME, ContentModel.PROP_NAME,
|
||||
PARAM_CREATEDAT, ContentModel.PROP_CREATED,
|
||||
PARAM_MODIFIEDAT, ContentModel.PROP_MODIFIED);
|
||||
@@ -104,23 +111,22 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
PARAM_SITE_DESCRIPTION, ContentModel.PROP_DESCRIPTION);
|
||||
|
||||
/**
|
||||
* Helper method to build a map of sort parameter names to QNames. This method iterates through
|
||||
* the parameters. If a parameter is a String it is assumed to be a sort parameter name and will
|
||||
* be followed by a QName to which it maps. If however it is a QName the local name of the OName
|
||||
* is used as the sort parameter name.
|
||||
* @param parameters to build up the map.
|
||||
* Helper method to build a map of sort parameter names to QNames. This method iterates through the parameters. If a parameter is a String it is assumed to be a sort parameter name and will be followed by a QName to which it maps. If however it is a QName the local name of the OName is used as the sort parameter name.
|
||||
*
|
||||
* @param parameters
|
||||
* to build up the map.
|
||||
* @return the map
|
||||
*/
|
||||
private static Map<String, QName> sortParamsToQNames(Object... parameters)
|
||||
{
|
||||
Map<String, QName> map = new HashMap<>();
|
||||
for (int i=0; i<parameters.length; i++)
|
||||
for (int i = 0; i < parameters.length; i++)
|
||||
{
|
||||
map.put(
|
||||
parameters[i] instanceof String
|
||||
? (String)parameters[i++]
|
||||
: ((QName)parameters[i]).getLocalName(),
|
||||
(QName)parameters[i]);
|
||||
? (String) parameters[i++]
|
||||
: ((QName) parameters[i]).getLocalName(),
|
||||
(QName) parameters[i]);
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
@@ -173,8 +179,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
public CollectionWithPagingInfo<Node> findNodes(Parameters parameters)
|
||||
{
|
||||
SearchService searchService = sr.getSearchService();
|
||||
return new AbstractQuery<Node>(nodeService, searchService)
|
||||
{
|
||||
return new AbstractQuery<Node>(nodeService, searchService) {
|
||||
private final Map<String, UserInfo> mapUserInfo = new HashMap<>(10);
|
||||
|
||||
@Override
|
||||
@@ -205,7 +210,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
QName filterNodeTypeQName = nodes.createQName(nodeTypeStr);
|
||||
if (dictionaryService.getType(filterNodeTypeQName) == null)
|
||||
{
|
||||
throw new InvalidArgumentException("Unknown filter nodeType: "+nodeTypeStr);
|
||||
throw new InvalidArgumentException("Unknown filter nodeType: " + nodeTypeStr);
|
||||
}
|
||||
|
||||
query.append(" AND (+TYPE:\"").append(nodeTypeStr).append(("\")"));
|
||||
@@ -248,7 +253,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
{
|
||||
// first request for this namespace prefix, get and cache result
|
||||
Collection<String> prefixes = namespaceService.getPrefixes(qname.getNamespaceURI());
|
||||
prefix = prefixes.size() != 0 ? prefixes.iterator().next() : "";
|
||||
prefix = !prefixes.isEmpty() ? prefixes.iterator().next() : "";
|
||||
cache.put(qname.getNamespaceURI(), prefix);
|
||||
}
|
||||
buf.append('/').append(prefix).append(':').append(ISO9075.encode(qname.getLocalName()));
|
||||
@@ -262,12 +267,6 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Node> newList(int capacity)
|
||||
{
|
||||
return new ArrayList<Node>(capacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node convert(NodeRef nodeRef, List<String> includeParam)
|
||||
{
|
||||
@@ -291,8 +290,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
public CollectionWithPagingInfo<Person> findPeople(Parameters parameters)
|
||||
{
|
||||
SearchService searchService = sr.getSearchService();
|
||||
return new AbstractQuery<Person>(nodeService, searchService)
|
||||
{
|
||||
return new AbstractQuery<Person>(nodeService, searchService) {
|
||||
@Override
|
||||
protected void buildQuery(StringBuilder query, String term, SearchParameters sp, String queryTemplateName)
|
||||
{
|
||||
@@ -305,18 +303,11 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
query.append("*\")");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Person> newList(int capacity)
|
||||
{
|
||||
return new ArrayList<Person>(capacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Person convert(NodeRef nodeRef, List<String> includeParam)
|
||||
{
|
||||
String personId = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_USERNAME);
|
||||
Person person = people.getPerson(personId);
|
||||
return person;
|
||||
return people.getPerson(personId);
|
||||
}
|
||||
|
||||
// TODO Do the sort in the query on day. A comment in the code for the V0 API used for live people
|
||||
@@ -330,8 +321,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
public CollectionWithPagingInfo<Site> findSites(Parameters parameters)
|
||||
{
|
||||
SearchService searchService = sr.getSearchService();
|
||||
return new AbstractQuery<Site>(nodeService, searchService)
|
||||
{
|
||||
return new AbstractQuery<Site>(nodeService, searchService) {
|
||||
@Override
|
||||
protected void buildQuery(StringBuilder query, String term, SearchParameters sp, String queryTemplateName)
|
||||
{
|
||||
@@ -344,28 +334,18 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
query.append("*\")");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Site> newList(int capacity)
|
||||
{
|
||||
return new ArrayList<>(capacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Site convert(NodeRef nodeRef, List<String> includeParam)
|
||||
{
|
||||
return getSite(siteService.getSite(nodeRef), true);
|
||||
return getSite(siteService.getSite(nodeRef));
|
||||
}
|
||||
|
||||
// note: see also Sites.getSite
|
||||
private Site getSite(SiteInfo siteInfo, boolean includeRole)
|
||||
private Site getSite(SiteInfo siteInfo)
|
||||
{
|
||||
// set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url)
|
||||
String siteId = siteInfo.getShortName();
|
||||
String role = null;
|
||||
if(includeRole)
|
||||
{
|
||||
role = sites.getSiteRole(siteId);
|
||||
}
|
||||
String role = sites.getSiteRole(siteId);
|
||||
return new Site(siteInfo, role);
|
||||
}
|
||||
}.find(parameters, PARAM_TERM, MIN_TERM_LENGTH_SITES, "_SITE", POST_QUERY_SORT, SITE_SORT_PARAMS_TO_QNAMES, new SortColumn(PARAM_SITE_TITLE, true));
|
||||
@@ -415,34 +395,41 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
}
|
||||
|
||||
ResultSet queryResults = null;
|
||||
List<T> collection = null;
|
||||
try
|
||||
{
|
||||
queryResults = searchService.query(sp);
|
||||
|
||||
List<NodeRef> nodeRefs = queryResults.getNodeRefs();
|
||||
|
||||
if (sort == POST_QUERY_SORT)
|
||||
{
|
||||
nodeRefs = postQuerySort(parameters, sortParamsToQNames, defaultSortCols, nodeRefs);
|
||||
}
|
||||
Map<NodeRef, T>
|
||||
|
||||
collection = newList(nodeRefs.size());
|
||||
collection = new LinkedHashMap<>(nodeRefs.size());
|
||||
List<String> includeParam = parameters.getInclude();
|
||||
|
||||
for (NodeRef nodeRef : nodeRefs)
|
||||
{
|
||||
try
|
||||
{
|
||||
T t = convert(nodeRef, includeParam);
|
||||
collection.add(t);
|
||||
collection.put(nodeRef, t);
|
||||
}
|
||||
catch (AccessDeniedException ade)
|
||||
{
|
||||
LOGGER.debug("Ignoring search result for nodeRef " + nodeRef + " due to access denied exception", ade);
|
||||
}
|
||||
}
|
||||
|
||||
if (sort == POST_QUERY_SORT)
|
||||
{
|
||||
return listPage(collection, paging);
|
||||
List<T> postQuerySortedCollection = postQuerySort(parameters, sortParamsToQNames, defaultSortCols, collection.keySet())
|
||||
.stream()
|
||||
.map(collection::get)
|
||||
.toList();
|
||||
return listPage(postQuerySortedCollection, paging);
|
||||
}
|
||||
else
|
||||
{
|
||||
return CollectionWithPagingInfo.asPaged(paging, collection, queryResults.hasMore(), Long.valueOf(queryResults.getNumberFound()).intValue());
|
||||
return CollectionWithPagingInfo.asPaged(paging, collection.values(), queryResults.hasMore(), Long.valueOf(queryResults.getNumberFound()).intValue());
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -455,26 +442,25 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds up the query and is expected to call {@link SearchParameters#setDefaultFieldName(String)}
|
||||
* and {@link SearchParameters#addQueryTemplate(String, String)}
|
||||
* @param query StringBuilder into which the query should be built.
|
||||
* @param term to be searched for
|
||||
* @param sp SearchParameters
|
||||
* Builds up the query and is expected to call {@link SearchParameters#setDefaultFieldName(String)} and {@link SearchParameters#addQueryTemplate(String, String)}
|
||||
*
|
||||
* @param query
|
||||
* StringBuilder into which the query should be built.
|
||||
* @param term
|
||||
* to be searched for
|
||||
* @param sp
|
||||
* SearchParameters
|
||||
* @param queryTemplateName
|
||||
*/
|
||||
protected abstract void buildQuery(StringBuilder query, String term, SearchParameters sp, String queryTemplateName);
|
||||
|
||||
/**
|
||||
* Returns a list of the correct type.
|
||||
* @param capacity of the list
|
||||
* @return a new list.
|
||||
*/
|
||||
protected abstract List<T> newList(int capacity);
|
||||
|
||||
/**
|
||||
* Converts a nodeRef into the an object of the required type.
|
||||
* @param nodeRef to be converted
|
||||
* @param includeParam additional fields to be included
|
||||
*
|
||||
* @param nodeRef
|
||||
* to be converted
|
||||
* @param includeParam
|
||||
* additional fields to be included
|
||||
* @return the object
|
||||
*/
|
||||
protected abstract T convert(NodeRef nodeRef, List<String> includeParam);
|
||||
@@ -484,7 +470,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
String term = parameters.getParameter(termName);
|
||||
if (term == null)
|
||||
{
|
||||
throw new InvalidArgumentException("Query '"+termName+"' not specified");
|
||||
throw new InvalidArgumentException("Query '" + termName + "' not specified");
|
||||
}
|
||||
|
||||
term = escapeTerm(term);
|
||||
@@ -505,7 +491,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
|
||||
if (cnt < minTermLength)
|
||||
{
|
||||
throw new InvalidArgumentException("Query '"+termName+"' is too short. Must have at least "+minTermLength+" alphanumeric chars");
|
||||
throw new InvalidArgumentException("Query '" + termName + "' is too short. Must have at least " + minTermLength + " alphanumeric chars");
|
||||
}
|
||||
|
||||
return term;
|
||||
@@ -537,7 +523,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
QName sortPropQName = sortParamsToQNames.get(sortCol.column);
|
||||
if (sortPropQName == null)
|
||||
{
|
||||
throw new InvalidArgumentException("Invalid sort field: "+sortCol.column);
|
||||
throw new InvalidArgumentException("Invalid sort field: " + sortCol.column);
|
||||
}
|
||||
sp.addSort("@" + sortPropQName, sortCol.asc);
|
||||
}
|
||||
@@ -546,7 +532,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
private List<SortColumn> getSorting(Parameters parameters, List<SortColumn> defaultSortCols)
|
||||
{
|
||||
List<SortColumn> sortCols = parameters.getSorting();
|
||||
if (sortCols == null || sortCols.size() == 0)
|
||||
if (sortCols == null || sortCols.isEmpty())
|
||||
{
|
||||
sortCols = defaultSortCols == null ? Collections.emptyList() : defaultSortCols;
|
||||
}
|
||||
@@ -554,14 +540,18 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
}
|
||||
|
||||
protected List<NodeRef> postQuerySort(Parameters parameters, Map<String, QName> sortParamsToQNames,
|
||||
List<SortColumn> defaultSortCols, List<NodeRef> nodeRefs)
|
||||
List<SortColumn> defaultSortCols, Set<NodeRef> unsortedNodeRefs)
|
||||
{
|
||||
final List<SortColumn> sortCols = getSorting(parameters, defaultSortCols);
|
||||
int sortColCount = sortCols.size();
|
||||
if (sortColCount > 0)
|
||||
|
||||
if (sortColCount == 0)
|
||||
{
|
||||
return new ArrayList<>(unsortedNodeRefs);
|
||||
}
|
||||
|
||||
// make copy of nodeRefs because it can be unmodifiable list.
|
||||
nodeRefs = new ArrayList<NodeRef>(nodeRefs);
|
||||
List<NodeRef> sortedNodeRefs = new ArrayList<>(unsortedNodeRefs);
|
||||
|
||||
List<QName> sortPropQNames = new ArrayList<>(sortColCount);
|
||||
for (SortColumn sortCol : sortCols)
|
||||
@@ -569,19 +559,18 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
QName sortPropQName = sortParamsToQNames.get(sortCol.column);
|
||||
if (sortPropQName == null)
|
||||
{
|
||||
throw new InvalidArgumentException("Invalid sort field: "+sortCol.column);
|
||||
throw new InvalidArgumentException("Invalid sort field: " + sortCol.column);
|
||||
}
|
||||
sortPropQNames.add(sortPropQName);
|
||||
}
|
||||
|
||||
final Collator col = AlfrescoCollator.getInstance(I18NUtil.getLocale());
|
||||
Collections.sort(nodeRefs, new Comparator<NodeRef>()
|
||||
{
|
||||
Collections.sort(sortedNodeRefs, new Comparator<NodeRef>() {
|
||||
@Override
|
||||
public int compare(NodeRef n1, NodeRef n2)
|
||||
{
|
||||
int result = 0;
|
||||
for (int i=0; i<sortCols.size(); i++)
|
||||
for (int i = 0; i < sortCols.size(); i++)
|
||||
{
|
||||
SortColumn sortCol = sortCols.get(i);
|
||||
QName sortPropQName = sortPropQNames.get(i);
|
||||
@@ -590,7 +579,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
Serializable p2 = getProperty(n2, sortPropQName);
|
||||
|
||||
result = ((p1 instanceof Long) && (p2 instanceof Long)
|
||||
? Long.compare((Long)p1, (Long)p2)
|
||||
? Long.compare((Long) p1, (Long) p2)
|
||||
: col.compare(p1.toString(), p2.toString()))
|
||||
* (sortCol.asc ? 1 : -1);
|
||||
|
||||
@@ -609,8 +598,8 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
return nodeRefs;
|
||||
|
||||
return sortedNodeRefs;
|
||||
}
|
||||
|
||||
// note: see also AbstractNodeRelation
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -39,6 +39,9 @@ import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
|
||||
import org.alfresco.repo.action.executer.CheckOutActionExecuter;
|
||||
import org.alfresco.repo.action.executer.CopyActionExecuter;
|
||||
import org.alfresco.repo.action.executer.ImageTransformActionExecuter;
|
||||
@@ -58,8 +61,6 @@ import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
|
||||
/**
|
||||
* This class provides logic for validation of permissions for action parameters which reference node.
|
||||
@@ -67,15 +68,14 @@ import org.apache.logging.log4j.util.Strings;
|
||||
public class ActionNodeParameterValidator implements ActionValidator
|
||||
{
|
||||
/**
|
||||
* This list holds action parameter names which require only READ permission on a referenced node
|
||||
* That means, all other parameters that reference nodes will require WRITE permission
|
||||
* This list holds action parameter names which require only READ permission on a referenced node That means, all other parameters that reference nodes will require WRITE permission
|
||||
*/
|
||||
static final Map<String, List<String>> REQUIRE_READ_PERMISSION_PARAMS =
|
||||
Map.of(LinkCategoryActionExecuter.NAME, List.of(LinkCategoryActionExecuter.PARAM_CATEGORY_VALUE));
|
||||
static final Map<String, List<String>> REQUIRE_READ_PERMISSION_PARAMS = Map.of(LinkCategoryActionExecuter.NAME, List.of(LinkCategoryActionExecuter.PARAM_CATEGORY_VALUE));
|
||||
|
||||
static final String NO_PROPER_PERMISSIONS_FOR_NODE = "No proper permissions for node: ";
|
||||
static final String NOT_A_CATEGORY = "Node is not a category ";
|
||||
static final String NOT_A_FOLDER = "Node is not a folder ";
|
||||
static final String NO_LONGER_EXISTS = "%s having Id: %s no longer exists. Please update your rule definition.";
|
||||
|
||||
private final Actions actions;
|
||||
private final NamespaceService namespaceService;
|
||||
@@ -94,7 +94,8 @@ public class ActionNodeParameterValidator implements ActionValidator
|
||||
/**
|
||||
* Validates action parameters that reference nodes against access permissions for executing user.
|
||||
*
|
||||
* @param action Action to be validated
|
||||
* @param action
|
||||
* Action to be validated
|
||||
*/
|
||||
@Override
|
||||
public void validate(Action action)
|
||||
@@ -132,7 +133,15 @@ public class ActionNodeParameterValidator implements ActionValidator
|
||||
.filter(pd -> action.getParams().containsKey(pd.getName()))
|
||||
.forEach(p -> {
|
||||
final String nodeId = Objects.toString(action.getParams().get(p.getName()), Strings.EMPTY);
|
||||
final NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
NodeRef nodeRef;
|
||||
try
|
||||
{
|
||||
nodeRef = nodes.validateNode(nodeId);
|
||||
}
|
||||
catch (EntityNotFoundException e)
|
||||
{
|
||||
throw new EntityNotFoundException(String.format(NO_LONGER_EXISTS, p.getDisplayLabel(), nodeId), e);
|
||||
}
|
||||
validatePermission(action.getActionDefinitionId(), p.getName(), nodeRef);
|
||||
validateType(action.getActionDefinitionId(), nodeRef);
|
||||
});
|
||||
@@ -163,7 +172,8 @@ public class ActionNodeParameterValidator implements ActionValidator
|
||||
{
|
||||
throw new InvalidArgumentException(NOT_A_FOLDER + nodeRef.getId());
|
||||
}
|
||||
} else if (!nodes.nodeMatches(nodeRef, Set.of(TYPE_CATEGORY), Collections.emptySet()))
|
||||
}
|
||||
else if (!nodes.nodeMatches(nodeRef, Set.of(TYPE_CATEGORY), Collections.emptySet()))
|
||||
{
|
||||
throw new InvalidArgumentException(NOT_A_CATEGORY + nodeRef.getId());
|
||||
}
|
||||
|
@@ -214,9 +214,13 @@
|
||||
<property name="authenticationListener" ref="webScriptAuthenticationListener"/>
|
||||
<property name="remoteUserMapper" ref="RemoteUserMapper" />
|
||||
<property name="adminConsoleAuthenticator" ref="AdminConsoleAuthenticator" />
|
||||
<property name="webScriptsHomeAuthenticator" ref="WebScriptsHomeAuthenticator" />
|
||||
<property name="alwaysAllowBasicAuthForAdminConsole">
|
||||
<value>${authentication.alwaysAllowBasicAuthForAdminConsole.enabled}</value>
|
||||
</property>
|
||||
<property name="alwaysAllowBasicAuthForWebScriptsHome">
|
||||
<value>${authentication.alwaysAllowBasicAuthForWebScriptsHome.enabled}</value>
|
||||
</property>
|
||||
<property name="getRemoteUserTimeoutMilliseconds">
|
||||
<value>${authentication.getRemoteUserTimeoutMilliseconds}</value>
|
||||
</property>
|
||||
|
@@ -25,6 +25,20 @@
|
||||
*/
|
||||
package org.alfresco.rest.api.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.rest.AbstractSingleNetworkSiteTest;
|
||||
import org.alfresco.rest.api.Queries;
|
||||
@@ -36,27 +50,12 @@ import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.search.SearchParameters;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.service.cmr.site.SiteVisibility;
|
||||
import org.alfresco.util.testing.category.LuceneTests;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* V1 REST API tests for pre-defined 'live' search Queries on Sites
|
||||
* V1 REST API tests for pre-defined 'live' search Queries on Sites
|
||||
*
|
||||
* <ul>
|
||||
* <li> {@literal <host>:<port>/alfresco/api/<networkId>/public/alfresco/versions/1/queries/sites} </li>
|
||||
* <li>{@literal <host>:<port>/alfresco/api/<networkId>/public/alfresco/versions/1/queries/sites}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author janv
|
||||
@@ -72,7 +71,7 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
public void setup() throws Exception
|
||||
{
|
||||
super.setup();
|
||||
siteService = (SiteService)applicationContext.getBean("SiteService");
|
||||
siteService = (SiteService) applicationContext.getBean("SiteService");
|
||||
}
|
||||
|
||||
// Note expectedIds defaults to ids
|
||||
@@ -86,7 +85,7 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
}
|
||||
|
||||
dummySearchServiceQueryNodeRefs.clear();
|
||||
for (String id: ids)
|
||||
for (String id : ids)
|
||||
{
|
||||
NodeRef nodeRef = getNodeRef(id);
|
||||
dummySearchServiceQueryNodeRefs.add(nodeRef);
|
||||
@@ -98,7 +97,7 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
if (expectedStatus == 200)
|
||||
{
|
||||
String termWithEscapedAsterisks = term.replaceAll("\\*", "\\\\*");
|
||||
String expectedQuery = "TYPE:\"{http://www.alfresco.org/model/site/1.0}site\" AND (\"*"+ termWithEscapedAsterisks +"*\")";
|
||||
String expectedQuery = "TYPE:\"{http://www.alfresco.org/model/site/1.0}site\" AND (\"*" + termWithEscapedAsterisks + "*\")";
|
||||
ArgumentCaptor<SearchParameters> searchParametersCaptor = ArgumentCaptor.forClass(SearchParameters.class);
|
||||
verify(mockSearchService, times(++callCountToMockSearchService)).query(searchParametersCaptor.capture());
|
||||
SearchParameters parameters = searchParametersCaptor.getValue();
|
||||
@@ -109,11 +108,11 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
|
||||
if (orderBy != null)
|
||||
{
|
||||
for (int i=0; i<expectedIds.length; i++)
|
||||
for (int i = 0; i < expectedIds.length; i++)
|
||||
{
|
||||
String id = expectedIds[i];
|
||||
String actualId = sites.get(i).getId();
|
||||
assertEquals("Order "+i+":", id, actualId);
|
||||
assertEquals("Order " + i + ":", id, actualId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,14 +121,16 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
/**
|
||||
* Tests basic api for nodes live search sites - metadata (id, title, description)
|
||||
*
|
||||
* <p>GET:</p>
|
||||
* <p>
|
||||
* GET:
|
||||
* </p>
|
||||
* {@literal <host>:<port>/alfresco/api/<networkId>/public/alfresco/versions/1/queries/sites}
|
||||
*/
|
||||
@Test
|
||||
public void testLiveSearchSites() throws Exception
|
||||
{
|
||||
setRequestContext(user1);
|
||||
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(user1);
|
||||
int sCount = 5;
|
||||
assertTrue(sCount > 4); // as relied on by test below
|
||||
|
||||
@@ -155,8 +156,8 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
{
|
||||
String num = String.format("%05d", i);
|
||||
|
||||
charValue = charValue+1;
|
||||
siteI = siteI + String.valueOf((char)charValue);
|
||||
charValue = charValue + 1;
|
||||
siteI = siteI + String.valueOf((char) charValue);
|
||||
|
||||
String siteId = siteI + num + RUNID;
|
||||
String siteTitle = siteT + num + siteT;
|
||||
@@ -230,7 +231,11 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
|
||||
private NodeRef getNodeRef(String createdSiteId)
|
||||
{
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(user1);
|
||||
// Created sites do not return NodeRefs to the caller so we need to get the NodeRef from the siteService.
|
||||
// Temporarily as admin we will get NodeRefs to handle ACL authorization.
|
||||
String userUnderTest = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(DEFAULT_ADMIN);
|
||||
|
||||
// The following call to siteService.getSite(createdSiteId).getNodeRef() returns a NodeRef like:
|
||||
// workspace://SpacesStore/9db76769-96de-4de4-bdb4-a127130af362
|
||||
// We call tenantService.getName(nodeRef) to get a fully qualified NodeRef as Solr returns this.
|
||||
@@ -238,6 +243,8 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
// workspace://@org.alfresco.rest.api.tests.queriespeopleapitest@SpacesStore/9db76769-96de-4de4-bdb4-a127130af362
|
||||
NodeRef nodeRef = siteService.getSite(createdSiteId).getNodeRef();
|
||||
nodeRef = tenantService.getName(nodeRef);
|
||||
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(userUnderTest);
|
||||
return nodeRef;
|
||||
}
|
||||
|
||||
@@ -245,7 +252,7 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
public void testLiveSearchSites_SortPage() throws Exception
|
||||
{
|
||||
setRequestContext(user1);
|
||||
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(user1);
|
||||
List<String> siteIds = new ArrayList<>(5);
|
||||
|
||||
try
|
||||
@@ -255,11 +262,11 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
Paging paging = getPaging(0, 100);
|
||||
|
||||
// create site
|
||||
String s1 = createSite("siABCDEF"+RUNID, "ABCDEF DEF", "sdABCDEF", SiteVisibility.PRIVATE, 201).getId();
|
||||
String s2 = createSite("siABCD"+RUNID, "ABCD DEF", "sdABCD", SiteVisibility.PRIVATE, 201).getId();
|
||||
String s3 = createSite("siABCDE"+RUNID, "ABCDE DEF", "sdABCDE", SiteVisibility.PRIVATE, 201).getId();
|
||||
String s4 = createSite("siAB"+RUNID, "AB DEF", "sdAB", SiteVisibility.PRIVATE, 201).getId();
|
||||
String s5 = createSite("siABC"+RUNID, "ABC DEF", "sdABC", SiteVisibility.PRIVATE, 201).getId();
|
||||
String s1 = createSite("siABCDEF" + RUNID, "ABCDEF DEF", "sdABCDEF", SiteVisibility.PRIVATE, 201).getId();
|
||||
String s2 = createSite("siABCD" + RUNID, "ABCD DEF", "sdABCD", SiteVisibility.PRIVATE, 201).getId();
|
||||
String s3 = createSite("siABCDE" + RUNID, "ABCDE DEF", "sdABCDE", SiteVisibility.PRIVATE, 201).getId();
|
||||
String s4 = createSite("siAB" + RUNID, "AB DEF", "sdAB", SiteVisibility.PRIVATE, 201).getId();
|
||||
String s5 = createSite("siABC" + RUNID, "ABC DEF", "sdABC", SiteVisibility.PRIVATE, 201).getId();
|
||||
|
||||
// test sort order
|
||||
{
|
||||
@@ -276,9 +283,9 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
// basic paging tests
|
||||
{
|
||||
// sort order - title desc
|
||||
checkApiCall("siAB", "title desc", getPaging(0, 2), 200, new String[] {s1, s3}, s1, s3, s2, s5, s4);
|
||||
checkApiCall("siAB", "title desc", getPaging(2, 2), 200, new String[] {s2, s5}, s1, s3, s2, s5, s4);
|
||||
checkApiCall("siAB", "title desc", getPaging(4, 2), 200, new String[] {s4}, s1, s3, s2, s5, s4);
|
||||
checkApiCall("siAB", "title desc", getPaging(0, 2), 200, new String[]{s1, s3}, s1, s3, s2, s5, s4);
|
||||
checkApiCall("siAB", "title desc", getPaging(2, 2), 200, new String[]{s2, s5}, s1, s3, s2, s5, s4);
|
||||
checkApiCall("siAB", "title desc", getPaging(4, 2), 200, new String[]{s4}, s1, s3, s2, s5, s4);
|
||||
}
|
||||
|
||||
// -ve tests
|
||||
@@ -305,6 +312,51 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the search service do not support ACL filtering, then the Queries API should handle the response to exclude private sites and potential unauthorized error when building response.
|
||||
*/
|
||||
@Test
|
||||
public void testLiveSearchExcludesPrivateSites() throws Exception
|
||||
{
|
||||
String publicSiteId = null;
|
||||
String privateSiteId = null;
|
||||
try
|
||||
{
|
||||
// given
|
||||
setRequestContext(null, DEFAULT_ADMIN, DEFAULT_ADMIN_PWD);
|
||||
createUser("bartender");
|
||||
|
||||
publicSiteId = createSite("samePrefixPublicSite", "samePrefixPublicSite", "Visible to all users", SiteVisibility.PUBLIC, 201).getId();
|
||||
privateSiteId = createSite("samePrefixPrivateSite", "samePrefixPrivateSite", "Hidden from bartender", SiteVisibility.PRIVATE, 201).getId();
|
||||
|
||||
String[] searchResults = {publicSiteId, privateSiteId};
|
||||
String[] expectedSites = {publicSiteId};
|
||||
|
||||
// when
|
||||
setRequestContext(null, "bartender", "password");
|
||||
AuthenticationUtil.setFullyAuthenticatedUser("bartender");
|
||||
|
||||
// then
|
||||
checkApiCall("samePrefix", null, getPaging(0, 100), 200, expectedSites, searchResults);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// cleanup
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(DEFAULT_ADMIN);
|
||||
setRequestContext(null, DEFAULT_ADMIN, DEFAULT_ADMIN_PWD);
|
||||
if (publicSiteId != null)
|
||||
{
|
||||
deleteSite(publicSiteId, true, 204);
|
||||
}
|
||||
if (privateSiteId != null)
|
||||
{
|
||||
deleteSite(privateSiteId, true, 204);
|
||||
}
|
||||
deleteUser("bartender", null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getScope()
|
||||
{
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.5.0.19</version>
|
||||
<version>23.6.0.7</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
@@ -85,7 +85,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-fileupload2-jakarta</artifactId>
|
||||
<artifactId>commons-fileupload2-jakarta-servlet6</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -30,6 +30,9 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.cache.lookup.EntityLookupCache;
|
||||
import org.alfresco.repo.domain.node.Node;
|
||||
@@ -41,8 +44,6 @@ import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.EqualsHelper;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
public class NodePermissionAssessor
|
||||
{
|
||||
@@ -114,15 +115,15 @@ public class NodePermissionAssessor
|
||||
Set<QName> nodeAspects = nodeService.getAspects(node.getNodeRef());
|
||||
|
||||
String userName = null;
|
||||
if (nodeAspects.contains(ContentModel.ASPECT_AUDITABLE))
|
||||
{
|
||||
userName = node.getAuditableProperties().getAuditCreator();
|
||||
}
|
||||
else if (nodeAspects.contains(ContentModel.ASPECT_OWNABLE))
|
||||
if (nodeAspects.contains(ContentModel.ASPECT_OWNABLE))
|
||||
{
|
||||
Serializable owner = nodeService.getProperty(node.getNodeRef(), ContentModel.PROP_OWNER);
|
||||
userName = DefaultTypeConverter.INSTANCE.convert(String.class, owner);
|
||||
}
|
||||
else if (nodeAspects.contains(ContentModel.ASPECT_AUDITABLE))
|
||||
{
|
||||
userName = node.getAuditableProperties().getAuditCreator();
|
||||
}
|
||||
|
||||
return userName;
|
||||
}
|
||||
|
@@ -30,12 +30,12 @@ import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.alfresco.repo.management.subsystems.ActivateableBean;
|
||||
|
||||
/**
|
||||
* A default {@link AdminConsoleAuthenticator} implementation. Returns null to request a basic auth challenge.
|
||||
* A default {@link ExternalUserAuthenticator} implementation. Returns null to request a basic auth challenge.
|
||||
*/
|
||||
public class DefaultAdminConsoleAuthenticator implements AdminConsoleAuthenticator, ActivateableBean
|
||||
public class DefaultAdminConsoleAuthenticator implements ExternalUserAuthenticator, ActivateableBean
|
||||
{
|
||||
@Override
|
||||
public String getAdminConsoleUser(HttpServletRequest request, HttpServletResponse response)
|
||||
public String getUserId(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2025 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 <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.external;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.alfresco.repo.management.subsystems.ActivateableBean;
|
||||
|
||||
/**
|
||||
* A default {@link ExternalUserAuthenticator} implementation. Returns null to request a basic auth challenge.
|
||||
*/
|
||||
public class DefaultWebScriptsHomeAuthenticator implements ExternalUserAuthenticator, ActivateableBean
|
||||
{
|
||||
@Override
|
||||
public String getUserId(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestAuthentication(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
// No implementation
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -29,28 +29,17 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* An interface for objects capable of extracting an externally authenticated user ID from the HTTP Admin Console webscript request.
|
||||
* An interface for objects capable of extracting an externally authenticated user ID from the HTTP request.
|
||||
*/
|
||||
public interface AdminConsoleAuthenticator
|
||||
public interface ExternalUserAuthenticator
|
||||
{
|
||||
/**
|
||||
* Gets an externally authenticated user ID from the HTTP Admin Console webscript request.
|
||||
* Gets an externally authenticated user ID from the HTTP request.
|
||||
*
|
||||
* @param request
|
||||
* the request
|
||||
* @param response
|
||||
* the response
|
||||
* @return the user ID or <code>null</code> if the user is unauthenticated
|
||||
*/
|
||||
String getAdminConsoleUser(HttpServletRequest request, HttpServletResponse response);
|
||||
String getUserId(HttpServletRequest request, HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* Requests an authentication.
|
||||
*
|
||||
* @param request
|
||||
* the request
|
||||
* @param response
|
||||
* the response
|
||||
*/
|
||||
/* Sends redirect to external site to initiate the OIDC authorization code flow. */
|
||||
void requestAuthentication(HttpServletRequest request, HttpServletResponse response);
|
||||
}
|
@@ -76,6 +76,18 @@ public class IdentityServiceConfig
|
||||
private String lastNameAttribute;
|
||||
private String emailAttribute;
|
||||
private long jwtClockSkewMs;
|
||||
private String webScriptsHomeRedirectPath;
|
||||
private String webScriptsHomeScopes;
|
||||
|
||||
public String getWebScriptsHomeRedirectPath()
|
||||
{
|
||||
return webScriptsHomeRedirectPath;
|
||||
}
|
||||
|
||||
public void setWebScriptsHomeRedirectPath(String webScriptsHomeRedirectPath)
|
||||
{
|
||||
this.webScriptsHomeRedirectPath = webScriptsHomeRedirectPath;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -359,6 +371,18 @@ public class IdentityServiceConfig
|
||||
this.adminConsoleScopes = adminConsoleScopes;
|
||||
}
|
||||
|
||||
public Set<String> getWebScriptsHomeScopes()
|
||||
{
|
||||
return Stream.of(webScriptsHomeScopes.split(","))
|
||||
.map(String::trim)
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
}
|
||||
|
||||
public void setWebScriptsHomeScopes(String webScriptsHomeScopes)
|
||||
{
|
||||
this.webScriptsHomeScopes = webScriptsHomeScopes;
|
||||
}
|
||||
|
||||
public Set<String> getPasswordGrantScopes()
|
||||
{
|
||||
return Stream.of(passwordGrantScopes.split(","))
|
||||
|
@@ -23,7 +23,7 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.identityservice.admin;
|
||||
package org.alfresco.repo.security.authentication.identityservice.authentication;
|
||||
|
||||
import static org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacade.AuthorizationGrant.authorizationCode;
|
||||
import static org.alfresco.repo.security.authentication.identityservice.IdentityServiceMetadataKey.SCOPES_SUPPORTED;
|
||||
@@ -32,7 +32,6 @@ import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@@ -50,9 +49,8 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration.ProviderDetails;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import org.alfresco.repo.management.subsystems.ActivateableBean;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
import org.alfresco.repo.security.authentication.external.AdminConsoleAuthenticator;
|
||||
import org.alfresco.repo.security.authentication.external.ExternalUserAuthenticator;
|
||||
import org.alfresco.repo.security.authentication.external.RemoteUserMapper;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceConfig;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacade;
|
||||
@@ -60,27 +58,26 @@ import org.alfresco.repo.security.authentication.identityservice.IdentityService
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacade.AuthorizationException;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacade.AuthorizationGrant;
|
||||
|
||||
/**
|
||||
* An {@link AdminConsoleAuthenticator} implementation to extract an externally authenticated user ID or to initiate the OIDC authorization code flow.
|
||||
*/
|
||||
public class IdentityServiceAdminConsoleAuthenticator implements AdminConsoleAuthenticator, ActivateableBean
|
||||
public abstract class AbstractIdentityServiceAuthenticator implements ExternalUserAuthenticator
|
||||
{
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(IdentityServiceAdminConsoleAuthenticator.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractIdentityServiceAuthenticator.class);
|
||||
|
||||
private static final String ALFRESCO_ACCESS_TOKEN = "ALFRESCO_ACCESS_TOKEN";
|
||||
private static final String ALFRESCO_REFRESH_TOKEN = "ALFRESCO_REFRESH_TOKEN";
|
||||
private static final String ALFRESCO_TOKEN_EXPIRATION = "ALFRESCO_TOKEN_EXPIRATION";
|
||||
|
||||
private IdentityServiceConfig identityServiceConfig;
|
||||
private IdentityServiceFacade identityServiceFacade;
|
||||
private AdminConsoleAuthenticationCookiesService cookiesService;
|
||||
private RemoteUserMapper remoteUserMapper;
|
||||
private boolean isEnabled;
|
||||
protected IdentityServiceConfig identityServiceConfig;
|
||||
protected IdentityServiceFacade identityServiceFacade;
|
||||
protected AdminAuthenticationCookiesService cookiesService;
|
||||
protected RemoteUserMapper remoteUserMapper;
|
||||
|
||||
protected abstract String getConfiguredRedirectPath();
|
||||
|
||||
protected abstract Set<String> getConfiguredScopes();
|
||||
|
||||
@Override
|
||||
public String getAdminConsoleUser(HttpServletRequest request, HttpServletResponse response)
|
||||
public String getUserId(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
// Try to extract username from the authorization header
|
||||
String username = remoteUserMapper.getRemoteUser(request);
|
||||
if (username != null)
|
||||
{
|
||||
@@ -107,16 +104,12 @@ public class IdentityServiceAdminConsoleAuthenticator implements AdminConsoleAut
|
||||
return null;
|
||||
}
|
||||
|
||||
return remoteUserMapper.getRemoteUser(decorateBearerHeader(bearerToken, request));
|
||||
HttpServletRequest wrappedRequest = newRequestWrapper(Map.of("Authorization", "Bearer " + bearerToken), request);
|
||||
return remoteUserMapper.getRemoteUser(wrappedRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestAuthentication(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
respondWithAuthChallenge(request, response);
|
||||
}
|
||||
|
||||
private void respondWithAuthChallenge(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -124,7 +117,8 @@ public class IdentityServiceAdminConsoleAuthenticator implements AdminConsoleAut
|
||||
{
|
||||
LOGGER.debug("Responding with the authentication challenge");
|
||||
}
|
||||
response.sendRedirect(getAuthenticationRequest(request));
|
||||
String authenticationRequest = buildAuthRequestUrl(request);
|
||||
response.sendRedirect(authenticationRequest);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
@@ -133,84 +127,34 @@ public class IdentityServiceAdminConsoleAuthenticator implements AdminConsoleAut
|
||||
}
|
||||
}
|
||||
|
||||
private String retrieveTokenUsingAuthCode(HttpServletRequest request, HttpServletResponse response, String code)
|
||||
protected String getRedirectUri(String requestURL)
|
||||
{
|
||||
String bearerToken = null;
|
||||
if (LOGGER.isDebugEnabled())
|
||||
{
|
||||
LOGGER.debug("Retrieving a response using the Authorization Code at the Token Endpoint");
|
||||
}
|
||||
try
|
||||
{
|
||||
AccessTokenAuthorization accessTokenAuthorization = identityServiceFacade.authorize(
|
||||
authorizationCode(code, request.getRequestURL().toString()));
|
||||
addCookies(response, accessTokenAuthorization);
|
||||
bearerToken = accessTokenAuthorization.getAccessToken().getTokenValue();
|
||||
}
|
||||
catch (AuthorizationException exception)
|
||||
{
|
||||
if (LOGGER.isWarnEnabled())
|
||||
{
|
||||
LOGGER.warn(
|
||||
"Error while trying to retrieve a response using the Authorization Code at the Token Endpoint: {}",
|
||||
exception.getMessage());
|
||||
}
|
||||
}
|
||||
return bearerToken;
|
||||
return buildRedirectUri(requestURL, getConfiguredRedirectPath());
|
||||
}
|
||||
|
||||
private String refreshTokenIfNeeded(HttpServletRequest request, HttpServletResponse response, String bearerToken)
|
||||
{
|
||||
String refreshToken = cookiesService.getCookie(ALFRESCO_REFRESH_TOKEN, request);
|
||||
String authTokenExpiration = cookiesService.getCookie(ALFRESCO_TOKEN_EXPIRATION, request);
|
||||
try
|
||||
{
|
||||
if (isAuthTokenExpired(authTokenExpiration))
|
||||
{
|
||||
bearerToken = refreshAuthToken(refreshToken, response);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (LOGGER.isDebugEnabled())
|
||||
{
|
||||
LOGGER.debug("Error while trying to refresh Auth Token: {}", e.getMessage());
|
||||
}
|
||||
bearerToken = null;
|
||||
resetCookies(response);
|
||||
}
|
||||
return bearerToken;
|
||||
}
|
||||
|
||||
private void addCookies(HttpServletResponse response, AccessTokenAuthorization accessTokenAuthorization)
|
||||
{
|
||||
cookiesService.addCookie(ALFRESCO_ACCESS_TOKEN, accessTokenAuthorization.getAccessToken().getTokenValue(), response);
|
||||
cookiesService.addCookie(ALFRESCO_TOKEN_EXPIRATION, String.valueOf(
|
||||
accessTokenAuthorization.getAccessToken().getExpiresAt().toEpochMilli()), response);
|
||||
cookiesService.addCookie(ALFRESCO_REFRESH_TOKEN, accessTokenAuthorization.getRefreshTokenValue(), response);
|
||||
}
|
||||
|
||||
private String getAuthenticationRequest(HttpServletRequest request)
|
||||
public String buildAuthRequestUrl(HttpServletRequest request)
|
||||
{
|
||||
ClientRegistration clientRegistration = identityServiceFacade.getClientRegistration();
|
||||
State state = new State();
|
||||
|
||||
UriComponentsBuilder authRequestBuilder = UriComponentsBuilder.fromUriString(clientRegistration.getProviderDetails().getAuthorizationUri())
|
||||
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(clientRegistration.getProviderDetails()
|
||||
.getAuthorizationUri())
|
||||
.queryParam("client_id", clientRegistration.getClientId())
|
||||
.queryParam("redirect_uri", getRedirectUri(request.getRequestURL().toString()))
|
||||
.queryParam("response_type", "code")
|
||||
.queryParam("scope", String.join("+", getScopes(clientRegistration)))
|
||||
.queryParam("scope", String.join("+", getConfiguredScopes(clientRegistration)))
|
||||
.queryParam("state", state.toString());
|
||||
|
||||
if (StringUtils.isNotBlank(identityServiceConfig.getAudience()))
|
||||
{
|
||||
authRequestBuilder.queryParam("audience", identityServiceConfig.getAudience());
|
||||
builder.queryParam("audience", identityServiceConfig.getAudience());
|
||||
}
|
||||
|
||||
return authRequestBuilder.build().toUriString();
|
||||
return builder.build()
|
||||
.toUriString();
|
||||
}
|
||||
|
||||
private Set<String> getScopes(ClientRegistration clientRegistration)
|
||||
private Set<String> getConfiguredScopes(ClientRegistration clientRegistration)
|
||||
{
|
||||
return Optional.ofNullable(clientRegistration.getProviderDetails())
|
||||
.map(ProviderDetails::getConfigurationMetadata)
|
||||
@@ -223,100 +167,149 @@ public class IdentityServiceAdminConsoleAuthenticator implements AdminConsoleAut
|
||||
|
||||
private Set<String> getSupportedScopes(Scope scopes)
|
||||
{
|
||||
Set<String> configuredScopes = getConfiguredScopes();
|
||||
return scopes.stream()
|
||||
.filter(this::hasAdminConsoleScope)
|
||||
.map(Identifier::getValue)
|
||||
.filter(configuredScopes::contains)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private boolean hasAdminConsoleScope(Scope.Value scope)
|
||||
{
|
||||
return identityServiceConfig.getAdminConsoleScopes().contains(scope.getValue());
|
||||
}
|
||||
|
||||
private String getRedirectUri(String requestURL)
|
||||
protected String buildRedirectUri(String requestURL, String overridePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
URI originalUri = new URI(requestURL);
|
||||
URI redirectUri = new URI(originalUri.getScheme(), originalUri.getAuthority(), identityServiceConfig.getAdminConsoleRedirectPath(), originalUri.getQuery(), originalUri.getFragment());
|
||||
String path = overridePath != null ? overridePath : originalUri.getPath();
|
||||
|
||||
URI redirectUri = new URI(
|
||||
originalUri.getScheme(),
|
||||
originalUri.getAuthority(),
|
||||
path,
|
||||
originalUri.getQuery(),
|
||||
originalUri.getFragment());
|
||||
|
||||
return redirectUri.toASCIIString();
|
||||
}
|
||||
catch (URISyntaxException e)
|
||||
{
|
||||
LOGGER.error("Error while trying to get the redirect URI and respond with the authentication challenge: {}", e.getMessage(), e);
|
||||
LOGGER.error("Redirect URI construction failed: {}", e.getMessage(), e);
|
||||
throw new AuthenticationException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void resetCookies(HttpServletResponse response)
|
||||
public void challenge(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
try
|
||||
{
|
||||
response.sendRedirect(buildAuthRequestUrl(request));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new AuthenticationException("Auth redirect failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected String retrieveTokenUsingAuthCode(HttpServletRequest request, HttpServletResponse response, String code)
|
||||
{
|
||||
try
|
||||
{
|
||||
AccessTokenAuthorization accessTokenAuthorization = identityServiceFacade.authorize(authorizationCode(code, getRedirectUri(request.getRequestURL()
|
||||
.toString())));
|
||||
addCookies(response, accessTokenAuthorization);
|
||||
return accessTokenAuthorization.getAccessToken()
|
||||
.getTokenValue();
|
||||
}
|
||||
catch (AuthorizationException exception)
|
||||
{
|
||||
LOGGER.warn("Error while trying to retrieve token using Authorization Code: {}", exception.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected String refreshTokenIfNeeded(HttpServletRequest request, HttpServletResponse response, String bearerToken)
|
||||
{
|
||||
String refreshToken = cookiesService.getCookie(ALFRESCO_REFRESH_TOKEN, request);
|
||||
String authTokenExpiration = cookiesService.getCookie(ALFRESCO_TOKEN_EXPIRATION, request);
|
||||
|
||||
try
|
||||
{
|
||||
if (isAuthTokenExpired(authTokenExpiration))
|
||||
{
|
||||
bearerToken = refreshAuthToken(refreshToken, response);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (LOGGER.isDebugEnabled())
|
||||
{
|
||||
LOGGER.debug("Token refresh failed: {}", e.getMessage());
|
||||
}
|
||||
bearerToken = null;
|
||||
resetCookies(response);
|
||||
}
|
||||
|
||||
return bearerToken;
|
||||
}
|
||||
|
||||
private static boolean isAuthTokenExpired(String authTokenExpiration)
|
||||
{
|
||||
return authTokenExpiration == null || Instant.now()
|
||||
.compareTo(Instant.ofEpochMilli(Long.parseLong(authTokenExpiration))) >= 0;
|
||||
}
|
||||
|
||||
private String refreshAuthToken(String refreshToken, HttpServletResponse response)
|
||||
{
|
||||
AccessTokenAuthorization accessTokenAuthorization = identityServiceFacade.authorize(AuthorizationGrant.refreshToken(refreshToken));
|
||||
if (accessTokenAuthorization == null || accessTokenAuthorization.getAccessToken() == null)
|
||||
{
|
||||
throw new AuthenticationException("Refresh token response is invalid.");
|
||||
}
|
||||
addCookies(response, accessTokenAuthorization);
|
||||
return accessTokenAuthorization.getAccessToken()
|
||||
.getTokenValue();
|
||||
|
||||
}
|
||||
|
||||
protected void addCookies(HttpServletResponse response, AccessTokenAuthorization accessTokenAuthorization)
|
||||
{
|
||||
cookiesService.addCookie(ALFRESCO_ACCESS_TOKEN, accessTokenAuthorization.getAccessToken()
|
||||
.getTokenValue(), response);
|
||||
cookiesService.addCookie(ALFRESCO_TOKEN_EXPIRATION, String.valueOf(accessTokenAuthorization.getAccessToken()
|
||||
.getExpiresAt()
|
||||
.toEpochMilli()), response);
|
||||
cookiesService.addCookie(ALFRESCO_REFRESH_TOKEN, accessTokenAuthorization.getRefreshTokenValue(), response);
|
||||
}
|
||||
|
||||
protected void resetCookies(HttpServletResponse response)
|
||||
{
|
||||
cookiesService.resetCookie(ALFRESCO_TOKEN_EXPIRATION, response);
|
||||
cookiesService.resetCookie(ALFRESCO_ACCESS_TOKEN, response);
|
||||
cookiesService.resetCookie(ALFRESCO_REFRESH_TOKEN, response);
|
||||
}
|
||||
|
||||
private String refreshAuthToken(String refreshToken, HttpServletResponse response)
|
||||
protected HttpServletRequest newRequestWrapper(Map<String, String> headers, HttpServletRequest request)
|
||||
{
|
||||
AccessTokenAuthorization accessTokenAuthorization = doRefreshAuthToken(refreshToken);
|
||||
addCookies(response, accessTokenAuthorization);
|
||||
return accessTokenAuthorization.getAccessToken().getTokenValue();
|
||||
return new AdditionalHeadersHttpServletRequestWrapper(headers, request);
|
||||
}
|
||||
|
||||
private AccessTokenAuthorization doRefreshAuthToken(String refreshToken)
|
||||
// Setters
|
||||
public void setIdentityServiceConfig(IdentityServiceConfig config)
|
||||
{
|
||||
AccessTokenAuthorization accessTokenAuthorization = identityServiceFacade.authorize(
|
||||
AuthorizationGrant.refreshToken(refreshToken));
|
||||
if (accessTokenAuthorization == null || accessTokenAuthorization.getAccessToken() == null)
|
||||
{
|
||||
throw new AuthenticationException("AccessTokenResponse is null or empty");
|
||||
}
|
||||
return accessTokenAuthorization;
|
||||
this.identityServiceConfig = config;
|
||||
}
|
||||
|
||||
private static boolean isAuthTokenExpired(String authTokenExpiration)
|
||||
public void setIdentityServiceFacade(IdentityServiceFacade facade)
|
||||
{
|
||||
return Instant.now().compareTo(Instant.ofEpochMilli(Long.parseLong(authTokenExpiration))) >= 0;
|
||||
this.identityServiceFacade = facade;
|
||||
}
|
||||
|
||||
private HttpServletRequest decorateBearerHeader(String authToken, HttpServletRequest servletRequest)
|
||||
public void setCookiesService(AdminAuthenticationCookiesService service)
|
||||
{
|
||||
Map<String, String> additionalHeaders = new HashMap<>();
|
||||
additionalHeaders.put("Authorization", "Bearer " + authToken);
|
||||
return new AdminConsoleHttpServletRequestWrapper(additionalHeaders, servletRequest);
|
||||
this.cookiesService = service;
|
||||
}
|
||||
|
||||
public void setIdentityServiceFacade(
|
||||
IdentityServiceFacade identityServiceFacade)
|
||||
public void setRemoteUserMapper(RemoteUserMapper mapper)
|
||||
{
|
||||
this.identityServiceFacade = identityServiceFacade;
|
||||
}
|
||||
|
||||
public void setRemoteUserMapper(RemoteUserMapper remoteUserMapper)
|
||||
{
|
||||
this.remoteUserMapper = remoteUserMapper;
|
||||
}
|
||||
|
||||
public void setCookiesService(
|
||||
AdminConsoleAuthenticationCookiesService cookiesService)
|
||||
{
|
||||
this.cookiesService = cookiesService;
|
||||
}
|
||||
|
||||
public void setIdentityServiceConfig(
|
||||
IdentityServiceConfig identityServiceConfig)
|
||||
{
|
||||
this.identityServiceConfig = identityServiceConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive()
|
||||
{
|
||||
return this.isEnabled;
|
||||
}
|
||||
|
||||
public void setActive(boolean isEnabled)
|
||||
{
|
||||
this.isEnabled = isEnabled;
|
||||
this.remoteUserMapper = mapper;
|
||||
}
|
||||
}
|
@@ -23,7 +23,7 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.identityservice.admin;
|
||||
package org.alfresco.repo.security.authentication.identityservice.authentication;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.enumeration;
|
||||
@@ -37,18 +37,12 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
|
||||
public class AdminConsoleHttpServletRequestWrapper extends HttpServletRequestWrapper
|
||||
public class AdditionalHeadersHttpServletRequestWrapper extends HttpServletRequestWrapper
|
||||
{
|
||||
private final Map<String, String> additionalHeaders;
|
||||
private final HttpServletRequest wrappedRequest;
|
||||
|
||||
/**
|
||||
* Constructs a request object wrapping the given request.
|
||||
*
|
||||
* @param request the request to wrap
|
||||
* @throws IllegalArgumentException if the request is null
|
||||
*/
|
||||
public AdminConsoleHttpServletRequestWrapper(Map<String, String> additionalHeaders, HttpServletRequest request)
|
||||
public AdditionalHeadersHttpServletRequestWrapper(Map<String, String> additionalHeaders, HttpServletRequest request)
|
||||
{
|
||||
super(request);
|
||||
PropertyCheck.mandatory(this, "additionalHeaders", additionalHeaders);
|
@@ -23,7 +23,7 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.identityservice.admin;
|
||||
package org.alfresco.repo.security.authentication.identityservice.authentication;
|
||||
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
@@ -33,12 +33,12 @@ import org.alfresco.repo.admin.SysAdminParams;
|
||||
/**
|
||||
* Service to handle Admin Console authentication-related cookies.
|
||||
*/
|
||||
public class AdminConsoleAuthenticationCookiesService
|
||||
public class AdminAuthenticationCookiesService
|
||||
{
|
||||
private final SysAdminParams sysAdminParams;
|
||||
private final int cookieLifetime;
|
||||
|
||||
public AdminConsoleAuthenticationCookiesService(SysAdminParams sysAdminParams, int cookieLifetime)
|
||||
public AdminAuthenticationCookiesService(SysAdminParams sysAdminParams, int cookieLifetime)
|
||||
{
|
||||
this.sysAdminParams = sysAdminParams;
|
||||
this.cookieLifetime = cookieLifetime;
|
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2025 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 <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.identityservice.authentication.admin;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.management.subsystems.ActivateableBean;
|
||||
import org.alfresco.repo.security.authentication.external.ExternalUserAuthenticator;
|
||||
import org.alfresco.repo.security.authentication.identityservice.authentication.AbstractIdentityServiceAuthenticator;
|
||||
|
||||
/**
|
||||
* An {@link ExternalUserAuthenticator} implementation to extract an externally authenticated user ID or to initiate the OIDC authorization code flow.
|
||||
*/
|
||||
public class IdentityServiceAdminConsoleAuthenticator extends AbstractIdentityServiceAuthenticator
|
||||
implements ExternalUserAuthenticator, ActivateableBean
|
||||
{
|
||||
private boolean isEnabled;
|
||||
|
||||
@Override
|
||||
protected Set<String> getConfiguredScopes()
|
||||
{
|
||||
return identityServiceConfig.getAdminConsoleScopes();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getConfiguredRedirectPath()
|
||||
{
|
||||
return identityServiceConfig.getAdminConsoleRedirectPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive()
|
||||
{
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
public void setActive(boolean isEnabled)
|
||||
{
|
||||
this.isEnabled = isEnabled;
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2025 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 <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.identityservice.authentication.webscripts;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.management.subsystems.ActivateableBean;
|
||||
import org.alfresco.repo.security.authentication.external.ExternalUserAuthenticator;
|
||||
import org.alfresco.repo.security.authentication.identityservice.authentication.AbstractIdentityServiceAuthenticator;
|
||||
|
||||
/**
|
||||
* An {@link ExternalUserAuthenticator} implementation to extract an externally authenticated user ID or to initiate the OIDC authorization code flow.
|
||||
*/
|
||||
public class IdentityServiceWebScriptsHomeAuthenticator extends AbstractIdentityServiceAuthenticator
|
||||
implements ExternalUserAuthenticator, ActivateableBean
|
||||
{
|
||||
private boolean isEnabled;
|
||||
|
||||
@Override
|
||||
protected String getConfiguredRedirectPath()
|
||||
{
|
||||
return identityServiceConfig.getWebScriptsHomeRedirectPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<String> getConfiguredScopes()
|
||||
{
|
||||
return identityServiceConfig.getWebScriptsHomeScopes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive()
|
||||
{
|
||||
return this.isEnabled;
|
||||
}
|
||||
|
||||
public void setActive(boolean isEnabled)
|
||||
{
|
||||
this.isEnabled = isEnabled;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -28,9 +28,6 @@ package org.alfresco.repo.transaction;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
@@ -38,6 +35,10 @@ import org.springframework.transaction.TransactionManager;
|
||||
import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
||||
import org.springframework.transaction.interceptor.TransactionAttribute;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
|
||||
/**
|
||||
* @author Dmitry Velichkevich
|
||||
*/
|
||||
@@ -64,7 +65,7 @@ public class RetryingTransactionInterceptor extends TransactionAspectSupport imp
|
||||
final TransactionAttribute txnAttr = getTransactionAttributeSource().getTransactionAttribute(
|
||||
method, invocation.getThis().getClass());
|
||||
|
||||
final TransactionManager tm = determineTransactionManager(txnAttr);
|
||||
final TransactionManager tm = determineTransactionManager(txnAttr, null);
|
||||
|
||||
if (tm != null && !(tm instanceof PlatformTransactionManager))
|
||||
{
|
||||
@@ -83,8 +84,7 @@ public class RetryingTransactionInterceptor extends TransactionAspectSupport imp
|
||||
retryingTransactionHelper.setExtraExceptions(extraExceptions);
|
||||
|
||||
return retryingTransactionHelper.doInTransaction(
|
||||
new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
new RetryingTransactionCallback<Object>() {
|
||||
public Object execute()
|
||||
{
|
||||
TransactionInfo txInfo = createTransactionIfNecessary(ptm, TransactionAttribute.PROPAGATION_REQUIRES_NEW == txnAttr
|
||||
|
@@ -135,7 +135,7 @@
|
||||
</property>
|
||||
<property name="interfaces">
|
||||
<list>
|
||||
<value>org.alfresco.repo.security.authentication.external.AdminConsoleAuthenticator</value>
|
||||
<value>org.alfresco.repo.security.authentication.external.ExternalUserAuthenticator</value>
|
||||
<value>org.alfresco.repo.management.subsystems.ActivateableBean</value>
|
||||
</list>
|
||||
</property>
|
||||
@@ -144,6 +144,22 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="WebScriptsHomeAuthenticator"
|
||||
class="org.alfresco.repo.management.subsystems.ChainingSubsystemProxyFactory">
|
||||
<property name="applicationContextManager">
|
||||
<ref bean="Authentication" />
|
||||
</property>
|
||||
<property name="interfaces">
|
||||
<list>
|
||||
<value>org.alfresco.repo.security.authentication.external.ExternalUserAuthenticator</value>
|
||||
<value>org.alfresco.repo.management.subsystems.ActivateableBean</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="sourceBeanName">
|
||||
<value>webScriptsHomeAuthenticator</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Passwords are encoded using MD4 -->
|
||||
<!-- This is not ideal and only done to be compatible with NTLM -->
|
||||
<!-- authentication against the default authentication mechanism. -->
|
||||
|
@@ -3,7 +3,7 @@
|
||||
repository.name=Main Repository
|
||||
|
||||
# Schema number
|
||||
version.schema=19400
|
||||
version.schema=19500
|
||||
|
||||
# Directory configuration
|
||||
|
||||
@@ -563,6 +563,7 @@ authentication.ticket.validDuration=PT1H
|
||||
authentication.ticket.useSingleTicketPerUser=true
|
||||
|
||||
authentication.alwaysAllowBasicAuthForAdminConsole.enabled=true
|
||||
authentication.alwaysAllowBasicAuthForWebScriptsHome.enabled=true
|
||||
authentication.getRemoteUserTimeoutMilliseconds=10000
|
||||
|
||||
# FTP access
|
||||
|
@@ -104,4 +104,7 @@
|
||||
<ref bean="transactionService" />
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="webScriptsHomeAuthenticator" class="org.alfresco.repo.security.authentication.external.DefaultWebScriptsHomeAuthenticator" />
|
||||
|
||||
</beans>
|
@@ -170,6 +170,9 @@
|
||||
<property name="adminConsoleScopes">
|
||||
<value>${identity-service.admin-console.scopes:openid,profile,email,offline_access}</value>
|
||||
</property>
|
||||
<property name="webScriptsHomeScopes">
|
||||
<value>${identity-service.webscripts-home.scopes:openid,profile,email,offline_access}</value>
|
||||
</property>
|
||||
<property name="passwordGrantScopes">
|
||||
<value>${identity-service.password-grant.scopes:openid,profile,email}</value>
|
||||
</property>
|
||||
@@ -179,6 +182,9 @@
|
||||
<property name="jwtClockSkewMs">
|
||||
<value>${identity-service.jwt-clock-skew-ms:0}</value>
|
||||
</property>
|
||||
<property name="webScriptsHomeRedirectPath">
|
||||
<value>${identity-service.webscripts-home.redirect-path}</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Enable control over mapping between request and user ID -->
|
||||
@@ -197,12 +203,12 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="adminConsoleAuthenticationCookiesService" class="org.alfresco.repo.security.authentication.identityservice.admin.AdminConsoleAuthenticationCookiesService">
|
||||
<bean id="adminAuthenticationCookiesService" class="org.alfresco.repo.security.authentication.identityservice.authentication.AdminAuthenticationCookiesService">
|
||||
<constructor-arg ref="sysAdminParams" />
|
||||
<constructor-arg value="${admin.console.cookie.lifetime:86400}" />
|
||||
</bean>
|
||||
|
||||
<bean id="adminConsoleAuthenticator" class="org.alfresco.repo.security.authentication.identityservice.admin.IdentityServiceAdminConsoleAuthenticator">
|
||||
<bean id="adminConsoleAuthenticator" class="org.alfresco.repo.security.authentication.identityservice.authentication.admin.IdentityServiceAdminConsoleAuthenticator">
|
||||
<property name="active">
|
||||
<value>${identity-service.authentication.enabled}</value>
|
||||
</property>
|
||||
@@ -210,7 +216,25 @@
|
||||
<ref bean="identityServiceFacade"/>
|
||||
</property>
|
||||
<property name="cookiesService">
|
||||
<ref bean="adminConsoleAuthenticationCookiesService" />
|
||||
<ref bean="adminAuthenticationCookiesService" />
|
||||
</property>
|
||||
<property name="remoteUserMapper">
|
||||
<ref bean="remoteUserMapper" />
|
||||
</property>
|
||||
<property name="identityServiceConfig">
|
||||
<ref bean="identityServiceConfig" />
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="webScriptsHomeAuthenticator" class="org.alfresco.repo.security.authentication.identityservice.authentication.webscripts.IdentityServiceWebScriptsHomeAuthenticator">
|
||||
<property name="active">
|
||||
<value>${identity-service.authentication.enabled}</value>
|
||||
</property>
|
||||
<property name="identityServiceFacade">
|
||||
<ref bean="identityServiceFacade"/>
|
||||
</property>
|
||||
<property name="cookiesService">
|
||||
<ref bean="adminAuthenticationCookiesService" />
|
||||
</property>
|
||||
<property name="remoteUserMapper">
|
||||
<ref bean="remoteUserMapper" />
|
||||
|
@@ -12,11 +12,13 @@ identity-service.resource=alfresco
|
||||
identity-service.credentials.secret=
|
||||
identity-service.public-client=true
|
||||
identity-service.admin-console.redirect-path=/alfresco/s/admin/admin-communitysummary
|
||||
identity-service.webscripts-home.redirect-path=/alfresco/s/index
|
||||
identity-service.signature-algorithms=RS256,PS256
|
||||
identity-service.first-name-attribute=given_name
|
||||
identity-service.last-name-attribute=family_name
|
||||
identity-service.email-attribute=email
|
||||
identity-service.admin-console.scopes=openid,profile,email,offline_access
|
||||
identity-service.webscripts-home.scopes=openid,profile,email,offline_access
|
||||
identity-service.password-grant.scopes=openid,profile,email
|
||||
identity-service.issuer-attribute=issuer
|
||||
identity-service.jwt-clock-skew-ms=0
|
||||
|
@@ -34,11 +34,12 @@ import org.alfresco.repo.security.authentication.identityservice.IdentityService
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceJITProvisioningHandlerUnitTest;
|
||||
import org.alfresco.repo.security.authentication.identityservice.LazyInstantiatingIdentityServiceFacadeUnitTest;
|
||||
import org.alfresco.repo.security.authentication.identityservice.SpringBasedIdentityServiceFacadeUnitTest;
|
||||
import org.alfresco.repo.security.authentication.identityservice.admin.AdminConsoleAuthenticationCookiesServiceUnitTest;
|
||||
import org.alfresco.repo.security.authentication.identityservice.admin.AdminConsoleHttpServletRequestWrapperUnitTest;
|
||||
import org.alfresco.repo.security.authentication.identityservice.admin.IdentityServiceAdminConsoleAuthenticatorUnitTest;
|
||||
import org.alfresco.repo.security.authentication.identityservice.authentication.AdditionalHeadersHttpServletRequestWrapperUnitTest;
|
||||
import org.alfresco.repo.security.authentication.identityservice.authentication.AdminAuthenticationCookiesServiceUnitTest;
|
||||
import org.alfresco.repo.security.authentication.identityservice.authentication.admin.IdentityServiceAdminConsoleAuthenticatorUnitTest;
|
||||
import org.alfresco.repo.security.authentication.identityservice.user.AccessTokenToDecodedTokenUserMapperUnitTest;
|
||||
import org.alfresco.repo.security.authentication.identityservice.user.TokenUserToOIDCUserMapperUnitTest;
|
||||
import org.alfresco.repo.security.authentication.identityservice.webscript.IdentityServiceWebScriptsHomeAuthenticatorUnitTest;
|
||||
import org.alfresco.util.testing.category.DBTests;
|
||||
import org.alfresco.util.testing.category.NonBuildTests;
|
||||
|
||||
@@ -153,9 +154,10 @@ import org.alfresco.util.testing.category.NonBuildTests;
|
||||
IdentityServiceJITProvisioningHandlerUnitTest.class,
|
||||
AccessTokenToDecodedTokenUserMapperUnitTest.class,
|
||||
TokenUserToOIDCUserMapperUnitTest.class,
|
||||
AdminConsoleAuthenticationCookiesServiceUnitTest.class,
|
||||
AdminConsoleHttpServletRequestWrapperUnitTest.class,
|
||||
AdminAuthenticationCookiesServiceUnitTest.class,
|
||||
AdditionalHeadersHttpServletRequestWrapperUnitTest.class,
|
||||
IdentityServiceAdminConsoleAuthenticatorUnitTest.class,
|
||||
IdentityServiceWebScriptsHomeAuthenticatorUnitTest.class,
|
||||
ClientRegistrationProviderUnitTest.class,
|
||||
org.alfresco.repo.security.authentication.CompositePasswordEncoderTest.class,
|
||||
org.alfresco.repo.security.authentication.PasswordHashingTest.class,
|
||||
|
@@ -23,7 +23,7 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.identityservice.admin;
|
||||
package org.alfresco.repo.security.authentication.identityservice.authentication;
|
||||
|
||||
import static java.util.Collections.enumeration;
|
||||
import static java.util.Collections.list;
|
||||
@@ -40,51 +40,45 @@ import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
|
||||
@SuppressWarnings("PMD.UseDiamondOperator")
|
||||
public class AdminConsoleHttpServletRequestWrapperUnitTest
|
||||
{
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
|
||||
@SuppressWarnings("PMD.UseDiamondOperator")
|
||||
public class AdditionalHeadersHttpServletRequestWrapperUnitTest
|
||||
{
|
||||
private static final String DEFAULT_HEADER = "default_header";
|
||||
private static final String DEFAULT_HEADER_VALUE = "default_value";
|
||||
private static final String ADDITIONAL_HEADER = "additional_header";
|
||||
private static final String ADDITIONAL_HEADER_VALUE = "additional_value";
|
||||
private static final Map<String, String> DEFAULT_HEADERS = new HashMap<String, String>()
|
||||
{{
|
||||
put(DEFAULT_HEADER, DEFAULT_HEADER_VALUE);
|
||||
}};
|
||||
private static final Map<String, String> ADDITIONAL_HEADERS = new HashMap<String, String>()
|
||||
{{
|
||||
put(ADDITIONAL_HEADER, ADDITIONAL_HEADER_VALUE);
|
||||
}};
|
||||
private static final Map<String, String> DEFAULT_HEADERS = Map.of(DEFAULT_HEADER, DEFAULT_HEADER_VALUE);
|
||||
private static final Map<String, String> ADDITIONAL_HEADERS = Map.of(ADDITIONAL_HEADER, ADDITIONAL_HEADER_VALUE);
|
||||
|
||||
@Mock
|
||||
private HttpServletRequest request;
|
||||
private AdminConsoleHttpServletRequestWrapper requestWrapper;
|
||||
private AdditionalHeadersHttpServletRequestWrapper requestWrapper;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
initMocks(this);
|
||||
requestWrapper = new AdminConsoleHttpServletRequestWrapper(ADDITIONAL_HEADERS, request);
|
||||
requestWrapper = new AdditionalHeadersHttpServletRequestWrapper(ADDITIONAL_HEADERS, request);
|
||||
}
|
||||
|
||||
@Test(expected = AlfrescoRuntimeException.class)
|
||||
public void wrapperShouldNotBeInstancedWithoutAdditionalHeaders()
|
||||
{
|
||||
new AdminConsoleHttpServletRequestWrapper(null, request);
|
||||
new AdditionalHeadersHttpServletRequestWrapper(null, request);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void wrapperShouldNotBeInstancedWithoutRequestsToWrap()
|
||||
{
|
||||
new AdminConsoleHttpServletRequestWrapper(new HashMap<>(), null);
|
||||
new AdditionalHeadersHttpServletRequestWrapper(new HashMap<>(), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -109,7 +103,7 @@ public class AdminConsoleHttpServletRequestWrapperUnitTest
|
||||
{
|
||||
when(request.getHeaderNames()).thenReturn(enumeration(DEFAULT_HEADERS.keySet()));
|
||||
|
||||
requestWrapper = new AdminConsoleHttpServletRequestWrapper(new HashMap<>(), request);
|
||||
requestWrapper = new AdditionalHeadersHttpServletRequestWrapper(new HashMap<>(), request);
|
||||
Enumeration<String> headerNames = requestWrapper.getHeaderNames();
|
||||
assertNotNull("headerNames should not be null", headerNames);
|
||||
assertTrue("headerNames should not be empty", headerNames.hasMoreElements());
|
||||
@@ -161,7 +155,7 @@ public class AdminConsoleHttpServletRequestWrapperUnitTest
|
||||
Map<String, String> overrideHeaders = new HashMap<>();
|
||||
overrideHeaders.put(DEFAULT_HEADER, overrideHeaderValue);
|
||||
|
||||
requestWrapper = new AdminConsoleHttpServletRequestWrapper(overrideHeaders, request);
|
||||
requestWrapper = new AdditionalHeadersHttpServletRequestWrapper(overrideHeaders, request);
|
||||
String header = requestWrapper.getHeader(DEFAULT_HEADER);
|
||||
assertEquals("The header should have the overridden value", overrideHeaderValue, header);
|
||||
|
||||
@@ -201,7 +195,7 @@ public class AdminConsoleHttpServletRequestWrapperUnitTest
|
||||
Map<String, String> overrideHeaders = new HashMap<>();
|
||||
overrideHeaders.put(DEFAULT_HEADER, overrideHeaderValue);
|
||||
|
||||
requestWrapper = new AdminConsoleHttpServletRequestWrapper(overrideHeaders, request);
|
||||
requestWrapper = new AdditionalHeadersHttpServletRequestWrapper(overrideHeaders, request);
|
||||
Enumeration<String> headers = requestWrapper.getHeaders(DEFAULT_HEADER);
|
||||
assertNotNull("The headers enumeration should not be null", headers);
|
||||
assertTrue("The headers enumeration should not be empty", headers.hasMoreElements());
|
@@ -23,7 +23,7 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.identityservice.admin;
|
||||
package org.alfresco.repo.security.authentication.identityservice.authentication;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
@@ -37,14 +37,16 @@ import static org.mockito.MockitoAnnotations.initMocks;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.alfresco.repo.admin.SysAdminParams;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
|
||||
public class AdminConsoleAuthenticationCookiesServiceUnitTest
|
||||
import org.alfresco.repo.admin.SysAdminParams;
|
||||
|
||||
public class AdminAuthenticationCookiesServiceUnitTest
|
||||
{
|
||||
private static final int DEFAULT_COOKIE_LIFETIME = 86400;
|
||||
private static final String COOKIE_NAME = "cookie";
|
||||
@@ -57,13 +59,13 @@ public class AdminConsoleAuthenticationCookiesServiceUnitTest
|
||||
private SysAdminParams sysAdminParams;
|
||||
@Captor
|
||||
private ArgumentCaptor<Cookie> cookieCaptor;
|
||||
private AdminConsoleAuthenticationCookiesService cookiesService;
|
||||
private AdminAuthenticationCookiesService cookiesService;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
initMocks(this);
|
||||
cookiesService = new AdminConsoleAuthenticationCookiesService(sysAdminParams, DEFAULT_COOKIE_LIFETIME);
|
||||
cookiesService = new AdminAuthenticationCookiesService(sysAdminParams, DEFAULT_COOKIE_LIFETIME);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -136,7 +138,7 @@ public class AdminConsoleAuthenticationCookiesServiceUnitTest
|
||||
public void cookieWithCustomMaxAgeShouldBeAddedToTheResponse()
|
||||
{
|
||||
int customMaxAge = 60;
|
||||
cookiesService = new AdminConsoleAuthenticationCookiesService(sysAdminParams, customMaxAge);
|
||||
cookiesService = new AdminAuthenticationCookiesService(sysAdminParams, customMaxAge);
|
||||
when(sysAdminParams.getAlfrescoProtocol()).thenReturn("https");
|
||||
|
||||
cookiesService.addCookie(COOKIE_NAME, COOKIE_VALUE, response);
|
@@ -23,7 +23,7 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.identityservice.admin;
|
||||
package org.alfresco.repo.security.authentication.identityservice.authentication.admin;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
@@ -58,11 +58,12 @@ import org.alfresco.repo.security.authentication.identityservice.IdentityService
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacade.AccessTokenAuthorization;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacade.AuthorizationException;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacade.AuthorizationGrant;
|
||||
import org.alfresco.repo.security.authentication.identityservice.authentication.AdditionalHeadersHttpServletRequestWrapper;
|
||||
import org.alfresco.repo.security.authentication.identityservice.authentication.AdminAuthenticationCookiesService;
|
||||
|
||||
@SuppressWarnings("PMD.AvoidStringBufferField")
|
||||
public class IdentityServiceAdminConsoleAuthenticatorUnitTest
|
||||
{
|
||||
|
||||
private static final String ALFRESCO_ACCESS_TOKEN = "ALFRESCO_ACCESS_TOKEN";
|
||||
private static final String ALFRESCO_REFRESH_TOKEN = "ALFRESCO_REFRESH_TOKEN";
|
||||
private static final String ALFRESCO_TOKEN_EXPIRATION = "ALFRESCO_TOKEN_EXPIRATION";
|
||||
@@ -76,7 +77,7 @@ public class IdentityServiceAdminConsoleAuthenticatorUnitTest
|
||||
@Mock
|
||||
IdentityServiceConfig identityServiceConfig;
|
||||
@Mock
|
||||
AdminConsoleAuthenticationCookiesService cookiesService;
|
||||
AdminAuthenticationCookiesService cookiesService;
|
||||
@Mock
|
||||
RemoteUserMapper remoteUserMapper;
|
||||
@Mock
|
||||
@@ -84,7 +85,7 @@ public class IdentityServiceAdminConsoleAuthenticatorUnitTest
|
||||
@Mock
|
||||
AccessToken accessToken;
|
||||
@Captor
|
||||
ArgumentCaptor<AdminConsoleHttpServletRequestWrapper> requestCaptor;
|
||||
ArgumentCaptor<AdditionalHeadersHttpServletRequestWrapper> requestCaptor;
|
||||
|
||||
IdentityServiceAdminConsoleAuthenticator authenticator;
|
||||
|
||||
@@ -122,7 +123,7 @@ public class IdentityServiceAdminConsoleAuthenticatorUnitTest
|
||||
String.valueOf(Instant.now().plusSeconds(60).toEpochMilli()));
|
||||
when(remoteUserMapper.getRemoteUser(requestCaptor.capture())).thenReturn("admin");
|
||||
|
||||
String username = authenticator.getAdminConsoleUser(request, response);
|
||||
String username = authenticator.getUserId(request, response);
|
||||
|
||||
assertEquals("Bearer JWT_TOKEN", requestCaptor.getValue().getHeader("Authorization"));
|
||||
assertEquals("admin", username);
|
||||
@@ -143,7 +144,7 @@ public class IdentityServiceAdminConsoleAuthenticatorUnitTest
|
||||
when(identityServiceFacade.authorize(any(AuthorizationGrant.class))).thenReturn(accessTokenAuthorization);
|
||||
when(remoteUserMapper.getRemoteUser(requestCaptor.capture())).thenReturn("admin");
|
||||
|
||||
String username = authenticator.getAdminConsoleUser(request, response);
|
||||
String username = authenticator.getUserId(request, response);
|
||||
|
||||
verify(cookiesService).addCookie(ALFRESCO_ACCESS_TOKEN, "REFRESHED_JWT_TOKEN", response);
|
||||
verify(cookiesService).addCookie(ALFRESCO_REFRESH_TOKEN, "REFRESH_TOKEN", response);
|
||||
@@ -207,7 +208,7 @@ public class IdentityServiceAdminConsoleAuthenticatorUnitTest
|
||||
|
||||
when(identityServiceFacade.authorize(any(AuthorizationGrant.class))).thenThrow(AuthorizationException.class);
|
||||
|
||||
String username = authenticator.getAdminConsoleUser(request, response);
|
||||
String username = authenticator.getUserId(request, response);
|
||||
|
||||
verify(cookiesService).resetCookie(ALFRESCO_ACCESS_TOKEN, response);
|
||||
verify(cookiesService).resetCookie(ALFRESCO_REFRESH_TOKEN, response);
|
||||
@@ -228,7 +229,7 @@ public class IdentityServiceAdminConsoleAuthenticatorUnitTest
|
||||
.thenReturn(accessTokenAuthorization);
|
||||
when(remoteUserMapper.getRemoteUser(requestCaptor.capture())).thenReturn("admin");
|
||||
|
||||
String username = authenticator.getAdminConsoleUser(request, response);
|
||||
String username = authenticator.getUserId(request, response);
|
||||
|
||||
verify(cookiesService).addCookie(ALFRESCO_ACCESS_TOKEN, "JWT_TOKEN", response);
|
||||
verify(cookiesService).addCookie(ALFRESCO_REFRESH_TOKEN, "REFRESH_TOKEN", response);
|
||||
@@ -241,7 +242,7 @@ public class IdentityServiceAdminConsoleAuthenticatorUnitTest
|
||||
{
|
||||
when(remoteUserMapper.getRemoteUser(request)).thenReturn("admin");
|
||||
|
||||
String username = authenticator.getAdminConsoleUser(request, response);
|
||||
String username = authenticator.getUserId(request, response);
|
||||
|
||||
assertEquals("admin", username);
|
||||
}
|
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2025 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 <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.identityservice.webscript;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.nimbusds.oauth2.sdk.Scope;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration.ProviderDetails;
|
||||
|
||||
import org.alfresco.repo.security.authentication.external.RemoteUserMapper;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceConfig;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacade;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacade.AccessToken;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacade.AccessTokenAuthorization;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacade.AuthorizationException;
|
||||
import org.alfresco.repo.security.authentication.identityservice.IdentityServiceFacade.AuthorizationGrant;
|
||||
import org.alfresco.repo.security.authentication.identityservice.authentication.AdditionalHeadersHttpServletRequestWrapper;
|
||||
import org.alfresco.repo.security.authentication.identityservice.authentication.AdminAuthenticationCookiesService;
|
||||
import org.alfresco.repo.security.authentication.identityservice.authentication.webscripts.IdentityServiceWebScriptsHomeAuthenticator;
|
||||
|
||||
@SuppressWarnings("PMD.AvoidStringBufferField")
|
||||
public class IdentityServiceWebScriptsHomeAuthenticatorUnitTest
|
||||
{
|
||||
|
||||
private static final String ALFRESCO_ACCESS_TOKEN = "ALFRESCO_ACCESS_TOKEN";
|
||||
private static final String ALFRESCO_REFRESH_TOKEN = "ALFRESCO_REFRESH_TOKEN";
|
||||
private static final String ALFRESCO_TOKEN_EXPIRATION = "ALFRESCO_TOKEN_EXPIRATION";
|
||||
|
||||
@Mock
|
||||
HttpServletRequest request;
|
||||
@Mock
|
||||
HttpServletResponse response;
|
||||
@Mock
|
||||
IdentityServiceFacade identityServiceFacade;
|
||||
@Mock
|
||||
IdentityServiceConfig identityServiceConfig;
|
||||
@Mock
|
||||
AdminAuthenticationCookiesService cookiesService;
|
||||
@Mock
|
||||
RemoteUserMapper remoteUserMapper;
|
||||
@Mock
|
||||
AccessTokenAuthorization accessTokenAuthorization;
|
||||
@Mock
|
||||
AccessToken accessToken;
|
||||
@Captor
|
||||
ArgumentCaptor<AdditionalHeadersHttpServletRequestWrapper> requestCaptor;
|
||||
|
||||
IdentityServiceWebScriptsHomeAuthenticator authenticator;
|
||||
|
||||
StringBuffer webScriptHomeURL = new StringBuffer("http://localhost:8080/alfresco/s/index");
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
{
|
||||
initMocks(this);
|
||||
ClientRegistration clientRegistration = mock(ClientRegistration.class);
|
||||
ProviderDetails providerDetails = mock(ProviderDetails.class);
|
||||
Scope scope = Scope.parse(Arrays.asList("openid", "profile", "email", "offline_access"));
|
||||
|
||||
when(clientRegistration.getProviderDetails()).thenReturn(providerDetails);
|
||||
when(clientRegistration.getClientId()).thenReturn("alfresco");
|
||||
when(providerDetails.getAuthorizationUri()).thenReturn("http://localhost:8999/auth");
|
||||
when(providerDetails.getConfigurationMetadata()).thenReturn(Map.of("scopes_supported", scope));
|
||||
when(identityServiceFacade.getClientRegistration()).thenReturn(clientRegistration);
|
||||
when(request.getRequestURL()).thenReturn(webScriptHomeURL);
|
||||
when(remoteUserMapper.getRemoteUser(request)).thenReturn(null);
|
||||
|
||||
authenticator = new IdentityServiceWebScriptsHomeAuthenticator();
|
||||
authenticator.setActive(true);
|
||||
authenticator.setIdentityServiceFacade(identityServiceFacade);
|
||||
authenticator.setCookiesService(cookiesService);
|
||||
authenticator.setRemoteUserMapper(remoteUserMapper);
|
||||
authenticator.setIdentityServiceConfig(identityServiceConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCallRemoteMapperIfTokenIsInCookies()
|
||||
{
|
||||
when(cookiesService.getCookie(ALFRESCO_ACCESS_TOKEN, request)).thenReturn("JWT_TOKEN");
|
||||
when(cookiesService.getCookie(ALFRESCO_TOKEN_EXPIRATION, request)).thenReturn(
|
||||
String.valueOf(Instant.now().plusSeconds(60).toEpochMilli()));
|
||||
when(remoteUserMapper.getRemoteUser(requestCaptor.capture())).thenReturn("admin");
|
||||
|
||||
String username = authenticator.getUserId(request, response);
|
||||
|
||||
assertEquals("Bearer JWT_TOKEN", requestCaptor.getValue().getHeader("Authorization"));
|
||||
assertEquals("admin", username);
|
||||
assertTrue(authenticator.isActive());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRefreshExpiredTokenAndCallRemoteMapper()
|
||||
{
|
||||
when(cookiesService.getCookie(ALFRESCO_ACCESS_TOKEN, request)).thenReturn("EXPIRED_JWT_TOKEN");
|
||||
when(cookiesService.getCookie(ALFRESCO_REFRESH_TOKEN, request)).thenReturn("REFRESH_TOKEN");
|
||||
when(cookiesService.getCookie(ALFRESCO_TOKEN_EXPIRATION, request)).thenReturn(
|
||||
String.valueOf(Instant.now().minusSeconds(60).toEpochMilli()));
|
||||
when(accessToken.getTokenValue()).thenReturn("REFRESHED_JWT_TOKEN");
|
||||
when(accessToken.getExpiresAt()).thenReturn(Instant.now().plusSeconds(60));
|
||||
when(accessTokenAuthorization.getAccessToken()).thenReturn(accessToken);
|
||||
when(accessTokenAuthorization.getRefreshTokenValue()).thenReturn("REFRESH_TOKEN");
|
||||
when(identityServiceFacade.authorize(any(AuthorizationGrant.class))).thenReturn(accessTokenAuthorization);
|
||||
when(remoteUserMapper.getRemoteUser(requestCaptor.capture())).thenReturn("admin");
|
||||
|
||||
String username = authenticator.getUserId(request, response);
|
||||
|
||||
verify(cookiesService).addCookie(ALFRESCO_ACCESS_TOKEN, "REFRESHED_JWT_TOKEN", response);
|
||||
verify(cookiesService).addCookie(ALFRESCO_REFRESH_TOKEN, "REFRESH_TOKEN", response);
|
||||
assertEquals("Bearer REFRESHED_JWT_TOKEN", requestCaptor.getValue().getHeader("Authorization"));
|
||||
assertEquals("admin", username);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCallAuthChallengeWebScriptHome() throws IOException
|
||||
{
|
||||
|
||||
String redirectPath = "/alfresco/s/index";
|
||||
when(request.getRequestURL()).thenReturn(webScriptHomeURL);
|
||||
when(identityServiceConfig.getWebScriptsHomeScopes()).thenReturn(Set.of("openid", "email", "profile", "offline_access"));
|
||||
when(identityServiceConfig.getWebScriptsHomeRedirectPath()).thenReturn(redirectPath);
|
||||
ArgumentCaptor<String> authenticationRequest = ArgumentCaptor.forClass(String.class);
|
||||
String expectedUri = "http://localhost:8999/auth?client_id=alfresco&redirect_uri=%s%s&response_type=code&scope="
|
||||
.formatted("http://localhost:8080", redirectPath);
|
||||
|
||||
authenticator.requestAuthentication(request, response);
|
||||
|
||||
verify(response).sendRedirect(authenticationRequest.capture());
|
||||
assertTrue(authenticationRequest.getValue().contains(expectedUri));
|
||||
assertTrue(authenticationRequest.getValue().contains("openid"));
|
||||
assertTrue(authenticationRequest.getValue().contains("profile"));
|
||||
assertTrue(authenticationRequest.getValue().contains("email"));
|
||||
assertTrue(authenticationRequest.getValue().contains("offline_access"));
|
||||
assertTrue(authenticationRequest.getValue().contains("state"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCallAuthChallengeWebScriptHomeWithAudience() throws IOException
|
||||
{
|
||||
String audience = "http://localhost:8082";
|
||||
String redirectPath = "/alfresco/s/index";
|
||||
when(request.getRequestURL()).thenReturn(webScriptHomeURL);
|
||||
when(identityServiceConfig.getAudience()).thenReturn(audience);
|
||||
when(identityServiceConfig.getWebScriptsHomeRedirectPath()).thenReturn(redirectPath);
|
||||
when(identityServiceConfig.getWebScriptsHomeScopes()).thenReturn(Set.of("openid", "email", "profile", "offline_access"));
|
||||
ArgumentCaptor<String> authenticationRequest = ArgumentCaptor.forClass(String.class);
|
||||
String expectedUri = "http://localhost:8999/auth?client_id=alfresco&redirect_uri=%s%s&response_type=code&scope="
|
||||
.formatted("http://localhost:8080", redirectPath);
|
||||
|
||||
authenticator.requestAuthentication(request, response);
|
||||
|
||||
verify(response).sendRedirect(authenticationRequest.capture());
|
||||
assertTrue(authenticationRequest.getValue().contains(expectedUri));
|
||||
assertTrue(authenticationRequest.getValue().contains("openid"));
|
||||
assertTrue(authenticationRequest.getValue().contains("profile"));
|
||||
assertTrue(authenticationRequest.getValue().contains("email"));
|
||||
assertTrue(authenticationRequest.getValue().contains("offline_access"));
|
||||
assertTrue(authenticationRequest.getValue().contains("audience=%s".formatted(audience)));
|
||||
assertTrue(authenticationRequest.getValue().contains("state"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldResetCookiesAndCallAuthChallenge() throws IOException
|
||||
{
|
||||
when(cookiesService.getCookie(ALFRESCO_ACCESS_TOKEN, request)).thenReturn("EXPIRED_JWT_TOKEN");
|
||||
when(cookiesService.getCookie(ALFRESCO_REFRESH_TOKEN, request)).thenReturn("REFRESH_TOKEN");
|
||||
when(cookiesService.getCookie(ALFRESCO_TOKEN_EXPIRATION, request)).thenReturn(
|
||||
String.valueOf(Instant.now().minusSeconds(60).toEpochMilli()));
|
||||
|
||||
when(identityServiceFacade.authorize(any(AuthorizationGrant.class))).thenThrow(AuthorizationException.class);
|
||||
|
||||
String username = authenticator.getUserId(request, response);
|
||||
|
||||
verify(cookiesService).resetCookie(ALFRESCO_ACCESS_TOKEN, response);
|
||||
verify(cookiesService).resetCookie(ALFRESCO_REFRESH_TOKEN, response);
|
||||
verify(cookiesService).resetCookie(ALFRESCO_TOKEN_EXPIRATION, response);
|
||||
assertNull(username);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAuthorizeCodeAndSetCookies()
|
||||
{
|
||||
when(request.getParameter("code")).thenReturn("auth_code");
|
||||
when(accessToken.getTokenValue()).thenReturn("JWT_TOKEN");
|
||||
when(accessToken.getExpiresAt()).thenReturn(Instant.now().plusSeconds(60));
|
||||
when(accessTokenAuthorization.getAccessToken()).thenReturn(accessToken);
|
||||
when(accessTokenAuthorization.getRefreshTokenValue()).thenReturn("REFRESH_TOKEN");
|
||||
when(identityServiceFacade.authorize(
|
||||
AuthorizationGrant.authorizationCode("auth_code", webScriptHomeURL.toString())))
|
||||
.thenReturn(accessTokenAuthorization);
|
||||
when(remoteUserMapper.getRemoteUser(requestCaptor.capture())).thenReturn("admin");
|
||||
|
||||
String username = authenticator.getUserId(request, response);
|
||||
|
||||
verify(cookiesService).addCookie(ALFRESCO_ACCESS_TOKEN, "JWT_TOKEN", response);
|
||||
verify(cookiesService).addCookie(ALFRESCO_REFRESH_TOKEN, "REFRESH_TOKEN", response);
|
||||
assertEquals("Bearer JWT_TOKEN", requestCaptor.getValue().getHeader("Authorization"));
|
||||
assertEquals("admin", username);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldExtractUsernameFromAuthorizationHeader()
|
||||
{
|
||||
when(remoteUserMapper.getRemoteUser(request)).thenReturn("admin");
|
||||
|
||||
String username = authenticator.getUserId(request, response);
|
||||
|
||||
assertEquals("admin", username);
|
||||
}
|
||||
}
|
@@ -25,17 +25,25 @@
|
||||
*/
|
||||
package org.alfresco.repo.site;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
@@ -44,6 +52,8 @@ import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.admin.SysAdminParams;
|
||||
import org.alfresco.repo.admin.SysAdminParamsImpl;
|
||||
import org.alfresco.repo.cache.MemoryCache;
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
import org.alfresco.repo.dictionary.DictionaryDAO;
|
||||
import org.alfresco.repo.dictionary.M2Model;
|
||||
import org.alfresco.repo.dictionary.M2Property;
|
||||
@@ -53,6 +63,7 @@ import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
|
||||
import org.alfresco.repo.node.archive.NodeArchiveService;
|
||||
import org.alfresco.repo.node.getchildren.FilterProp;
|
||||
import org.alfresco.repo.node.getchildren.FilterPropString;
|
||||
import org.alfresco.repo.search.EmptyResultSet;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
@@ -66,21 +77,10 @@ import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.CopyService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.ScriptLocation;
|
||||
import org.alfresco.service.cmr.repository.ScriptService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.security.AccessPermission;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.AuthorityService;
|
||||
import org.alfresco.service.cmr.security.AuthorityType;
|
||||
import org.alfresco.service.cmr.security.MutableAuthenticationService;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.cmr.repository.*;
|
||||
import org.alfresco.service.cmr.search.SearchParameters;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.cmr.security.*;
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.site.SiteMemberInfo;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
@@ -90,22 +90,10 @@ import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.test_category.BaseSpringTestsCategory;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.alfresco.util.BaseAlfrescoSpringTest;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.alfresco.util.testing.category.LuceneTests;
|
||||
import org.alfresco.util.testing.category.RedundantTests;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Site service implementation unit test
|
||||
@@ -172,8 +160,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
public void before() throws Exception
|
||||
{
|
||||
super.before();
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>() {
|
||||
|
||||
@Override
|
||||
public Object execute() throws Throwable
|
||||
@@ -252,7 +239,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
return null;
|
||||
}
|
||||
};
|
||||
transactionService = (TransactionService)this.applicationContext.getBean("transactionComponent");
|
||||
transactionService = (TransactionService) this.applicationContext.getBean("transactionComponent");
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(work, false, true);
|
||||
}
|
||||
|
||||
@@ -266,8 +253,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
}
|
||||
|
||||
/**
|
||||
* This test method ensures that public sites can be created and that their site info is correct.
|
||||
* It also tests that a duplicate site cannot be created.
|
||||
* This test method ensures that public sites can be created and that their site info is correct. It also tests that a duplicate site cannot be created.
|
||||
*/
|
||||
@Test
|
||||
public void testCreateSite() throws Exception
|
||||
@@ -278,7 +264,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
checkSiteInfo(siteInfo, TEST_SITE_PRESET, mySiteTest, TEST_TITLE, TEST_DESCRIPTION, SiteVisibility.PUBLIC);
|
||||
|
||||
String name = "!£$%^&*()_+=-[]{}";
|
||||
//Calls deprecated method (still creates a public Site)
|
||||
// Calls deprecated method (still creates a public Site)
|
||||
siteInfo = this.siteService.createSite(TEST_SITE_PRESET, name, TEST_TITLE, TEST_DESCRIPTION, true);
|
||||
checkSiteInfo(siteInfo, TEST_SITE_PRESET, name, TEST_TITLE, TEST_DESCRIPTION, SiteVisibility.PUBLIC);
|
||||
siteInfo = this.siteService.getSite(name);
|
||||
@@ -323,7 +309,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
|
||||
try
|
||||
{
|
||||
//Create a site with an invalid site type
|
||||
// Create a site with an invalid site type
|
||||
this.siteService.createSite(TEST_SITE_PRESET, "InvalidSiteType", TEST_TITLE, TEST_DESCRIPTION, SiteVisibility.PUBLIC, ServiceRegistry.CMIS_SERVICE);
|
||||
fail("Shouldn't allow invalid site type.");
|
||||
}
|
||||
@@ -336,8 +322,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
@Test
|
||||
public void testHasSite() throws Exception
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>() {
|
||||
|
||||
@Override
|
||||
public Object execute() throws Throwable
|
||||
@@ -375,8 +360,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
@Test
|
||||
public void testETHREEOH_2133() throws Exception
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>() {
|
||||
|
||||
@Override
|
||||
public Object execute() throws Throwable
|
||||
@@ -407,10 +391,12 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
}
|
||||
|
||||
/**
|
||||
* This method tests https://issues.alfresco.com/jira/browse/ALF-3785 which allows 'public' sites
|
||||
* to be only visible to members of a configured group, by default EVERYONE.
|
||||
* This method tests https://issues.alfresco.com/jira/browse/ALF-3785 which allows 'public' sites to be only visible to members of a configured group, by default EVERYONE.
|
||||
*
|
||||
* <br>
|
||||
* <br/>
|
||||
* author Neil McErlean
|
||||
*
|
||||
* <br><br/>author Neil McErlean
|
||||
* @since 3.4
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@@ -436,7 +422,6 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
TEST_TITLE, TEST_DESCRIPTION, SiteVisibility.PUBLIC);
|
||||
assertTrue(containsConsumerPermission(originalSitePublicGroup, unconfiguredSite));
|
||||
|
||||
|
||||
// Now set the managed bean's visibility group to something other than GROUP_EVERYONE.
|
||||
// This is the group that will have visibility of subsequently created sites.
|
||||
//
|
||||
@@ -464,11 +449,9 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
fail("Expected exception on createSite with non-existent group was not thrown.");
|
||||
}
|
||||
|
||||
|
||||
// Now we'll create the group used above.
|
||||
authorityService.createAuthority(AuthorityType.GROUP, newGroupName);
|
||||
|
||||
|
||||
// And create the site as before. This time it should succeed.
|
||||
SiteInfo configuredSite = siteService.createSite(TEST_SITE_PRESET, "configured",
|
||||
TEST_TITLE, TEST_DESCRIPTION, SiteVisibility.PUBLIC);
|
||||
@@ -510,8 +493,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
@Test
|
||||
public void testETHREEOH_15() throws Exception
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>() {
|
||||
|
||||
@Override
|
||||
public Object execute() throws Throwable
|
||||
@@ -540,16 +522,14 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
fail("Shouldn't be able to do this cos you don't have permissions");
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
}
|
||||
{}
|
||||
try
|
||||
{
|
||||
siteService.removeMembership(siteInfo.getShortName(), USER_ONE);
|
||||
fail("Shouldn't be able to do this cos you don't have permissions");
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
}
|
||||
{}
|
||||
siteService.removeMembership(siteInfo.getShortName(), USER_THREE);
|
||||
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
@@ -583,10 +563,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
/**
|
||||
* Test listSite and findSites methods.
|
||||
* <p/>
|
||||
* Note that {@link SiteService#findSites(String, int)} offers eventually consistent results and therefore may
|
||||
* exhibit changed behaviour if Lucene is switched off or is replaced by SOLR.
|
||||
* {@link SiteService#listSites(List, List, org.alfresco.query.PagingRequest)} and the other listSites methods
|
||||
* should offer consistent, accurate result sets.
|
||||
* Note that {@link SiteService#findSites(String, int)} offers eventually consistent results and therefore may exhibit changed behaviour if Lucene is switched off or is replaced by SOLR. {@link SiteService#listSites(List, List, org.alfresco.query.PagingRequest)} and the other listSites methods should offer consistent, accurate result sets.
|
||||
*/
|
||||
@Category(RedundantTests.class)
|
||||
@Test
|
||||
@@ -687,7 +664,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
}
|
||||
}
|
||||
|
||||
//Test the public method on the implementation.
|
||||
// Test the public method on the implementation.
|
||||
Set<String> sitesSet = new HashSet<>(2);
|
||||
sitesSet.add("mySiteOne");
|
||||
sitesSet.add("mySiteTwo");
|
||||
@@ -812,8 +789,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
@Test
|
||||
public void testMNT_13710() throws Exception
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>() {
|
||||
|
||||
@Override
|
||||
public Object execute() throws Throwable
|
||||
@@ -884,7 +860,6 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This test method ensures that searches with wildcards work as they should
|
||||
*/
|
||||
@@ -936,11 +911,11 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
this.siteService.createSite(TEST_SITE_PRESET, "siteLiveB", "getafix1vitalstatistix", TEST_DESCRIPTION, SiteVisibility.PUBLIC);
|
||||
this.siteService.createSite(TEST_SITE_PRESET, "siteLiveC", "Armorican Gaul France", TEST_DESCRIPTION, SiteVisibility.PUBLIC);
|
||||
|
||||
//ACE-1428
|
||||
// ACE-1428
|
||||
this.siteService.createSite(TEST_SITE_PRESET, "siteLiveD", "n3w s1t3 creat3ed 88", TEST_DESCRIPTION, SiteVisibility.PUBLIC);
|
||||
this.siteService.createSite(TEST_SITE_PRESET, "siteLiveE", "n3w s1t3 creat3ed 99", TEST_DESCRIPTION, SiteVisibility.PUBLIC);
|
||||
|
||||
//More scenarios
|
||||
// More scenarios
|
||||
this.siteService.createSite(TEST_SITE_PRESET, "siteLiveF", "super exciting product", TEST_DESCRIPTION, SiteVisibility.PUBLIC);
|
||||
this.siteService.createSite(TEST_SITE_PRESET, "siteLiveG", "super exciting launch", TEST_DESCRIPTION, SiteVisibility.PUBLIC);
|
||||
this.siteService.createSite(TEST_SITE_PRESET, "siteLiveH", "amazing sales 54", TEST_DESCRIPTION, SiteVisibility.PUBLIC);
|
||||
@@ -1186,7 +1161,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
@Test
|
||||
public void testMoveFolderStructureWithNonInheritedPermission()
|
||||
{
|
||||
//Login to share as the admin user
|
||||
// Login to share as the admin user
|
||||
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
|
||||
|
||||
// Create 2 sites test1, test2 as admin
|
||||
@@ -1253,16 +1228,16 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
|
||||
// This is what Share does:
|
||||
// move the node
|
||||
//result.success = fileNode.move(parent, destNode);
|
||||
// result.success = fileNode.move(parent, destNode);
|
||||
//
|
||||
//if (result.success)
|
||||
//{
|
||||
// if (result.success)
|
||||
// {
|
||||
// // If this was an inter-site move, we'll need to clean up the permissions on the node
|
||||
// if ((fromSite) && (String(fromSite) !== String(fileNode.siteShortName)))
|
||||
// {
|
||||
// siteService.cleanSitePermissions(fileNode);
|
||||
// }
|
||||
//}
|
||||
// }
|
||||
siteService.cleanSitePermissions(fol1, test2SiteInfo);
|
||||
|
||||
childAssocs = nodeService.getChildAssocs(documentLibraryTest1Site);
|
||||
@@ -1293,12 +1268,11 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
public void testDeleteSite()
|
||||
{
|
||||
@SuppressWarnings("deprecation")
|
||||
SiteService smallSiteService = (SiteService)this.applicationContext.getBean("siteService");
|
||||
SiteService smallSiteService = (SiteService) this.applicationContext.getBean("siteService");
|
||||
// Create a test group
|
||||
final String testGroupName = "siteServiceImplTestGroup_" + GUID.generate();
|
||||
String testGroup = AuthenticationUtil.runAs(
|
||||
new AuthenticationUtil.RunAsWork<String>()
|
||||
{
|
||||
new AuthenticationUtil.RunAsWork<String>() {
|
||||
public String doWork() throws Exception
|
||||
{
|
||||
return authorityService.createAuthority(AuthorityType.GROUP, testGroupName);
|
||||
@@ -1322,12 +1296,12 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
|
||||
// related site groups should remain after site delete but should be deleted on site purge from trashcan.
|
||||
// Such case is tested in SiteServiceImplMoreTest.deleteSiteAndRestoreEnsuringSiteGroupsAreRecovered
|
||||
assertTrue(authorityService.authorityExists(((SiteServiceImpl)smallSiteService).getSiteGroup(siteShortName, true)));
|
||||
assertTrue(authorityService.authorityExists(((SiteServiceImpl) smallSiteService).getSiteGroup(siteShortName, true)));
|
||||
assertTrue(authorityService.authorityExists(((SiteServiceImpl) smallSiteService).getSiteGroup(siteShortName)));
|
||||
Set<String> permissions = permissionService.getSettablePermissions(SiteModel.TYPE_SITE);
|
||||
for (String permission : permissions)
|
||||
{
|
||||
String siteRoleGroup = ((SiteServiceImpl)smallSiteService).getSiteRoleGroup(siteShortName, permission, true);
|
||||
String siteRoleGroup = ((SiteServiceImpl) smallSiteService).getSiteRoleGroup(siteShortName, permission, true);
|
||||
assertTrue(authorityService.authorityExists(siteRoleGroup));
|
||||
}
|
||||
|
||||
@@ -1338,8 +1312,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
@Test
|
||||
public void testIsPublic()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>() {
|
||||
|
||||
@Override
|
||||
public Object execute() throws Throwable
|
||||
@@ -1391,8 +1364,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
@Test
|
||||
public void testMembership()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>() {
|
||||
|
||||
@Override
|
||||
public Object execute() throws Throwable
|
||||
@@ -1451,9 +1423,8 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
assertTrue(members.containsKey(USER_THREE));
|
||||
assertEquals(SiteModel.SITE_COLLABORATOR, members.get(USER_THREE));
|
||||
|
||||
//Check other listMember calls
|
||||
siteService.listMembers(siteShortName, null, null, false, new SiteService.SiteMembersCallback()
|
||||
{
|
||||
// Check other listMember calls
|
||||
siteService.listMembers(siteShortName, null, null, false, new SiteService.SiteMembersCallback() {
|
||||
List<String> USERS = Arrays.asList(USER_ONE, USER_TWO, USER_THREE);
|
||||
int userCount = 0;
|
||||
|
||||
@@ -1469,7 +1440,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
@Override
|
||||
public boolean isDone()
|
||||
{
|
||||
return userCount==USERS.size();
|
||||
return userCount == USERS.size();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1580,8 +1551,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
@Test
|
||||
public void testListSiteMemberships()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>() {
|
||||
|
||||
@Override
|
||||
public Object execute() throws Throwable
|
||||
@@ -1669,13 +1639,10 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(work);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testJoinLeave()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>() {
|
||||
|
||||
@Override
|
||||
public Object execute() throws Throwable
|
||||
@@ -1869,8 +1836,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a site with a custom type, and ensures that
|
||||
* it behaves correctly.
|
||||
* Creates a site with a custom type, and ensures that it behaves correctly.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
@@ -1880,31 +1846,27 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
final String CS_PFX = "cs";
|
||||
|
||||
// Setup our custom site type
|
||||
DictionaryDAO dictionaryDAO = (DictionaryDAO)this.applicationContext.getBean("dictionaryDAO");
|
||||
DictionaryDAO dictionaryDAO = (DictionaryDAO) this.applicationContext.getBean("dictionaryDAO");
|
||||
M2Model model = M2Model.createModel("cm:CustomSiteModel");
|
||||
model.createNamespace(CS_URI, CS_PFX);
|
||||
|
||||
// Import the usual suspects too
|
||||
model.createImport(
|
||||
NamespaceService.CONTENT_MODEL_1_0_URI,
|
||||
NamespaceService.CONTENT_MODEL_PREFIX
|
||||
);
|
||||
NamespaceService.CONTENT_MODEL_PREFIX);
|
||||
model.createImport(
|
||||
NamespaceService.DICTIONARY_MODEL_1_0_URI,
|
||||
NamespaceService.DICTIONARY_MODEL_PREFIX
|
||||
);
|
||||
NamespaceService.DICTIONARY_MODEL_PREFIX);
|
||||
model.createImport(
|
||||
SiteModel.SITE_MODEL_URL,
|
||||
SiteModel.SITE_MODEL_PREFIX
|
||||
);
|
||||
SiteModel.SITE_MODEL_PREFIX);
|
||||
|
||||
// Custom type
|
||||
M2Type customType = model.createType("cs:customSite");
|
||||
customType.setTitle("customSite");
|
||||
customType.setParentName(
|
||||
SiteModel.SITE_MODEL_PREFIX + ":" +
|
||||
SiteModel.TYPE_SITE.getLocalName()
|
||||
);
|
||||
SiteModel.TYPE_SITE.getLocalName());
|
||||
|
||||
M2Property customProp = customType.createProperty("cs:customSiteProp");
|
||||
customProp.setTitle("customSiteProp");
|
||||
@@ -1919,8 +1881,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
// Create a site
|
||||
SiteInfo site = siteService.createSite(
|
||||
"custom", "custom", "Custom", "Custom",
|
||||
SiteVisibility.PUBLIC
|
||||
);
|
||||
SiteVisibility.PUBLIC);
|
||||
|
||||
// Check the roles on it
|
||||
List<String> roles = siteService.getSiteRoles();
|
||||
@@ -1937,7 +1898,6 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
assertEquals(true, roles.contains(SiteServiceImpl.SITE_COLLABORATOR));
|
||||
assertEquals(true, roles.contains(SiteServiceImpl.SITE_MANAGER));
|
||||
|
||||
|
||||
// Swap the type
|
||||
nodeService.setType(site.getNodeRef(), customTypeQ);
|
||||
|
||||
@@ -1956,20 +1916,16 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
assertEquals(true, roles.contains(SiteServiceImpl.SITE_COLLABORATOR));
|
||||
assertEquals(true, roles.contains(SiteServiceImpl.SITE_MANAGER));
|
||||
|
||||
|
||||
// Alter the permissions for the custom site
|
||||
PermissionService testPermissionService = spy(
|
||||
(PermissionService)this.applicationContext.getBean("permissionServiceImpl")
|
||||
);
|
||||
(PermissionService) this.applicationContext.getBean("permissionServiceImpl"));
|
||||
Set<String> customPerms = new HashSet<String>();
|
||||
customPerms.add(SiteServiceImpl.SITE_MANAGER);
|
||||
customPerms.add("CUSTOM");
|
||||
when(testPermissionService.getSettablePermissions(customTypeQ)).
|
||||
thenReturn(customPerms);
|
||||
when(testPermissionService.getSettablePermissions(customTypeQ)).thenReturn(customPerms);
|
||||
|
||||
// Check it changed for the custom site, but not normal
|
||||
SiteServiceImpl siteServiceImpl = (SiteServiceImpl)
|
||||
this.applicationContext.getBean("siteService");
|
||||
SiteServiceImpl siteServiceImpl = (SiteServiceImpl) this.applicationContext.getBean("siteService");
|
||||
siteServiceImpl.setPermissionService(testPermissionService);
|
||||
roles = siteService.getSiteRoles();
|
||||
|
||||
@@ -2004,8 +1960,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
@Test
|
||||
public void testGroupMembership()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>() {
|
||||
@Override
|
||||
public Object execute() throws Throwable
|
||||
{
|
||||
@@ -2070,7 +2025,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
assertEquals(SiteModel.SITE_CONSUMER, siteService.getMembersRole(testGroupMembership, USER_THREE));
|
||||
assertEquals(SiteModel.SITE_CONSUMER, siteService.getMembersRole(testGroupMembership, groupTwo));
|
||||
|
||||
//Uses Members role info
|
||||
// Uses Members role info
|
||||
assertEquals(SiteModel.SITE_MANAGER, siteService.getMembersRoleInfo(testGroupMembership, USER_ONE).getMemberRole());
|
||||
/**
|
||||
* Check we can filter this list by name and role correctly
|
||||
@@ -2111,7 +2066,6 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
assertNotNull(members);
|
||||
assertEquals(0, members.size());
|
||||
|
||||
|
||||
// - filter by name - group name
|
||||
members = siteService.listMembers(testGroupMembership, GROUP_TWO, null, 0, false);
|
||||
assertNotNull(members);
|
||||
@@ -2132,7 +2086,6 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
assertNotNull(members);
|
||||
assertEquals(0, members.size());
|
||||
|
||||
|
||||
/**
|
||||
* Add a group member (USER_THREE) as an explicit member
|
||||
*/
|
||||
@@ -2180,12 +2133,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
/**
|
||||
* Add other group (GROUP_3) with higher (MANAGER) role
|
||||
*
|
||||
* - is group in list?
|
||||
* - is new user a member?
|
||||
* - does redefined user have highest role?
|
||||
* USER_TWO should be Manager from group 3 having higher priority than group 2
|
||||
* USER_THREE should still be Contributor from explicit membership.
|
||||
* USER_FOUR should be Manager - from group 4 sub-group
|
||||
* - is group in list? - is new user a member? - does redefined user have highest role? USER_TWO should be Manager from group 3 having higher priority than group 2 USER_THREE should still be Contributor from explicit membership. USER_FOUR should be Manager - from group 4 sub-group
|
||||
*/
|
||||
siteService.setMembership(testGroupMembership, groupThree, SiteModel.SITE_MANAGER);
|
||||
|
||||
@@ -2229,7 +2177,6 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* See https://issues.alfresco.com/jira/browse/MNT-2229
|
||||
*/
|
||||
@Test
|
||||
@@ -2262,8 +2209,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
@Test
|
||||
public void testSiteVisibility()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>() {
|
||||
|
||||
@Override
|
||||
public Object execute() throws Throwable
|
||||
@@ -2352,7 +2298,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
*/
|
||||
private Map<String, Set<String>> getAllowedPermissionsMap(NodeRef nodeRef)
|
||||
{
|
||||
Map<String,Set<String>> perms = new HashMap<String, Set<String>>();
|
||||
Map<String, Set<String>> perms = new HashMap<String, Set<String>>();
|
||||
for (AccessPermission ap : permissionService.getAllSetPermissions(nodeRef))
|
||||
{
|
||||
if (ap.getAccessStatus() == AccessStatus.ALLOWED)
|
||||
@@ -2370,8 +2316,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
}
|
||||
|
||||
/**
|
||||
* ALF-10343 - When the default public group for sites isn't EVERYBODY,
|
||||
* check that creating and altering sites results in the correct permissions
|
||||
* ALF-10343 - When the default public group for sites isn't EVERYBODY, check that creating and altering sites results in the correct permissions
|
||||
*/
|
||||
@Test
|
||||
public void testNonDefaultPublicGroupPermissions() throws Exception
|
||||
@@ -2384,13 +2329,11 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
sp.setSitePublicGroup(groupFour);
|
||||
siteServiceImpl.setSysAdminParams(sp);
|
||||
|
||||
|
||||
// Create sites of the three types
|
||||
SiteInfo s1 = this.siteService.createSite(TEST_SITE_PRESET, "SiteTest_priv", "priv", "priv", SiteVisibility.PRIVATE);
|
||||
SiteInfo s2 = this.siteService.createSite(TEST_SITE_PRESET, "SiteTest_mod", "mod", "mod", SiteVisibility.MODERATED);
|
||||
SiteInfo s3 = this.siteService.createSite(TEST_SITE_PRESET, "SiteTest_pub", "pub", "pub", SiteVisibility.PUBLIC);
|
||||
|
||||
|
||||
// Check the permissions on them
|
||||
// Everyone has read permissions only, not Consumer
|
||||
assertTrue(getAllowedPermissionsMap(s1).get(PermissionService.ALL_AUTHORITIES).contains("ReadPermissions"));
|
||||
@@ -2407,7 +2350,6 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
assertEquals(SiteModel.SITE_MANAGER, siteService.getMembersRole(s2.getShortName(), USER_ONE));
|
||||
assertEquals(SiteModel.SITE_MANAGER, siteService.getMembersRole(s3.getShortName(), USER_ONE));
|
||||
|
||||
|
||||
// Swap the visibilites around, private+moderated -> public, public -> private
|
||||
s1.setVisibility(SiteVisibility.PUBLIC);
|
||||
s2.setVisibility(SiteVisibility.PUBLIC);
|
||||
@@ -2433,7 +2375,6 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
assertEquals(SiteModel.SITE_MANAGER, siteService.getMembersRole(s2.getShortName(), USER_ONE));
|
||||
assertEquals(SiteModel.SITE_MANAGER, siteService.getMembersRole(s3.getShortName(), USER_ONE));
|
||||
|
||||
|
||||
// Swap them back again
|
||||
s1.setVisibility(SiteVisibility.PRIVATE);
|
||||
s2.setVisibility(SiteVisibility.MODERATED);
|
||||
@@ -2466,8 +2407,8 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a site with a simple content tree within it.
|
||||
* The content looks like
|
||||
* Creates a site with a simple content tree within it. The content looks like
|
||||
*
|
||||
* <pre>
|
||||
* [site] {siteShortName}
|
||||
* |
|
||||
@@ -2484,10 +2425,14 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
* |-- [cm:content] fileFolderPrefix + "fileInSubfolder.txt"
|
||||
* </pre>
|
||||
*
|
||||
* @param siteShortName short name for the site
|
||||
* @param componentId the component id for the container
|
||||
* @param visibility visibility for the site.
|
||||
* @param fileFolderPrefix a prefix String to put on all folders/files created.
|
||||
* @param siteShortName
|
||||
* short name for the site
|
||||
* @param componentId
|
||||
* the component id for the container
|
||||
* @param visibility
|
||||
* visibility for the site.
|
||||
* @param fileFolderPrefix
|
||||
* a prefix String to put on all folders/files created.
|
||||
*/
|
||||
private SiteInfo createTestSiteWithContent(String siteShortName, String componentId, SiteVisibility visibility, String fileFolderPrefix)
|
||||
{
|
||||
@@ -2565,17 +2510,13 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a site with a USER manager.
|
||||
* Add Group manager membership.
|
||||
* Create a site with a USER manager. Add Group manager membership.
|
||||
*
|
||||
* Lower User membership - should be O.K. because of Group Membership
|
||||
* Lower Group membership - should be prevented (last manager)
|
||||
* Lower User membership - should be O.K. because of Group Membership Lower Group membership - should be prevented (last manager)
|
||||
*
|
||||
* Reset User membership to Manager
|
||||
*
|
||||
* Lower Group membership - should be O.K. because of User Membership
|
||||
* Lower User membership - should be prevented (last manager)
|
||||
*
|
||||
* Lower Group membership - should be O.K. because of User Membership Lower User membership - should be prevented (last manager)
|
||||
*/
|
||||
@Test
|
||||
public void testALFCOM_3109()
|
||||
@@ -2631,17 +2572,13 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a site with a USER manager.
|
||||
* Add Group manager membership.
|
||||
* Create a site with a USER manager. Add Group manager membership.
|
||||
*
|
||||
* Remove User membership - should be O.K. because of Group Membership
|
||||
* Remove Group membership - should be prevented (last manager)
|
||||
* Remove User membership - should be O.K. because of Group Membership Remove Group membership - should be prevented (last manager)
|
||||
*
|
||||
* Add User membership to Manager
|
||||
*
|
||||
* Remove Group membership - should be O.K. because of User Membership
|
||||
* Remove User membership - should be prevented (last manager)
|
||||
*
|
||||
* Remove Group membership - should be O.K. because of User Membership Remove User membership - should be prevented (last manager)
|
||||
*/
|
||||
@Test
|
||||
public void testALFCOM_3111()
|
||||
@@ -2700,13 +2637,11 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
* Create a private site.
|
||||
*
|
||||
* Attempt to access a private site by someone that is not a consumer of that site.
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testETHREEOH_1268()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>() {
|
||||
|
||||
@Override
|
||||
public Object execute() throws Throwable
|
||||
@@ -2739,11 +2674,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
}
|
||||
|
||||
/**
|
||||
* ALF-3200
|
||||
* You shouldn't be able to rename a Site using the normal node service
|
||||
* type operations, because the relationship between a site and its
|
||||
* authorities is based on a pattern that uses the site name.
|
||||
* However, you are free to change a site's display name.
|
||||
* ALF-3200 You shouldn't be able to rename a Site using the normal node service type operations, because the relationship between a site and its authorities is based on a pattern that uses the site name. However, you are free to change a site's display name.
|
||||
*/
|
||||
@Test
|
||||
public void testALF_3200() throws Exception
|
||||
@@ -2762,7 +2693,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
fileFolderService.rename(siteNodeRef, "RenamedName");
|
||||
fail("Shouldn't be able to rename a site but did");
|
||||
}
|
||||
catch(SiteServiceException e)
|
||||
catch (SiteServiceException e)
|
||||
{
|
||||
// expected
|
||||
}
|
||||
@@ -2868,8 +2799,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
}
|
||||
|
||||
/**
|
||||
* ALF-1017 - Non sites in the Sites Space container shouldn't
|
||||
* break the listing methods
|
||||
* ALF-1017 - Non sites in the Sites Space container shouldn't break the listing methods
|
||||
*/
|
||||
@Test
|
||||
public void testALF_1017_nonSitesInSitesSpace() throws Exception
|
||||
@@ -2886,39 +2816,39 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
// Listing is still ok
|
||||
sites = this.siteService.listSites(null, null);
|
||||
assertNotNull("sites list was null.", sites);
|
||||
assertEquals(preexistingSitesCount+2, sites.size());
|
||||
assertEquals(preexistingSitesCount + 2, sites.size());
|
||||
|
||||
// Now add a random folder, and a random document to the sites root
|
||||
final NodeRef sitesSpace = this.nodeService.getPrimaryParent(site1.getNodeRef()).getParentRef();
|
||||
final NodeRef folder = AuthenticationUtil.runAsSystem(new RunAsWork<NodeRef>() {
|
||||
@Override
|
||||
public NodeRef doWork() throws Exception {
|
||||
public NodeRef doWork() throws Exception
|
||||
{
|
||||
return nodeService.createNode(
|
||||
sitesSpace, ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName("Folder"), ContentModel.TYPE_FOLDER
|
||||
).getChildRef();
|
||||
QName.createQName("Folder"), ContentModel.TYPE_FOLDER).getChildRef();
|
||||
}
|
||||
});
|
||||
final NodeRef document = AuthenticationUtil.runAsSystem(new RunAsWork<NodeRef>() {
|
||||
@Override
|
||||
public NodeRef doWork() throws Exception {
|
||||
public NodeRef doWork() throws Exception
|
||||
{
|
||||
return nodeService.createNode(
|
||||
sitesSpace, ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName("Document"), ContentModel.TYPE_CONTENT
|
||||
).getChildRef();
|
||||
QName.createQName("Document"), ContentModel.TYPE_CONTENT).getChildRef();
|
||||
}
|
||||
});
|
||||
|
||||
// Listing should still be fine, and count won't have increased
|
||||
sites = this.siteService.listSites(null, null);
|
||||
assertNotNull("sites list was null.", sites);
|
||||
assertEquals(preexistingSitesCount+2, sites.size());
|
||||
assertEquals(preexistingSitesCount + 2, sites.size());
|
||||
|
||||
// Delete one site, listing still ok
|
||||
this.siteService.deleteSite(site2.getShortName());
|
||||
sites = this.siteService.listSites(null, null);
|
||||
assertNotNull("sites list was null.", sites);
|
||||
assertEquals(preexistingSitesCount+1, sites.size());
|
||||
assertEquals(preexistingSitesCount + 1, sites.size());
|
||||
|
||||
// Tidy up the random nodes, listing still fine
|
||||
this.nodeService.deleteNode(folder);
|
||||
@@ -2926,7 +2856,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
|
||||
sites = this.siteService.listSites(null, null);
|
||||
assertNotNull("sites list was null.", sites);
|
||||
assertEquals(preexistingSitesCount+1, sites.size());
|
||||
assertEquals(preexistingSitesCount + 1, sites.size());
|
||||
}
|
||||
|
||||
private SiteInfo createSite(String siteShortName, String componentId, SiteVisibility visibility)
|
||||
@@ -2960,7 +2890,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
|
||||
fail("Should have caught rename");
|
||||
}
|
||||
catch(SiteServiceException e)
|
||||
catch (SiteServiceException e)
|
||||
{
|
||||
assertTrue(e.getMessage().contains("can not be renamed"));
|
||||
}
|
||||
@@ -3088,7 +3018,6 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* From CLOUD-957, insure that GROUP_EVERYONE does not have read access to private sites' containers.
|
||||
*/
|
||||
@@ -3103,7 +3032,6 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
|
||||
assertNull("GROUP_EVERYONE shouldn't have any permissions on a private site's containers", getAllowedPermissionsMap(container).get(PermissionService.ALL_AUTHORITIES));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3120,7 +3048,6 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
|
||||
assertNull("GROUP_EVERYONE shouldn't have any permissions on a moderated site's containers", getAllowedPermissionsMap(container).get(PermissionService.ALL_AUTHORITIES));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3131,7 +3058,7 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
{
|
||||
String siteName = GUID.generate();
|
||||
|
||||
//Check Private->public
|
||||
// Check Private->public
|
||||
SiteInfo siteInfo = createSite(siteName, "doclib", SiteVisibility.PRIVATE);
|
||||
|
||||
NodeRef container = this.siteService.getContainer(siteInfo.getShortName(), "doclib");
|
||||
@@ -3141,19 +3068,19 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
|
||||
assertTrue(getAllowedPermissionsMap(container).get(PermissionService.ALL_AUTHORITIES).contains("ReadPermissions"));
|
||||
|
||||
//Check public->moderated
|
||||
// Check public->moderated
|
||||
siteInfo.setVisibility(SiteVisibility.MODERATED);
|
||||
siteService.updateSite(siteInfo);
|
||||
|
||||
assertNull("GROUP_EVERYONE shouldn't have any permissions on a moderated site's containers", getAllowedPermissionsMap(container).get(PermissionService.ALL_AUTHORITIES));
|
||||
|
||||
//Check moderated->public
|
||||
// Check moderated->public
|
||||
siteInfo.setVisibility(SiteVisibility.PUBLIC);
|
||||
siteService.updateSite(siteInfo);
|
||||
|
||||
assertTrue(getAllowedPermissionsMap(container).get(PermissionService.ALL_AUTHORITIES).contains("ReadPermissions"));
|
||||
|
||||
//Check public->private
|
||||
// Check public->private
|
||||
siteInfo.setVisibility(SiteVisibility.PRIVATE);
|
||||
siteService.updateSite(siteInfo);
|
||||
|
||||
@@ -3162,7 +3089,8 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteSiteAsAdministrator() throws Exception {
|
||||
public void testDeleteSiteAsAdministrator() throws Exception
|
||||
{
|
||||
this.authenticationComponent.setCurrentUser(AuthenticationUtil.getAdminUserName());
|
||||
String shortName = GUID.generate();
|
||||
createSite(shortName, "doclib", SiteVisibility.MODERATED);
|
||||
@@ -3185,4 +3113,34 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
|
||||
|
||||
siteService.deleteSite(shortName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindSitesQueryWithReservedCharacter()
|
||||
{
|
||||
// given
|
||||
SiteServiceImpl cut = new SiteServiceImpl();
|
||||
|
||||
ArgumentCaptor<SearchParameters> searchParametersCaptor = ArgumentCaptor.forClass(SearchParameters.class);
|
||||
|
||||
SimpleCache<String, Object> cache = new MemoryCache<>();
|
||||
cache.put("key.sitehome.noderef", new NodeRef("mock", "mock", "mock"));
|
||||
cut.setSingletonCache(cache);
|
||||
|
||||
SearchService searchService = Mockito.mock(SearchService.class);
|
||||
cut.setSearchService(searchService);
|
||||
when(searchService.query(any(SearchParameters.class))).thenReturn(new EmptyResultSet());
|
||||
|
||||
// when
|
||||
cut.findSites("-chu", 5);
|
||||
|
||||
// then
|
||||
verify(searchService).query(searchParametersCaptor.capture());
|
||||
SearchParameters actualSearchParameters = searchParametersCaptor.getValue();
|
||||
assertThat(actualSearchParameters.getQuery())
|
||||
.isEqualTo("+TYPE:\"{http://www.alfresco.org/model/site/1.0}site\""
|
||||
+ " AND ( cm:name:\"\\-chu*\""
|
||||
+ " OR cm:title: (\"\\-chu*\" )"
|
||||
+ " OR cm:description:\"\\-chu\")");
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -32,20 +32,19 @@ import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.ContextCustomizerFactories;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Base test class providing Hibernate sessions.
|
||||
* <p>
|
||||
* By default this is auto-wired by type. If a this is going to
|
||||
* result in a conlict the use auto-wire by name. This can be done by
|
||||
* setting populateProtectedVariables to true in the constructor and
|
||||
* then adding protected members with the same name as the bean you require.
|
||||
* By default this is auto-wired by type. If a this is going to result in a conlict the use auto-wire by name. This can be done by setting populateProtectedVariables to true in the constructor and then adding protected members with the same name as the bean you require.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration({"classpath:alfresco/application-context.xml"})
|
||||
@ContextCustomizerFactories(factories = {}, mergeMode = ContextCustomizerFactories.MergeMode.REPLACE_DEFAULTS)
|
||||
public abstract class BaseSpringTest extends TestCase
|
||||
{
|
||||
public Log logger = LogFactory.getLog(getClass().getName());
|
||||
|
Reference in New Issue
Block a user