diff --git a/.env.example.complete b/.env.example.complete index 3067202b7..8851bd268 100644 --- a/.env.example.complete +++ b/.env.example.complete @@ -90,6 +90,10 @@ STORAGE_S3_SECRET=your-s3-secret STORAGE_S3_BUCKET=s3-bucket-name STORAGE_S3_REGION=s3-bucket-region +# S3 endpoint to use for storage calls +# Only set this if using a non-Amazon s3-compatible service such as Minio +STORAGE_S3_ENDPOINT=https://my-custom-s3-compatible.service.com:8001 + # Storage URL prefix # Used as a base for any generated image urls. # An s3-format URL will be generated if not set. diff --git a/app/Auth/Access/LdapService.php b/app/Auth/Access/LdapService.php index 1e95ac513..654ea2f99 100644 --- a/app/Auth/Access/LdapService.php +++ b/app/Auth/Access/LdapService.php @@ -176,8 +176,8 @@ class LdapService * 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); + 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); diff --git a/app/Auth/Permissions/PermissionService.php b/app/Auth/Permissions/PermissionService.php index d0e6cccea..af2a5e1fd 100644 --- a/app/Auth/Permissions/PermissionService.php +++ b/app/Auth/Permissions/PermissionService.php @@ -190,10 +190,10 @@ class PermissionService { return $this->entityProvider->book->newQuery() ->select(['id', 'restricted', 'created_by'])->with(['chapters' => function ($query) { - $query->select(['id', 'restricted', 'created_by', 'book_id']); - }, 'pages' => function ($query) { - $query->select(['id', 'restricted', 'created_by', 'book_id', 'chapter_id']); - }]); + $query->select(['id', 'restricted', 'created_by', 'book_id']); + }, 'pages' => function ($query) { + $query->select(['id', 'restricted', 'created_by', 'book_id', 'chapter_id']); + }]); } /** @@ -612,13 +612,13 @@ class PermissionService $entities = $this->entityProvider; $pageSelect = $this->db->table('pages')->selectRaw($entities->page->entityRawQuery($fetchPageContent)) ->where('book_id', '=', $book_id)->where(function ($query) use ($filterDrafts) { - $query->where('draft', '=', 0); - if (!$filterDrafts) { - $query->orWhere(function ($query) { - $query->where('draft', '=', 1)->where('created_by', '=', $this->currentUser()->id); - }); - } - }); + $query->where('draft', '=', 0); + if (!$filterDrafts) { + $query->orWhere(function ($query) { + $query->where('draft', '=', 1)->where('created_by', '=', $this->currentUser()->id); + }); + } + }); $chapterSelect = $this->db->table('chapters')->selectRaw($entities->chapter->entityRawQuery())->where('book_id', '=', $book_id); $query = $this->db->query()->select('*')->from($this->db->raw("({$pageSelect->toSql()} UNION {$chapterSelect->toSql()}) AS U")) ->mergeBindings($pageSelect)->mergeBindings($chapterSelect); diff --git a/app/Entities/EntityProvider.php b/app/Entities/EntityProvider.php index 46a883ec4..04939a14a 100644 --- a/app/Entities/EntityProvider.php +++ b/app/Entities/EntityProvider.php @@ -84,6 +84,4 @@ class EntityProvider $type = strtolower($type); return $this->all()[$type]; } - - -} \ No newline at end of file +} diff --git a/app/Entities/Repos/PageRepo.php b/app/Entities/Repos/PageRepo.php index 3558b29b3..148ae8459 100644 --- a/app/Entities/Repos/PageRepo.php +++ b/app/Entities/Repos/PageRepo.php @@ -505,4 +505,4 @@ class PageRepo extends EntityRepo return $this->publishPageDraft($copyPage, $pageData); } -} \ No newline at end of file +} diff --git a/app/Exceptions/HttpFetchException.php b/app/Exceptions/HttpFetchException.php index 48e30e1e6..2a34bbc62 100644 --- a/app/Exceptions/HttpFetchException.php +++ b/app/Exceptions/HttpFetchException.php @@ -2,4 +2,6 @@ use Exception; -class HttpFetchException extends Exception {} +class HttpFetchException extends Exception +{ +} diff --git a/app/Exceptions/UserUpdateException.php b/app/Exceptions/UserUpdateException.php index eb41dece6..81e95b16f 100644 --- a/app/Exceptions/UserUpdateException.php +++ b/app/Exceptions/UserUpdateException.php @@ -1,3 +1,5 @@ 'ar', + 'de' => 'de_DE', + 'de_informal' => 'de_DE', + 'en' => 'en_GB', + 'es' => 'es_ES', + 'es_AR' => 'es_AR', + 'fr' => 'fr_FR', + 'it' => 'it_IT', + 'ja' => 'ja', + 'kr' => 'ko_KR', + 'nl' => 'nl_NL', + 'pl' => 'pl_PL', + 'pt_BR' => 'pt_BR', + 'pt_BR' => 'pt_BR', + 'ru' => 'ru', + 'sk' => 'sk_SK', + 'sv' => 'sv_SE', + 'uk' => 'uk_UA', + 'uk' => 'uk_UA', + 'zh_CN' => 'zh_CN', + 'zh_TW' => 'zh_TW', + ]; + /** * Handle an incoming request. * @@ -31,8 +63,11 @@ class Localization config()->set('app.rtl', true); } + + app()->setLocale($locale); Carbon::setLocale($locale); + $this->setSystemDateLocale($locale); return $next($request); } @@ -53,4 +88,18 @@ class Localization } return $default; } + + /** + * Set the system date locale for localized date formatting. + * Will try both the standard locale name and the UTF8 variant. + * @param string $locale + */ + protected function setSystemDateLocale(string $locale) + { + $systemLocale = $this->localeMap[$locale] ?? $locale; + $set = setlocale(LC_TIME, $systemLocale); + if ($set === false) { + setlocale(LC_TIME, $systemLocale . '.utf8'); + } + } } diff --git a/app/Notifications/MailNotification.php b/app/Notifications/MailNotification.php index 413ac6d73..5aa9b1e4a 100644 --- a/app/Notifications/MailNotification.php +++ b/app/Notifications/MailNotification.php @@ -31,5 +31,4 @@ class MailNotification extends Notification implements ShouldQueue 'text' => 'vendor.notifications.email-plain' ]); } - -} \ No newline at end of file +} diff --git a/app/Notifications/ResetPassword.php b/app/Notifications/ResetPassword.php index 282aa335a..305a7da72 100644 --- a/app/Notifications/ResetPassword.php +++ b/app/Notifications/ResetPassword.php @@ -1,6 +1,5 @@ baseLocaleMap[$locale] ?? null; } - -} \ No newline at end of file +} diff --git a/app/Uploads/HttpFetcher.php b/app/Uploads/HttpFetcher.php index 3ebe17eee..5e8115637 100644 --- a/app/Uploads/HttpFetcher.php +++ b/app/Uploads/HttpFetcher.php @@ -30,5 +30,4 @@ class HttpFetcher return $data; } - -} \ No newline at end of file +} diff --git a/composer.json b/composer.json index 48b977e23..61bb8509e 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "laravel/framework": "~5.5.44", "fideloper/proxy": "~3.3", "intervention/image": "^2.4", - "laravel/socialite": "^3.0", + "laravel/socialite": "3.0.x-dev", "league/flysystem-aws-s3-v3": "^1.0", "barryvdh/laravel-dompdf": "^0.8.1", "predis/predis": "^1.1", diff --git a/composer.lock b/composer.lock index c524c0999..d7734ce1a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "06219a5c2419ca23ec2924eb31f4ed16", + "content-hash": "0946a07729a7a1bfef9bac185a870afd", "packages": [ { "name": "aws/aws-sdk-php", - "version": "3.82.3", + "version": "3.86.2", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "a0353c24b18d2ba0f5bb7ca8a478b4ce0b8153f7" + "reference": "50224232ac7a4e2a6fa4ebbe0281e5b7503acf76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/a0353c24b18d2ba0f5bb7ca8a478b4ce0b8153f7", - "reference": "a0353c24b18d2ba0f5bb7ca8a478b4ce0b8153f7", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/50224232ac7a4e2a6fa4ebbe0281e5b7503acf76", + "reference": "50224232ac7a4e2a6fa4ebbe0281e5b7503acf76", "shasum": "" }, "require": { @@ -87,7 +87,7 @@ "s3", "sdk" ], - "time": "2018-12-21T22:21:50+00:00" + "time": "2019-01-18T21:10:44+00:00" }, { "name": "barryvdh/laravel-dompdf", @@ -1457,16 +1457,16 @@ }, { "name": "laravel/socialite", - "version": "v3.2.0", + "version": "3.0.x-dev", "source": { "type": "git", "url": "https://github.com/laravel/socialite.git", - "reference": "7194c0cd9fb2ce449669252b8ec316b85b7de481" + "reference": "79316f36641f1916a50ab14d368acdf1d97e46de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/socialite/zipball/7194c0cd9fb2ce449669252b8ec316b85b7de481", - "reference": "7194c0cd9fb2ce449669252b8ec316b85b7de481", + "url": "https://api.github.com/repos/laravel/socialite/zipball/79316f36641f1916a50ab14d368acdf1d97e46de", + "reference": "79316f36641f1916a50ab14d368acdf1d97e46de", "shasum": "" }, "require": { @@ -1516,7 +1516,7 @@ "laravel", "oauth" ], - "time": "2018-10-18T03:39:04+00:00" + "time": "2018-12-21T14:06:32+00:00" }, { "name": "league/flysystem", @@ -1891,16 +1891,16 @@ }, { "name": "nesbot/carbon", - "version": "1.36.1", + "version": "1.36.2", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "63da8cdf89d7a5efe43aabc794365f6e7b7b8983" + "reference": "cd324b98bc30290f233dd0e75e6ce49f7ab2a6c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/63da8cdf89d7a5efe43aabc794365f6e7b7b8983", - "reference": "63da8cdf89d7a5efe43aabc794365f6e7b7b8983", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/cd324b98bc30290f233dd0e75e6ce49f7ab2a6c9", + "reference": "cd324b98bc30290f233dd0e75e6ce49f7ab2a6c9", "shasum": "" }, "require": { @@ -1945,7 +1945,7 @@ "datetime", "time" ], - "time": "2018-11-22T18:23:02+00:00" + "time": "2018-12-28T10:07:33+00:00" }, { "name": "paragonie/random_compat", @@ -2555,20 +2555,20 @@ }, { "name": "socialiteproviders/manager", - "version": "v3.3.1", + "version": "v3.3.4", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Manager.git", - "reference": "1de3f3d874392da6f1a4c0bf30d843e9cd903ea7" + "reference": "58b72a667da292a1d0a0b1e6e9aeda4053617030" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/1de3f3d874392da6f1a4c0bf30d843e9cd903ea7", - "reference": "1de3f3d874392da6f1a4c0bf30d843e9cd903ea7", + "url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/58b72a667da292a1d0a0b1e6e9aeda4053617030", + "reference": "58b72a667da292a1d0a0b1e6e9aeda4053617030", "shasum": "" }, "require": { - "laravel/socialite": "~3.0", + "laravel/socialite": "~3.0|~4.0", "php": "^5.6 || ^7.0" }, "require-dev": { @@ -2585,8 +2585,7 @@ }, "autoload": { "psr-4": { - "SocialiteProviders\\Manager\\": "src/", - "SocialiteProviders\\Manager\\Test\\": "tests/" + "SocialiteProviders\\Manager\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2597,10 +2596,14 @@ { "name": "Andy Wendt", "email": "andy@awendt.com" + }, + { + "name": "Anton Komarev", + "email": "a.komarev@cybercog.su" } ], "description": "Easily add new or override built-in providers in Laravel Socialite.", - "time": "2017-11-20T08:42:57+00:00" + "time": "2019-01-16T07:58:54+00:00" }, { "name": "socialiteproviders/microsoft-azure", @@ -3664,16 +3667,16 @@ }, { "name": "vlucas/phpdotenv", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "8abb4f9aa89ddea9d52112c65bbe8d0125e2fa8e" + "reference": "cfd5dc225767ca154853752abc93aeec040fcf36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/8abb4f9aa89ddea9d52112c65bbe8d0125e2fa8e", - "reference": "8abb4f9aa89ddea9d52112c65bbe8d0125e2fa8e", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/cfd5dc225767ca154853752abc93aeec040fcf36", + "reference": "cfd5dc225767ca154853752abc93aeec040fcf36", "shasum": "" }, "require": { @@ -3710,7 +3713,7 @@ "env", "environment" ], - "time": "2018-07-29T20:33:41+00:00" + "time": "2018-10-30T17:29:25+00:00" } ], "packages-dev": [ @@ -4423,23 +4426,23 @@ }, { "name": "justinrainbow/json-schema", - "version": "5.2.7", + "version": "5.2.8", "source": { "type": "git", "url": "https://github.com/justinrainbow/json-schema.git", - "reference": "8560d4314577199ba51bf2032f02cd1315587c23" + "reference": "dcb6e1006bb5fd1e392b4daa68932880f37550d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/8560d4314577199ba51bf2032f02cd1315587c23", - "reference": "8560d4314577199ba51bf2032f02cd1315587c23", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/dcb6e1006bb5fd1e392b4daa68932880f37550d4", + "reference": "dcb6e1006bb5fd1e392b4daa68932880f37550d4", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.1", + "friendsofphp/php-cs-fixer": "~2.2.20", "json-schema/json-schema-test-suite": "1.2.0", "phpunit/phpunit": "^4.8.35" }, @@ -4485,7 +4488,7 @@ "json", "schema" ], - "time": "2018-02-14T22:26:30+00:00" + "time": "2019-01-14T23:55:14+00:00" }, { "name": "laravel/browser-kit-testing", @@ -6265,20 +6268,21 @@ }, { "name": "webmozart/assert", - "version": "1.3.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a" + "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a", + "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9", + "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^5.3.3 || ^7.0", + "symfony/polyfill-ctype": "^1.8" }, "require-dev": { "phpunit/phpunit": "^4.6", @@ -6311,12 +6315,14 @@ "check", "validate" ], - "time": "2018-01-29T19:49:41+00:00" + "time": "2018-12-25T11:19:39+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "laravel/socialite": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -6326,7 +6332,8 @@ "ext-dom": "*", "ext-xml": "*", "ext-mbstring": "*", - "ext-gd": "*" + "ext-gd": "*", + "ext-curl": "*" }, "platform-dev": [], "platform-overrides": { diff --git a/config/filesystems.php b/config/filesystems.php index abaf3c6a4..13198a505 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -49,6 +49,8 @@ return [ 'secret' => env('STORAGE_S3_SECRET', 'your-secret'), 'region' => env('STORAGE_S3_REGION', 'your-region'), 'bucket' => env('STORAGE_S3_BUCKET', 'your-bucket'), + 'endpoint' => env('STORAGE_S3_ENDPOINT', null), + 'use_path_style_endpoint' => env('STORAGE_S3_ENDPOINT', null) !== null, ], 'rackspace' => [ diff --git a/readme.md b/readme.md index e6fd59e98..337870c59 100644 --- a/readme.md +++ b/readme.md @@ -9,8 +9,7 @@ A platform for storing and organising information and documentation. General inf * [Installation Instructions](https://www.bookstackapp.com/docs/admin/installation) * [Documentation](https://www.bookstackapp.com/docs) * [Demo Instance](https://demo.bookstackapp.com) - * *Username: `admin@example.com`* - * *Password: `password`* + * [Admin Login](https://demo.bookstackapp.com/login?email=admin@example.com&password=password) * [BookStack Blog](https://www.bookstackapp.com/blog) ## Project Definition @@ -19,7 +18,7 @@ BookStack is an opinionated wiki system that provides a pleasant and simple out BookStack is not designed as an extensible platform to be used for purposes that differ to the statement above. -In regards to development philosophy, BookStack has a relaxed, open & positive approach. Put simply, At the end of the day this is free software developed and maintained by people donating their own free time. +In regards to development philosophy, BookStack has a relaxed, open & positive approach. At the end of the day this is free software developed and maintained by people donating their own free time. ## Development & Testing @@ -85,15 +84,15 @@ PHP code within BookStack is generally to [PSR-2](http://www.php-fig.org/psr/psr ### Pull Requests -Pull requests are very welcome. If the scope of your pull request is large it may be best to open the pull request early or create an issue for it to discuss how it will fit in to the project and plan out the merge. +Pull requests are welcome. Unless a small tweak or language update, It may be best to open the pull request early or create an issue for your intended change to discuss how it will fit in to the project and plan out the merge. -Pull requests should be created from the `master` branch and should be merged back into `master` once done. Please do not build from or request a merge into the `release` branch as this is only for publishing releases. +Pull requests should be created from the `master` branch since they will be merged back into `master` once done. Please do not build from or request a merge into the `release` branch as this is only for publishing releases. If you are looking to alter CSS or JavaScript content please edit the source files found in `resources/assets`. Any CSS or JS files within `public` are built from these source files and therefore should not be edited directly. ## Website, Docs & Blog -The website project docs & Blog can be found in the [BookStackApp/website](https://github.com/BookStackApp/website) repo. +The website which contains the project docs & Blog can be found in the [BookStackApp/website](https://github.com/BookStackApp/website) repo. ## License @@ -117,7 +116,6 @@ These are the great open-source projects used to help build BookStack: * [clipboard.js](https://clipboardjs.com/) * [TinyColorPicker](http://www.dematte.at/tinyColorPicker/index.html) * [markdown-it](https://github.com/markdown-it/markdown-it) and [markdown-it-task-lists](https://github.com/revin/markdown-it-task-lists) -* [Moment.js](http://momentjs.com/) * [BarryVD](https://github.com/barryvdh) * [Debugbar](https://github.com/barryvdh/laravel-debugbar) * [Dompdf](https://github.com/barryvdh/laravel-dompdf) diff --git a/resources/assets/js/components/page-display.js b/resources/assets/js/components/page-display.js index e7dacea64..bca641cb6 100644 --- a/resources/assets/js/components/page-display.js +++ b/resources/assets/js/components/page-display.js @@ -123,20 +123,21 @@ class PageDisplay { setupStickySidebar() { // Make the sidebar stick in view on scroll - let $window = $(window); - let $sidebar = $("#sidebar .scroll-body"); - let $bookTreeParent = $sidebar.parent(); + const $window = $(window); + const $sidebar = $("#sidebar .scroll-body"); + const $sidebarContainer = $sidebar.parent(); + const sidebarHeight = $sidebar.height() + 32; // Check the page is scrollable and the content is taller than the tree - let pageScrollable = ($(document).height() > ($window.height() + 40)) && ($sidebar.height() < $('.page-content').height()); + const pageScrollable = ($(document).height() > ($window.height() + 40)) && (sidebarHeight < $('.page-content').height()); // Get current tree's width and header height - let headerHeight = $("#header").height() + $(".toolbar").height(); + const headerHeight = $("#header").height() + $(".toolbar").height(); let isFixed = $window.scrollTop() > headerHeight; // Fix the tree as a sidebar function stickTree() { - $sidebar.css('width', $bookTreeParent.width()); + $sidebar.width($sidebarContainer.width() + 15); $sidebar.addClass("fixed"); isFixed = true; } diff --git a/resources/assets/sass/print-styles.scss b/resources/assets/sass/print-styles.scss index c05600073..c67f98642 100644 --- a/resources/assets/sass/print-styles.scss +++ b/resources/assets/sass/print-styles.scss @@ -16,6 +16,14 @@ body { margin: 0 auto; } +.flex-fill { + display: block; +} + +.flex.sidebar + .flex.content { + border-left: none; +} + .print-hidden { display: none; } @@ -31,4 +39,8 @@ h2 { line-height: 1; margin-top: 0.6em; margin-bottom: 0.3em; +} + +.comments-container { + display: none; } \ No newline at end of file diff --git a/resources/views/pages/revisions.blade.php b/resources/views/pages/revisions.blade.php index 82fb47c96..d3a55a2e6 100644 --- a/resources/views/pages/revisions.blade.php +++ b/resources/views/pages/revisions.blade.php @@ -35,7 +35,7 @@ @endif