From 5ef0992d5b771f6348e131023eaa3a8be7fac646 Mon Sep 17 00:00:00 2001 From: abijeet Date: Sun, 27 Jan 2019 15:59:23 +0530 Subject: [PATCH 01/15] PHPCS related fixes. --- app/Auth/Access/LdapService.php | 4 ++-- app/Auth/Permissions/PermissionService.php | 22 ++++++++++---------- app/Entities/EntityProvider.php | 4 +--- app/Entities/Repos/PageRepo.php | 2 +- app/Exceptions/HttpFetchException.php | 4 +++- app/Exceptions/UserUpdateException.php | 4 +++- app/Notifications/MailNotification.php | 3 +-- app/Notifications/ResetPassword.php | 1 - app/Providers/TranslationServiceProvider.php | 3 +-- app/Translation/Translator.php | 4 +--- app/Uploads/HttpFetcher.php | 3 +-- 11 files changed, 25 insertions(+), 29 deletions(-) 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 @@ '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 +} From ba1b3fc1815596ec3ea1d1e72e22563cf777a06f Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 4 Feb 2019 19:57:21 +0000 Subject: [PATCH 02/15] Made some readme tweaks --- readme.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) 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) From 56004abdf429254905bac7569b1fea066687aa3b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Wed, 6 Feb 2019 00:09:39 +0000 Subject: [PATCH 03/15] Added high-level release and roadmap info to readme Closes #1259 --- readme.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/readme.md b/readme.md index 337870c59..037fbedb5 100644 --- a/readme.md +++ b/readme.md @@ -20,6 +20,29 @@ BookStack is not designed as an extensible platform to be used for purposes that 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. +## Road Map + +Below is a high-level road map view for BookStack to provide a sense of direction of where the project is going. This can change at any point and does not reflect many features and improvements that will also be included as part of the journey along this road map. For more granular detail of what will be included in upcoming releases you can review the project milestones as defined in the "Release Process" section below. + +- **Design Revamp** *[(In Progress)](https://github.com/BookStackApp/BookStack/pull/1153)* + - *A more organised modern design to clean things up, make BookStack more efficient to use and increase mobile usability.* +- **Platform REST API** + - *A REST API covering, at minimum, control of core content models (Books, Chapters, Pages) for automation and platform extension.* +- **Editor Alignment & Review** + - *Review the page editors with goal of achieving increased interoperability & feature parity while also considering collaborative editing potential.* +- **Permission System Review** + - *Improvement in how permissions are applied and a review of the efficiency of the permission & roles system.* +- **Installation & Deployment Process Revamp** + - *Creation of a streamlined & secure process for users to deploy & update BookStack with reduced development requirements (No git or composer requirement).* + +## Release Versioning & Process + +BookStack releases are each assigned a version number, such as "v0.25.2", in the format `v..`. A change only in the `patch` number indicates a fairly minor release that mainly contains fixes and therefore is very unlikely to cause breakages upon update. A change in the `feature` number indicates a release which will generally bring new features in addition to fixes and enhancements. These releases have a small chance of introducing breaking changes upon update so it's worth checking for any notes in the [update guide](https://www.bookstackapp.com/docs/admin/updates/). A change in the `phase` indicates a much large change in BookStack that will likely incur breakages requiring manual intervention. + +Each BookStack release will have a [milestone](https://github.com/BookStackApp/BookStack/milestones) created with issues & pull requests assigned to it to define what will be in that release. Milestones are built up then worked through until complete at which point, after some testing and documentation updates, the release will be deployed. + +For feature releases, and some patch releases, the release will be accompanied by a post on the [BookStack blog](https://www.bookstackapp.com/blog/) which will provide additional detail on features, changes & updates otherwise the [GitHub release page](https://github.com/BookStackApp/BookStack/releases) will show a list of changes. You can sign up to be alerted to new BookStack blogs posts (once per week maximum) [at this link](http://eepurl.com/cmmq5j). + ## Development & Testing All development on BookStack is currently done on the master branch. When it's time for a release the master branch is merged into release with built & minified CSS & JS then tagged at its version. Here are the current development requirements: From 77d3bd31a6f9ea6be09fbea65866611a5f7a8d33 Mon Sep 17 00:00:00 2001 From: Christopher Tran Date: Wed, 6 Feb 2019 01:06:59 -0500 Subject: [PATCH 04/15] add powershell code block link --- resources/views/components/code-editor.blade.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/views/components/code-editor.blade.php b/resources/views/components/code-editor.blade.php index cd235f1d2..cc6c10949 100644 --- a/resources/views/components/code-editor.blade.php +++ b/resources/views/components/code-editor.blade.php @@ -22,6 +22,7 @@ JavaScript JSON PHP + Powershell MarkDown Nginx Python @@ -48,4 +49,4 @@ - \ No newline at end of file + From 9511d10ec852bab3b9f7aefaa8848c5d97d28918 Mon Sep 17 00:00:00 2001 From: Xiphoseer Date: Tue, 12 Feb 2019 12:24:01 +0100 Subject: [PATCH 05/15] Update entities.php Add german shelve localizations --- resources/lang/de/entities.php | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/resources/lang/de/entities.php b/resources/lang/de/entities.php index 7c27be17b..9b24bd72c 100644 --- a/resources/lang/de/entities.php +++ b/resources/lang/de/entities.php @@ -60,6 +60,39 @@ return [ 'search_created_after' => 'Erstellt nach', 'search_set_date' => 'Datum auswählen', 'search_update' => 'Suche aktualisieren', + + /* + * Shelves + */ + 'shelf' => 'Regal', + 'shelves' => 'Regale', + 'shelves_long' => 'Bücherregal', + 'shelves_empty' => 'Es wurden noch keine Regale angelegt', + 'shelves_create' => 'Erzeuge ein Regal', + 'shelves_popular' => 'Beliebte Regale', + 'shelves_new' => 'Kürzlich erstellte Regale', + 'shelves_popular_empty' => 'Die beliebtesten Regale werden hier angezeigt.', + 'shelves_new_empty' => 'Die neusten Regale werden hier angezeigt.', + 'shelves_save' => 'Regal speichern', + 'shelves_books' => 'Bücher in diesem Regal', + 'shelves_add_books' => 'Buch zu diesem Regal hinzufügen', + 'shelves_drag_books' => 'Bücher hier hin ziehen um sie dem Regal hinzuzufügen', + 'shelves_empty_contents' => 'Diesem Regal sind keine Bücher zugewiesen', + 'shelves_edit_and_assign' => 'Regal bearbeiten um Bücher hinzuzufügen', + 'shelves_edit_named' => 'Bücherregal :name bearbeiten', + 'shelves_edit' => 'Bücherregal bearbeiten', + 'shelves_delete' => 'Bücherregal löschen', + 'shelves_delete_named' => 'Bücherregal :name löschen', + 'shelves_delete_explain' => "Sie sind im Begriff das Bücherregal mit dem Namen ':name' zu löschen. Enthaltene Bücher werden nicht gelöscht.", + 'shelves_delete_confirmation' => 'Sind Sie sicher, dass Sie dieses Bücherregal löschen wollen?', + 'shelves_permissions' => 'Regal-Berechtigungen', + 'shelves_permissions_updated' => 'Regal-Berechtigungen aktualisiert', + 'shelves_permissions_active' => 'Regal-Berechtigungen aktiv', + 'shelves_copy_permissions_to_books' => 'Kopiere die Berechtigungen zum Buch', + 'shelves_copy_permissions' => 'Berechtigungen kopieren', + 'shelves_copy_permissions_explain' => 'Hiermit werden die Berechtigungen des aktuellen Regals auf alle enthaltenen Bücher übertragen. Überprüfe vor der Aktivierung ob alle Berechtigungsänderungen am aktuellen Buch gespeichert wurden.', + 'shelves_copy_permission_success' => 'Regal-Berechtigungen wurden zu :count Büchern kopiert', + /** * Books */ From 19bb11a1c90643fb8814289b61120bd3276075ed Mon Sep 17 00:00:00 2001 From: Xiphoseer Date: Tue, 12 Feb 2019 12:28:48 +0100 Subject: [PATCH 06/15] Update entities.php Add informal german shelve localisations --- resources/lang/de_informal/entities.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/resources/lang/de_informal/entities.php b/resources/lang/de_informal/entities.php index 21fdbb13d..8d7abc4fa 100644 --- a/resources/lang/de_informal/entities.php +++ b/resources/lang/de_informal/entities.php @@ -9,6 +9,13 @@ return [ 'no_pages_recently_created' => 'Du hast bisher keine Seiten angelegt.', 'no_pages_recently_updated' => 'Du hast bisher keine Seiten aktualisiert.', + /** + * Shelves + */ + 'shelves_delete_explain' => "Du bist im Begriff das Bücherregal mit dem Namen ':name' zu löschen. Enthaltene Bücher werden nicht gelöscht.", + 'shelves_delete_confirmation' => 'Bist du sicher, dass du dieses Bücherregal löschen willst?', + 'shelves_copy_permissions_explain' => 'Hiermit werden die Berechtigungen des aktuellen Regals auf alle enthaltenen Bücher übertragen. Überprüfe vor der Aktivierung, ob alle Berechtigungsänderungen am aktuellen Buch gespeichert wurden.', + /** * Books */ From edd98c00e565cd421cd6290dc01a4235162ba519 Mon Sep 17 00:00:00 2001 From: Xiphoseer Date: Tue, 12 Feb 2019 12:30:12 +0100 Subject: [PATCH 07/15] Update entities.php --- resources/lang/de/entities.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lang/de/entities.php b/resources/lang/de/entities.php index 9b24bd72c..07a92e2c7 100644 --- a/resources/lang/de/entities.php +++ b/resources/lang/de/entities.php @@ -90,7 +90,7 @@ return [ 'shelves_permissions_active' => 'Regal-Berechtigungen aktiv', 'shelves_copy_permissions_to_books' => 'Kopiere die Berechtigungen zum Buch', 'shelves_copy_permissions' => 'Berechtigungen kopieren', - 'shelves_copy_permissions_explain' => 'Hiermit werden die Berechtigungen des aktuellen Regals auf alle enthaltenen Bücher übertragen. Überprüfe vor der Aktivierung ob alle Berechtigungsänderungen am aktuellen Buch gespeichert wurden.', + 'shelves_copy_permissions_explain' => 'Hiermit werden die Berechtigungen des aktuellen Regals auf alle enthaltenen Bücher übertragen. Überprüfen Sie vor der Aktivierung, ob alle Berechtigungsänderungen am aktuellen Regal gespeichert wurden.', 'shelves_copy_permission_success' => 'Regal-Berechtigungen wurden zu :count Büchern kopiert', /** From 058cc2cbd65ce7d963e05228d751f34104b8c69b Mon Sep 17 00:00:00 2001 From: Xiphoseer Date: Tue, 12 Feb 2019 12:30:43 +0100 Subject: [PATCH 08/15] Update entities.php --- resources/lang/de_informal/entities.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lang/de_informal/entities.php b/resources/lang/de_informal/entities.php index 8d7abc4fa..1decdd7b7 100644 --- a/resources/lang/de_informal/entities.php +++ b/resources/lang/de_informal/entities.php @@ -14,7 +14,7 @@ return [ */ 'shelves_delete_explain' => "Du bist im Begriff das Bücherregal mit dem Namen ':name' zu löschen. Enthaltene Bücher werden nicht gelöscht.", 'shelves_delete_confirmation' => 'Bist du sicher, dass du dieses Bücherregal löschen willst?', - 'shelves_copy_permissions_explain' => 'Hiermit werden die Berechtigungen des aktuellen Regals auf alle enthaltenen Bücher übertragen. Überprüfe vor der Aktivierung, ob alle Berechtigungsänderungen am aktuellen Buch gespeichert wurden.', + 'shelves_copy_permissions_explain' => 'Hiermit werden die Berechtigungen des aktuellen Regals auf alle enthaltenen Bücher übertragen. Überprüfe vor der Aktivierung, ob alle Berechtigungsänderungen am aktuellen Regal gespeichert wurden.', /** * Books From e471d0c52a59752c609a19f29af0d4ccebf0048b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 2 Mar 2019 08:52:14 +0000 Subject: [PATCH 09/15] Added lua to code languages Closes #1223 --- resources/assets/js/services/code.js | 4 +++- resources/views/components/code-editor.blade.php | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/resources/assets/js/services/code.js b/resources/assets/js/services/code.js index cfeabd3be..bd749033d 100644 --- a/resources/assets/js/services/code.js +++ b/resources/assets/js/services/code.js @@ -8,6 +8,7 @@ import 'codemirror/mode/diff/diff'; import 'codemirror/mode/go/go'; import 'codemirror/mode/htmlmixed/htmlmixed'; import 'codemirror/mode/javascript/javascript'; +import 'codemirror/mode/lua/lua'; import 'codemirror/mode/markdown/markdown'; import 'codemirror/mode/nginx/nginx'; import 'codemirror/mode/php/php'; @@ -38,12 +39,13 @@ const modeMap = { javascript: 'javascript', json: {name: 'javascript', json: true}, js: 'javascript', - php: 'php', + lua: 'lua', md: 'markdown', mdown: 'markdown', markdown: 'markdown', nginx: 'nginx', powershell: 'powershell', + php: 'php', py: 'python', python: 'python', ruby: 'ruby', diff --git a/resources/views/components/code-editor.blade.php b/resources/views/components/code-editor.blade.php index cc6c10949..67e7b7773 100644 --- a/resources/views/components/code-editor.blade.php +++ b/resources/views/components/code-editor.blade.php @@ -21,6 +21,7 @@ Java JavaScript JSON + Lua PHP Powershell MarkDown From b273b9d6d04e3c0de999cda0ce52560137dc47f1 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 2 Mar 2019 09:08:01 +0000 Subject: [PATCH 10/15] Improved alignment classes used by WYSIWYG editor - Fixed table cells being floated, Fixes #1284. - Made it possible to easily center linked images. --- resources/assets/sass/_pages.scss | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/resources/assets/sass/_pages.scss b/resources/assets/sass/_pages.scss index 21fdf90de..84280319d 100755 --- a/resources/assets/sass/_pages.scss +++ b/resources/assets/sass/_pages.scss @@ -51,15 +51,22 @@ margin: $-xs $-s $-xs 0; } .align-right { - float: right !important; + text-align: right !important; } img.align-right, table.align-right { - text-align: right; + float: right !important; margin: $-xs 0 $-xs $-s; } .align-center { text-align: center; } + img.align-center { + display: block; + } + img.align-center, table.align-center { + margin-left: auto; + margin-right: auto; + } img { max-width: 100%; height:auto; From 6f710225b51f10ea474aa2b2f62573c5d9251209 Mon Sep 17 00:00:00 2001 From: Jamie Schouten Date: Wed, 6 Mar 2019 17:10:15 +0100 Subject: [PATCH 11/15] Update Dutch password_hint translation to correspond with validation rule At the moment the translation says ```Minimaal 5 tekens``` which means your password should be at least 5 characters long. But a 5 character long password is not allowed by the validator. I think this was a translation error from the English one where it says ```Must be over 5 characters```. To make the Dutch translation correct the Dutch translation should be changed to ```Minimaal 6 tekens```. ``` /** * Get a validator for an incoming registration request. * * @param array $data * @return \Illuminate\Contracts\Validation\Validator */ protected function validator(array $data) { return Validator::make($data, [ 'name' => 'required|max:255', 'email' => 'required|email|max:255|unique:users', 'password' => 'required|min:6', ]); } ``` --- resources/lang/nl/auth.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lang/nl/auth.php b/resources/lang/nl/auth.php index d8813f07b..31bd330cc 100644 --- a/resources/lang/nl/auth.php +++ b/resources/lang/nl/auth.php @@ -27,7 +27,7 @@ return [ 'email' => 'Email', 'password' => 'Wachtwoord', 'password_confirm' => 'Wachtwoord Bevestigen', - 'password_hint' => 'Minimaal 5 tekens', + 'password_hint' => 'Minimaal 6 tekens', 'forgot_password' => 'Wachtwoord vergeten?', 'remember_me' => 'Mij onthouden', 'ldap_email_hint' => 'Geef een email op waarmee je dit account wilt gebruiken.', @@ -73,4 +73,4 @@ return [ 'email_not_confirmed_click_link' => 'Klik op de link in de e-mail die vlak na je registratie is verstuurd.', 'email_not_confirmed_resend' => 'Als je deze e-mail niet kunt vinden kun je deze met onderstaande formulier opnieuw verzenden.', 'email_not_confirmed_resend_button' => 'Bevestigingsmail Opnieuw Verzenden', -]; \ No newline at end of file +]; From 98a4359198d84fe3519361d5ccc3d0a6ff26fd64 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 7 Mar 2019 21:09:23 +0000 Subject: [PATCH 12/15] Updated user language select to use correct default - Updated localisation system to take note of system defaul locale before replacing the current locale Fixes #1316 --- app/Http/Middleware/Localization.php | 3 +-- app/Settings/SettingService.php | 1 + resources/views/users/edit.blade.php | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/Http/Middleware/Localization.php b/app/Http/Middleware/Localization.php index e65b417d5..ff5526cc7 100644 --- a/app/Http/Middleware/Localization.php +++ b/app/Http/Middleware/Localization.php @@ -51,6 +51,7 @@ class Localization public function handle($request, Closure $next) { $defaultLang = config('app.locale'); + config()->set('app.default_locale', $defaultLang); if (user()->isDefault() && config('app.auto_detect_locale')) { $locale = $this->autoDetectLocale($request, $defaultLang); @@ -63,8 +64,6 @@ class Localization config()->set('app.rtl', true); } - - app()->setLocale($locale); Carbon::setLocale($locale); $this->setSystemDateLocale($locale); diff --git a/app/Settings/SettingService.php b/app/Settings/SettingService.php index c903bd60a..c9491e3ee 100644 --- a/app/Settings/SettingService.php +++ b/app/Settings/SettingService.php @@ -41,6 +41,7 @@ class SettingService if ($default === false) { $default = config('setting-defaults.' . $key, false); } + if (isset($this->localCache[$key])) { return $this->localCache[$key]; } diff --git a/resources/views/users/edit.blade.php b/resources/views/users/edit.blade.php index c4b02f9b9..1b0514f9c 100644 --- a/resources/views/users/edit.blade.php +++ b/resources/views/users/edit.blade.php @@ -38,8 +38,9 @@
From 1c312906bc8eec26d75934e74cab01284dee2bb3 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 8 Mar 2019 21:06:37 +0000 Subject: [PATCH 13/15] Added a configurable upload size limit Closes #1293 --- resources/assets/js/vues/components/dropzone.js | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/assets/js/vues/components/dropzone.js b/resources/assets/js/vues/components/dropzone.js index 31a84a267..9d3d22b4d 100644 --- a/resources/assets/js/vues/components/dropzone.js +++ b/resources/assets/js/vues/components/dropzone.js @@ -16,6 +16,7 @@ function mounted() { addRemoveLinks: true, dictRemoveFile: trans('components.image_upload_remove'), timeout: Number(window.uploadTimeout) || 60000, + maxFilesize: Number(window.uploadLimit) || 256, url: function() { return _this.uploadUrl; }, From d96baf2d4ac79909959361165887dbb963851ce0 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 8 Mar 2019 21:32:31 +0000 Subject: [PATCH 14/15] Set 'uploaded_to' parameters for editor-pasted/dragged images Allows image-listing permission system to work as intended. Fixes #1287 --- .../assets/js/components/markdown-editor.js | 43 ++++++++++++------- .../assets/js/components/wysiwyg-editor.js | 43 ++++++++++++------- 2 files changed, 55 insertions(+), 31 deletions(-) diff --git a/resources/assets/js/components/markdown-editor.js b/resources/assets/js/components/markdown-editor.js index 9228cfe2c..b8e2bc040 100644 --- a/resources/assets/js/components/markdown-editor.js +++ b/resources/assets/js/components/markdown-editor.js @@ -8,7 +8,11 @@ class MarkdownEditor { constructor(elem) { this.elem = elem; - this.textDirection = document.getElementById('page-editor').getAttribute('text-direction'); + + const pageEditor = document.getElementById('page-editor'); + this.pageId = pageEditor.getAttribute('page-id'); + this.textDirection = pageEditor.getAttribute('text-direction'); + this.markdown = new MarkdownIt({html: true}); this.markdown.use(mdTasksLists, {label: true}); @@ -98,7 +102,9 @@ class MarkdownEditor { } codeMirrorSetup() { - let cm = this.cm; + const cm = this.cm; + const context = this; + // Text direction // cm.setOption('direction', this.textDirection); cm.setOption('direction', 'ltr'); // Will force to remain as ltr for now due to issues when HTML is in editor. @@ -266,17 +272,18 @@ class MarkdownEditor { } // Insert image into markdown - let id = "image-" + Math.random().toString(16).slice(2); - let placeholderImage = window.baseUrl(`/loading.gif#upload${id}`); - let selectedText = cm.getSelection(); - let placeHolderText = `![${selectedText}](${placeholderImage})`; - let cursor = cm.getCursor(); + const id = "image-" + Math.random().toString(16).slice(2); + const placeholderImage = window.baseUrl(`/loading.gif#upload${id}`); + const selectedText = cm.getSelection(); + const placeHolderText = `![${selectedText}](${placeholderImage})`; + const cursor = cm.getCursor(); cm.replaceSelection(placeHolderText); cm.setCursor({line: cursor.line, ch: cursor.ch + selectedText.length + 3}); - let remoteFilename = "image-" + Date.now() + "." + ext; - let formData = new FormData(); + const remoteFilename = "image-" + Date.now() + "." + ext; + const formData = new FormData(); formData.append('file', file, remoteFilename); + formData.append('uploaded_to', context.pageId); window.$http.post('/images/gallery/upload', formData).then(resp => { const newContent = `[![${selectedText}](${resp.data.thumbs.display})](${resp.data.url})`; @@ -302,7 +309,7 @@ class MarkdownEditor { } actionInsertImage() { - let cursorPos = this.cm.getCursor('from'); + const cursorPos = this.cm.getCursor('from'); window.ImageManager.show(image => { let selectedText = this.cm.getSelection(); let newText = "[![" + (selectedText || image.name) + "](" + image.thumbs.display + ")](" + image.url + ")"; @@ -313,7 +320,7 @@ class MarkdownEditor { } actionShowImageManager() { - let cursorPos = this.cm.getCursor('from'); + const cursorPos = this.cm.getCursor('from'); window.ImageManager.show(image => { this.insertDrawing(image, cursorPos); }, 'drawio'); @@ -321,7 +328,7 @@ class MarkdownEditor { // Show the popup link selector and insert a link when finished actionShowLinkSelector() { - let cursorPos = this.cm.getCursor('from'); + const cursorPos = this.cm.getCursor('from'); window.EntitySelectorPopup.show(entity => { let selectedText = this.cm.getSelection() || entity.name; let newText = `[${selectedText}](${entity.link})`; @@ -357,7 +364,7 @@ class MarkdownEditor { } insertDrawing(image, originalCursor) { - let newText = `
`; + const newText = `
`; this.cm.focus(); this.cm.replaceSelection(newText); this.cm.setCursor(originalCursor.line, originalCursor.ch + newText.length); @@ -365,9 +372,13 @@ class MarkdownEditor { // Show draw.io if enabled and handle save. actionEditDrawing(imgContainer) { - if (document.querySelector('[drawio-enabled]').getAttribute('drawio-enabled') !== 'true') return; - let cursorPos = this.cm.getCursor('from'); - let drawingId = imgContainer.getAttribute('drawio-diagram'); + const drawingDisabled = document.querySelector('[drawio-enabled]').getAttribute('drawio-enabled') !== 'true'; + if (drawingDisabled) { + return; + } + + const cursorPos = this.cm.getCursor('from'); + const drawingId = imgContainer.getAttribute('drawio-diagram'); DrawIO.show(() => { return window.$http.get(window.baseUrl(`/images/base64/${drawingId}`)).then(resp => { diff --git a/resources/assets/js/components/wysiwyg-editor.js b/resources/assets/js/components/wysiwyg-editor.js index 39bce4959..9deb1d0a7 100644 --- a/resources/assets/js/components/wysiwyg-editor.js +++ b/resources/assets/js/components/wysiwyg-editor.js @@ -4,22 +4,24 @@ import DrawIO from "../services/drawio"; /** * Handle pasting images from clipboard. * @param {ClipboardEvent} event + * @param {WysiwygEditor} wysiwygComponent * @param editor */ -function editorPaste(event, editor) { +function editorPaste(event, editor, wysiwygComponent) { if (!event.clipboardData || !event.clipboardData.items) return; - let items = event.clipboardData.items; - for (let i = 0; i < items.length; i++) { - if (items[i].type.indexOf("image") === -1) continue; + for (let clipboardItem of event.clipboardData.items) { + if (clipboardItem.type.indexOf("image") === -1) continue; event.preventDefault(); - let id = "image-" + Math.random().toString(16).slice(2); - let loadingImage = window.baseUrl('/loading.gif'); - let file = items[i].getAsFile(); + const id = "image-" + Math.random().toString(16).slice(2); + const loadingImage = window.baseUrl('/loading.gif'); + const file = clipboardItem.getAsFile(); + setTimeout(() => { editor.insertContent(`

`); - uploadImageFile(file).then(resp => { + + uploadImageFile(file, wysiwygComponent).then(resp => { editor.dom.setAttrib(id, 'src', resp.thumbs.display); }).catch(err => { editor.dom.remove(id); @@ -33,9 +35,12 @@ function editorPaste(event, editor) { /** * Upload an image file to the server * @param {File} file + * @param {WysiwygEditor} wysiwygComponent */ -function uploadImageFile(file) { - if (file === null || file.type.indexOf('image') !== 0) return Promise.reject(`Not an image file`); +async function uploadImageFile(file, wysiwygComponent) { + if (file === null || file.type.indexOf('image') !== 0) { + throw new Error(`Not an image file`); + } let ext = 'png'; if (file.name) { @@ -43,11 +48,13 @@ function uploadImageFile(file) { if (fileNameMatches.length > 1) ext = fileNameMatches[1]; } - let remoteFilename = "image-" + Date.now() + "." + ext; - let formData = new FormData(); + const remoteFilename = "image-" + Date.now() + "." + ext; + const formData = new FormData(); formData.append('file', file, remoteFilename); + formData.append('uploaded_to', wysiwygComponent.pageId); - return window.$http.post(window.baseUrl('/images/gallery/upload'), formData).then(resp => (resp.data)); + const resp = await window.$http.post(window.baseUrl('/images/gallery/upload'), formData); + return resp.data; } function registerEditorShortcuts(editor) { @@ -370,7 +377,10 @@ class WysiwygEditor { constructor(elem) { this.elem = elem; - this.textDirection = document.getElementById('page-editor').getAttribute('text-direction'); + + const pageEditor = document.getElementById('page-editor'); + this.pageId = pageEditor.getAttribute('page-id'); + this.textDirection = pageEditor.getAttribute('text-direction'); this.plugins = "image table textcolor paste link autolink fullscreen imagetools code customhr autosave lists codeeditor media"; this.loadPlugins(); @@ -397,6 +407,9 @@ class WysiwygEditor { } getTinyMceConfig() { + + const context = this; + return { selector: '#html-editor', content_css: [ @@ -586,7 +599,7 @@ class WysiwygEditor { }); // Paste image-uploads - editor.on('paste', event => editorPaste(event, editor)); + editor.on('paste', event => editorPaste(event, editor, context)); } }; } From 646fd822c5e35485af23aa5319e3f34559a5a799 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 8 Mar 2019 22:42:48 +0000 Subject: [PATCH 15/15] Updated redis config logic, Now takes a password - Previous config did not use multiple servers in any way. - Cluster will now be created automatically if multiple servers given. - Removed REDIS_CLUSTER option. Closes #1283 --- .env.example.complete | 6 ++++++ config/database.php | 36 ++++++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/.env.example.complete b/.env.example.complete index 8851bd268..77a0508dc 100644 --- a/.env.example.complete +++ b/.env.example.complete @@ -75,6 +75,12 @@ CACHE_PREFIX=bookstack # For multiple servers separate with a comma MEMCACHED_SERVERS=127.0.0.1:11211:100 +# Redis server configuration +# This follows the following format: HOST:PORT:DATABASE +# or, if using a password: HOST:PORT:DATABASE:PASSWORD +# For multiple servers separate with a comma. These will be clustered. +REDIS_SERVERS=127.0.0.1:6379:0 + # Queue driver to use # Queue not really currently used but may be configurable in the future. # Would advise not to change this for now. diff --git a/config/database.php b/config/database.php index 6ca902944..93a44854f 100644 --- a/config/database.php +++ b/config/database.php @@ -8,23 +8,39 @@ * Do not edit this file unless you're happy to maintain any changes yourself. */ -// REDIS - Split out configuration into an array +// REDIS +// Split out configuration into an array if (env('REDIS_SERVERS', false)) { - $redisServerKeys = ['host', 'port', 'database']; + + $redisDefaults = ['host' => '127.0.0.1', 'port' => '6379', 'database' => '0', 'password' => null]; $redisServers = explode(',', trim(env('REDIS_SERVERS', '127.0.0.1:6379:0'), ',')); - $redisConfig = [ - 'cluster' => env('REDIS_CLUSTER', false) - ]; + $redisConfig = []; + $cluster = count($redisServers) > 1; + + if ($cluster) { + $redisConfig['clusters'] = ['default' => []]; + } + foreach ($redisServers as $index => $redisServer) { - $redisServerName = ($index === 0) ? 'default' : 'redis-server-' . $index; $redisServerDetails = explode(':', $redisServer); - if (count($redisServerDetails) < 2) $redisServerDetails[] = '6379'; - if (count($redisServerDetails) < 3) $redisServerDetails[] = '0'; - $redisConfig[$redisServerName] = array_combine($redisServerKeys, $redisServerDetails); + + $serverConfig = []; + $configIndex = 0; + foreach ($redisDefaults as $configKey => $configDefault) { + $serverConfig[$configKey] = ($redisServerDetails[$configIndex] ?? $configDefault); + $configIndex++; + } + + if ($cluster) { + $redisConfig['clusters']['default'][] = $serverConfig; + } else { + $redisConfig['default'] = $serverConfig; + } } } -// MYSQL - Split out port from host if set +// MYSQL +// Split out port from host if set $mysql_host = env('DB_HOST', 'localhost'); $mysql_host_exploded = explode(':', $mysql_host); $mysql_port = env('DB_PORT', 3306);