Skip to content

Commit d4025d9

Browse files
committed
Merge branch 'development' into release
2 parents d6021f4 + 3a058a6 commit d4025d9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+2250
-2113
lines changed

app/Access/Ldap.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,25 @@ public function setVersion($ldapConnection, int $version): bool
5252
*
5353
* @param resource|\LDAP\Connection $ldapConnection
5454
*
55-
* @return resource|\LDAP\Result
55+
* @return \LDAP\Result|array|false
5656
*/
5757
public function search($ldapConnection, string $baseDn, string $filter, array $attributes = null)
5858
{
5959
return ldap_search($ldapConnection, $baseDn, $filter, $attributes);
6060
}
6161

62+
/**
63+
* Read an entry from the LDAP tree.
64+
*
65+
* @param resource|\Ldap\Connection $ldapConnection
66+
*
67+
* @return \LDAP\Result|array|false
68+
*/
69+
public function read($ldapConnection, string $baseDn, string $filter, array $attributes = null)
70+
{
71+
return ldap_read($ldapConnection, $baseDn, $filter, $attributes);
72+
}
73+
6274
/**
6375
* Get entries from an LDAP search result.
6476
*

app/Access/LdapService.php

Lines changed: 46 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -321,94 +321,105 @@ public function getUserGroups(string $userName): array
321321
return [];
322322
}
323323

324-
$userGroups = $this->groupFilter($user);
324+
$userGroups = $this->extractGroupsFromSearchResponseEntry($user);
325325
$allGroups = $this->getGroupsRecursive($userGroups, []);
326+
$formattedGroups = $this->extractGroupNamesFromLdapGroupDns($allGroups);
326327

327328
if ($this->config['dump_user_groups']) {
328329
throw new JsonDebugException([
329-
'details_from_ldap' => $user,
330-
'parsed_direct_user_groups' => $userGroups,
331-
'parsed_recursive_user_groups' => $allGroups,
330+
'details_from_ldap' => $user,
331+
'parsed_direct_user_groups' => $userGroups,
332+
'parsed_recursive_user_groups' => $allGroups,
333+
'parsed_resulting_group_names' => $formattedGroups,
332334
]);
333335
}
334336

335-
return $allGroups;
337+
return $formattedGroups;
338+
}
339+
340+
protected function extractGroupNamesFromLdapGroupDns(array $groupDNs): array
341+
{
342+
$names = [];
343+
344+
foreach ($groupDNs as $groupDN) {
345+
$exploded = $this->ldap->explodeDn($groupDN, 1);
346+
if ($exploded !== false && count($exploded) > 0) {
347+
$names[] = $exploded[0];
348+
}
349+
}
350+
351+
return array_unique($names);
336352
}
337353

338354
/**
339-
* Get the parent groups of an array of groups.
355+
* Build an array of all relevant groups DNs after recursively scanning
356+
* across parents of the groups given.
340357
*
341358
* @throws LdapException
342359
*/
343-
private function getGroupsRecursive(array $groupsArray, array $checked): array
360+
protected function getGroupsRecursive(array $groupDNs, array $checked): array
344361
{
345362
$groupsToAdd = [];
346-
foreach ($groupsArray as $groupName) {
347-
if (in_array($groupName, $checked)) {
363+
foreach ($groupDNs as $groupDN) {
364+
if (in_array($groupDN, $checked)) {
348365
continue;
349366
}
350367

351-
$parentGroups = $this->getGroupGroups($groupName);
368+
$parentGroups = $this->getParentsOfGroup($groupDN);
352369
$groupsToAdd = array_merge($groupsToAdd, $parentGroups);
353-
$checked[] = $groupName;
370+
$checked[] = $groupDN;
354371
}
355372

356-
$groupsArray = array_unique(array_merge($groupsArray, $groupsToAdd), SORT_REGULAR);
373+
$uniqueDNs = array_unique(array_merge($groupDNs, $groupsToAdd), SORT_REGULAR);
357374

358375
if (empty($groupsToAdd)) {
359-
return $groupsArray;
376+
return $uniqueDNs;
360377
}
361378

362-
return $this->getGroupsRecursive($groupsArray, $checked);
379+
return $this->getGroupsRecursive($uniqueDNs, $checked);
363380
}
364381

365382
/**
366-
* Get the parent groups of a single group.
367-
*
368383
* @throws LdapException
369384
*/
370-
private function getGroupGroups(string $groupName): array
385+
protected function getParentsOfGroup(string $groupDN): array
371386
{
387+
$groupsAttr = strtolower($this->config['group_attribute']);
372388
$ldapConnection = $this->getConnection();
373389
$this->bindSystemUser($ldapConnection);
374390

375391
$followReferrals = $this->config['follow_referrals'] ? 1 : 0;
376392
$this->ldap->setOption($ldapConnection, LDAP_OPT_REFERRALS, $followReferrals);
377-
378-
$baseDn = $this->config['base_dn'];
379-
$groupsAttr = strtolower($this->config['group_attribute']);
380-
381-
$groupFilter = 'CN=' . $this->ldap->escape($groupName);
382-
$groups = $this->ldap->searchAndGetEntries($ldapConnection, $baseDn, $groupFilter, [$groupsAttr]);
383-
if ($groups['count'] === 0) {
393+
$read = $this->ldap->read($ldapConnection, $groupDN, '(objectClass=*)', [$groupsAttr]);
394+
$results = $this->ldap->getEntries($ldapConnection, $read);
395+
if ($results['count'] === 0) {
384396
return [];
385397
}
386398

387-
return $this->groupFilter($groups[0]);
399+
return $this->extractGroupsFromSearchResponseEntry($results[0]);
388400
}
389401

390402
/**
391-
* Filter out LDAP CN and DN language in a ldap search return.
392-
* Gets the base CN (common name) of the string.
403+
* Extract an array of group DN values from the given LDAP search response entry
393404
*/
394-
protected function groupFilter(array $userGroupSearchResponse): array
405+
protected function extractGroupsFromSearchResponseEntry(array $ldapEntry): array
395406
{
396407
$groupsAttr = strtolower($this->config['group_attribute']);
397-
$ldapGroups = [];
408+
$groupDNs = [];
398409
$count = 0;
399410

400-
if (isset($userGroupSearchResponse[$groupsAttr]['count'])) {
401-
$count = (int) $userGroupSearchResponse[$groupsAttr]['count'];
411+
if (isset($ldapEntry[$groupsAttr]['count'])) {
412+
$count = (int) $ldapEntry[$groupsAttr]['count'];
402413
}
403414

404415
for ($i = 0; $i < $count; $i++) {
405-
$dnComponents = $this->ldap->explodeDn($userGroupSearchResponse[$groupsAttr][$i], 1);
406-
if (!in_array($dnComponents[0], $ldapGroups)) {
407-
$ldapGroups[] = $dnComponents[0];
416+
$dn = $ldapEntry[$groupsAttr][$i];
417+
if (!in_array($dn, $groupDNs)) {
418+
$groupDNs[] = $dn;
408419
}
409420
}
410421

411-
return $ldapGroups;
422+
return $groupDNs;
412423
}
413424

414425
/**

app/Entities/Controllers/BookApiController.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use BookStack\Entities\Models\Chapter;
88
use BookStack\Entities\Models\Entity;
99
use BookStack\Entities\Queries\BookQueries;
10+
use BookStack\Entities\Queries\PageQueries;
1011
use BookStack\Entities\Repos\BookRepo;
1112
use BookStack\Entities\Tools\BookContents;
1213
use BookStack\Http\ApiController;
@@ -18,6 +19,7 @@ class BookApiController extends ApiController
1819
public function __construct(
1920
protected BookRepo $bookRepo,
2021
protected BookQueries $queries,
22+
protected PageQueries $pageQueries,
2123
) {
2224
}
2325

@@ -69,7 +71,8 @@ public function read(string $id)
6971
->withType()
7072
->withField('pages', function (Entity $entity) {
7173
if ($entity instanceof Chapter) {
72-
return (new ApiEntityListFormatter($entity->pages->all()))->format();
74+
$pages = $this->pageQueries->visibleForChapterList($entity->id)->get()->all();
75+
return (new ApiEntityListFormatter($pages))->format();
7376
}
7477
return null;
7578
})->format();

app/Uploads/Controllers/AttachmentApiController.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,16 +171,16 @@ protected function rules(): array
171171
{
172172
return [
173173
'create' => [
174-
'name' => ['required', 'min:1', 'max:255', 'string'],
174+
'name' => ['required', 'string', 'min:1', 'max:255'],
175175
'uploaded_to' => ['required', 'integer', 'exists:pages,id'],
176176
'file' => array_merge(['required_without:link'], $this->attachmentService->getFileValidationRules()),
177-
'link' => ['required_without:file', 'min:1', 'max:2000', 'safe_url'],
177+
'link' => ['required_without:file', 'string', 'min:1', 'max:2000', 'safe_url'],
178178
],
179179
'update' => [
180-
'name' => ['min:1', 'max:255', 'string'],
180+
'name' => ['string', 'min:1', 'max:255'],
181181
'uploaded_to' => ['integer', 'exists:pages,id'],
182182
'file' => $this->attachmentService->getFileValidationRules(),
183-
'link' => ['min:1', 'max:2000', 'safe_url'],
183+
'link' => ['string', 'min:1', 'max:2000', 'safe_url'],
184184
],
185185
];
186186
}

app/Users/Controllers/UserApiController.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,27 +37,28 @@ protected function rules(int $userId = null): array
3737
{
3838
return [
3939
'create' => [
40-
'name' => ['required', 'min:2', 'max:100'],
40+
'name' => ['required', 'string', 'min:2', 'max:100'],
4141
'email' => [
42-
'required', 'min:2', 'email', new Unique('users', 'email'),
42+
'required', 'string', 'email', 'min:2', new Unique('users', 'email'),
4343
],
4444
'external_auth_id' => ['string'],
4545
'language' => ['string', 'max:15', 'alpha_dash'],
46-
'password' => [Password::default()],
46+
'password' => ['string', Password::default()],
4747
'roles' => ['array'],
4848
'roles.*' => ['integer'],
4949
'send_invite' => ['boolean'],
5050
],
5151
'update' => [
52-
'name' => ['min:2', 'max:100'],
52+
'name' => ['string', 'min:2', 'max:100'],
5353
'email' => [
54-
'min:2',
54+
'string',
5555
'email',
56+
'min:2',
5657
(new Unique('users', 'email'))->ignore($userId ?? null),
5758
],
5859
'external_auth_id' => ['string'],
5960
'language' => ['string', 'max:15', 'alpha_dash'],
60-
'password' => [Password::default()],
61+
'password' => ['string', Password::default()],
6162
'roles' => ['array'],
6263
'roles.*' => ['integer'],
6364
],

0 commit comments

Comments
 (0)