add LDAP integr. test for receiving share candidates with group limitationtags/v17.0.0beta1
@@ -130,7 +130,6 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface, IGroupLD | |||
//usually, LDAP attributes are said to be case insensitive. But there are exceptions of course. | |||
$members = $this->_groupMembers($groupDN); | |||
$members = array_keys($members); // uids are returned as keys | |||
if(!is_array($members) || count($members) === 0) { | |||
$this->access->connection->writeToCache($cacheKey, false); | |||
return false; |
@@ -84,7 +84,7 @@ default: | |||
admin: | |||
- admin | |||
- admin | |||
regular_user_password: what_for | |||
regular_user_password: 123456 | |||
remoteapi: | |||
paths: | |||
- "%paths.base%/../remoteapi_features" |
@@ -23,8 +23,8 @@ | |||
*/ | |||
use Behat\Behat\Hook\Scope\AfterScenarioScope; | |||
use Behat\Behat\Hook\Scope\BeforeScenarioScope; | |||
use GuzzleHttp\Message\ResponseInterface; | |||
use PHPUnit\Framework\Assert; | |||
use Psr\Http\Message\ResponseInterface; | |||
require __DIR__ . '/../../vendor/autoload.php'; | |||
@@ -29,6 +29,7 @@ | |||
* | |||
*/ | |||
use Behat\Gherkin\Node\TableNode; | |||
use GuzzleHttp\Client; | |||
use GuzzleHttp\Cookie\CookieJar; | |||
use GuzzleHttp\Exception\ClientException; | |||
@@ -165,7 +166,7 @@ trait BasicStructure { | |||
* @When /^sending "([^"]*)" to "([^"]*)" with$/ | |||
* @param string $verb | |||
* @param string $url | |||
* @param \Behat\Gherkin\Node\TableNode $body | |||
* @param TableNode $body | |||
*/ | |||
public function sendingToWith($verb, $url, $body) { | |||
$fullUrl = $this->baseUrl . "v{$this->apiVersion}.php" . $url; | |||
@@ -179,7 +180,7 @@ trait BasicStructure { | |||
$options['headers'] = [ | |||
'OCS_APIREQUEST' => 'true' | |||
]; | |||
if ($body instanceof \Behat\Gherkin\Node\TableNode) { | |||
if ($body instanceof TableNode) { | |||
$fd = $body->getRowsHash(); | |||
$options['form_params'] = $fd; | |||
} | |||
@@ -216,7 +217,7 @@ trait BasicStructure { | |||
} else { | |||
$options['auth'] = [$this->currentUser, $this->regularUser]; | |||
} | |||
if ($body instanceof \Behat\Gherkin\Node\TableNode) { | |||
if ($body instanceof TableNode) { | |||
$fd = $body->getRowsHash(); | |||
$options['form_params'] = $fd; | |||
} | |||
@@ -504,4 +505,27 @@ trait BasicStructure { | |||
public function cookiesAreReset() { | |||
$this->cookieJar = new CookieJar(); | |||
} | |||
/** | |||
* @Then The following headers should be set | |||
* @param TableNode $table | |||
* @throws \Exception | |||
*/ | |||
public function theFollowingHeadersShouldBeSet(TableNode $table) { | |||
foreach($table->getTable() as $header) { | |||
$headerName = $header[0]; | |||
$expectedHeaderValue = $header[1]; | |||
$returnedHeader = $this->response->getHeader($headerName)[0]; | |||
if($returnedHeader !== $expectedHeaderValue) { | |||
throw new \Exception( | |||
sprintf( | |||
"Expected value '%s' for header '%s', got '%s'", | |||
$expectedHeaderValue, | |||
$headerName, | |||
$returnedHeader | |||
) | |||
); | |||
} | |||
} | |||
} | |||
} |
@@ -25,7 +25,7 @@ | |||
require __DIR__ . '/../../vendor/autoload.php'; | |||
use GuzzleHttp\Client; | |||
use GuzzleHttp\Message\ResponseInterface; | |||
use Psr\Http\Message\ResponseInterface; | |||
class CalDavContext implements \Behat\Behat\Context\Context { | |||
/** @var string */ |
@@ -26,8 +26,9 @@ use Behat\Gherkin\Node\TableNode; | |||
use PHPUnit\Framework\Assert; | |||
class LDAPContext implements Context { | |||
use BasicStructure; | |||
use CommandLine; | |||
use AppConfiguration, | |||
CommandLine, | |||
Sharing; // Pulls in BasicStructure | |||
protected $configID; | |||
@@ -204,4 +205,8 @@ class LDAPContext implements Context { | |||
$configKey = $this->configID . 'ldap_configuration_active'; | |||
$this->invokingTheCommand('config:app:set user_ldap ' . $configKey . ' --value="0"'); | |||
} | |||
protected function resetAppConfigs() { | |||
// not implemented | |||
} | |||
} |
@@ -33,60 +33,9 @@ require __DIR__ . '/../../vendor/autoload.php'; | |||
* Features context. | |||
*/ | |||
class ShareesContext implements Context, SnippetAcceptingContext { | |||
use Provisioning; | |||
use Sharing; | |||
use AppConfiguration; | |||
/** | |||
* @When /^getting sharees for$/ | |||
* @param \Behat\Gherkin\Node\TableNode $body | |||
*/ | |||
public function whenGettingShareesFor($body) { | |||
$url = '/apps/files_sharing/api/v1/sharees'; | |||
if ($body instanceof \Behat\Gherkin\Node\TableNode) { | |||
$parameters = []; | |||
foreach ($body->getRowsHash() as $key => $value) { | |||
$parameters[] = $key . '=' . $value; | |||
} | |||
if (!empty($parameters)) { | |||
$url .= '?' . implode('&', $parameters); | |||
} | |||
} | |||
$this->sendingTo('GET', $url); | |||
} | |||
/** | |||
* @Then /^"([^"]*)" sharees returned (are|is empty)$/ | |||
* @param string $shareeType | |||
* @param string $isEmpty | |||
* @param \Behat\Gherkin\Node\TableNode|null $shareesList | |||
*/ | |||
public function thenListOfSharees($shareeType, $isEmpty, $shareesList = null) { | |||
if ($isEmpty !== 'is empty') { | |||
$sharees = $shareesList->getRows(); | |||
$respondedArray = $this->getArrayOfShareesResponded($this->response, $shareeType); | |||
Assert::assertEquals($sharees, $respondedArray); | |||
} else { | |||
$respondedArray = $this->getArrayOfShareesResponded($this->response, $shareeType); | |||
Assert::assertEmpty($respondedArray); | |||
} | |||
} | |||
public function getArrayOfShareesResponded(ResponseInterface $response, $shareeType) { | |||
$elements = simplexml_load_string($response->getBody())->data; | |||
$elements = json_decode(json_encode($elements), 1); | |||
if (strpos($shareeType, 'exact ') === 0) { | |||
$elements = $elements['exact']; | |||
$shareeType = substr($shareeType, 6); | |||
} | |||
$sharees = []; | |||
foreach ($elements[$shareeType] as $element) { | |||
$sharees[] = [$element['label'], $element['value']['shareType'], $element['value']['shareWith']]; | |||
} | |||
return $sharees; | |||
} | |||
protected function resetAppConfigs() { | |||
$this->modifyServerConfig('core', 'shareapi_only_share_with_group_members', 'no'); | |||
$this->modifyServerConfig('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes'); |
@@ -26,8 +26,8 @@ | |||
* | |||
*/ | |||
use GuzzleHttp\Client; | |||
use GuzzleHttp\Message\ResponseInterface; | |||
use PHPUnit\Framework\Assert; | |||
use Psr\Http\Message\ResponseInterface; | |||
require __DIR__ . '/../../vendor/autoload.php'; | |||
@@ -48,7 +48,7 @@ trait Sharing { | |||
/** @var int */ | |||
private $savedShareId = null; | |||
/** @var \Psr\Http\Message\ResponseInterface */ | |||
/** @var ResponseInterface */ | |||
private $response; | |||
/** | |||
@@ -546,26 +546,54 @@ trait Sharing { | |||
} | |||
/** | |||
* @Then The following headers should be set | |||
* @param \Behat\Gherkin\Node\TableNode $table | |||
* @throws \Exception | |||
* @When /^getting sharees for$/ | |||
* @param \Behat\Gherkin\Node\TableNode $body | |||
*/ | |||
public function theFollowingHeadersShouldBeSet(\Behat\Gherkin\Node\TableNode $table) { | |||
foreach($table->getTable() as $header) { | |||
$headerName = $header[0]; | |||
$expectedHeaderValue = $header[1]; | |||
$returnedHeader = $this->response->getHeader($headerName)[0]; | |||
if($returnedHeader !== $expectedHeaderValue) { | |||
throw new \Exception( | |||
sprintf( | |||
"Expected value '%s' for header '%s', got '%s'", | |||
$expectedHeaderValue, | |||
$headerName, | |||
$returnedHeader | |||
) | |||
); | |||
public function whenGettingShareesFor($body) { | |||
$url = '/apps/files_sharing/api/v1/sharees'; | |||
if ($body instanceof \Behat\Gherkin\Node\TableNode) { | |||
$parameters = []; | |||
foreach ($body->getRowsHash() as $key => $value) { | |||
$parameters[] = $key . '=' . $value; | |||
} | |||
if (!empty($parameters)) { | |||
$url .= '?' . implode('&', $parameters); | |||
} | |||
} | |||
$this->sendingTo('GET', $url); | |||
} | |||
/** | |||
* @Then /^"([^"]*)" sharees returned (are|is empty)$/ | |||
* @param string $shareeType | |||
* @param string $isEmpty | |||
* @param \Behat\Gherkin\Node\TableNode|null $shareesList | |||
*/ | |||
public function thenListOfSharees($shareeType, $isEmpty, $shareesList = null) { | |||
if ($isEmpty !== 'is empty') { | |||
$sharees = $shareesList->getRows(); | |||
$respondedArray = $this->getArrayOfShareesResponded($this->response, $shareeType); | |||
Assert::assertEquals($sharees, $respondedArray); | |||
} else { | |||
$respondedArray = $this->getArrayOfShareesResponded($this->response, $shareeType); | |||
Assert::assertEmpty($respondedArray); | |||
} | |||
} | |||
public function getArrayOfShareesResponded(ResponseInterface $response, $shareeType) { | |||
$elements = simplexml_load_string($response->getBody())->data; | |||
$elements = json_decode(json_encode($elements), 1); | |||
if (strpos($shareeType, 'exact ') === 0) { | |||
$elements = $elements['exact']; | |||
$shareeType = substr($shareeType, 6); | |||
} | |||
$sharees = []; | |||
foreach ($elements[$shareeType] as $element) { | |||
$sharees[] = [$element['label'], $element['value']['shareType'], $element['value']['shareWith']]; | |||
} | |||
return $sharees; | |||
} | |||
} | |||
@@ -226,29 +226,6 @@ trait WebDav { | |||
} | |||
} | |||
/** | |||
* @Then The following headers should be set | |||
* @param \Behat\Gherkin\Node\TableNode $table | |||
* @throws \Exception | |||
*/ | |||
public function theFollowingHeadersShouldBeSet(\Behat\Gherkin\Node\TableNode $table) { | |||
foreach ($table->getTable() as $header) { | |||
$headerName = $header[0]; | |||
$expectedHeaderValue = $header[1]; | |||
$returnedHeader = $this->response->getHeader($headerName)[0]; | |||
if ($returnedHeader !== $expectedHeaderValue) { | |||
throw new \Exception( | |||
sprintf( | |||
"Expected value '%s' for header '%s', got '%s'", | |||
$expectedHeaderValue, | |||
$headerName, | |||
$returnedHeader | |||
) | |||
); | |||
} | |||
} | |||
} | |||
/** | |||
* @Then Downloaded content should start with :start | |||
* @param int $start |
@@ -118,3 +118,24 @@ Feature: LDAP | |||
And the command output contains the text "Clean up the user's remnants by" | |||
And invoking occ with "user:delete alice" | |||
Then the command output contains the text "The specified user was deleted" | |||
Scenario: Search only with group members - allowed | |||
Given modify LDAP configuration | |||
| ldapGroupFilter | cn=Orcharding | | |||
| ldapGroupMemberAssocAttr | member | | |||
| ldapBaseGroups | ou=OtherGroups,dc=nextcloud,dc=ci | | |||
| ldapAttributesForUserSearch | employeeNumber | | |||
| useMemberOfToDetectMembership | 1 | | |||
And parameter "shareapi_only_share_with_group_members" of app "core" is set to "yes" | |||
And As an "alice" | |||
When getting sharees for | |||
# "5" is part of the employee number of some LDAP records | |||
| search | 5 | | |||
| itemType | file | | |||
Then the OCS status code should be "200" | |||
And the HTTP status code should be "200" | |||
And "exact users" sharees returned is empty | |||
And "users" sharees returned are | |||
| Elisa | 0 | elisa | | |||
And "exact groups" sharees returned is empty | |||