Skip to content

Commit

Permalink
Merge remote-tracking branch 'parent/master'
Browse files Browse the repository at this point in the history
* parent/master: (77 commits)
  Updated TinyMCE to version 4.9.4
  Updated register link text/placement on login card
  Added deeper content id de-duplication
  Add revision restore confirm and changed http method
  Updated md drawing mngr shortcut to work on mac cmd key
  Added test to check page HTML id de-duplication
  Updated ldap server option parsing to work with protocol and port
  Add min length validation on name on register form & add sign up link
  Reduced markup for books icon
  Prevented bad duplicate IDs causing major exception
  Aligned item creation wording and updated shelf-book-add logic
  Replace dots with something else on user create and edit screens
  Update create new book button on shelves to 2019 design
  Fix phpcs issues
  Add tests for creating a book and adding directly to a shelf
  Add button to add a book directly from a shelf view
  Tweaked header font size to fit redesign better
  Updated user references to be app-default-supporting functions
  Updated view toggle to store date
  Updated markdown editor for mobile
  ...
  • Loading branch information
iranreyes committed May 1, 2019
2 parents 2e600df + 884e20c commit ce82b7a
Show file tree
Hide file tree
Showing 254 changed files with 7,089 additions and 7,761 deletions.
4 changes: 2 additions & 2 deletions app/Actions/ActivityService.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public function latest($count = 20, $page = 0)
* @param int $page
* @return array
*/
public function entityActivity($entity, $count = 20, $page = 0)
public function entityActivity($entity, $count = 20, $page = 1)
{
if ($entity->isA('book')) {
$query = $this->activity->where('book_id', '=', $entity->id);
Expand All @@ -114,7 +114,7 @@ public function entityActivity($entity, $count = 20, $page = 0)

$activity = $this->permissionService
->filterRestrictedEntityRelations($query, 'activities', 'entity_id', 'entity_type')
->orderBy('created_at', 'desc')->with(['entity', 'user.avatar'])->skip($count * $page)->take($count)->get();
->orderBy('created_at', 'desc')->with(['entity', 'user.avatar'])->skip($count * ($page - 1))->take($count)->get();

return $this->filterSimilar($activity);
}
Expand Down
23 changes: 13 additions & 10 deletions app/Actions/ViewService.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,26 @@

use BookStack\Auth\Permissions\PermissionService;
use BookStack\Entities\Entity;
use BookStack\Entities\EntityProvider;
use Illuminate\Support\Collection;

class ViewService
{
protected $view;
protected $permissionService;
protected $entityProvider;

/**
* ViewService constructor.
* @param \BookStack\Actions\View $view
* @param \BookStack\Auth\Permissions\PermissionService $permissionService
* @param EntityProvider $entityProvider
*/
public function __construct(View $view, PermissionService $permissionService)
public function __construct(View $view, PermissionService $permissionService, EntityProvider $entityProvider)
{
$this->view = $view;
$this->permissionService = $permissionService;
$this->entityProvider = $entityProvider;
}

/**
Expand Down Expand Up @@ -50,23 +55,21 @@ public function add(Entity $entity)
* Get the entities with the most views.
* @param int $count
* @param int $page
* @param Entity|false|array $filterModel
* @param string|array $filterModels
* @param string $action - used for permission checking
* @return
* @return Collection
*/
public function getPopular($count = 10, $page = 0, $filterModel = false, $action = 'view')
public function getPopular(int $count = 10, int $page = 0, $filterModels = null, string $action = 'view')
{
// TODO - Standardise input filter
$skipCount = $count * $page;
$query = $this->permissionService->filterRestrictedEntityRelations($this->view, 'views', 'viewable_id', 'viewable_type', $action)
$query = $this->permissionService
->filterRestrictedEntityRelations($this->view, 'views', 'viewable_id', 'viewable_type', $action)
->select('*', 'viewable_id', 'viewable_type', \DB::raw('SUM(views) as view_count'))
->groupBy('viewable_id', 'viewable_type')
->orderBy('view_count', 'desc');

if ($filterModel && is_array($filterModel)) {
$query->whereIn('viewable_type', $filterModel);
} else if ($filterModel) {
$query->where('viewable_type', '=', $filterModel->getMorphClass());
if ($filterModels) {
$query->whereIn('viewable_type', $this->entityProvider->getMorphClasses($filterModels));
}

return $query->with('viewable')->skip($skipCount)->take($count)->get()->pluck('viewable');
Expand Down
50 changes: 30 additions & 20 deletions app/Auth/Access/LdapService.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public function getUserDetails($userName)
$userCn = $this->getUserResponseProperty($user, 'cn', null);
return [
'uid' => $this->getUserResponseProperty($user, 'uid', $user['dn']),
'name' => $this->getUserResponseProperty($user, $displayNameAttr, $userCn),
'name' => $this->getUserResponseProperty($user, $displayNameAttr, $userCn),
'dn' => $user['dn'],
'email' => $this->getUserResponseProperty($user, $emailAttr, null),
];
Expand All @@ -116,8 +116,8 @@ protected function getUserResponseProperty(array $userDetails, string $propertyK

/**
* @param Authenticatable $user
* @param string $username
* @param string $password
* @param string $username
* @param string $password
* @return bool
* @throws LdapException
*/
Expand Down Expand Up @@ -182,25 +182,14 @@ protected function getConnection()
throw new LdapException(trans('errors.ldap_extension_not_installed'));
}

// Get port from server string and protocol if specified.
$ldapServer = explode(':', $this->config['server']);
$hasProtocol = preg_match('/^ldaps{0,1}\:\/\//', $this->config['server']) === 1;
if (!$hasProtocol) {
array_unshift($ldapServer, '');
}
$hostName = $ldapServer[0] . ($hasProtocol?':':'') . $ldapServer[1];
$defaultPort = $ldapServer[0] === 'ldaps' ? 636 : 389;

/*
* Check if TLS_INSECURE is set. The handle is set to NULL due to the nature of
* the LDAP_OPT_X_TLS_REQUIRE_CERT option. It can only be set globally and not
* per handle.
*/
// Check if TLS_INSECURE is set. The handle is set to NULL due to the nature of
// the LDAP_OPT_X_TLS_REQUIRE_CERT option. It can only be set globally and not per handle.
if ($this->config['tls_insecure']) {
$this->ldap->setOption(null, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_NEVER);
}

$ldapConnection = $this->ldap->connect($hostName, count($ldapServer) > 2 ? intval($ldapServer[2]) : $defaultPort);
$serverDetails = $this->parseServerString($this->config['server']);
$ldapConnection = $this->ldap->connect($serverDetails['host'], $serverDetails['port']);

if ($ldapConnection === false) {
throw new LdapException(trans('errors.ldap_cannot_connect'));
Expand All @@ -215,6 +204,27 @@ protected function getConnection()
return $this->ldapConnection;
}

/**
* Parse a LDAP server string and return the host and port for
* a connection. Is flexible to formats such as 'ldap.example.com:8069' or 'ldaps://ldap.example.com'
* @param $serverString
* @return array
*/
protected function parseServerString($serverString)
{
$serverNameParts = explode(':', $serverString);

// If we have a protocol just return the full string since PHP will ignore a separate port.
if ($serverNameParts[0] === 'ldaps' || $serverNameParts[0] === 'ldap') {
return ['host' => $serverString, 'port' => 389];
}

// Otherwise, extract the port out
$hostName = $serverNameParts[0];
$ldapPort = (count($serverNameParts) > 1) ? intval($serverNameParts[1]) : 389;
return ['host' => $hostName, 'port' => $ldapPort];
}

/**
* Build a filter string by injecting common variables.
* @param string $filterString
Expand Down Expand Up @@ -319,10 +329,10 @@ protected function groupFilter(array $userGroupSearchResponse)
$count = 0;

if (isset($userGroupSearchResponse[$groupsAttr]['count'])) {
$count = (int) $userGroupSearchResponse[$groupsAttr]['count'];
$count = (int)$userGroupSearchResponse[$groupsAttr]['count'];
}

for ($i=0; $i<$count; $i++) {
for ($i = 0; $i < $count; $i++) {
$dnComponents = $this->ldap->explodeDn($userGroupSearchResponse[$groupsAttr][$i], 1);
if (!in_array($dnComponents[0], $ldapGroups)) {
$ldapGroups[] = $dnComponents[0];
Expand Down
4 changes: 2 additions & 2 deletions app/Auth/Permissions/PermissionService.php
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ public function checkUserHasPermissionOnAnything(string $permission, string $ent
$query2->where('has_permission_own', '=', 1)
->where('created_by', '=', $userId);
});
}) ;
});

if (!is_null($entityClass)) {
$entityInstance = app()->make($entityClass);
Expand Down Expand Up @@ -704,7 +704,7 @@ public function enforceEntityRestrictions($entityType, $query, $action = 'view')
* @param string $entityIdColumn
* @param string $entityTypeColumn
* @param string $action
* @return mixed
* @return QueryBuilder
*/
public function filterRestrictedEntityRelations($query, $tableName, $entityIdColumn, $entityTypeColumn, $action = 'view')
{
Expand Down
13 changes: 7 additions & 6 deletions app/Auth/Role.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php namespace BookStack\Auth;

use BookStack\Auth\Permissions\JointPermission;
use BookStack\Auth\Permissions\RolePermission;
use BookStack\Model;

class Role extends Model
Expand All @@ -13,7 +14,7 @@ class Role extends Model
*/
public function users()
{
return $this->belongsToMany(User::class);
return $this->belongsToMany(User::class)->orderBy('name', 'asc');
}

/**
Expand All @@ -30,7 +31,7 @@ public function jointPermissions()
*/
public function permissions()
{
return $this->belongsToMany(Permissions\RolePermission::class, 'permission_role', 'role_id', 'permission_id');
return $this->belongsToMany(RolePermission::class, 'permission_role', 'role_id', 'permission_id');
}

/**
Expand All @@ -51,18 +52,18 @@ public function hasPermission($permissionName)

/**
* Add a permission to this role.
* @param \BookStack\Auth\Permissions\RolePermission $permission
* @param RolePermission $permission
*/
public function attachPermission(Permissions\RolePermission $permission)
public function attachPermission(RolePermission $permission)
{
$this->permissions()->attach($permission->id);
}

/**
* Detach a single permission from this role.
* @param \BookStack\Auth\Permissions\RolePermission $permission
* @param RolePermission $permission
*/
public function detachPermission(Permissions\RolePermission $permission)
public function detachPermission(RolePermission $permission)
{
$this->permissions()->detach($permission->id);
}
Expand Down
25 changes: 13 additions & 12 deletions app/Auth/UserRepo.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use BookStack\Exceptions\UserUpdateException;
use BookStack\Uploads\Image;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Images;

class UserRepo
Expand Down Expand Up @@ -48,7 +49,7 @@ public function getById($id)

/**
* Get all the users with their permissions.
* @return \Illuminate\Database\Eloquent\Builder|static
* @return Builder|static
*/
public function getAllUsers()
{
Expand All @@ -59,7 +60,7 @@ public function getAllUsers()
* Get all the users with their permissions in a paginated format.
* @param int $count
* @param $sortData
* @return \Illuminate\Database\Eloquent\Builder|static
* @return Builder|static
*/
public function getAllUsersPaginatedAndSorted($count, $sortData)
{
Expand Down Expand Up @@ -223,16 +224,15 @@ public function getActivity(User $user, $count = 20, $page = 0)
*/
public function getRecentlyCreated(User $user, $count = 20)
{
$createdByUserQuery = function(Builder $query) use ($user) {
$query->where('created_by', '=', $user->id);
};

return [
'pages' => $this->entityRepo->getRecentlyCreated('page', $count, 0, function ($query) use ($user) {
$query->where('created_by', '=', $user->id);
}),
'chapters' => $this->entityRepo->getRecentlyCreated('chapter', $count, 0, function ($query) use ($user) {
$query->where('created_by', '=', $user->id);
}),
'books' => $this->entityRepo->getRecentlyCreated('book', $count, 0, function ($query) use ($user) {
$query->where('created_by', '=', $user->id);
})
'pages' => $this->entityRepo->getRecentlyCreated('page', $count, 0, $createdByUserQuery),
'chapters' => $this->entityRepo->getRecentlyCreated('chapter', $count, 0, $createdByUserQuery),
'books' => $this->entityRepo->getRecentlyCreated('book', $count, 0, $createdByUserQuery),
'shelves' => $this->entityRepo->getRecentlyCreated('bookshelf', $count, 0, $createdByUserQuery)
];
}

Expand All @@ -247,6 +247,7 @@ public function getAssetCounts(User $user)
'pages' => $this->entityRepo->getUserTotalCreated('page', $user),
'chapters' => $this->entityRepo->getUserTotalCreated('chapter', $user),
'books' => $this->entityRepo->getUserTotalCreated('book', $user),
'shelves' => $this->entityRepo->getUserTotalCreated('bookshelf', $user),
];
}

Expand All @@ -256,7 +257,7 @@ public function getAssetCounts(User $user)
*/
public function getAllRoles()
{
return $this->role->all();
return $this->role->newQuery()->orderBy('name', 'asc')->get();
}

/**
Expand Down
13 changes: 11 additions & 2 deletions app/Entities/Book.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public function getUrl($path = false)
*/
public function getBookCover($width = 440, $height = 250)
{
$default = baseUrl('/book_default_cover.png');
$default = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
if (!$this->image_id) {
return $default;
}
Expand Down Expand Up @@ -69,6 +69,15 @@ public function pages()
return $this->hasMany(Page::class);
}

/**
* Get the direct child pages of this book.
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function directPages()
{
return $this->pages()->where('chapter_id', '=', '0');
}

/**
* Get all chapters within this book.
* @return \Illuminate\Database\Eloquent\Relations\HasMany
Expand All @@ -92,7 +101,7 @@ public function shelves()
* @param int $length
* @return string
*/
public function getExcerpt($length = 100)
public function getExcerpt(int $length = 100)
{
$description = $this->description;
return strlen($description) > $length ? substr($description, 0, $length-3) . '...' : $description;
Expand Down
21 changes: 17 additions & 4 deletions app/Entities/Bookshelf.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ public function getMorphClass()
*/
public function books()
{
return $this->belongsToMany(Book::class, 'bookshelves_books', 'bookshelf_id', 'book_id')->orderBy('order', 'asc');
return $this->belongsToMany(Book::class, 'bookshelves_books', 'bookshelf_id', 'book_id')
->withPivot('order')
->orderBy('order', 'asc');
}

/**
Expand All @@ -50,7 +52,8 @@ public function getUrl($path = false)
*/
public function getBookCover($width = 440, $height = 250)
{
$default = baseUrl('/book_default_cover.png');
// TODO - Make generic, focused on books right now, Perhaps set-up a better image
$default = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
if (!$this->image_id) {
return $default;
}
Expand All @@ -64,7 +67,7 @@ public function getBookCover($width = 440, $height = 250)
}

/**
* Get the cover image of the book
* Get the cover image of the shelf
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function cover()
Expand All @@ -77,7 +80,7 @@ public function cover()
* @param int $length
* @return string
*/
public function getExcerpt($length = 100)
public function getExcerpt(int $length = 100)
{
$description = $this->description;
return strlen($description) > $length ? substr($description, 0, $length-3) . '...' : $description;
Expand All @@ -91,4 +94,14 @@ public function entityRawQuery()
{
return "'BookStack\\\\BookShelf' as entity_type, id, id as entity_id, slug, name, {$this->textField} as text,'' as html, '0' as book_id, '0' as priority, '0' as chapter_id, '0' as draft, created_by, updated_by, updated_at, created_at";
}

/**
* Check if this shelf contains the given book.
* @param Book $book
* @return bool
*/
public function contains(Book $book)
{
return $this->books()->where('id', '=', $book->id)->count() > 0;
}
}
Loading

0 comments on commit ce82b7a

Please sign in to comment.