Compare commits

...

1666 Commits

Author SHA1 Message Date
Dan Brown
9b226e7d39 Updated version and assets for release v21.08 2021-08-31 22:07:53 +01:00
Dan Brown
9865446267 Merge branch 'master' into release 2021-08-31 22:07:23 +01:00
Dan Brown
173f728e4a Updated translator attribution before release v21.08 2021-08-31 22:05:16 +01:00
Dan Brown
9772b2f69d Applied stylci changes 2021-08-31 22:03:51 +01:00
Dan Brown
c0f4cf4b5c Merge branch 'master' of github.com:BookStackApp/BookStack 2021-08-31 21:59:37 +01:00
Dan Brown
cc1f46cbf4 New Crowdin updates (#2893)
* New translations settings.php (Chinese Traditional)

* New translations settings.php (Indonesian)

* New translations settings.php (Swedish)

* New translations settings.php (Turkish)

* New translations settings.php (Ukrainian)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Vietnamese)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Persian)

* New translations settings.php (Slovak)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Croatian)

* New translations settings.php (Latvian)

* New translations settings.php (Bosnian)

* New translations settings.php (Norwegian Bokmal)

* New translations settings.php (German Informal)

* New translations settings.php (Slovenian)

* New translations settings.php (Russian)

* New translations settings.php (French)

* New translations settings.php (German)

* New translations settings.php (Spanish)

* New translations settings.php (Arabic)

* New translations settings.php (Bulgarian)

* New translations settings.php (Catalan)

* New translations settings.php (Czech)

* New translations settings.php (Danish)

* New translations settings.php (Hebrew)

* New translations settings.php (Portuguese)

* New translations settings.php (Hungarian)

* New translations settings.php (Italian)

* New translations settings.php (Japanese)

* New translations settings.php (Korean)

* New translations settings.php (Dutch)

* New translations settings.php (Polish)

* New translations settings.php (Lithuanian)

* New translations activities.php (German)

* New translations auth.php (German)

* New translations common.php (German)

* New translations settings.php (German)

* New translations validation.php (German)

* New translations settings.php (French)

* New translations validation.php (French)

* New translations activities.php (French)

* New translations auth.php (French)

* New translations common.php (French)

* New translations activities.php (Norwegian Bokmal)

* New translations auth.php (Norwegian Bokmal)

* New translations auth.php (Norwegian Bokmal)

* New translations common.php (Norwegian Bokmal)

* New translations settings.php (Norwegian Bokmal)

* New translations validation.php (Norwegian Bokmal)

* New translations auth.php (French)

* New translations entities.php (Chinese Traditional)

* New translations entities.php (Indonesian)

* New translations entities.php (Swedish)

* New translations entities.php (Turkish)

* New translations entities.php (Ukrainian)

* New translations entities.php (Chinese Simplified)

* New translations entities.php (Vietnamese)

* New translations entities.php (Portuguese, Brazilian)

* New translations entities.php (Persian)

* New translations entities.php (Slovak)

* New translations entities.php (Spanish, Argentina)

* New translations entities.php (Croatian)

* New translations entities.php (Latvian)

* New translations entities.php (Bosnian)

* New translations entities.php (Norwegian Bokmal)

* New translations entities.php (German Informal)

* New translations entities.php (Slovenian)

* New translations entities.php (Russian)

* New translations entities.php (French)

* New translations entities.php (German)

* New translations entities.php (Spanish)

* New translations entities.php (Arabic)

* New translations entities.php (Bulgarian)

* New translations entities.php (Catalan)

* New translations entities.php (Czech)

* New translations entities.php (Danish)

* New translations entities.php (Hebrew)

* New translations entities.php (Portuguese)

* New translations entities.php (Hungarian)

* New translations entities.php (Italian)

* New translations entities.php (Japanese)

* New translations entities.php (Korean)

* New translations entities.php (Dutch)

* New translations entities.php (Polish)

* New translations entities.php (Lithuanian)

* New translations entities.php (Spanish)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Indonesian)

* New translations settings.php (Swedish)

* New translations settings.php (Turkish)

* New translations settings.php (Ukrainian)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Vietnamese)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Persian)

* New translations settings.php (Slovak)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Croatian)

* New translations settings.php (Latvian)

* New translations settings.php (Bosnian)

* New translations settings.php (Norwegian Bokmal)

* New translations settings.php (German Informal)

* New translations settings.php (Slovenian)

* New translations settings.php (Russian)

* New translations settings.php (French)

* New translations settings.php (German)

* New translations settings.php (Spanish)

* New translations settings.php (Arabic)

* New translations settings.php (Bulgarian)

* New translations settings.php (Catalan)

* New translations settings.php (Czech)

* New translations settings.php (Danish)

* New translations settings.php (Hebrew)

* New translations settings.php (Portuguese)

* New translations settings.php (Hungarian)

* New translations settings.php (Italian)

* New translations settings.php (Japanese)

* New translations settings.php (Korean)

* New translations settings.php (Dutch)

* New translations settings.php (Polish)

* New translations settings.php (Lithuanian)

* New translations settings.php (Spanish)

* New translations activities.php (Persian)

* New translations auth.php (Persian)

* New translations activities.php (Chinese Simplified)

* New translations auth.php (Chinese Simplified)

* New translations activities.php (Chinese Simplified)

* New translations auth.php (Chinese Simplified)

* New translations common.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations validation.php (Chinese Simplified)

* New translations entities.php (Chinese Simplified)
2021-08-31 21:59:26 +01:00
Dan Brown
a641b4da2c Swapped injected db instance with facade
Injected db instance was causing the DB connection to be
made a lot earlier than desired or required.
Swapped to a facade for now but ideally this extension of services needs
to be cleaned up with a better approach in general.
2021-08-31 21:50:23 +01:00
Dan Brown
4f85ce02c6 Updated php deps again 2021-08-31 20:56:07 +01:00
Dan Brown
9eb65dcd78 Updated the login redirect logic to ignore mfa routes 2021-08-31 20:54:43 +01:00
Dan Brown
bee5e2c7ca Added untrusted server fetching control
WKHTMLtoPDF provides limited control for external fetching
so that will now be disabled by default unless
ALLOW_UNTRUSTED_SERVER_FETCHING=true is specifically set.
This new option will also control DOMPDF fetching.
2021-08-31 20:22:42 +01:00
Dan Brown
8f12c8bc99 Applied styleci changes 2021-08-30 21:32:07 +01:00
Dan Brown
2740603d99 Added back email confirmation check in middleware
During writing of the update notes, found that the upgrade path would be
tricky from a security point of view. If people were pending email
confirmation but had an active session, they could technically be
actively logged in after the next release.

Added middlware as an extra precaution for now.
2021-08-30 21:28:17 +01:00
Dan Brown
3e870c30e1 Updated php deps 2021-08-30 12:03:52 +01:00
Dan Brown
8f0d08763a Merge pull request #2899 from BookStackApp/export_permissions
Added role permissions for exporting content
2021-08-28 21:57:11 +01:00
Dan Brown
0e7166f7f6 Cleaned up DB usage in migration 2021-08-28 21:55:04 +01:00
Dan Brown
7d9de23a25 Applied styleci patches 2021-08-28 21:51:15 +01:00
Dan Brown
eda9e89c55 Added role permissions for exporting content 2021-08-28 21:48:17 +01:00
Dan Brown
82c6597a60 Added notice for lack of shelf permission cascade
Closes #2876
2021-08-28 15:44:44 +01:00
Dan Brown
cd35e13024 Added styleci badge 2021-08-24 21:27:21 +01:00
Dan Brown
4400ad7e8d Applied stylci advisories 2021-08-24 21:23:55 +01:00
Dan Brown
610ee2c182 Updated markdown task list test to check new list class
- Updated to align with custom list item render added yesterday.
2021-08-24 21:09:40 +01:00
Dan Brown
4fd5dbcfdd Updated visual consistency of lists and markdown task list rendering
- Numbered and bullet list margins have been made consistent
   - Numbered lists margins were increase at some point to handle 3-digit
  numbers, Normal bullet margins updated to match this.
- Consistent margin for sub-lists.
- System back-end markdown renderer (For pages) updated with a custom
  list item renderer to apply class for to align with front-end renderer.
   - This means that task list items will be consistent with the preview
     and not render a number/bullet.
- Indentation styles for task list items fixed to be visually indented.

For #2854 and #2837
2021-08-23 22:31:07 +01:00
Dan Brown
613228fab2 Fixed issues caused by flex content parent in markdown preview
Fixes #2858
2021-08-22 18:30:46 +01:00
Dan Brown
a61c9c5e98 Reorgranised blade view files to form a convention
- Primarily moved and re-organised view files.
- Included readme within views to document the convention.
- Fixed some issues with page field select list in previous commit.
- Tweaked some route names while going through.
- Split some views out further.

Closes #2805
2021-08-22 13:17:32 +01:00
Dan Brown
2036618fbd Merge branch 'master' of github.com:BookStackApp/BookStack 2021-08-21 20:25:22 +01:00
Dan Brown
ce6e25b341 Added lithuanian option to locale system 2021-08-21 20:24:58 +01:00
Dan Brown
73ebe571a1 New Crowdin updates (#2892)
* New translations entities.php (Spanish, Argentina)

* New translations entities.php (German Informal)

* New translations activities.php (Lithuanian)

* New translations settings.php (Lithuanian)

* New translations passwords.php (Lithuanian)

* New translations errors.php (Lithuanian)

* New translations entities.php (Lithuanian)

* New translations common.php (Lithuanian)

* New translations auth.php (Lithuanian)

* New translations validation.php (Spanish, Argentina)

* New translations settings.php (Spanish, Argentina)

* New translations common.php (Spanish, Argentina)

* New translations auth.php (Spanish, Argentina)

* New translations activities.php (Spanish, Argentina)

* New translations validation.php (Lithuanian)
2021-08-21 20:24:31 +01:00
Dan Brown
a274406038 Merge pull request #2868 from ffranchina/master
Adding Lithuanian language
2021-08-21 20:05:35 +01:00
Dan Brown
1a6293ce24 Optimized loading of page/chapter URLs to be a little more efficient
- Loaded book_slug as part of chapter/page queries instead of books
 being loaded in afterwards.
- Removed unused page method.
- Updated some page queries to load specific attributes.
2021-08-21 19:59:55 +01:00
Dan Brown
8db047de70 New Crowdin updates (#2807)
* New translations entities.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations common.php (Chinese Simplified)

* New translations entities.php (Chinese Simplified)

* New translations settings.php (Portuguese)

* New translations activities.php (Portuguese)

* New translations common.php (Portuguese)

* New translations entities.php (Portuguese)

* New translations settings.php (French)

* New translations entities.php (Latvian)

* New translations common.php (Latvian)

* New translations common.php (Italian)

* New translations settings.php (Italian)

* New translations entities.php (Italian)

* New translations entities.php (German)

* New translations entities.php (Dutch)

* New translations settings.php (German)

* New translations settings.php (Dutch)

* New translations common.php (German)

* New translations common.php (Dutch)

* New translations settings.php (Italian)

* New translations activities.php (Persian)

* New translations activities.php (Persian)

* New translations auth.php (Persian)

* New translations auth.php (Persian)

* New translations validation.php (Persian)

* New translations validation.php (Persian)

* New translations common.php (Persian)

* New translations pagination.php (Persian)

* New translations passwords.php (Persian)

* New translations common.php (Persian)

* New translations components.php (Persian)

* New translations errors.php (Persian)

* New translations errors.php (Persian)

* New translations entities.php (Persian)

* New translations activities.php (Norwegian Bokmal)

* New translations common.php (Norwegian Bokmal)

* New translations entities.php (Norwegian Bokmal)

* New translations errors.php (Norwegian Bokmal)

* New translations settings.php (Norwegian Bokmal)

* New translations settings.php (Norwegian Bokmal)

* New translations activities.php (Polish)

* New translations common.php (Polish)

* New translations errors.php (Polish)

* New translations settings.php (Polish)

* New translations activities.php (Czech)

* New translations activities.php (Czech)

* New translations auth.php (Czech)

* New translations common.php (Czech)

* New translations entities.php (Czech)

* New translations errors.php (Czech)

* New translations passwords.php (Czech)

* New translations auth.php (Czech)

* New translations entities.php (Czech)

* New translations settings.php (Czech)

* New translations validation.php (Czech)

* New translations auth.php (Czech)

* New translations auth.php (Czech)

* New translations entities.php (Czech)

* New translations settings.php (Czech)

* New translations components.php (Czech)

* New translations activities.php (Czech)

* New translations activities.php (Indonesian)

* New translations entities.php (Indonesian)

* New translations settings.php (Indonesian)

* New translations errors.php (Vietnamese)

* New translations common.php (Vietnamese)

* New translations activities.php (Chinese Traditional)

* New translations common.php (Chinese Traditional)

* New translations entities.php (Chinese Traditional)

* New translations errors.php (Chinese Traditional)

* New translations errors.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations common.php (Portuguese, Brazilian)

* New translations common.php (Portuguese, Brazilian)

* New translations activities.php (Chinese Traditional)

* New translations common.php (Chinese Simplified)

* New translations activities.php (Ukrainian)

* New translations auth.php (Ukrainian)

* New translations common.php (Ukrainian)

* New translations settings.php (Ukrainian)

* New translations validation.php (Ukrainian)

* New translations activities.php (Chinese Simplified)

* New translations auth.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Turkish)

* New translations validation.php (Chinese Simplified)

* New translations auth.php (Chinese Traditional)

* New translations validation.php (Chinese Traditional)

* New translations activities.php (Vietnamese)

* New translations auth.php (Vietnamese)

* New translations common.php (Vietnamese)

* New translations settings.php (Vietnamese)

* New translations validation.php (Vietnamese)

* New translations validation.php (Turkish)

* New translations common.php (Turkish)

* New translations auth.php (Portuguese, Brazilian)

* New translations auth.php (Slovenian)

* New translations validation.php (Russian)

* New translations activities.php (Slovak)

* New translations auth.php (Slovak)

* New translations common.php (Slovak)

* New translations settings.php (Slovak)

* New translations validation.php (Slovak)

* New translations activities.php (Slovenian)

* New translations common.php (Slovenian)

* New translations auth.php (Turkish)

* New translations settings.php (Slovenian)

* New translations validation.php (Slovenian)

* New translations activities.php (Swedish)

* New translations auth.php (Swedish)

* New translations common.php (Swedish)

* New translations settings.php (Swedish)

* New translations validation.php (Swedish)

* New translations activities.php (Turkish)

* New translations activities.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese, Brazilian)

* New translations common.php (Russian)

* New translations validation.php (Bosnian)

* New translations common.php (Latvian)

* New translations settings.php (Latvian)

* New translations validation.php (Latvian)

* New translations activities.php (Bosnian)

* New translations auth.php (Bosnian)

* New translations common.php (Bosnian)

* New translations settings.php (Bosnian)

* New translations activities.php (Norwegian Bokmal)

* New translations activities.php (Latvian)

* New translations auth.php (Norwegian Bokmal)

* New translations common.php (Norwegian Bokmal)

* New translations settings.php (Norwegian Bokmal)

* New translations validation.php (Norwegian Bokmal)

* New translations activities.php (German Informal)

* New translations auth.php (German Informal)

* New translations common.php (German Informal)

* New translations settings.php (German Informal)

* New translations auth.php (Latvian)

* New translations validation.php (Croatian)

* New translations validation.php (Portuguese, Brazilian)

* New translations settings.php (Persian)

* New translations activities.php (Indonesian)

* New translations auth.php (Indonesian)

* New translations common.php (Indonesian)

* New translations settings.php (Indonesian)

* New translations validation.php (Indonesian)

* New translations activities.php (Persian)

* New translations auth.php (Persian)

* New translations common.php (Persian)

* New translations validation.php (Persian)

* New translations settings.php (Croatian)

* New translations activities.php (Spanish, Argentina)

* New translations auth.php (Spanish, Argentina)

* New translations common.php (Spanish, Argentina)

* New translations settings.php (Spanish, Argentina)

* New translations validation.php (Spanish, Argentina)

* New translations activities.php (Croatian)

* New translations auth.php (Croatian)

* New translations common.php (Croatian)

* New translations settings.php (Russian)

* New translations auth.php (Russian)

* New translations common.php (Chinese Traditional)

* New translations common.php (Czech)

* New translations validation.php (Bulgarian)

* New translations activities.php (Catalan)

* New translations auth.php (Catalan)

* New translations common.php (Catalan)

* New translations settings.php (Catalan)

* New translations validation.php (Catalan)

* New translations auth.php (Czech)

* New translations settings.php (Czech)

* New translations common.php (Bulgarian)

* New translations validation.php (Czech)

* New translations activities.php (Danish)

* New translations auth.php (Danish)

* New translations common.php (Danish)

* New translations settings.php (Danish)

* New translations validation.php (Danish)

* New translations activities.php (German)

* New translations auth.php (German)

* New translations settings.php (Bulgarian)

* New translations auth.php (Bulgarian)

* New translations settings.php (German)

* New translations activities.php (Spanish)

* New translations settings.php (Chinese Traditional)

* New translations common.php (Portuguese, Brazilian)

* New translations activities.php (Czech)

* New translations activities.php (French)

* New translations auth.php (French)

* New translations common.php (French)

* New translations settings.php (French)

* New translations validation.php (French)

* New translations auth.php (Spanish)

* New translations activities.php (Bulgarian)

* New translations common.php (Spanish)

* New translations settings.php (Spanish)

* New translations validation.php (Spanish)

* New translations activities.php (Arabic)

* New translations auth.php (Arabic)

* New translations common.php (Arabic)

* New translations settings.php (Arabic)

* New translations validation.php (Arabic)

* New translations common.php (German)

* New translations validation.php (German)

* New translations activities.php (Russian)

* New translations activities.php (Polish)

* New translations settings.php (Korean)

* New translations validation.php (Korean)

* New translations activities.php (Dutch)

* New translations auth.php (Dutch)

* New translations common.php (Dutch)

* New translations settings.php (Dutch)

* New translations validation.php (Dutch)

* New translations auth.php (Polish)

* New translations auth.php (Korean)

* New translations common.php (Polish)

* New translations settings.php (Polish)

* New translations validation.php (Polish)

* New translations activities.php (Portuguese)

* New translations auth.php (Portuguese)

* New translations common.php (Portuguese)

* New translations settings.php (Portuguese)

* New translations validation.php (Portuguese)

* New translations common.php (Korean)

* New translations activities.php (Korean)

* New translations activities.php (Hebrew)

* New translations validation.php (Hungarian)

* New translations auth.php (Hebrew)

* New translations common.php (Hebrew)

* New translations settings.php (Hebrew)

* New translations validation.php (Hebrew)

* New translations activities.php (Hungarian)

* New translations auth.php (Hungarian)

* New translations common.php (Hungarian)

* New translations settings.php (Hungarian)

* New translations activities.php (Italian)

* New translations validation.php (Japanese)

* New translations auth.php (Italian)

* New translations common.php (Italian)

* New translations settings.php (Italian)

* New translations validation.php (Italian)

* New translations activities.php (Japanese)

* New translations auth.php (Japanese)

* New translations common.php (Japanese)

* New translations settings.php (Japanese)

* New translations validation.php (German Informal)

* New translations activities.php (Spanish)

* New translations auth.php (Spanish)

* New translations common.php (Spanish)

* New translations settings.php (Spanish)

* New translations validation.php (Spanish)
2021-08-21 18:57:32 +01:00
Dan Brown
b005acdd6c Updated pages API to not clear content if not provided
Can now update page details without supplying page content.
Added test to cover.

Closes #2856
2021-08-21 18:54:38 +01:00
Dan Brown
822fea4303 Updated js dependancies 2021-08-21 15:53:45 +01:00
Dan Brown
ac110eb6b2 Merge pull request #2890 from BookStackApp/analysis-kabPRy
Apply fixes from StyleCI
2021-08-21 15:50:16 +01:00
Dan Brown
64785ed9da Apply fixes from StyleCI 2021-08-21 14:49:40 +00:00
Dan Brown
cac31b2074 Merge pull request #2827 from BookStackApp/mfa
MFA System
2021-08-21 15:47:55 +01:00
Dan Brown
2d306949b5 Cleaned some unused elements during testing 2021-08-21 15:38:43 +01:00
Dan Brown
78e94bb003 Improved login redirect and setup experience
- Updated auth system for mfa to not update intended URL so that the
  user is not redirected to mfa setup after eventual login.
- Added notification for users setting up MFA, after setup when
  redirected back to login screen to advise that MFA setup was complete
  but they need to login again.
- Updated some bits of wording to display better.
2021-08-21 15:14:24 +01:00
Dan Brown
622ea03c65 Added attribution for new libs added
- Also hard-set TOTP algorithm with comment from testing others.
2021-08-08 14:52:29 +01:00
Dan Brown
f1f59cf086 Extracted text to translation files
Also aligned mfa method delete route to align with others.
2021-08-08 14:24:44 +01:00
Dan Brown
773be963ba Updated auth changes to work with remember me 2021-08-07 22:32:19 +01:00
Dan Brown
ef9354a0cb Verified mfa session expires on logout
Since sessions are invalidated upon logout.
2021-08-07 21:53:13 +01:00
Dan Brown
39a205ed28 Quick test of email confirmation routes and fix of tests 2021-08-07 21:18:59 +01:00
Dan Brown
70f39757b1 Updated API auth handling of email confirmations
Email confirmations are now done within the guard during auth checking
instead of at the middleware layer.
2021-08-05 22:07:08 +01:00
Dan Brown
c429cf7818 Merge branch 'v21.05.x' 2021-08-04 21:32:29 +01:00
Dan Brown
926abbe776 Updated version and assets for release v21.05.4 2021-08-04 21:29:10 +01:00
Dan Brown
4fabef3a57 Merge branch 'v21.05.x' into release 2021-08-04 21:28:45 +01:00
Dan Brown
65ebffa002 Updated when github actions run 2021-08-04 21:22:53 +01:00
Dan Brown
a04064f981 Updated php dependancies up minor versions 2021-08-04 21:10:55 +01:00
Dan Brown
7d19057e68 Fixed issue where user id still used on profile pages
Updated to use slugs and added testing to cover.
2021-08-04 21:08:51 +01:00
Dan Brown
0de0507137 Added vb.net code language option
Related to #2869
2021-08-04 20:56:34 +01:00
Dan Brown
7a8954ee65 Fixed audit log user dropdown usability issue
User search input blur would trigger the submission of the search
filters which would cause strange thing where you'd click on a search
filtered user which would blur the input hence submit, but the user
would think they've clicked the user and the page would reload but the
input had not updated at that point.

Related to #2863
2021-08-04 20:48:23 +01:00
Francesco Franchina
a3ad840bdd Adding Lithuanian language 2021-08-03 23:42:34 +02:00
Dan Brown
9b271e559f Worked on MFA setup required flow
- Restructured some of the route naming to be a little more consistent.
- Moved the routes about to be more logically in one place.
- Created a new middleware to handle the auth of people that should be
  allowed access to mfa setup routes, since these could be used by
  existing logged in users or by people needing to setup MFA on access.
- Added testing to cover MFA setup required flow.
- Added TTL and method tracking to session last-login tracking system.
2021-08-02 22:02:25 +01:00
Dan Brown
4597069083 Added Backup code verification logic
Also added testing to cover as part of this in addition to adding the
core backup code handling required.

Also added the standardised translations for switching mfa mode and
adding testing for this switching.
2021-08-02 16:35:37 +01:00
Dan Brown
a3f19ebe96 Added TOTP verification upon access 2021-08-02 15:04:43 +01:00
Dan Brown
1af5bbf3f7 Added login redirect system to confirm/mfa
Also continued a bit on the MFA verification system.
Moved some MFA routes to public space using updated login service to get
the current user that is either logged in or last attempted login (With
correct creds).
2021-07-18 16:52:31 +01:00
Dan Brown
1278fb4969 Started moving MFA and email confirmation to new login flow
Instead of being soley middleware based.
2021-07-17 18:24:50 +01:00
Dan Brown
9249addb5c Updated all login events to route through single service 2021-07-17 17:45:00 +01:00
Dan Brown
78f9c01519 Started on some MFA access-time checks
Discovered some difficult edge cases:
- User image loading in header bar when using local_secure storage
- 404s showing user-specific visible content due to content listing on
  404 page since user is in semi-logged in state. Maybe need to go
  through and change up how logins are handled to centralise and
  provide us better control at login time to prevent any auth level.
2021-07-16 23:23:36 +01:00
Dan Brown
f696aa5eea Added the ability to remove an MFA method
Includes testing to cover
2021-07-14 21:27:21 +01:00
Dan Brown
7c86c26cd0 Added command to reset user MFA
Includes tests to cover the command.
2021-07-14 20:50:36 +01:00
Dan Brown
cfc0c593db Added MFA indicator to user list
Also fixed issue with showing incorrect MFA method count on user edit
page changes done in last commit
2021-07-14 20:19:05 +01:00
Dan Brown
bb43acef21 Added MFA setup link on user edit view 2021-07-14 20:06:41 +01:00
Dan Brown
09c2814dc7 Added role based MFA control
- Added new DB column for control and role updated create/update actions.
- Created new middleware as a start to actual enforcement logic.
- Added indicator to role list of whether MFA is enforced.
2021-07-03 13:34:48 +01:00
Dan Brown
1c43602f4b Merge branch 'v21.05.x' 2021-07-03 12:02:13 +01:00
Dan Brown
5ef4cd80c3 Updated version and assets for release v21.05.3 2021-07-03 11:59:52 +01:00
Dan Brown
e01f23583f Merge branch 'v21.05.x' into release 2021-07-03 11:59:21 +01:00
Dan Brown
b1ee1a856f Updated php dependancies for minor release 2021-07-03 11:57:32 +01:00
Dan Brown
4da72aa267 Fixed issue with translation loading without theme
System was using the empty state return from theme_path,
when no theme was configured, for loading in languages
which would result in the root path being looked up upon.

This changes the theme_path helper to return null in cases a theme
is not configured instead of empty string to help prevent assumed
return path will be legitimate, and to help enforce error case
handling.

For #2836
2021-07-03 11:53:46 +01:00
Dan Brown
529971c534 Added backup code setup flow
- Includes testing to cover flow.
- Moved TOTP logic to its own controller.
- Added some extra totp tests.
2021-07-02 20:53:33 +01:00
Dan Brown
83c8f73142 Covered TOTP setup with testing 2021-07-02 19:51:30 +01:00
Dan Brown
916a82616f Complete base flow for TOTP setup
- Includes DB storage and code validation.
- Extracted TOTP work to its own service file.
- Still needs testing to cover this side of things.
2021-06-30 22:10:02 +01:00
Dan Brown
d25cd83d8e Added TOTP generation view and started verification stage
Also updated MFA setup view to have settings-like listed interface to
make it possible to extend with extra options in the future.
2021-06-29 22:06:49 +01:00
Dan Brown
efb6a6b457 Started barebones work of MFA system 2021-06-28 22:02:45 +01:00
Dan Brown
f295ab87b4 Updated comments of theme event to match usage 2021-06-28 21:17:10 +01:00
Dan Brown
ca8be9af3c Swapped PHPCS for StyleCI
Trying out StyleCI as an automated easy way to ensure code style is
consistent across the PHP codebase.
PHPCS+PHPCBF was good but I wouldn't run it enough then I'd get paranoid
about running it with pending PRs. Better to let the robots stay on top
of things.
2021-06-26 16:40:29 +01:00
Dan Brown
0155525945 Merge pull request #2820 from BookStackApp/analysis-6470L9
Apply fixes from StyleCI
2021-06-26 16:28:09 +01:00
Dan Brown
934a833818 Apply fixes from StyleCI 2021-06-26 15:23:15 +00:00
Dan Brown
3a402f6adc Review of #2682, Also added parent deletion link on restore
On restore, added a link to the parent deletion restore if any exists
on a cascading parent. Added a test to cover this case to ensure its shown.

Also tweaked default empty state message on recycle bin item list to align
with new column count.

Also done a little existing code cleanup including a getUrl helper on
the deletion items.

Related to #2682 & #2594
2021-06-26 12:12:11 +01:00
Dan Brown
8a9505bf8c Merge branch 'master' of https://github.com/arjvand/BookStack into arjvand-master 2021-06-26 11:19:21 +01:00
Dan Brown
265f5db03f Reviewed #2393, Removed image guessing and added testing
For review of meta tag additions as per PR #2393.
This commit removes any image guesswork and only uses images that have
been set by the author for the specific content.
This also adds tests to cover the expected OG tags.
2021-06-23 20:42:48 +01:00
Dan Brown
58fa7679bc Merge branch 'create-content-meta-tags' of https://github.com/james-geiger/BookStack into james-geiger-create-content-meta-tags 2021-06-23 20:11:07 +01:00
Dan Brown
992f03a3c0 Added markdown export endpoints to API
- Added tests to cover.
- Added slight extra spaces at content joins.
2021-06-22 21:39:29 +01:00
Dan Brown
57ea2e92ec Updated markdown export implementation
- Removed ZIP system for now, until the idea can be fleshed out.
- Added testing to cover.
- Upgraded used library.
- Added custom handling for BookStack callouts.
- Added HTML cleanup to better produce output for things like code
  blocks.
2021-06-22 21:02:18 +01:00
Dan Brown
9af636bd48 Merge branch 'markdown-export' of https://github.com/nikhiljha/BookStack-1 into nikhiljha-markdown-export 2021-06-22 19:12:24 +01:00
Dan Brown
3dda622f0a Added a "skip to content" link.
Closes #2810
2021-06-15 20:58:45 +01:00
Dan Brown
7d951b842c Made social account detach a POST request
Closes #2808
2021-06-14 22:37:58 +01:00
Dan Brown
94bf5b8fbb Added test for social account detach 2021-06-14 22:30:53 +01:00
Dan Brown
7792cb3915 Updated version and assets for release v21.05.2 2021-06-13 14:26:34 +01:00
Dan Brown
be26253a18 Merge branch 'master' into release 2021-06-13 14:25:39 +01:00
Dan Brown
3d5899d28c Fixed issue with using old non-existing reference in controller
Also done a little code cleanup.
2021-06-13 14:16:09 +01:00
Dan Brown
917d7428d6 Updated composer.lock 2021-06-13 14:06:56 +01:00
Dan Brown
bcc01bd8ff New Crowdin updates (#2790)
* New translations common.php (Indonesian)

* New translations entities.php (Indonesian)

* New translations errors.php (Indonesian)

* New translations auth.php (Chinese Simplified)

* New translations auth.php (Chinese Simplified)

* New translations errors.php (Indonesian)

* New translations entities.php (Indonesian)

* New translations errors.php (Indonesian)

* New translations settings.php (Indonesian)

* New translations validation.php (Indonesian)

* New translations settings.php (Spanish, Argentina)
2021-06-13 14:04:23 +01:00
Dan Brown
2c34a99248 Merge pull request #2791 from BookStackApp/attachments_open_in_browser
Attachment serving without forced download
2021-06-13 14:03:08 +01:00
Dan Brown
789d17ab3f Updated platform deps and development version number 2021-06-13 13:57:29 +01:00
Dan Brown
58117bcf2d Extracted not found text into its own simple blade file
Related/intended for #2796
2021-06-13 13:53:59 +01:00
Dan Brown
b5caaa73b7 Fixed content parsing break with line html comment
Fixes issues thrown in custom HMTL head & page content filtering when
the content is comprised of only a single HTML comment.
Adds tests to cover.

For #2804
2021-06-13 12:53:04 +01:00
Dan Brown
7997300f96 Added front-end toggle and testing of inline attachments 2021-06-06 13:55:56 +01:00
Dan Brown
888f435651 Added back-end attachments-in-browser support
A query string will cause attachments to be provided inline
with an appropriate mime type.
Remaining actions:
- Tests
- Front-end functionality
- Config option?
2021-06-06 00:51:06 +01:00
Dan Brown
1bdd1f8189 Updated version for release v21.05.1 2021-06-04 23:09:42 +01:00
Dan Brown
fa62c79b17 Merge branch 'master' into release 2021-06-04 23:08:59 +01:00
Dan Brown
a8471b2c66 Updated translator attribution before release v21.05.1 2021-06-04 23:08:43 +01:00
Dan Brown
0627efe5e9 Updated base64 image extraction to use url instead of path
To ensure it works with all storage types and follows the format of
manually uploaded image content
2021-06-04 22:59:31 +01:00
Dan Brown
af7d62799c New Crowdin updates (#2787)
* New translations common.php (German)

* New translations common.php (Dutch)
2021-06-04 22:50:48 +01:00
Dan Brown
bb00c331e4 Ordered entity permission roles by display name
Closes #2782
2021-06-04 22:36:30 +01:00
Dan Brown
807f92b693 Updated homepage action button colors for consistency
Were previously inconsistent with other homepage buttons for non-default
homepage options.
2021-06-04 22:28:38 +01:00
Dan Brown
c5d31ea7b2 Merge branch 'master' of github.com:BookStackApp/BookStack 2021-06-04 22:21:06 +01:00
Dan Brown
ef1bde8bb1 Fixed wrong styles for homepage favourites
When using a non-default homepage option.

Fixes #2783
2021-06-04 22:20:11 +01:00
Dan Brown
8897945609 Roll-out and re-fix of croation via crowdin (#2785)
* New translations auth.php (Croatian)

* New translations activities.php (Croatian)

* New translations activities.php (German Informal)

* New translations common.php (Croatian)

* New translations passwords.php (Croatian)

* New translations settings.php (Czech)

* New translations settings.php (Spanish)

* New translations settings.php (Catalan)

* New translations settings.php (Arabic)

* New translations settings.php (French)

* New translations pagination.php (Croatian)

* New translations settings.php (German)

* New translations settings.php (Danish)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Hebrew)

* New translations validation.php (Korean)

* New translations validation.php (Croatian)

* New translations settings.php (Hungarian)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Japanese)

* New translations settings.php (Korean)

* New translations settings.php (Dutch)

* New translations settings.php (Polish)

* New translations settings.php (Portuguese)

* New translations settings.php (Russian)

* New translations settings.php (Slovak)

* New translations settings.php (Slovenian)

* New translations settings.php (Turkish)

* New translations settings.php (Ukrainian)

* New translations settings.php (Vietnamese)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Indonesian)

* New translations settings.php (Persian)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Croatian)

* New translations settings.php (Latvian)

* New translations settings.php (Bosnian)

* New translations settings.php (Norwegian Bokmal)

* New translations settings.php (German Informal)

* New translations entities.php (German Informal)

* New translations settings.php (Italian)

* New translations settings.php (Swedish)

* New translations settings.php (Bulgarian)

* New translations errors.php (German Informal)

* New translations errors.php (Croatian)

* New translations components.php (Croatian)

* New translations entities.php (Croatian)

* New translations pagination.php (Croatian)

* New translations entities.php (Croatian)

* New translations components.php (Croatian)

* New translations errors.php (Croatian)

* New translations settings.php (Croatian)

* New translations validation.php (Croatian)

* New translations passwords.php (Croatian)

* New translations auth.php (Croatian)

* New translations common.php (Croatian)

* New translations activities.php (Croatian)
2021-06-02 22:15:58 +01:00
Dan Brown
9382d647d7 Merge branch 'ffranchina-master' 2021-06-02 21:57:23 +01:00
Dan Brown
0d17d18d07 New Crowdin updates (#2777)
* New translations common.php (Latvian)

* New translations entities.php (Latvian)

* New translations activities.php (Italian)

* New translations common.php (Italian)

* New translations entities.php (Italian)

* New translations errors.php (Italian)

* New translations settings.php (Italian)

* New translations common.php (Spanish, Argentina)

* New translations entities.php (Spanish, Argentina)

* New translations activities.php (Spanish, Argentina)

* New translations common.php (Spanish, Argentina)

* New translations common.php (French)

* New translations common.php (Swedish)

* New translations activities.php (Swedish)

* New translations common.php (Swedish)

* New translations entities.php (Swedish)

* New translations errors.php (Swedish)

* New translations settings.php (Swedish)

* New translations validation.php (Bulgarian)

* New translations validation.php (Bulgarian)

* New translations common.php (Bulgarian)

* New translations validation.php (Bulgarian)

* New translations settings.php (Bulgarian)

* New translations activities.php (Indonesian)

* New translations settings.php (Bulgarian)

* New translations common.php (Bulgarian)

* New translations entities.php (Bulgarian)

* New translations activities.php (Turkish)

* New translations settings.php (Bulgarian)

* New translations components.php (Bulgarian)

* New translations activities.php (Russian)

* New translations common.php (Russian)

* New translations entities.php (Russian)

* New translations common.php (Russian)

* New translations entities.php (Russian)
2021-06-02 21:56:53 +01:00
Dan Brown
24eef03fb9 Added croatian to required arrays/lists 2021-06-02 21:55:30 +01:00
Dan Brown
e51352e1a4 Added back in commas, reset settings language array
Related to #2784
2021-06-02 21:50:38 +01:00
Dan Brown
2dfb1ae3ee Merge branch 'master' of https://github.com/ffranchina/BookStack into ffranchina-master 2021-06-02 21:44:39 +01:00
Dan Brown
39928e1c63 Reviewed base64 image upload support
- Added test cases to cover.
- Altered parsing logic to be a little less reliant on regex.
- Added new iamge repo method for creating from data.
- Added extension validation and additional type support.
- Done some cleanup of common operations within PageContent.
- Added message to API docs/method to mention image usage.

For #2700 and #2631.
2021-06-02 21:34:34 +01:00
Dan Brown
40ca50e44f Merge branch 'master' of https://github.com/awarre/BookStack into awarre-master 2021-06-02 20:25:20 +01:00
Francesco Franchina
fc7b8c49fb Adding Croatian translation files 2021-06-02 17:32:31 +02:00
Dan Brown
d7d8fa1e5b Updated version and assets for release v21.05 2021-05-30 16:17:56 +01:00
Dan Brown
18562f1e10 Merge branch 'master' into release 2021-05-30 16:17:44 +01:00
Dan Brown
fdabafffda Added thumbnail attribute to complete .env 2021-05-30 15:22:58 +01:00
Dan Brown
e2df15fe20 Updated translators before next release 2021-05-30 15:11:59 +01:00
Dan Brown
54bac17ef0 New Crowdin updates (#2764) 2021-05-30 15:10:11 +01:00
Dan Brown
7634ac4e12 Updated test to align with export date format change 2021-05-30 13:23:51 +01:00
Dan Brown
c4f5ab12cf Aligned export and revision shown date format
As raised in #2771
2021-05-30 00:02:32 +01:00
Dan Brown
57a063cdfb Updated nav tests to look for shortened item names 2021-05-29 23:46:33 +01:00
Dan Brown
1fa90e4f12 Converted another couple of tests from browserkit 2021-05-29 23:42:21 +01:00
Dan Brown
d62cdd58d3 Upgraded php and npm deps
- Sass upgrade had some breaking changes where division was used
hence updated for newer sass version support.
2021-05-29 13:08:28 +01:00
Dan Brown
ed6ec341df Added testing to cover next/previous navigation
For #2511
2021-05-29 12:49:10 +01:00
Dan Brown
0cfff6ab6f Reviewed and refactored next/previous navigation button implementation
- Updated styling to include item name.
- Extracted used text to translations.
- Updated the design to better suit the surrounding blocks.
- Removed newly added model/repo methods.
- Moved core logic out of controller and instead into a "NextPreviousContentLocator"
helper with re-uses the output from the book-tree generation.
- Also added the system to chapters.

For #2511
2021-05-29 12:39:41 +01:00
Dan Brown
7ca66c5d5e Merge branch 'prev-next-button' of https://github.com/shubhamosmosys/BookStack into shubhamosmosys-prev-next-button 2021-05-26 22:13:19 +01:00
Dan Brown
9cbea1eb08 Updated drawing upload error to shown/handle server limit errors
Closes #2740
2021-05-26 18:23:27 +01:00
Dan Brown
1a2d374f24 Revert "Added app logo to outgoing emails"
This reverts commit e32929029b.
2021-05-26 17:13:59 +01:00
Dan Brown
e32929029b Added app logo to outgoing emails
Required changing the header bar of the email to be solid color to match
the configuration of the main app header since otherwise colors may not
work together.

Closes #2577
2021-05-26 17:11:03 +01:00
Dan Brown
eb76e882c5 Added deletion of revisions on page delete
Added testing to cover.
Closes #2668
2021-05-26 16:40:56 +01:00
Dan Brown
d326417edc Added name input autofocus on shelves, books and chapters
Closes #1956
2021-05-26 15:25:23 +01:00
Dan Brown
a3a8fef6b2 Made users header interface more adaptable
Search input was stacking on create button on default desktop view
due when viewing in russian due to combined width exceeding container.
Made into normal flexbox instead.

Closes #2147
2021-05-26 15:20:35 +01:00
Dan Brown
0c16334426 Merge branch 'master' of github.com:BookStackApp/BookStack 2021-05-25 00:06:13 +01:00
Dan Brown
600f8cd142 Added origin verification to postMessage usage.
Closes #2769
2021-05-25 00:05:20 +01:00
Dan Brown
5c8c85a0ff Merge pull request #2768 from CorruptComputer/RSPEC-5148-Fixes
[sec] Fixes a few minor vulnerabilies when using target="_blank" on links (RSPEC-5148)
2021-05-24 22:11:49 +01:00
Nickolas Gupton
7a6f21648a Fixes minor vulnerability when using target="_blank" on links (RSPEC-5148) 2021-05-24 16:17:08 -04:00
Dan Brown
df0e03cd07 Reviewed PR to add import user avatars va LDAP
- Reduced options to single new configuration paramter instead of two.
- Moved more logic into UserAvatars class.
- Updated LDAP avatar import to also run on login when no image is
  currently set.
- Added thumbnail fetching to search requests.
- Added testing to cover.

Related to PR #2320, and issue #1161
2021-05-24 18:54:08 +01:00
Dan Brown
85db812fea Merge branch 'master' of https://github.com/jasonhoule/BookStack into jasonhoule-master 2021-05-24 17:06:50 +01:00
Dan Brown
fb5b5e138d Updated existing tag tests away from browserkit testing 2021-05-24 16:16:58 +01:00
Dan Brown
3eaf03a7ac Reviewed tag in seach work
- Refactored some tag code bits while reviewing.
- Updated tag design in search listing to be more subtle.
- Moved tags out of entity-list-item-basic template and instead moved
  them into entity-list-item, below the existing content.
- Tweaked existing tag colors a little.
- Changed tag icon to be more tag-like.
- Added tag-on-search test case.

Review of #2487, Related to #2462
2021-05-24 16:12:09 +01:00
Dan Brown
5420f3451c Merge branch 'show-tags' of https://github.com/burnoutberni/BookStack into burnoutberni-show-tags 2021-05-24 15:12:45 +01:00
Dan Brown
7d94da10fb Merge branch 'v21.04.x' 2021-05-24 13:08:51 +01:00
Dan Brown
86090a694f Updated version and assets for release v21.04.6 2021-05-24 13:06:03 +01:00
Dan Brown
1ee8287c73 Merge branch 'v21.04.x' into release 2021-05-24 13:05:34 +01:00
Dan Brown
c7322a71f7 Added theme add social driver redirect configuration callback
Allows someone using the theme system to configure the social driver
before a redirect action occurs, by passing a callback as an additional
param to the theme 'addSocialDriver' method.
2021-05-24 12:55:45 +01:00
Dan Brown
2c3523f6a1 Updated image permission setting logic
To ensure thhat the visibility is still set on local storage options
since the previous recent changes could cause problems where in
scenarios where the server user could not read images uploaded by the
php process user.

Closes #2758
2021-05-24 12:09:28 +01:00
Dan Brown
dd6076049c Merge pull request #2748 from BookStackApp/favourite_system
Favourite System
2021-05-23 14:45:42 +01:00
Dan Brown
ba8ba5c634 Added testing to favourite system
- Also removed some old view service references.
- Updated TopFavourites query to be based on favourites table and join
  in the views instead of the other way around, so that favourites still
show even if they have no views.
2021-05-23 14:34:36 +01:00
Dan Brown
c2069f37cc Added deletion of favourites on entity/user delete 2021-05-23 13:41:56 +01:00
Dan Brown
1e0aa7ee2c Added favourites page with link from header and home 2021-05-23 13:34:08 +01:00
Dan Brown
27942f5ce8 Deleted redundant complex relationmultimodel query class 2021-05-22 14:07:57 +01:00
Dan Brown
d0ff79ea60 Revamped some complex queries, added favourites to home
- Removed old view system and started use of new query classes instead.
- Finished off RelationMultiModelQuery but found it was less efficient
than x-many queries due to the amount of tables being scanned.
Adding now for history but will delete as not used.
- Updated recently viewed to use same query system as popular items
  rather than running and joining x-entities queries.
- Added "Most Viewed Faviourites" listing to homepages.
2021-05-22 14:05:28 +01:00
Dan Brown
3de02566bf Started building system for cross-model queries 2021-05-19 23:37:23 +01:00
Dan Brown
93fd869ba3 Started refactoring of view service
Phasing out the view service from being a generic 'service' class,
moving the core create/delete methods into the model.
The idea is that the existing query work will need to interlink
with the favourite system so maybe we have a (or many composable)
query building classes rather than mixing query building and
create/delete work as per the old service.
2021-05-16 10:49:37 +01:00
Dan Brown
3ca149137e Added faviourtes to other entity types 2021-05-16 10:26:28 +01:00
Dan Brown
db9aa41096 Started writing testing for favourites 2021-05-16 01:07:20 +01:00
Dan Brown
bf8e7f3393 Started addition of favourite system 2021-05-16 00:29:56 +01:00
Dan Brown
8eb98cd591 Updated version and assets for release v21.04.5 2021-05-15 17:56:29 +01:00
Dan Brown
0f9ba21b05 Merge branch 'v21.04.x' into release 2021-05-15 17:56:03 +01:00
Dan Brown
7a059a5e90 Updated translator attribution before release v21.04.5 2021-05-15 17:54:57 +01:00
Dan Brown
e5fc104aff New Crowdin updates (#2737)
* New translations errors.php (Italian)

* New translations errors.php (Slovak)

* New translations errors.php (Norwegian Bokmal)

* New translations errors.php (Bosnian)

* New translations errors.php (Latvian)

* New translations errors.php (Spanish, Argentina)

* New translations errors.php (Persian)

* New translations errors.php (Indonesian)

* New translations errors.php (Portuguese, Brazilian)

* New translations errors.php (Vietnamese)

* New translations errors.php (Chinese Traditional)

* New translations errors.php (Chinese Simplified)

* New translations errors.php (Ukrainian)

* New translations errors.php (Turkish)

* New translations errors.php (Swedish)

* New translations errors.php (Slovenian)

* New translations errors.php (Russian)

* New translations errors.php (French)

* New translations errors.php (Portuguese)

* New translations errors.php (Polish)

* New translations errors.php (Dutch)

* New translations errors.php (Korean)

* New translations errors.php (Japanese)

* New translations errors.php (Hungarian)

* New translations errors.php (Hebrew)

* New translations errors.php (German)

* New translations errors.php (Danish)

* New translations errors.php (Czech)

* New translations errors.php (Catalan)

* New translations errors.php (Bulgarian)

* New translations errors.php (Arabic)

* New translations errors.php (Spanish)

* New translations errors.php (German Informal)

* New translations errors.php (Chinese Simplified)

* New translations errors.php (French)

* New translations common.php (French)

* New translations errors.php (Spanish, Argentina)

* New translations common.php (Spanish, Argentina)

* New translations entities.php (Spanish, Argentina)

* New translations activities.php (Arabic)

* New translations auth.php (Arabic)

* New translations entities.php (Arabic)

* New translations auth.php (Arabic)

* New translations components.php (Arabic)

* New translations entities.php (Arabic)

* New translations errors.php (Russian)

* New translations common.php (Portuguese)

* New translations errors.php (Portuguese)
2021-05-15 17:50:02 +01:00
Dan Brown
d0ed165630 Merge pull request #2735 from dopyrory3/table_column_fix
Fix table width styling on pages rendered in markdown
2021-05-15 17:48:27 +01:00
Dan Brown
68ef6a842f Fixed issue thrown upon empty markdown content save
Closes #2741
2021-05-15 17:33:53 +01:00
Dan Brown
c1f070a136 Handle acl set of images differently for s3 and s3-like
Related to #2739
2021-05-15 17:25:51 +01:00
Dan Brown
c2cc1ec5e5 Adjusted dompdf font path to writable folder
Related to #2746
2021-05-15 12:19:36 +01:00
Rory Maher
386925ad8e Apply column fix to all tables 2021-05-10 12:11:28 +01:00
Rory Maher
243c1db408 Revert "Fix table width style"
This reverts commit b010d2663d.
2021-05-10 12:10:02 +01:00
Dan Brown
834f8e7046 Updated version and assets for release v21.04.4 2021-05-09 14:46:05 +01:00
Dan Brown
32e3399334 Merge branch 'master' into release 2021-05-09 14:45:36 +01:00
Dan Brown
9e7bcacf8c Moved NotifyException render work from handler to exception
As continued from last commit.
2021-05-08 19:00:09 +01:00
Dan Brown
7be7d7d1e7 Updated not-found image path handling to have better ux
Added test to cover.
Started refactoring some of the app error handling in
the process of this.

Fixes #2696
2021-05-08 18:49:58 +01:00
Dan Brown
04c1d0e071 Updated translators before v21.04.4 release 2021-05-08 17:56:35 +01:00
Dan Brown
ab62e0f75b Merge pull request #2716 from Jokuna/master
Update Korean translation
2021-05-08 17:53:02 +01:00
Dan Brown
d85f99c87c New Crowdin updates (#2719)
* New translations entities.php (Dutch)

* New translations components.php (Italian)

* New translations entities.php (Italian)

* New translations entities.php (Italian)

* New translations errors.php (Italian)

* New translations passwords.php (Italian)

* New translations settings.php (Italian)

* New translations validation.php (Italian)

* New translations settings.php (Italian)

* New translations settings.php (Italian)

* New translations common.php (Indonesian)

* New translations settings.php (Italian)

* New translations settings.php (Italian)

* New translations settings.php (Italian)

* New translations settings.php (Italian)

* New translations settings.php (Italian)

* New translations common.php (Portuguese)

* New translations common.php (Arabic)

* New translations common.php (Arabic)

* New translations entities.php (Arabic)

* New translations entities.php (Arabic)

* New translations settings.php (Italian)
2021-05-08 17:52:32 +01:00
Dan Brown
c42b6aece9 Updated composer deps again and run npm audit fix 2021-05-08 17:50:28 +01:00
Dan Brown
7f8f3080c5 Removed php8-only 'mixed' type from test method 2021-05-08 13:23:28 +01:00
Dan Brown
9cf4191079 Reviewed and updated SAML2 authncontext option
Added tests to cover.
Changed default to align with existing default.
Added env option parsing.
For #1998
2021-05-08 13:07:25 +01:00
Dan Brown
b8e2d75014 Merge branch 'ivir-authncontext' of https://github.com/ivir/BookStack into ivir-ivir-authncontext 2021-05-08 12:13:27 +01:00
Dan Brown
f522f16526 Fixed SAML login button alignment 2021-05-08 11:49:18 +01:00
Rory Maher
b010d2663d Fix table width style
Tables generated by the markdown renderer don't honour the max-width property without applying word-break styling to the td elements
2021-05-06 13:23:38 +01:00
Dan Brown
a083ceaf44 Fixed item export with deleted creator/updated
Added test to cover.
Fixes #2733
2021-05-05 22:52:08 +01:00
Dan Brown
95798a2eba Standardised export views with base layout, Reduced included export styles
Related to #2666
2021-05-04 23:15:05 +01:00
Dan Brown
43b6633183 Filtered scripts in custom HTML head for exports
Since it appeared to cause problems in some scenarios.
Related to #2490
2021-05-03 23:59:52 +01:00
Dan Brown
c50ac022a8 Updated composer deps 2021-05-03 22:32:19 +01:00
Dan Brown
a3d36237e2 Fixed white borders on layout tabs on ios
Closes #2728
2021-05-03 22:28:25 +01:00
Jokuna
a2be61f26d [Fix] app_footer_links_desc 2021-04-29 15:06:58 +09:00
Jokuna
79f5b579d7 [Fix] maint_delete_images_only_in_revisions better 2021-04-29 14:49:46 +09:00
Jokuna
66ecee1e26 [Fix] maint_delete_images_only_in_revisions 2021-04-29 13:54:24 +09:00
Jokuna
02e86ea18f [Fix] app_footer_links_desc 2021-04-29 13:44:50 +09:00
Jokuna
723dbe1da7 [Fix] korean 2021-04-29 13:43:10 +09:00
Jokuna
65fe89441f fix pages_revisions_resotred_from 2021-04-29 13:39:11 +09:00
Jokuna
2093122ac5 Korean translation
resources/lang/ko/settings.php
2021-04-29 12:58:53 +09:00
Jokuna
ab584c93bc Korean translations
activities.php
common.php
entities.php
validation.php
2021-04-29 00:11:01 +09:00
Dan Brown
2d8698a218 Updated version and assets for release v21.04.3 2021-04-27 22:01:37 +01:00
Dan Brown
454fb883a2 Merge branch 'master' into release 2021-04-27 22:01:15 +01:00
Dan Brown
fc504a3d2c Updated translator attribution before release v21.04.3 2021-04-27 22:00:51 +01:00
Dan Brown
dd805503fb New Crowdin updates (#2695)
* New translations settings.php (Japanese)

* New translations settings.php (Japanese)

* New translations common.php (Latvian)

* New translations common.php (Russian)

* New translations settings.php (Dutch)

* New translations common.php (Dutch)

* New translations settings.php (Dutch)

* New translations entities.php (Dutch)

* New translations validation.php (Dutch)

* New translations activities.php (Dutch)

* New translations common.php (German)

* New translations common.php (Dutch)

* New translations common.php (German Informal)

* New translations activities.php (Dutch)

* New translations entities.php (German)

* New translations settings.php (German)

* New translations auth.php (Dutch)

* New translations components.php (Dutch)

* New translations common.php (German Informal)

* New translations entities.php (German Informal)

* New translations settings.php (German Informal)

* New translations common.php (Catalan)

* New translations common.php (Catalan)

* New translations passwords.php (Catalan)

* New translations validation.php (Catalan)

* New translations validation.php (Catalan)

* New translations auth.php (Catalan)

* New translations common.php (Italian)

* New translations activities.php (Italian)

* New translations common.php (Italian)
2021-04-27 21:58:09 +01:00
Dan Brown
f24336f77a Updated mobile content tabs to respect dark mode 2021-04-27 21:55:33 +01:00
Dan Brown
aa6a752e38 Implemented custom select controls because apple hates web developers
They'd rather keep pushing their 2007 era strange form control styles
even though they're horribly outdated, ugly and hard to style. The
only way to override is a full nuking of the default styles, which means
we have to then implement the frigging arrow icon using hacks which would
then conflict with all other sensible browsers so we have to nuke their
styles aswell to ensure some stupid backgroud hack is used everywhere.

I bet apple don't even use their shite default control styles and nuke
them also, Lets see. Yup, First thing I see on the top of their homepage
is a locale select dropdown custom built from about 10 HTML elements. FML

For #2709
2021-04-27 21:36:08 +01:00
Dan Brown
83b576eb19 Prevented "Recently Viewed" homepage list showing non-user-viewed items
Triggered when the user has no/limited views. Added a test to cover.
Closes #2703
2021-04-27 21:05:01 +01:00
Dan Brown
c4e31a0d5e Updated hard-coded string lengths for indexed columns
Since this is what's causing issues for people during migration due to max
key lengths.
Related to #2710.
2021-04-27 20:53:22 +01:00
Dan Brown
f8cdd6e80d Reduced calls for s3-based uploads
Combined the public ACL update into the put operation.
2021-04-27 20:36:42 +01:00
awarre
f8b5a0fd50 Add base64 image support 2021-04-20 23:41:21 +00:00
Dan Brown
6f4a6ab8ea Updated version for release v21.04.2 2021-04-20 22:37:05 +01:00
Dan Brown
9c4b6f36f1 Merge branch 'master' into release 2021-04-20 22:36:35 +01:00
Dan Brown
140aed3586 Updated translator attribution before release v21.04.2 2021-04-20 22:36:21 +01:00
Dan Brown
cf87b78636 New Crowdin updates (#2691)
* New translations common.php (Spanish)

* New translations common.php (Danish)

* New translations auth.php (Danish)

* New translations components.php (Danish)

* New translations entities.php (Danish)

* New translations entities.php (Danish)

* New translations settings.php (Danish)

* New translations common.php (Chinese Simplified)

* New translations auth.php (Chinese Simplified)

* New translations settings.php (Danish)

* New translations settings.php (Danish)

* New translations activities.php (Danish)

* New translations validation.php (Danish)

* New translations common.php (Danish)

* New translations auth.php (Danish)

* New translations activities.php (Danish)
2021-04-20 22:14:37 +01:00
Dan Brown
ec827da5a5 Updated public view test case to be more reliable
Was failing due to either common name or view share being
sticky across requests.
2021-04-20 22:14:01 +01:00
Dan Brown
20528a2442 Fixed error thrown when owner existed but the creator did not
Added test to cover.
For #2687
2021-04-20 21:04:38 +01:00
Dan Brown
78886b1e67 Updated version and assets for release v21.04.1 2021-04-19 22:26:19 +01:00
Dan Brown
d9debaf032 Merge branch 'master' into release 2021-04-19 22:25:29 +01:00
Dan Brown
b3c47649b4 New Crowdin updates (#2672)
* New translations common.php (French)

* New translations entities.php (French)

* New translations settings.php (Russian)

* New translations settings.php (Ukrainian)

* New translations common.php (Spanish, Argentina)

* New translations common.php (Spanish)

* New translations entities.php (Spanish, Argentina)

* New translations settings.php (Spanish, Argentina)

* New translations common.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese, Brazilian)

* New translations common.php (Chinese Simplified)

* New translations common.php (Polish)

* New translations common.php (Norwegian Bokmal)

* New translations common.php (Bosnian)

* New translations common.php (Latvian)

* New translations common.php (Persian)

* New translations common.php (Indonesian)

* New translations common.php (Vietnamese)

* New translations common.php (Chinese Traditional)

* New translations common.php (Ukrainian)

* New translations common.php (Turkish)

* New translations common.php (Swedish)

* New translations common.php (Slovenian)

* New translations common.php (Slovak)

* New translations common.php (Russian)

* New translations common.php (Portuguese)

* New translations common.php (Dutch)

* New translations common.php (French)

* New translations common.php (Korean)

* New translations common.php (Japanese)

* New translations common.php (Italian)

* New translations common.php (Hungarian)

* New translations common.php (Hebrew)

* New translations common.php (German)

* New translations common.php (Danish)

* New translations common.php (Czech)

* New translations common.php (Catalan)

* New translations common.php (Bulgarian)

* New translations common.php (Arabic)

* New translations common.php (Portuguese, Brazilian)

* New translations common.php (Spanish)

* New translations common.php (Spanish, Argentina)

* New translations common.php (German Informal)
2021-04-19 22:04:05 +01:00
Dan Brown
70be28d22c Updated tinymce code block handling to help prevent breaking history states
Only used an undo transaction on startup and added a small delay
to codeMirror parsing on SetContent's to help avoid
the rendering activities getting caught in undoManager states.
Seemed to improve things a lot in Firefox & chrome on my dev machine.

For #2602
2021-04-19 22:00:33 +01:00
Dan Brown
9df4dee1b2 Improved header element accessibility when at mobile sizes
Intended to fix issues raised in #2681.
Changes up the tri-layout tabs, and the main header menu toggle,
to be buttons while adding better text and keyboard controls.

Updated the component format of a few elements along the way.
2021-04-19 21:41:13 +01:00
Dan Brown
60ffe6a993 Updated packages and added better upload failure logging
To fix #2689
Updates all packages but mainly focused on aws-sdk
2021-04-19 20:16:49 +01:00
Dan Brown
0c880def5e Fixed response JSON detection when charset existed
Fixes #2684
2021-04-18 22:12:26 +01:00
Alireza Arjvand
2744b2a243 Added parent info to recycle bin 2021-04-17 13:09:56 +04:30
Dan Brown
d4360d6347 Updated version and assets for release v21.04 2021-04-09 21:18:32 +01:00
Dan Brown
175b1785c0 Merge branch 'master' into release 2021-04-09 21:18:09 +01:00
Dan Brown
e4660a5ba2 Aligned facade accessor 2021-04-09 21:03:02 +01:00
Dan Brown
e2fa6d83c6 Removed some unused sass variables 2021-04-08 22:33:36 +01:00
Dan Brown
a0d32e7b88 Updated translator contribution list 2021-04-07 21:56:30 +01:00
Dan Brown
ced15b64a8 New Crowdin updates (#2621)
* New translations common.php (Russian)

* New translations settings.php (Russian)

* New translations activities.php (Indonesian)

* New translations settings.php (Indonesian)

* New translations settings.php (French)

* New translations activities.php (Chinese Traditional)

* New translations activities.php (Chinese Traditional)

* New translations auth.php (Chinese Traditional)

* New translations auth.php (Chinese Traditional)

* New translations auth.php (Chinese Traditional)

* New translations auth.php (Chinese Traditional)

* New translations common.php (Chinese Traditional)

* New translations components.php (Chinese Traditional)

* New translations entities.php (Chinese Traditional)

* New translations entities.php (Chinese Traditional)

* New translations entities.php (Chinese Traditional)

* New translations entities.php (Chinese Traditional)

* New translations entities.php (Chinese Traditional)

* New translations entities.php (Chinese Traditional)

* New translations entities.php (Chinese Traditional)

* New translations entities.php (Chinese Traditional)

* New translations entities.php (Chinese Traditional)

* New translations entities.php (Chinese Traditional)

* New translations errors.php (Chinese Traditional)

* New translations errors.php (Chinese Traditional)

* New translations errors.php (Chinese Traditional)

* New translations errors.php (Chinese Traditional)

* New translations errors.php (Chinese Traditional)

* New translations activities.php (Polish)

* New translations common.php (Polish)

* New translations entities.php (Polish)

* New translations settings.php (Polish)

* New translations settings.php (Polish)

* New translations validation.php (Polish)

* New translations settings.php (Latvian)

* New translations settings.php (Latvian)

* New translations settings.php (Latvian)

* New translations passwords.php (Chinese Traditional)

* New translations validation.php (Chinese Traditional)

* New translations validation.php (Chinese Traditional)

* New translations validation.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations validation.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations validation.php (Latvian)

* New translations validation.php (Polish)

* New translations validation.php (German Informal)

* New translations validation.php (Norwegian Bokmal)

* New translations validation.php (Spanish, Argentina)

* New translations validation.php (Persian)

* New translations validation.php (Portuguese, Brazilian)

* New translations validation.php (Vietnamese)

* New translations validation.php (Chinese Traditional)

* New translations validation.php (Chinese Simplified)

* New translations validation.php (Ukrainian)

* New translations validation.php (Turkish)

* New translations validation.php (Swedish)

* New translations validation.php (Slovenian)

* New translations validation.php (Slovak)

* New translations validation.php (Russian)

* New translations validation.php (Dutch)

* New translations validation.php (Portuguese)

* New translations validation.php (Korean)

* New translations validation.php (Japanese)

* New translations validation.php (Italian)

* New translations validation.php (Hungarian)

* New translations validation.php (Hebrew)

* New translations validation.php (German)

* New translations validation.php (Danish)

* New translations validation.php (Czech)

* New translations validation.php (Bulgarian)

* New translations validation.php (Arabic)

* New translations validation.php (Spanish)

* New translations validation.php (French)

* New translations validation.php (Bosnian)

* New translations validation.php (Indonesian)

* New translations validation.php (Catalan)

* New translations entities.php (Latvian)

* New translations entities.php (Polish)

* New translations entities.php (German Informal)

* New translations entities.php (Norwegian Bokmal)

* New translations entities.php (Spanish, Argentina)

* New translations entities.php (Persian)

* New translations entities.php (Portuguese, Brazilian)

* New translations entities.php (Vietnamese)

* New translations entities.php (Chinese Traditional)

* New translations entities.php (Chinese Simplified)

* New translations entities.php (Ukrainian)

* New translations entities.php (Turkish)

* New translations entities.php (Swedish)

* New translations entities.php (Slovenian)

* New translations entities.php (Slovak)

* New translations entities.php (Russian)

* New translations entities.php (Dutch)

* New translations entities.php (Portuguese)

* New translations entities.php (Korean)

* New translations entities.php (Japanese)

* New translations entities.php (Italian)

* New translations entities.php (Hungarian)

* New translations entities.php (Hebrew)

* New translations entities.php (German)

* New translations entities.php (Danish)

* New translations entities.php (Czech)

* New translations entities.php (Bulgarian)

* New translations entities.php (Arabic)

* New translations entities.php (Spanish)

* New translations entities.php (French)

* New translations entities.php (Bosnian)

* New translations entities.php (Indonesian)

* New translations entities.php (Catalan)

* New translations entities.php (Spanish)

* New translations settings.php (Chinese Simplified)

* New translations entities.php (Chinese Simplified)

* New translations entities.php (Portuguese)

* New translations entities.php (Latvian)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations common.php (German)

* New translations common.php (Japanese)

* New translations common.php (Chinese Simplified)

* New translations common.php (Ukrainian)

* New translations common.php (Turkish)

* New translations common.php (Swedish)

* New translations common.php (Slovenian)

* New translations common.php (Slovak)

* New translations common.php (Russian)

* New translations common.php (Portuguese)

* New translations common.php (Dutch)

* New translations common.php (Korean)

* New translations common.php (Polish)

* New translations common.php (Italian)

* New translations common.php (Arabic)

* New translations common.php (Hungarian)

* New translations common.php (French)

* New translations common.php (Spanish)

* New translations common.php (Catalan)

* New translations common.php (Bulgarian)

* New translations common.php (Czech)

* New translations common.php (Danish)

* New translations common.php (Hebrew)

* New translations common.php (Bosnian)

* New translations common.php (Chinese Traditional)

* New translations common.php (Vietnamese)

* New translations common.php (Portuguese, Brazilian)

* New translations common.php (Persian)

* New translations common.php (Spanish, Argentina)

* New translations common.php (Latvian)

* New translations common.php (Norwegian Bokmal)

* New translations common.php (German Informal)

* New translations common.php (Indonesian)

* New translations common.php (Indonesian)

* New translations entities.php (Indonesian)

* New translations common.php (Portuguese)

* New translations entities.php (Latvian)

* New translations common.php (Latvian)

* New translations settings.php (Portuguese)

* New translations common.php (Russian)

* New translations entities.php (Russian)

* New translations settings.php (Polish)

* New translations common.php (Ukrainian)

* New translations entities.php (Ukrainian)

* New translations settings.php (Ukrainian)

* New translations settings.php (Russian)

* New translations settings.php (Russian)

* New translations common.php (Chinese Simplified)
2021-04-07 21:49:45 +01:00
Dan Brown
f0723b6ee7 Fixed social button icon/text misalignment 2021-04-06 22:00:07 +01:00
Dan Brown
2162da3a14 Updated project npm deps 2021-04-06 21:55:49 +01:00
Dan Brown
f02cfd8271 Removed mentions of 'mail' mail driver
Closes #2657
2021-03-27 15:56:36 +00:00
Dan Brown
b6a0f9f069 Create config.yml
Totally not discovered/copied from viewing the linuxserver.io options (https://github.com/linuxserver/docker-bookstack/blob/master/.github/ISSUE_TEMPLATE/config.yml)
2021-03-25 21:52:32 +00:00
Dan Brown
5c9c1d1a4b Updated shelf sort to allow default sort, added testing
Done during review of #2515
2021-03-21 23:06:15 +00:00
Dan Brown
ab4c5a55b8 Merge branch 'feature/sort-shelf-books' of git://github.com/guillaumehanotel/BookStack into guillaumehanotel-feature/sort-shelf-books 2021-03-21 21:52:39 +00:00
Dan Brown
43c2fc3c37 Updated dev-docker setup to not alter phpunit.xml
Tested on my machine via fresh dev instance with tests passing.
May need old users to drop their old volume data.
2021-03-21 17:42:10 +00:00
Dan Brown
371033a0f2 Merge branch 'master' into docker-tests 2021-03-21 16:49:22 +00:00
Dan Brown
06706a2d9c Added user filter to audit log
Included testing to cover.
Closes #2472
2021-03-21 15:04:32 +00:00
Dan Brown
c548c06086 Updated dev-docker setup
Removed extension installs for already installed things.
Removed tidy build bits.
Ensured it ran via quick build and test
2021-03-20 16:44:47 +00:00
Dan Brown
8e5067ee91 Performed fixes for failing tests on php8
- Commands that run a truncate DB action failed due to messing up the
  test transations so we mnaully work around that now to ensure a
transaction exists for the test to cleanup afterwards.
- Updated dompdf lib version
2021-03-20 16:25:02 +00:00
Dan Brown
0310b8614e Updated GH actions to use strings for php versions
Looked like 8.0 was being converted to 8
2021-03-20 15:40:08 +00:00
Dan Brown
829fecd338 Updated app to PHP7.3 min supported version, For php8 support
- Updated remaining dependancies
- Upped min versions used
- Updated GH actions to drop 7.2 and include 8.0
- Updated phpunit & tests to 9.x
2021-03-20 15:35:39 +00:00
Dan Brown
44a293f051 Fleshed out and checked over theme system docs 2021-03-20 15:09:17 +00:00
Dan Brown
a92c35a7ac Worked on theme system documentation 2021-03-19 23:06:50 +00:00
Dan Brown
691db40a33 Added login/register theme events 2021-03-19 21:54:50 +00:00
Dan Brown
2ae89f2c32 Added the possibility of social provider extension via theme
Also started docs page
2021-03-19 16:22:47 +00:00
Dan Brown
9d37af9453 Added web-middleware based theme events 2021-03-17 12:56:56 +00:00
Dan Brown
a5d2a26fcc Added testing for the back-end theme system done so far 2021-03-16 17:55:19 +00:00
Dan Brown
c61c3bc608 Started backend theme system
Allows customization of back-end components via event-driven handling
from the theme folder.
2021-03-16 17:14:03 +00:00
Dan Brown
1420f239fc Made session cookie path dynamic based on APP_URL 2021-03-16 13:03:07 +00:00
Dan Brown
3d0e1bc9db Merge branch 'master' of git://github.com/ckleemann/BookStack into ckleemann-master 2021-03-16 12:45:12 +00:00
Dan Brown
71ccb90ef4 Amended owned by search filter to use slugs 2021-03-15 18:27:03 +00:00
Dan Brown
c8564b7792 Merge branch 'search-owned-by-me' of git://github.com/benediktvolke/BookStack into benediktvolke-search-owned-by-me 2021-03-15 18:21:09 +00:00
Dan Brown
215c69acb2 Merge image name cleaning functions
Updated testing for changes and to check existing of new expected file
name.
Related to #2611
2021-03-14 23:20:21 +00:00
Dan Brown
c1f67372a7 Merge branch 'master' of git://github.com/webfoersterei/BookStack into webfoersterei-master 2021-03-14 22:55:30 +00:00
Dan Brown
b929c0adbb Performed further cleanup in permission service 2021-03-14 20:32:33 +00:00
Dan Brown
1e5951a75f Done a refactor pass on PermissionService
Could do with splitting out into seperate query/build classess really.
Closes #2633.
2021-03-14 19:52:07 +00:00
Dan Brown
a644f64c6b Merge branch 'v0.31.x' 2021-03-13 15:37:44 +00:00
Dan Brown
c8740c0171 Updated version for release v0.31.8 2021-03-13 15:32:54 +00:00
Dan Brown
91ee895a74 Merge branch 'v0.31.x' into release 2021-03-13 15:32:06 +00:00
Dan Brown
339d4ec355 Fixed misalignment of page and chapter parent book
Could occur when a chapter was moved with deleted pages.
Fixes #2632
2021-03-13 15:18:37 +00:00
Dan Brown
615038ac6d Merge pull request #2626 from BookStackApp/2525_add_user_slugs
User slugs
2021-03-10 23:12:25 +00:00
Dan Brown
3c57cbc567 Updated testing for user slugs 2021-03-10 23:04:18 +00:00
Dan Brown
da929d5edc Updates search to use user slugs 2021-03-10 22:51:18 +00:00
Dan Brown
124c4d0778 Updated register paths to include user slugs 2021-03-10 22:37:53 +00:00
Dan Brown
19d79b6a0f Started rolling out user slugs to model and core controllers 2021-03-09 23:06:12 +00:00
Dan Brown
3a9caea846 Started work on user slugs
Related to #2525
2021-03-08 22:34:22 +00:00
Dan Brown
34e6098687 Merge branch 'master' of github.com:BookStackApp/BookStack 2021-03-07 22:24:41 +00:00
Dan Brown
98a1e57ba9 Ran phpcbf and updated phpcs.xml 2021-03-07 22:24:05 +00:00
Dan Brown
f31cdf7bff New Crowdin updates (#2620)
* New translations settings.php (Norwegian Bokmal)

* New translations auth.php (Catalan)

* New translations settings.php (Catalan)

* New translations entities.php (Catalan)

* New translations settings.php (German Informal)

* New translations settings.php (Bosnian)

* New translations settings.php (Spanish)

* New translations settings.php (French)

* New translations settings.php (Bulgarian)

* New translations settings.php (Arabic)

* New translations settings.php (Czech)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Slovenian)

* New translations settings.php (Persian)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Ukrainian)

* New translations settings.php (Turkish)

* New translations settings.php (Swedish)

* New translations settings.php (Slovak)

* New translations settings.php (Danish)

* New translations settings.php (Russian)

* New translations settings.php (Polish)

* New translations settings.php (Dutch)

* New translations settings.php (Korean)

* New translations settings.php (Japanese)

* New translations settings.php (Italian)

* New translations settings.php (Hungarian)

* New translations settings.php (Hebrew)

* New translations auth.php (German)

* New translations auth.php (Spanish)

* New translations settings.php (Portuguese)

* New translations settings.php (German)

* New translations settings.php (Latvian)

* New translations settings.php (Vietnamese)

* New translations activities.php (French)

* New translations settings.php (Indonesian)

* New translations entities.php (French)

* New translations components.php (German Informal)
2021-03-07 17:41:58 +00:00
Dan Brown
9a3e1490ff Merge branch 'Ereza-master' 2021-03-07 17:25:27 +00:00
Dan Brown
1f2fd58e28 Merge branch 'master' of git://github.com/Ereza/BookStack into Ereza-master 2021-03-07 17:25:07 +00:00
Dan Brown
bcf3a0f677 Merge pull request #2616 from geins/master
Fixed german formal translation
2021-03-07 17:20:07 +00:00
Dan Brown
f40dedb451 Merge branch 'master' into master 2021-03-07 17:19:55 +00:00
Dan Brown
266f6846b5 Merge pull request #2609 from arcoai/fix/user-invite-email-subject-spanish-translation
Fixed user invite email subject in spanish translation (#2608)
2021-03-07 17:18:07 +00:00
Dan Brown
49ca9a9db8 Merge pull request #2533 from benediktvolke/fix-german-language
Fix German translation string
2021-03-07 17:15:40 +00:00
Dan Brown
e7a7d8cc1d Merge pull request #2513 from Baptistou/patch-1
Fix French translations
2021-03-07 17:14:57 +00:00
Dan Brown
34c2da4ab1 New Crowdin updates (#2618)
* New translations settings.php (Russian)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Ukrainian)

* New translations settings.php (Turkish)

* New translations settings.php (Swedish)

* New translations settings.php (Slovenian)

* New translations settings.php (Slovak)

* New translations settings.php (Polish)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Dutch)

* New translations settings.php (Korean)

* New translations settings.php (Japanese)

* New translations settings.php (Italian)

* New translations settings.php (Hungarian)

* New translations settings.php (Hebrew)

* New translations settings.php (Danish)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Persian)

* New translations settings.php (Bulgarian)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (German Informal)

* New translations settings.php (Norwegian Bokmal)

* New translations settings.php (Bosnian)

* New translations settings.php (Czech)

* New translations settings.php (Arabic)

* New translations settings.php (Spanish)

* New translations settings.php (French)

* New translations settings.php (Portuguese)

* New translations settings.php (German)

* New translations settings.php (Latvian)

* New translations settings.php (Vietnamese)

* New translations settings.php (Indonesian)

* New translations common.php (German Informal)

* New translations common.php (Spanish, Argentina)
2021-03-07 17:11:18 +00:00
Dan Brown
7497203014 Merge branch 'master' of github.com:BookStackApp/BookStack 2021-03-07 17:03:21 +00:00
Dan Brown
d731a4f695 Updated language lists with Bosnian, Indonesian, Latvian & Portuguese 2021-03-07 17:02:28 +00:00
Dan Brown
03f6be6d0e New Crowdin updates (#2501)
* New translations activities.php (German Informal)

* New translations settings.php (Ukrainian)

* New translations settings.php (Turkish)

* New translations settings.php (Polish)

* New translations common.php (Russian)

* New translations settings.php (Russian)

* New translations common.php (Slovak)

* New translations settings.php (Slovak)

* New translations common.php (Slovenian)

* New translations settings.php (Slovenian)

* New translations common.php (Swedish)

* New translations settings.php (Swedish)

* New translations common.php (Turkish)

* New translations common.php (Ukrainian)

* New translations settings.php (Dutch)

* New translations common.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations common.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations common.php (Vietnamese)

* New translations settings.php (Vietnamese)

* New translations common.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese, Brazilian)

* New translations common.php (Spanish, Argentina)

* New translations settings.php (Spanish, Argentina)

* New translations common.php (Norwegian Bokmal)

* New translations common.php (Polish)

* New translations common.php (Dutch)

* New translations settings.php (Norwegian Bokmal)

* New translations settings.php (Czech)

* New translations settings.php (German)

* New translations settings.php (German Informal)

* New translations common.php (French)

* New translations settings.php (French)

* New translations common.php (Spanish)

* New translations settings.php (Spanish)

* New translations common.php (Arabic)

* New translations settings.php (Arabic)

* New translations common.php (Bulgarian)

* New translations settings.php (Bulgarian)

* New translations common.php (Czech)

* New translations common.php (Danish)

* New translations settings.php (Korean)

* New translations settings.php (Danish)

* New translations common.php (German)

* New translations common.php (Hebrew)

* New translations settings.php (Hebrew)

* New translations common.php (Hungarian)

* New translations settings.php (Hungarian)

* New translations common.php (Italian)

* New translations settings.php (Italian)

* New translations common.php (Japanese)

* New translations settings.php (Japanese)

* New translations common.php (Korean)

* New translations common.php (German Informal)

* New translations common.php (Spanish)

* New translations settings.php (Spanish)

* New translations settings.php (Hebrew)

* New translations settings.php (Hebrew)

* New translations settings.php (Hebrew)

* New translations settings.php (Hebrew)

* New translations common.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations components.php (Hebrew)

* New translations passwords.php (Hebrew)

* New translations activities.php (Persian)

* New translations settings.php (Latvian)

* New translations settings.php (Bosnian)

* New translations passwords.php (Bosnian)

* New translations pagination.php (Bosnian)

* New translations errors.php (Bosnian)

* New translations entities.php (Bosnian)

* New translations components.php (Bosnian)

* New translations common.php (Bosnian)

* New translations auth.php (Bosnian)

* New translations activities.php (Bosnian)

* New translations validation.php (Latvian)

* New translations passwords.php (Latvian)

* New translations common.php (Persian)

* New translations pagination.php (Latvian)

* New translations errors.php (Latvian)

* New translations entities.php (Latvian)

* New translations components.php (Latvian)

* New translations common.php (Latvian)

* New translations auth.php (Latvian)

* New translations activities.php (Latvian)

* New translations validation.php (Persian)

* New translations settings.php (Persian)

* New translations entities.php (Persian)

* New translations validation.php (Bosnian)

* New translations activities.php (Latvian)

* New translations common.php (Latvian)

* New translations common.php (Latvian)

* New translations passwords.php (Latvian)

* New translations auth.php (Latvian)

* New translations auth.php (Latvian)

* New translations activities.php (Bosnian)

* New translations activities.php (Bosnian)

* New translations components.php (Bosnian)

* New translations components.php (Bosnian)

* New translations activities.php (Latvian)

* New translations auth.php (Latvian)

* New translations activities.php (Latvian)

* New translations auth.php (Latvian)

* New translations pagination.php (Latvian)

* New translations passwords.php (Latvian)

* New translations auth.php (Latvian)

* New translations common.php (Latvian)

* New translations components.php (Latvian)

* New translations passwords.php (Latvian)

* New translations components.php (Latvian)

* New translations common.php (French)

* New translations settings.php (French)

* New translations entities.php (Latvian)

* New translations entities.php (Latvian)

* New translations entities.php (Latvian)

* New translations settings.php (Latvian)

* New translations errors.php (Latvian)

* New translations settings.php (Latvian)

* New translations common.php (Slovenian)

* New translations settings.php (Slovenian)

* New translations entities.php (Slovenian)

* New translations entities.php (Latvian)

* New translations entities.php (Latvian)

* New translations errors.php (Latvian)

* New translations validation.php (Latvian)

* New translations validation.php (Latvian)

* New translations entities.php (Latvian)

* New translations entities.php (Latvian)

* New translations errors.php (Latvian)

* New translations settings.php (Latvian)

* New translations activities.php (Portuguese, Brazilian)

* New translations common.php (Portuguese, Brazilian)

* New translations entities.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese, Brazilian)

* New translations validation.php (Portuguese, Brazilian)

* New translations validation.php (Latvian)

* New translations errors.php (Latvian)

* New translations settings.php (Latvian)

* New translations validation.php (Latvian)

* New translations common.php (German)

* New translations settings.php (German)

* New translations settings.php (Latvian)

* New translations validation.php (Latvian)

* New translations settings.php (Latvian)

* New translations entities.php (Latvian)

* New translations entities.php (Latvian)

* New translations entities.php (Latvian)

* New translations errors.php (Latvian)

* New translations settings.php (Latvian)

* New translations activities.php (Portuguese)

* New translations auth.php (Indonesian)

* New translations settings.php (Indonesian)

* New translations passwords.php (Indonesian)

* New translations pagination.php (Indonesian)

* New translations errors.php (Indonesian)

* New translations entities.php (Indonesian)

* New translations components.php (Indonesian)

* New translations common.php (Indonesian)

* New translations activities.php (Indonesian)

* New translations auth.php (Portuguese)

* New translations validation.php (Portuguese)

* New translations settings.php (Portuguese)

* New translations passwords.php (Portuguese)

* New translations pagination.php (Portuguese)

* New translations errors.php (Portuguese)

* New translations entities.php (Portuguese)

* New translations components.php (Portuguese)

* New translations common.php (Portuguese)

* New translations validation.php (Indonesian)

* New translations auth.php (Portuguese)

* New translations common.php (Portuguese)

* New translations components.php (Portuguese)

* New translations entities.php (Portuguese)

* New translations entities.php (Portuguese)

* New translations entities.php (Portuguese)

* New translations entities.php (Portuguese)

* New translations entities.php (Portuguese)

* New translations errors.php (Portuguese)

* New translations components.php (Bosnian)

* New translations auth.php (Bosnian)

* New translations common.php (Bosnian)

* New translations pagination.php (Bosnian)

* New translations passwords.php (Bosnian)

* New translations auth.php (Bosnian)

* New translations errors.php (Portuguese)

* New translations errors.php (Portuguese)

* New translations pagination.php (Portuguese)

* New translations passwords.php (Portuguese)

* New translations settings.php (Portuguese)

* New translations validation.php (Portuguese)

* New translations settings.php (Portuguese)

* New translations settings.php (Portuguese)

* New translations activities.php (Vietnamese)

* New translations settings.php (Vietnamese)

* New translations validation.php (Bosnian)

* New translations validation.php (Bosnian)

* New translations validation.php (Bosnian)

* New translations validation.php (Bosnian)

* New translations validation.php (Bosnian)

* New translations errors.php (Bosnian)

* New translations errors.php (Bosnian)

* New translations errors.php (Bosnian)

* New translations errors.php (Bosnian)

* New translations errors.php (Bosnian)

* New translations errors.php (Bosnian)

* New translations entities.php (Bosnian)

* New translations entities.php (Bosnian)

* New translations activities.php (Indonesian)

* New translations activities.php (Indonesian)

* New translations auth.php (Indonesian)

* New translations entities.php (Indonesian)

* New translations auth.php (Indonesian)

* New translations auth.php (Indonesian)

* New translations common.php (Indonesian)

* New translations components.php (Indonesian)

* New translations entities.php (Indonesian)

* New translations entities.php (Indonesian)

* New translations entities.php (Indonesian)

* New translations entities.php (Latvian)

* New translations errors.php (Latvian)

* New translations settings.php (Latvian)

* New translations entities.php (Indonesian)

* New translations settings.php (Latvian)

* New translations entities.php (Bosnian)

* New translations entities.php (Bosnian)

* New translations entities.php (Indonesian)

* New translations entities.php (Indonesian)

* New translations errors.php (Indonesian)

* New translations errors.php (Indonesian)

* New translations entities.php (Indonesian)

* New translations errors.php (Indonesian)

* New translations pagination.php (Indonesian)

* New translations passwords.php (Indonesian)

* New translations validation.php (Indonesian)

* New translations settings.php (Indonesian)

* New translations settings.php (Indonesian)

* New translations settings.php (Indonesian)

* New translations settings.php (Indonesian)

* New translations validation.php (Indonesian)

* New translations common.php (Indonesian)

* New translations entities.php (Indonesian)

* New translations validation.php (Indonesian)

* New translations entities.php (Bosnian)

* New translations entities.php (Bosnian)

* New translations entities.php (Bosnian)

* New translations validation.php (Indonesian)

* New translations auth.php (Indonesian)

* New translations validation.php (Indonesian)
2021-03-07 16:44:28 +00:00
Dan Brown
938b5b4d1d Updated github CI actions for ubuntu 20.04
Squash of:
commit 6b7d305e776dcec2103b9e4486f3c57c674d046f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sun Mar 7 16:25:43 2021 +0000

    Updated migrations action and added ldap

commit 139d87687d3d4d6c2368adb522932469419c848a
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sun Mar 7 16:18:55 2021 +0000

    Updated mysql user auth

commit 326d11e0d3b96bfb2e6ba446ada9cee479d3eb1a
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sun Mar 7 16:15:33 2021 +0000

    Moved extensions to right place

commit aaa1e159ccbf535292615e094bb58ce6488726df
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sun Mar 7 16:13:22 2021 +0000

    Added php extensions

commit 3720324288c974d825ff2a63306a5fbf1c0478ab
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sun Mar 7 16:07:37 2021 +0000

    Update gh ci branches list for testing

commit 4e3a302a5a4480b45d967f398abbe33883b6d0fb
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sun Mar 7 16:06:19 2021 +0000

    Updated github ci to use ubuntu 20.04
2021-03-07 16:31:51 +00:00
geins
792b51b5dc Merge pull request #2 from geins/settings.php-german-patch
completed german translation of 4 english residues
2021-03-06 21:32:27 +01:00
geins
a57eae20b0 completed german translation of 4 english residues 2021-03-06 21:29:59 +01:00
geins
1ffe212d83 Merge pull request #1 from geins/geins-patch-1
Translation error in formal german vs informal
2021-03-06 20:30:06 +01:00
geins
e29c07b28d Translation error
Translation error: informal language in formal file Sie<->Du
2021-03-06 18:57:49 +01:00
Timo Förster
745d15d200 Allow uploads of files containing dots in filename. Closes BookStackApp/BookStack#2217 2021-03-04 22:27:20 +01:00
Arco Aplicaciones - David Blanco
05cfe74904 Fixed user invite email subject in spanish translation (#2608) 2021-03-04 00:07:17 +01:00
Dan Brown
4d4a57d1bf Converted some tests from BrowserKit, Updated shared helpers 2021-03-03 22:11:00 +00:00
Dan Brown
382f155f76 Better aligned handler with core laravel 2021-03-02 21:59:12 +00:00
Dan Brown
60030a774d Merge branch 'v0.31.x' 2021-03-02 21:43:30 +00:00
Dan Brown
a045e46571 Updated version for release v0.31.7 2021-03-02 21:19:17 +00:00
Dan Brown
44eaa65c3b Merge branch 'v0.31.x' into release 2021-03-02 21:18:31 +00:00
Dan Brown
26730e56ea Updated composer dependancies
Primarily to fix aws library for non-amazon use.
Related to #2603
2021-03-02 21:06:45 +00:00
Dan Brown
7b6f8cb902 Merge pull request #2591 from philjak/add_bookshelf_view_type_to_env
Adding APP_VIEWS_BOOKSHELF to .ENV
2021-02-25 22:00:03 +00:00
Philip
111835f402 Adding APP_VIEWS_BOOKSHELF to .ENV 2021-02-25 07:51:38 +01:00
ckleemann
3fc935d4bb Introduce an env variable for the Session Cookie Path 2021-02-20 14:25:28 +01:00
Benedikt Volke
b939785ece Add checkbox on search page 2021-02-14 11:40:38 +01:00
Benedikt Volke
723628cfcf Add translation string 2021-02-14 11:40:24 +01:00
Benedikt Volke
cf489453c9 Add test for new search tag 2021-02-14 11:40:02 +01:00
Benedikt Volke
6616065d82 Add filter method to search runner 2021-02-14 11:39:18 +01:00
Dan Brown
2df82dd870 Added padding to the bottom of the WYSIWYG editor
Also fixed weird affects from body now always being flex.
For #1075
2021-02-12 23:35:42 +00:00
Dan Brown
0ca8d7fc03 Updated books list view description to be limited by css
Instead of length limited
Related to #1222
2021-02-12 23:10:30 +00:00
Dan Brown
f36e6d9917 Updtd entity-selector for keyboard nav and new component system
For #2064
2021-02-12 22:10:37 +00:00
Dan Brown
6a4b020dd8 Removed user and revision links in export meta
Closes #2526
2021-02-12 20:58:01 +00:00
Dan Brown
b51ede2372 Updated php deps to avoid a couple of abandoned packages 2021-02-11 23:46:26 +00:00
Dan Brown
1a4797abc4 Updated update-url command to handle array values
Also added message to clear the cache after running.
For #2546
2021-02-11 23:14:37 +00:00
Dan Brown
c09300c06f Split command tests out to indavidual test files 2021-02-11 22:42:36 +00:00
Dan Brown
ae353bb3f4 Updated update-url command to look at setting values
For #2546
Need to consider new JSON-array based setting values.
2021-02-10 23:47:58 +00:00
Dan Brown
54f5bf9437 Aligned setting helper with new get method changes
Also removed old unsused facade that existed for settings.
2021-02-10 23:21:49 +00:00
James Geiger
a0bfdf0e5c Code cleanup, bug squashing 2021-02-09 01:27:27 -06:00
James Geiger
7ef17bb394 PageContent return null issue 2021-02-09 00:21:07 -06:00
James Geiger
48587d2c38 Code cleanup, refactor
Updated to use Str::length for entity descriptions.
Moved function to get first image in page to PageContent class.
2021-02-09 00:16:24 -06:00
Dan Brown
b0f4500c34 Added env option for setting dark mode default
Also allowed config-centralised default user settings for this change
and bought existing user-level view options into that default settings
system to be cleaner in code usage.

For #2081
2021-02-07 23:12:05 +00:00
Dan Brown
af032f8993 Tweaked LDAP TLS Implementation
- Moved the ldap function out to our separate service for easier
  testing.
- Added testing for the option.
- Moved tls_insecure part back up above connection start as found more
  reliable there.

Done a lot of real-connection testing during this review.
Used wireshare to ensure TLS connection does take place.
Found LDAP_TLS_INSECURE=false can action unreliably, restarting php-fpm
helped.
Tested both trusted and untrusted certificates.
2021-02-07 20:00:04 +00:00
Dan Brown
f177b02cae Merge branch 'master' of git://github.com/Body4/BookStack into Body4-master 2021-02-07 18:33:10 +00:00
Dan Brown
5323cb5224 Removed some old front-end md rendering elements
Also ensured revisions were not created more often than expected.
Summary field null check was triggering revision save even when empty
since it was still in request.

Related to #1846
2021-02-06 23:11:20 +00:00
Dan Brown
0a22af7b14 Updated version for release v0.31.6 2021-02-06 14:41:19 +00:00
Dan Brown
b54702ab08 Merge branch 'v0.31.x' into release 2021-02-06 14:40:47 +00:00
Dan Brown
a98fc71720 Updated composer deps again after merge 2021-02-06 14:22:55 +00:00
Dan Brown
9a05223e7d Merge branch 'v0.31.x' 2021-02-06 14:22:19 +00:00
Dan Brown
a7e3c26fe3 Fixed markdown content on revision restore
Closes #2496
2021-02-06 14:14:38 +00:00
Dan Brown
37de4e2e0a Added test for markdown page revision restore
Also added md change detection in revision saving.
2021-02-06 13:51:05 +00:00
Dan Brown
61a911dd39 Removed "isA" usages from trashcan 2021-02-06 13:29:39 +00:00
Aleksandr Sazhin
cc5d0ef4cf Update TrashCan.php
bookshelf
2021-02-06 13:23:12 +00:00
Dan Brown
7843d8f054 Added recycle-bin test to cover type deletions 2021-02-06 13:22:31 +00:00
Dan Brown
d759f9c121 Merge branch 'master' of git://github.com/i4j5/BookStack into i4j5-master 2021-02-06 13:21:14 +00:00
Dan Brown
f25e585008 Moved sketchy file samples to base64 equivilents
Hides them from AV systems.
Done some test helper cleaning while at it.

Related to #1571
2021-02-06 00:16:27 +00:00
Dan Brown
4f96cd9164 Altered header to keep search box center
For #2310
2021-02-04 23:11:55 +00:00
Eduard Ereza Martínez
7893e8229f Add Catalan translation 2021-02-04 00:55:01 +01:00
Benedikt Volke
795ef67712 fix image delete confirm text 2021-02-03 13:00:08 +01:00
Aleksandr Sazhin
88f6d3f241 Update TrashCan.php
bookshelf
2021-02-03 10:03:54 +03:00
Dan Brown
8e87f01aa0 Added stats badge and league to attribution 2021-02-02 22:12:41 +00:00
Dan Brown
c4fdcfc5d1 Updated version for release v0.31.5 2021-02-02 20:58:06 +00:00
Dan Brown
cb8117e8df Merge branch 'v0.31.x' into release 2021-02-02 20:57:41 +00:00
Dan Brown
d547ed4a6b Updated laravel/framework to latest 6.x version 2021-02-02 20:56:19 +00:00
Baptiste Thémine
f40c389a15 Fix French translations
- "supprimer" is a better translation than "écarter" for "discard"
- "actuel" is a better translation than "courant" for "current"
- "modifications" is a better translation than "changements" for change
- "journal des modifications" is a better translation than "journal des changements" for changelog
- The button "Remplir le journal des changements" for pages_edit_set_changelog caused a wrapping in the header, it is replaced by "Décrivez vos modifications"
2021-02-02 13:12:07 +01:00
Dan Brown
bc1e84325c Made codemirror editor load a lot more efficient
Brings down total editor load time from about 11s to 7s from testing in
4x reduced CPU speed in chrome.
About 1.5 seconds of that is editor init/page load.
Post editor-init/page-load time is now 60% of previous from testing.

Related to #2518
2021-01-31 16:26:54 +00:00
Abijeet
a0c605faae Docker: Fix PHP tests
This creates another mysql_testing database during db service setup

Replace server with env tags in phpunit.xml in order to force
override certain parameters when tests are run. See:
https://github.com/sebastianbergmann/phpunit/issues/2353 for more
information.

Rename primary developer Docker database from bookstack-test to
bookstack-dev. bookstack-test is used as the mysql_testing database
2021-01-31 18:54:24 +05:30
Abijeet
ba2033a8fb Docker: Fix permission with node service by adding user key
Fixes the following error:

glob error:
[Error: EACCES: permission denied, scandir '/root/.npm/_logs'] {
  errno: -13,
  code: 'EACCES',
  syscall: 'scandir',
  path: '/root/.npm/_logs'
}

On Linux, these lines ensure file ownership is set to your host
user/group
2021-01-31 16:57:30 +05:30
Guillaume Hanotel
a7848b916b Improve sorting Shelf Books 2021-01-31 04:28:25 +01:00
Dan Brown
44c41e9e4d Updated footer links to be a configurable list
Made so footer link ordering, names and urls can be set.
Cleaned up some of the setting-service and added support for array
setting types, which are cleaned on entry and stored as json with a new
type indicator column on the settings table for auto-decode.
Also added testing to cover this feature.

Related to #1973 and #854
2021-01-31 00:23:15 +00:00
Dan Brown
a663364223 Merge branch 'footer-links' of git://github.com/james-geiger/BookStack into james-geiger-footer-links 2021-01-30 22:03:16 +00:00
Dan Brown
72fda8f592 Merge pull request #2510 from BookStackApp/fix-docker-perm
Docker: Fix permission with node service by adding node as user
2021-01-30 21:51:00 +00:00
Abijeet
1aa9465611 Docker: Fix permission with node service by adding node as user
See: https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md#non-root-user

Fixes the following error:

glob error:
[Error: EACCES: permission denied, scandir '/root/.npm/_logs'] {
  errno: -13,
  code: 'EACCES',
  syscall: 'scandir',
  path: '/root/.npm/_logs'
}
2021-01-30 23:46:53 +05:30
Dan Brown
4d3194d784 Merge branch 'patch-1' of git://github.com/l1n/BookStack into l1n-patch-1 2021-01-30 17:15:23 +00:00
Dan Brown
5404f22bf9 Added codemirror refresh on details blog toggle
For #781
2021-01-30 17:04:30 +00:00
Dan Brown
ccb2cb5b7c Merge branch 'feature_add_add-button_to_home_view' of git://github.com/philjak/BookStack into philjak-feature_add_add-button_to_home_view 2021-01-30 16:40:13 +00:00
Guillaume Hanotel
26ba056302 Sort Books within Shelves 2021-01-29 08:02:18 +01:00
Dan Brown
0dac9c68f0 Changed how the cache is mocked in status test 2021-01-28 23:13:55 +00:00
Dan Brown
3df6c9ac05 Updated service provider reference, added phpunit env var 2021-01-28 22:46:15 +00:00
Dan Brown
2db081938f Updated deps, focused on new version of htmldiff 2021-01-28 22:04:19 +00:00
Baptiste Thémine
d979570227 Fix French translation for permissions_update 2021-01-27 13:40:58 +01:00
Shubham Tiwari
99c42033b1 Add prev and next button to navigate through different pages 2021-01-27 10:15:28 +05:30
Dan Brown
7ba6962707 Removed lesser-used middleware and updated localization middleware
So that DB/User access is not explicitly enforced.
Same for GlobalViewData middleware although that was also just doubling
up on ways to access user/auth info.
Also cleaned up Localization Middleware doc blocks.
2021-01-17 13:41:43 +00:00
Dan Brown
6eda1c1fb2 Added status endpoint
For #2467
2021-01-17 13:21:57 +00:00
Dan Brown
5a218d5056 Updated version and assets for release v0.31.4 2021-01-16 17:50:45 +00:00
Dan Brown
8dbc5cf9c6 Merge branch 'master' into release 2021-01-16 17:50:11 +00:00
Dan Brown
d33f136660 Updated translator attribution before release v0.31.4 2021-01-16 17:49:56 +00:00
Dan Brown
173dad345e New Crowdin updates (#2482)
* New translations entities.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations activities.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)
2021-01-16 17:45:59 +00:00
Dan Brown
47b0eb6324 Updated framework and other php deps 2021-01-16 17:45:04 +00:00
Dan Brown
c35c37008d Added imagetools plugin back in
For #2493
2021-01-16 17:39:30 +00:00
Bernhard Hayden
aad2ee675c Show tags of all search results 2021-01-15 15:52:03 +01:00
Nova
b8aabfffe8 Update form.blade.php 2021-01-13 12:45:18 -08:00
Nova
ac8e124d01 Update form.blade.php 2021-01-13 12:23:20 -08:00
Nova
857f8c2a95 Disable autocomplete on the change password field 2021-01-13 12:21:57 -08:00
Dan Brown
71e81615a3 Updated version for release v0.31.3 2021-01-10 23:29:58 +00:00
Dan Brown
611d37da04 Merge branch 'master' into release 2021-01-10 23:29:11 +00:00
Dan Brown
ee400eece6 New Crowdin updates (#2469)
* New translations settings.php (Turkish)

* New translations entities.php (Turkish)

* New translations settings.php (Turkish)

* New translations activities.php (Turkish)

* New translations validation.php (Turkish)
2021-01-10 23:28:33 +00:00
Dan Brown
da7c686541 Made books and shelf listing views slightly more efficient 2021-01-10 23:12:51 +00:00
Dan Brown
d0a7a8b890 Improved some query efficiencies on user list 2021-01-10 23:02:30 +00:00
Dan Brown
28c706fee3 Added strikethrough support to back-end md rendering
Needed to tweak the default library strikethrough extension
so that it uses the same element as front-end.
Added testing to cover.
For #2470.
2021-01-10 23:01:11 +00:00
Dan Brown
0e799a3857 Updated version and assets for release v0.31.2 2021-01-10 14:05:16 +00:00
Dan Brown
b91d6e2bfa Merge branch 'master' into release 2021-01-10 14:04:59 +00:00
Dan Brown
44315233d7 Updated translator attribution before release v0.31.2 2021-01-10 14:04:38 +00:00
Dan Brown
91efa601be New Crowdin updates (#2464)
* New translations entities.php (Chinese Traditional)

* New translations entities.php (Chinese Traditional)

* New translations settings.php (Italian)

* New translations settings.php (Italian)

* New translations settings.php (Russian)

* New translations settings.php (Russian)

* New translations entities.php (Russian)

* New translations settings.php (Russian)

* New translations activities.php (Russian)
2021-01-10 13:44:29 +00:00
Dan Brown
18f86fbf9b Made recycle-bin settings navbar full width
For #2468
2021-01-10 13:36:46 +00:00
Dan Brown
e5a96b0cb0 Added test case for avatar failed fetch
Fixed non-imported log issue while there.
For #2449
2021-01-10 13:29:13 +00:00
Dan Brown
526be33ab2 Fixed page copying not retaining content
Was when there was no markdown content.
Added tests to cover both HTML and markdown scenarios.
Also removed old console.log

Related to #2463
2021-01-09 19:39:09 +00:00
Dan Brown
831f441879 Added in table + tasklist markdown rendering
For parity with markdown-it renderer.
Added tests to cover.
For #2452
2021-01-09 19:04:23 +00:00
Dan Brown
ea16ad7e94 Updated version and assets for release v0.31.1 2021-01-04 18:41:55 +00:00
Dan Brown
ba6eb54552 Merge branch 'master' into release 2021-01-04 18:41:26 +00:00
Dan Brown
47e3ef1be2 New Crowdin updates (#2441)
* New translations entities.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations entities.php (Chinese Simplified)

* New translations settings.php (French)

* New translations entities.php (French)

* New translations settings.php (Chinese Simplified)

* New translations entities.php (Chinese Simplified)

* New translations entities.php (Spanish, Argentina)
2021-01-04 18:35:31 +00:00
Dan Brown
7791599fb5 Fixed recycle bin dropdown being cut off in chrome
Fixes #2442
2021-01-04 18:24:34 +00:00
Dan Brown
bbfb330b92 Added check of owner field for manage-permissions-own
This permission was still checking based on created-by.
Updated testing to specifically check the owner since the tests
were passing by the fact of matching creator and owner.

Fixes #2445
2021-01-04 18:07:39 +00:00
Dan Brown
20729a618f Fixed markdown content not stored on first page save
HTML content was still saved.
This changes makes the back-end check for md content
instead of html to ensure that gets stored in cases
where both are sent to the system.

Closes #2446
2021-01-04 17:52:08 +00:00
Dan Brown
f705e7683b Updated assets for release v0.31.0 again 2021-01-03 22:33:36 +00:00
Dan Brown
dc996adb20 Merge branch 'master' into release 2021-01-03 22:32:40 +00:00
Dan Brown
14ea6c9de3 Made fixes/updates during pre-release review
- Fixed page editor default focus not working as expected due to
  misnamed attribute.
- Added owned_by to relevant areas of the API including the docs.
- Made book relation on page accessible even if deleted since it could cause an issue on views, such as audit trail, when the relation is accessed when the book is deleted.
2021-01-03 22:29:58 +00:00
Dan Brown
a64c638ccc Updated version and assets for release v0.31.0 2021-01-03 21:52:37 +00:00
Dan Brown
359c067279 Merge branch 'master' into release 2021-01-03 21:52:00 +00:00
Dan Brown
8bb6394b47 Merge branch 'master' of github.com:BookStackApp/BookStack 2021-01-03 20:55:34 +00:00
Dan Brown
ea8083ac6e Updated translators for v0.31 2021-01-03 20:55:08 +00:00
Dan Brown
04367eb4c5 New Crowdin updates (#2439)
* New translations entities.php (Norwegian Bokmal)

* New translations settings.php (Norwegian Bokmal)

* New translations validation.php (Norwegian Bokmal)

* New translations common.php (Norwegian Bokmal)

* New translations activities.php (Norwegian Bokmal)

* New translations entities.php (Spanish)
2021-01-03 20:54:01 +00:00
Dan Brown
f160020941 Added API request issue template 2021-01-03 19:23:41 +00:00
Dan Brown
75a795ab72 Made a couple of fixes during testing
- Updated audit table so long entity names did not squish everything
  else.
- Added filtering to view service popular list so that recycle binned
  items did not cause issues.
2021-01-03 19:02:50 +00:00
Dan Brown
47a6c621ff Squashed commit of the following:
commit f35d815ba0
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:54 2021 +0000

    New translations entities.php (Norwegian Bokmal)

commit 2aba672219
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:52 2021 +0000

    New translations entities.php (French)

commit 323ff9f0ef
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:51 2021 +0000

    New translations entities.php (Spanish)

commit c795e8649b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:49 2021 +0000

    New translations entities.php (Arabic)

commit 161011cf20
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:47 2021 +0000

    New translations entities.php (Bulgarian)

commit 7780f0a7e7
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:46 2021 +0000

    New translations entities.php (Czech)

commit f145e78456
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:44 2021 +0000

    New translations entities.php (Danish)

commit 35ed2f7dda
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:42 2021 +0000

    New translations entities.php (German)

commit 0c645d0905
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:40 2021 +0000

    New translations entities.php (Hebrew)

commit c890484cc5
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:38 2021 +0000

    New translations entities.php (Hungarian)

commit fab4a03ee7
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:36 2021 +0000

    New translations entities.php (Italian)

commit a2aca03833
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:34 2021 +0000

    New translations entities.php (Japanese)

commit a61d59818d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:33 2021 +0000

    New translations entities.php (Korean)

commit 8a684d1825
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:31 2021 +0000

    New translations entities.php (Swedish)

commit ae1c43871c
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:29 2021 +0000

    New translations entities.php (Dutch)

commit 61534ed8d1
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:27 2021 +0000

    New translations entities.php (Russian)

commit ca80c63af0
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:25 2021 +0000

    New translations entities.php (Slovak)

commit f1e75d4a8d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:24 2021 +0000

    New translations entities.php (Slovenian)

commit 88b261ef48
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:22 2021 +0000

    New translations entities.php (Turkish)

commit c9f085743b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:20 2021 +0000

    New translations entities.php (Ukrainian)

commit d3a36e2f2d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:18 2021 +0000

    New translations entities.php (Chinese Simplified)

commit a4bad00370
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:16 2021 +0000

    New translations entities.php (Chinese Traditional)

commit f20ad5ac7c
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:14 2021 +0000

    New translations entities.php (Vietnamese)

commit 7c3e053567
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:12 2021 +0000

    New translations entities.php (Portuguese, Brazilian)

commit 5d6ff41061
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:11 2021 +0000

    New translations entities.php (Spanish, Argentina)

commit e20bf841ad
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:09 2021 +0000

    New translations entities.php (German Informal)

commit bb1cb02b40
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:49:07 2021 +0000

    New translations entities.php (Polish)

commit d0e713c27e
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:09:05 2021 +0000

    New translations validation.php (German Informal)

commit b9510b3ff1
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:08:43 2021 +0000

    New translations activities.php (German Informal)

commit 2e218cc6ea
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:08:42 2021 +0000

    New translations activities.php (Norwegian Bokmal)

commit 34eff6404e
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:08:40 2021 +0000

    New translations activities.php (Spanish, Argentina)

commit ae11ceea66
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:08:28 2021 +0000

    New translations common.php (Norwegian Bokmal)

commit 33dd5743e9
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:08:02 2021 +0000

    New translations auth.php (Norwegian Bokmal)

commit 370ce5a4f1
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:07:56 2021 +0000

    New translations settings.php (Polish)

commit 3b2cf032e6
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:07:53 2021 +0000

    New translations settings.php (Dutch)

commit 1e340dfcbd
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:07:51 2021 +0000

    New translations settings.php (Korean)

commit d3b777db76
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:07:48 2021 +0000

    New translations settings.php (Japanese)

commit 2053eb7415
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:07:45 2021 +0000

    New translations settings.php (Italian)

commit e26cf93b3c
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:07:43 2021 +0000

    New translations settings.php (Hungarian)

commit 8beeb843fd
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:07:40 2021 +0000

    New translations settings.php (Hebrew)

commit e39753711a
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:07:38 2021 +0000

    New translations settings.php (Russian)

commit d04c910dde
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:07:35 2021 +0000

    New translations settings.php (Danish)

commit ff07b618d4
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:07:32 2021 +0000

    New translations settings.php (Czech)

commit d9e32ace61
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:07:29 2021 +0000

    New translations settings.php (Bulgarian)

commit 75b53ddc4a
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:07:26 2021 +0000

    New translations settings.php (Arabic)

commit a04eaf2c65
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:07:21 2021 +0000

    New translations settings.php (Swedish)

commit 7245c1f2bd
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:07:20 2021 +0000

    New translations settings.php (Spanish)

commit 030d146f1d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:07:18 2021 +0000

    New translations settings.php (French)

commit 717807791a
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:07:16 2021 +0000

    New translations settings.php (German)

commit abc29948b4
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:06:59 2021 +0000

    New translations settings.php (Slovak)

commit 35a59233cf
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:06:57 2021 +0000

    New translations settings.php (German Informal)

commit 06105a7b88
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:06:55 2021 +0000

    New translations settings.php (Spanish, Argentina)

commit eb0ac00cdd
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:06:53 2021 +0000

    New translations entities.php (Spanish, Argentina)

commit 1592c098f2
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:06:52 2021 +0000

    New translations settings.php (Portuguese, Brazilian)

commit 37e6ae7e0a
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:06:49 2021 +0000

    New translations settings.php (Vietnamese)

commit 19bdcaaeb6
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:06:46 2021 +0000

    New translations settings.php (Chinese Traditional)

commit d26318342b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:06:42 2021 +0000

    New translations settings.php (Ukrainian)

commit fd9e377d34
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:06:40 2021 +0000

    New translations settings.php (Turkish)

commit a5824bd615
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:06:37 2021 +0000

    New translations settings.php (Slovenian)

commit b3f025561d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:06:13 2021 +0000

    New translations pagination.php (Norwegian Bokmal)

commit 76a6fb78bf
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:06:00 2021 +0000

    New translations validation.php (Norwegian Bokmal)

commit d2f674dfc9
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:05:58 2021 +0000

    New translations validation.php (Spanish, Argentina)

commit 0a5fd95c44
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:05:34 2021 +0000

    New translations settings.php (Norwegian Bokmal)

commit 669788bbe5
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:05:31 2021 +0000

    New translations passwords.php (Norwegian Bokmal)

commit e9defbba8e
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:05:16 2021 +0000

    New translations entities.php (Norwegian Bokmal)

commit 04d1e118d4
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:05:14 2021 +0000

    New translations components.php (Norwegian Bokmal)

commit 93b79e5569
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:04:35 2021 +0000

    New translations errors.php (Norwegian Bokmal)

commit e1076d658d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 16:04:19 2021 +0000

    New translations settings.php (Chinese Simplified)

commit 9ca08f1913
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 01:03:29 2021 +0000

    New translations entities.php (Spanish)

commit ace8cec1bc
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 01:03:28 2021 +0000

    New translations settings.php (Spanish)

commit ad0090aa45
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:33:00 2021 +0000

    New translations settings.php (German Informal)

commit d5d335352a
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:58 2021 +0000

    New translations settings.php (Japanese)

commit 3054a9e421
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:56 2021 +0000

    New translations entities.php (Japanese)

commit e408360838
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:54 2021 +0000

    New translations settings.php (Italian)

commit 119b620af8
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:52 2021 +0000

    New translations entities.php (Italian)

commit 72a89d7852
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:50 2021 +0000

    New translations settings.php (Hungarian)

commit cc941b8ac9
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:49 2021 +0000

    New translations entities.php (Hungarian)

commit d9ec1bb0b0
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:47 2021 +0000

    New translations settings.php (Hebrew)

commit a67d6b8eef
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:45 2021 +0000

    New translations entities.php (Hebrew)

commit 91e8a24268
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:43 2021 +0000

    New translations settings.php (German)

commit 1cf6d211fa
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:41 2021 +0000

    New translations entities.php (German)

commit 23939bdb9b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:39 2021 +0000

    New translations settings.php (Danish)

commit 349946b2ba
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:37 2021 +0000

    New translations entities.php (Korean)

commit 611623eb45
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:36 2021 +0000

    New translations entities.php (Danish)

commit b10bd60e4d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:34 2021 +0000

    New translations entities.php (Czech)

commit 58e9cad253
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:32 2021 +0000

    New translations settings.php (Bulgarian)

commit e239d61c23
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:30 2021 +0000

    New translations entities.php (Bulgarian)

commit 8593e7c0bf
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:28 2021 +0000

    New translations settings.php (Arabic)

commit af4aefb89b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:26 2021 +0000

    New translations entities.php (Arabic)

commit 143d046ef0
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:24 2021 +0000

    New translations entities.php (Spanish)

commit bdd8d189c3
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:22 2021 +0000

    New translations entities.php (French)

commit ec761325e7
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:20 2021 +0000

    New translations settings.php (Swedish)

commit c0ae3b5b51
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:19 2021 +0000

    New translations settings.php (Spanish)

commit 27092813cd
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:17 2021 +0000

    New translations settings.php (French)

commit b5fde40cf5
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:15 2021 +0000

    New translations settings.php (Czech)

commit 7aabc8cc94
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:13 2021 +0000

    New translations entities.php (Swedish)

commit ceb4fd2aa4
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:11 2021 +0000

    New translations settings.php (Korean)

commit d764b5741c
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:09 2021 +0000

    New translations settings.php (Dutch)

commit 3e3884360b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:07 2021 +0000

    New translations entities.php (German Informal)

commit 9f4f7f9368
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:05 2021 +0000

    New translations settings.php (Spanish, Argentina)

commit 7ac467b28b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:03 2021 +0000

    New translations entities.php (Spanish, Argentina)

commit 169574ac42
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:01 2021 +0000

    New translations settings.php (Portuguese, Brazilian)

commit d49813b13e
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:32:00 2021 +0000

    New translations entities.php (Portuguese, Brazilian)

commit 5bb7221fa0
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:58 2021 +0000

    New translations settings.php (Vietnamese)

commit 2cb435970f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:56 2021 +0000

    New translations entities.php (Vietnamese)

commit f1a2dd5b8b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:54 2021 +0000

    New translations settings.php (Chinese Traditional)

commit c7991782a2
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:52 2021 +0000

    New translations entities.php (Chinese Traditional)

commit f85f71beca
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:50 2021 +0000

    New translations entities.php (Chinese Simplified)

commit 8131a4908d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:49 2021 +0000

    New translations entities.php (Dutch)

commit 3b0d5d2124
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:47 2021 +0000

    New translations settings.php (Ukrainian)

commit 178419208a
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:45 2021 +0000

    New translations settings.php (Turkish)

commit 88d6750971
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:43 2021 +0000

    New translations entities.php (Turkish)

commit 8ca6a95407
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:41 2021 +0000

    New translations settings.php (Slovenian)

commit 0effb9b150
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:39 2021 +0000

    New translations entities.php (Slovenian)

commit 85859fd58c
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:37 2021 +0000

    New translations settings.php (Slovak)

commit 1f2db3f4f0
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:35 2021 +0000

    New translations entities.php (Slovak)

commit d677c4020f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:34 2021 +0000

    New translations settings.php (Russian)

commit 9cecf56ef3
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:32 2021 +0000

    New translations entities.php (Russian)

commit fd58ed477e
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:30 2021 +0000

    New translations settings.php (Polish)

commit 2e358289b6
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:28 2021 +0000

    New translations entities.php (Polish)

commit 83a57c4b1d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:26 2021 +0000

    New translations entities.php (Ukrainian)

commit 8d819bac39
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Jan 2 00:31:24 2021 +0000

    New translations settings.php (Chinese Simplified)

commit 77bf64160c
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Dec 22 07:39:40 2020 +0000

    New translations settings.php (Chinese Simplified)

commit 24df157734
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 21 17:11:43 2020 +0000

    New translations settings.php (French)

commit 28cde11dc2
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 21 13:12:33 2020 +0000

    New translations settings.php (Swedish)

commit 630174f8e4
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 21 13:12:31 2020 +0000

    New translations entities.php (Swedish)

commit a40fc2203b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Dec 19 01:26:57 2020 +0000

    New translations settings.php (Spanish)

commit abbdb233c4
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:08:01 2020 +0000

    New translations settings.php (German Informal)

commit f7a8cae968
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:59 2020 +0000

    New translations settings.php (German)

commit e793fe8929
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:58 2020 +0000

    New translations settings.php (French)

commit f1efd0f559
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:56 2020 +0000

    New translations settings.php (Spanish)

commit 6fbec6be40
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:54 2020 +0000

    New translations settings.php (Bulgarian)

commit 708f5b1158
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:52 2020 +0000

    New translations settings.php (Czech)

commit 7c978c5822
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:50 2020 +0000

    New translations settings.php (Danish)

commit 875138d217
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:48 2020 +0000

    New translations settings.php (Hebrew)

commit ba24274078
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:46 2020 +0000

    New translations settings.php (Hungarian)

commit bd5fdbe981
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:45 2020 +0000

    New translations settings.php (Italian)

commit 62d71a20d7
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:43 2020 +0000

    New translations settings.php (Japanese)

commit a83f9bccb4
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:41 2020 +0000

    New translations settings.php (Korean)

commit 306a18aa87
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:39 2020 +0000

    New translations settings.php (Chinese Simplified)

commit 75724a14f2
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:37 2020 +0000

    New translations settings.php (Dutch)

commit b21ba5e3b7
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:35 2020 +0000

    New translations settings.php (Russian)

commit c292ef1389
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:33 2020 +0000

    New translations settings.php (Slovak)

commit f0dd37d476
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:32 2020 +0000

    New translations settings.php (Slovenian)

commit 0ffeadb959
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:30 2020 +0000

    New translations settings.php (Swedish)

commit 9dfd89120d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:28 2020 +0000

    New translations settings.php (Turkish)

commit f90d1056eb
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:26 2020 +0000

    New translations settings.php (Ukrainian)

commit 064222468a
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:24 2020 +0000

    New translations settings.php (Chinese Traditional)

commit 9dd05cc3e8
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:22 2020 +0000

    New translations settings.php (Vietnamese)

commit 70867261f0
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:20 2020 +0000

    New translations settings.php (Portuguese, Brazilian)

commit ff0c8151d0
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:19 2020 +0000

    New translations settings.php (Spanish, Argentina)

commit 53658cada6
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:16 2020 +0000

    New translations settings.php (Polish)

commit 223c4005ae
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 23:07:15 2020 +0000

    New translations settings.php (Arabic)

commit 503f166cc1
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 18 17:09:41 2020 +0000

    New translations entities.php (Chinese Simplified)

commit 401ecbb930
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 14:08:21 2020 +0000

    New translations validation.php (German)

commit de0d58658a
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 14:08:19 2020 +0000

    New translations settings.php (German)

commit 32b7036405
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 13:27:48 2020 +0000

    New translations settings.php (German)

commit 212f1f7639
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 13:27:46 2020 +0000

    New translations activities.php (German)

commit 853162082b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 13:27:44 2020 +0000

    New translations entities.php (German)

commit 9c72dc7a5e
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 12:55:26 2020 +0000

    New translations activities.php (German)

commit 261f71a6f4
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 07:52:54 2020 +0000

    New translations entities.php (Spanish)

commit e2d5ba8ff5
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 07:52:52 2020 +0000

    New translations entities.php (French)

commit 8ec28c59b2
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:49:08 2020 +0000

    New translations entities.php (German Informal)

commit dc8aec2b94
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:49:06 2020 +0000

    New translations entities.php (Spanish)

commit baa0cb24a3
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:49:04 2020 +0000

    New translations entities.php (Bulgarian)

commit 4c312d5d5b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:49:02 2020 +0000

    New translations entities.php (Czech)

commit e8c06380c6
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:49:00 2020 +0000

    New translations entities.php (Danish)

commit 79844ed95c
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:58 2020 +0000

    New translations entities.php (German)

commit f6177c301d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:56 2020 +0000

    New translations entities.php (Hebrew)

commit bc0d5cc853
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:54 2020 +0000

    New translations entities.php (Hungarian)

commit dfbeb4415f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:52 2020 +0000

    New translations entities.php (Italian)

commit 851ab730fb
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:50 2020 +0000

    New translations entities.php (Japanese)

commit a5cc758017
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:48 2020 +0000

    New translations entities.php (Korean)

commit 94e8b1fc0f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:46 2020 +0000

    New translations entities.php (Dutch)

commit 5ad322e822
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:44 2020 +0000

    New translations entities.php (French)

commit 69e709254e
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:42 2020 +0000

    New translations entities.php (Polish)

commit a54d3ad498
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:41 2020 +0000

    New translations entities.php (Slovak)

commit 9e5ec3e252
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:39 2020 +0000

    New translations entities.php (Slovenian)

commit 6fa88c13b7
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:37 2020 +0000

    New translations entities.php (Swedish)

commit 40528d97b2
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:35 2020 +0000

    New translations entities.php (Turkish)

commit 93303e6a13
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:33 2020 +0000

    New translations entities.php (Ukrainian)

commit fe9b70ced1
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:31 2020 +0000

    New translations entities.php (Chinese Simplified)

commit 4e34047747
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:29 2020 +0000

    New translations entities.php (Chinese Traditional)

commit 71e8f850dc
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:28 2020 +0000

    New translations entities.php (Vietnamese)

commit 9cb1542f0b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:26 2020 +0000

    New translations entities.php (Portuguese, Brazilian)

commit 35658ff827
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:24 2020 +0000

    New translations entities.php (Spanish, Argentina)

commit 6f75d1d972
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:22 2020 +0000

    New translations entities.php (Russian)

commit acf2ae03f3
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 17 02:48:20 2020 +0000

    New translations entities.php (Arabic)

commit c2f1e0d474
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Dec 15 10:49:10 2020 +0000

    New translations settings.php (Chinese Simplified)

commit ef64a956d2
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Dec 15 10:22:49 2020 +0000

    New translations settings.php (Chinese Simplified)

commit c14a1fe8db
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Dec 8 19:49:01 2020 +0000

    New translations validation.php (Arabic)

commit 73df1e1b88
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Dec 8 19:21:05 2020 +0000

    New translations validation.php (Arabic)

commit 231ccc8494
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Dec 8 18:52:38 2020 +0000

    New translations validation.php (Arabic)

commit 9f4039ad01
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Dec 8 18:09:41 2020 +0000

    New translations validation.php (Arabic)

commit c011045d5e
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Dec 8 17:31:18 2020 +0000

    New translations settings.php (Arabic)

commit b3e6888e31
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Dec 8 17:01:37 2020 +0000

    New translations settings.php (Arabic)

commit eaf13fb98d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Dec 8 15:11:11 2020 +0000

    New translations settings.php (Arabic)

commit 3f8585b81f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Dec 8 14:31:37 2020 +0000

    New translations settings.php (Arabic)

commit 84467849bf
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Dec 8 14:02:31 2020 +0000

    New translations settings.php (Arabic)

commit 185747b5e7
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Dec 8 13:34:36 2020 +0000

    New translations settings.php (Arabic)

commit 63201489d3
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Dec 8 13:06:27 2020 +0000

    New translations settings.php (Arabic)

commit f71d784ca5
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Dec 8 12:27:39 2020 +0000

    New translations settings.php (Arabic)

commit 188670ee9a
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Dec 8 11:55:04 2020 +0000

    New translations settings.php (Arabic)

commit 8674b284e9
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 22:59:30 2020 +0000

    New translations settings.php (Arabic)

commit 1589910fa4
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 22:31:22 2020 +0000

    New translations settings.php (Arabic)

commit bc99709e51
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 21:56:46 2020 +0000

    New translations passwords.php (Arabic)

commit c5e89e997c
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 21:56:44 2020 +0000

    New translations errors.php (Arabic)

commit 7a33938d5f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 21:56:42 2020 +0000

    New translations settings.php (Arabic)

commit 30de30d4bf
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 21:28:31 2020 +0000

    New translations errors.php (Arabic)

commit b4e028dc51
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 20:29:51 2020 +0000

    New translations entities.php (Arabic)

commit d6e056b0ad
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 20:29:49 2020 +0000

    New translations errors.php (Arabic)

commit 4edb96f2bb
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 19:59:59 2020 +0000

    New translations entities.php (Arabic)

commit c51cdf2936
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 19:33:28 2020 +0000

    New translations entities.php (Arabic)

commit afb058d36d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 18:57:54 2020 +0000

    New translations entities.php (Arabic)

commit 3b96a6d06b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 18:29:05 2020 +0000

    New translations entities.php (Arabic)

commit 874a40da76
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 17:53:03 2020 +0000

    New translations entities.php (Arabic)

commit e1c7f7e6a3
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 17:19:51 2020 +0000

    New translations entities.php (Arabic)

commit 1e921679c2
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 16:40:54 2020 +0000

    New translations entities.php (Arabic)

commit ffcfe54d65
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 14:56:17 2020 +0000

    New translations components.php (Arabic)

commit cb73a23985
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 14:56:15 2020 +0000

    New translations common.php (Arabic)

commit 8695dfe078
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 14:20:19 2020 +0000

    New translations validation.php (Chinese Simplified)

commit 671f9ec07b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 14:20:18 2020 +0000

    New translations activities.php (Chinese Simplified)

commit d9072286d7
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 14:20:16 2020 +0000

    New translations common.php (Arabic)

commit 8d4c07decc
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 14:20:14 2020 +0000

    New translations settings.php (Chinese Simplified)

commit 9f44955b55
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Dec 7 13:47:48 2020 +0000

    New translations settings.php (Chinese Simplified)

commit fe2914d07b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Dec 5 18:36:25 2020 +0000

    New translations auth.php (Arabic)

commit f9bf9da8bb
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Dec 5 05:59:40 2020 +0000

    New translations settings.php (Chinese Simplified)

commit 2d3ee7ceaf
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Dec 4 02:28:44 2020 +0000

    New translations errors.php (Arabic)

commit 49359be73e
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 3 20:27:57 2020 +0000

    New translations common.php (Arabic)

commit 97df834566
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 3 20:27:56 2020 +0000

    New translations auth.php (Arabic)

commit 73e5cbf8ab
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 3 20:27:54 2020 +0000

    New translations activities.php (Arabic)

commit 248e70dfc6
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Dec 3 19:58:00 2020 +0000

    New translations settings.php (Arabic)

commit b616c03db6
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Nov 30 20:29:48 2020 +0000

    New translations auth.php (Slovak)

commit c7978833a9
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Nov 30 20:29:46 2020 +0000

    New translations activities.php (Slovak)

commit 589d4ea407
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Nov 30 20:01:41 2020 +0000

    New translations activities.php (Slovak)

commit 4ae7e4f1cd
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 23:48:32 2020 +0000

    New translations settings.php (Portuguese, Brazilian)

commit 9b60eb7e6b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 23:18:00 2020 +0000

    New translations settings.php (Portuguese, Brazilian)

commit c02c0fc237
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 20:20:52 2020 +0000

    New translations auth.php (Slovenian)

commit bb742db8eb
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 19:54:55 2020 +0000

    New translations validation.php (Slovenian)

commit 159d4367ef
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 14:06:49 2020 +0000

    New translations validation.php (Swedish)

commit 1c95c87981
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 14:06:47 2020 +0000

    New translations activities.php (Swedish)

commit 4d869414d5
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 14:06:45 2020 +0000

    New translations settings.php (Swedish)

commit 3fbefead8f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 09:52:12 2020 +0000

    New translations settings.php (Slovenian)

commit 57170d5af7
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 09:07:31 2020 +0000

    New translations settings.php (Slovenian)

commit 62ec0fc156
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 08:40:38 2020 +0000

    New translations passwords.php (Slovenian)

commit 9133bd129b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 08:40:36 2020 +0000

    New translations pagination.php (Slovenian)

commit fde76e7eb8
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 08:40:34 2020 +0000

    New translations errors.php (Slovenian)

commit 321e495024
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 08:40:31 2020 +0000

    New translations settings.php (Slovenian)

commit d982458c90
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 08:11:18 2020 +0000

    New translations errors.php (Slovenian)

commit 8fc4571743
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 08:11:16 2020 +0000

    New translations entities.php (Slovenian)

commit 0a83121214
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 07:16:09 2020 +0000

    New translations entities.php (Slovenian)

commit ff4a76a102
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 06:49:09 2020 +0000

    New translations entities.php (Slovenian)

commit a0d254e0a6
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 06:18:19 2020 +0000

    New translations entities.php (Slovenian)

commit c57b8348e8
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 05:38:04 2020 +0000

    New translations components.php (Slovenian)

commit 8fe04e76be
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 05:38:02 2020 +0000

    New translations common.php (Slovenian)

commit 39e92b0e0d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 05:07:51 2020 +0000

    New translations common.php (Slovenian)

commit ea76a7ebd8
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 05:07:50 2020 +0000

    New translations activities.php (Slovenian)

commit 8f710f8b8a
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 26 04:37:47 2020 +0000

    New translations activities.php (Slovenian)

commit ffdd1e213d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sun Nov 22 12:09:18 2020 +0000

    New translations activities.php (French)

commit 9e2f0e9c87
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sun Nov 22 12:09:16 2020 +0000

    New translations settings.php (French)

commit 4faacad5ac
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:56:47 2020 +0000

    New translations activities.php (Spanish)

commit ae555d65e8
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:56:45 2020 +0000

    New translations settings.php (Spanish)

commit 19929c893d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:35 2020 +0000

    New translations activities.php (German Informal)

commit 72ab8cc461
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:33 2020 +0000

    New translations settings.php (Spanish, Argentina)

commit e3da50c52d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:31 2020 +0000

    New translations settings.php (Portuguese, Brazilian)

commit 1594fec763
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:30 2020 +0000

    New translations settings.php (Vietnamese)

commit b220afcbcb
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:28 2020 +0000

    New translations settings.php (Chinese Traditional)

commit 18ed9ecf20
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:26 2020 +0000

    New translations settings.php (Chinese Simplified)

commit 8f336c444c
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:25 2020 +0000

    New translations settings.php (Ukrainian)

commit d84e61e02e
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:23 2020 +0000

    New translations settings.php (Turkish)

commit 3c410a9121
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:21 2020 +0000

    New translations settings.php (Slovenian)

commit ab37f7a9fd
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:19 2020 +0000

    New translations settings.php (Slovak)

commit 432a1a8090
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:18 2020 +0000

    New translations settings.php (Russian)

commit 5a65dfabaf
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:16 2020 +0000

    New translations settings.php (Polish)

commit 7b731a19d5
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:14 2020 +0000

    New translations settings.php (German Informal)

commit 90ba8bf7b9
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:12 2020 +0000

    New translations settings.php (Dutch)

commit 8eb94f8faf
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:10 2020 +0000

    New translations settings.php (Japanese)

commit 5c4f07f5ef
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:09 2020 +0000

    New translations settings.php (Italian)

commit 892c2b6648
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:07 2020 +0000

    New translations settings.php (Hungarian)

commit 746924a3d9
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:05 2020 +0000

    New translations settings.php (Hebrew)

commit 3a3fcb8af2
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:03 2020 +0000

    New translations settings.php (German)

commit 6263182593
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:02 2020 +0000

    New translations settings.php (Danish)

commit fbd52a81c6
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:18:00 2020 +0000

    New translations settings.php (Czech)

commit bf2a2cddf2
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:58 2020 +0000

    New translations settings.php (Bulgarian)

commit f87af24738
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:56 2020 +0000

    New translations settings.php (Arabic)

commit e4e7930702
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:55 2020 +0000

    New translations settings.php (Spanish)

commit 1e74a74d18
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:53 2020 +0000

    New translations settings.php (Korean)

commit eeb0c0cd25
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:51 2020 +0000

    New translations settings.php (French)

commit 16ce659aa7
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:49 2020 +0000

    New translations activities.php (French)

commit 6bdda1c8b0
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:47 2020 +0000

    New translations activities.php (Arabic)

commit 3bf57e068f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:46 2020 +0000

    New translations activities.php (Spanish, Argentina)

commit 29b767c487
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:44 2020 +0000

    New translations activities.php (Portuguese, Brazilian)

commit 1a5223a346
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:43 2020 +0000

    New translations activities.php (Vietnamese)

commit 431eb55781
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:41 2020 +0000

    New translations activities.php (Chinese Traditional)

commit 510cc653fe
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:39 2020 +0000

    New translations activities.php (Chinese Simplified)

commit 2270e5a0d4
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:38 2020 +0000

    New translations activities.php (Ukrainian)

commit 89d4410062
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:36 2020 +0000

    New translations activities.php (Turkish)

commit 021ac828b2
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:34 2020 +0000

    New translations activities.php (Swedish)

commit 3d23b3f0c9
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:33 2020 +0000

    New translations activities.php (Slovenian)

commit 8504d11fc7
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:31 2020 +0000

    New translations activities.php (Slovak)

commit a81b167efd
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:30 2020 +0000

    New translations activities.php (Spanish)

commit bec7efca48
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:28 2020 +0000

    New translations activities.php (Russian)

commit 45ca2fd453
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:26 2020 +0000

    New translations activities.php (Dutch)

commit e30a3eb6a8
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:25 2020 +0000

    New translations activities.php (Korean)

commit 35476844f6
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:23 2020 +0000

    New translations activities.php (Japanese)

commit d6e3e61a63
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:22 2020 +0000

    New translations activities.php (Italian)

commit 3a80e68289
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:20 2020 +0000

    New translations activities.php (Hungarian)

commit 1b3efcdb62
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:18 2020 +0000

    New translations activities.php (Hebrew)

commit 59fcf3c4eb
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:17 2020 +0000

    New translations activities.php (German)

commit 8e838d09bc
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:15 2020 +0000

    New translations activities.php (Danish)

commit 67a43a5ba3
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:13 2020 +0000

    New translations activities.php (Czech)

commit cb166b1980
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:12 2020 +0000

    New translations activities.php (Bulgarian)

commit 5c86cc3dfc
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:10 2020 +0000

    New translations activities.php (Polish)

commit 0a9d90ef69
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 21 16:17:09 2020 +0000

    New translations settings.php (Swedish)

commit d57f402a00
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 19 06:09:10 2020 +0000

    New translations errors.php (Vietnamese)

commit 71ce4bfd1f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 19 06:09:08 2020 +0000

    New translations settings.php (Vietnamese)

commit 95adbaa0a9
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 19 05:39:57 2020 +0000

    New translations validation.php (Vietnamese)

commit 23f1e2b763
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 19 05:39:55 2020 +0000

    New translations passwords.php (Vietnamese)

commit efee1392d2
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 19 05:39:53 2020 +0000

    New translations entities.php (Vietnamese)

commit 8154f8648d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 19 05:39:52 2020 +0000

    New translations components.php (Vietnamese)

commit 5632f64d80
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 19 05:39:50 2020 +0000

    New translations common.php (Vietnamese)

commit 051c0b7896
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 19 05:39:48 2020 +0000

    New translations auth.php (Vietnamese)

commit 14b125d325
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Nov 17 02:37:49 2020 +0000

    New translations settings.php (Portuguese, Brazilian)

commit ee9692e65d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Nov 17 01:58:45 2020 +0000

    New translations settings.php (Portuguese, Brazilian)

commit df140ca216
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sun Nov 15 09:19:28 2020 +0000

    New translations settings.php (French)

commit ee691853dc
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sun Nov 15 08:47:39 2020 +0000

    New translations entities.php (French)

commit cc22bcf166
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 12 11:39:15 2020 +0000

    New translations entities.php (Hungarian)

commit a0f21aeebd
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 12 11:39:13 2020 +0000

    New translations components.php (Hungarian)

commit 437cd823b8
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 12 11:39:12 2020 +0000

    New translations common.php (Hungarian)

commit 367ba587c7
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Nov 12 11:39:09 2020 +0000

    New translations settings.php (Hungarian)

commit d656b9b982
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sun Nov 8 21:58:02 2020 +0000

    New translations settings.php (French)

commit f3ffe9b7c5
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sun Nov 8 21:27:30 2020 +0000

    New translations settings.php (French)

commit cc9e48f3af
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 18:21:29 2020 +0000

    New translations settings.php (Spanish)

commit cbb5aeaca4
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 17:26:14 2020 +0000

    New translations settings.php (Spanish)

commit addb0abc7c
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:19:00 2020 +0000

    New translations settings.php (German Informal)

commit d9912d7cda
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:58 2020 +0000

    New translations settings.php (Spanish)

commit b72960c002
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:57 2020 +0000

    New translations settings.php (Arabic)

commit 99248fdced
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:55 2020 +0000

    New translations settings.php (Bulgarian)

commit 3ac52510ee
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:53 2020 +0000

    New translations settings.php (Czech)

commit eea823faf3
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:51 2020 +0000

    New translations settings.php (Danish)

commit feea7f8c55
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:50 2020 +0000

    New translations settings.php (German)

commit 91a9441c60
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:48 2020 +0000

    New translations settings.php (Hebrew)

commit ec8020e36d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:46 2020 +0000

    New translations settings.php (Hungarian)

commit 0c4e394024
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:45 2020 +0000

    New translations settings.php (Italian)

commit 3527571d92
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:43 2020 +0000

    New translations settings.php (Japanese)

commit eaade5cf89
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:41 2020 +0000

    New translations settings.php (Korean)

commit e6383352bd
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:39 2020 +0000

    New translations settings.php (French)

commit ce2f779683
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:38 2020 +0000

    New translations settings.php (Dutch)

commit 1ea58e2da1
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:36 2020 +0000

    New translations settings.php (Russian)

commit 399b765d6f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:34 2020 +0000

    New translations settings.php (Slovak)

commit 1be992e9be
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:33 2020 +0000

    New translations settings.php (Slovenian)

commit 9b54b832e9
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:31 2020 +0000

    New translations settings.php (Turkish)

commit a7df19eef9
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:29 2020 +0000

    New translations settings.php (Ukrainian)

commit 2210d9d1a6
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:28 2020 +0000

    New translations settings.php (Chinese Simplified)

commit 72874dcfd4
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:26 2020 +0000

    New translations settings.php (Chinese Traditional)

commit b8d86a48ad
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:24 2020 +0000

    New translations settings.php (Vietnamese)

commit 54848d0c48
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:23 2020 +0000

    New translations settings.php (Portuguese, Brazilian)

commit 25cb81b85f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:21 2020 +0000

    New translations settings.php (Spanish, Argentina)

commit 5d318c1281
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:19 2020 +0000

    New translations settings.php (Polish)

commit b6aaba3496
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Nov 7 15:18:18 2020 +0000

    New translations settings.php (Swedish)

commit 820959b7df
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Nov 3 12:01:14 2020 +0000

    New translations validation.php (Russian)

commit 2527970488
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sun Nov 1 18:36:50 2020 +0000

    New translations validation.php (French)

commit d7edc4440d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 18:08:28 2020 +0000

    New translations validation.php (Spanish)

commit e91ffcb06f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:44 2020 +0000

    New translations validation.php (German Informal)

commit 64d67bec66
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:42 2020 +0000

    New translations validation.php (Arabic)

commit 387f20c865
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:41 2020 +0000

    New translations validation.php (Bulgarian)

commit 73b59470c2
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:39 2020 +0000

    New translations validation.php (Czech)

commit 12cec9b4c1
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:38 2020 +0000

    New translations validation.php (Danish)

commit 151c518683
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:36 2020 +0000

    New translations validation.php (German)

commit 6b1beff616
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:34 2020 +0000

    New translations validation.php (Hebrew)

commit 746c5f99fa
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:33 2020 +0000

    New translations validation.php (Hungarian)

commit d295fbc104
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:31 2020 +0000

    New translations validation.php (Italian)

commit ac828a6f92
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:30 2020 +0000

    New translations validation.php (Japanese)

commit 5a58e1010b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:28 2020 +0000

    New translations validation.php (Korean)

commit faeb298d66
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:27 2020 +0000

    New translations validation.php (Dutch)

commit b6450b012c
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:25 2020 +0000

    New translations validation.php (Spanish)

commit 8bc8bf1dd4
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:23 2020 +0000

    New translations validation.php (Polish)

commit 7361e41ef9
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:22 2020 +0000

    New translations validation.php (Slovak)

commit 2994fd900c
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:20 2020 +0000

    New translations validation.php (Slovenian)

commit 00e3803591
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:18 2020 +0000

    New translations validation.php (Swedish)

commit fb07b50ac0
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:17 2020 +0000

    New translations validation.php (Turkish)

commit 35f9f42517
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:15 2020 +0000

    New translations validation.php (Ukrainian)

commit 53c566289b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:14 2020 +0000

    New translations validation.php (Chinese Simplified)

commit f404ed79f1
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:12 2020 +0000

    New translations validation.php (Chinese Traditional)

commit 0b91647b17
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:10 2020 +0000

    New translations validation.php (Vietnamese)

commit 7f9be00e7f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:08 2020 +0000

    New translations validation.php (Portuguese, Brazilian)

commit 7e343bdfd9
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:07 2020 +0000

    New translations validation.php (Spanish, Argentina)

commit f2b5066533
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:05 2020 +0000

    New translations validation.php (Russian)

commit bdc22b7a24
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Oct 31 16:58:04 2020 +0000

    New translations validation.php (French)

commit ac6cd8c80a
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Oct 30 10:51:25 2020 +0000

    New translations settings.php (Swedish)

commit 72188ca92f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Oct 30 10:51:24 2020 +0000

    New translations passwords.php (Swedish)

commit 371ade8f33
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Oct 30 10:51:22 2020 +0000

    New translations entities.php (Swedish)

commit 0f69dafe97
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Oct 30 10:51:21 2020 +0000

    New translations components.php (Swedish)

commit 2a4607bb3f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Oct 30 10:51:19 2020 +0000

    New translations common.php (Swedish)

commit 359c132354
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Oct 30 10:51:17 2020 +0000

    New translations auth.php (Swedish)

commit eb5f7b13da
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Oct 23 18:22:40 2020 +0100

    New translations settings.php (Ukrainian)

commit b844928ee1
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Oct 23 17:51:17 2020 +0100

    New translations settings.php (Ukrainian)

commit 06af684aa4
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Oct 22 22:03:20 2020 +0100

    New translations settings.php (Ukrainian)

commit 27e499efe8
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Oct 22 21:11:53 2020 +0100

    New translations settings.php (Ukrainian)

commit 4994febc68
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Oct 22 21:11:51 2020 +0100

    New translations errors.php (Ukrainian)

commit de521b393b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Oct 22 21:11:49 2020 +0100

    New translations entities.php (Ukrainian)

commit 35cc7f933c
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Oct 22 21:11:47 2020 +0100

    New translations components.php (Ukrainian)

commit 04b2769fd5
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Oct 22 21:11:46 2020 +0100

    New translations common.php (Ukrainian)

commit 803c377b3b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Oct 22 13:31:18 2020 +0100

    New translations entities.php (Spanish, Argentina)

commit 5701efa78e
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Oct 22 13:31:16 2020 +0100

    New translations settings.php (Spanish, Argentina)

commit 11d85ebd71
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Thu Oct 22 13:04:52 2020 +0100

    New translations settings.php (Spanish, Argentina)

commit 271a7e0683
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Oct 16 15:50:10 2020 +0100

    New translations settings.php (Chinese Simplified)

commit 7a4663fba8
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Oct 16 14:18:38 2020 +0100

    New translations components.php (Korean)

commit 32b439a829
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Oct 16 14:18:36 2020 +0100

    New translations settings.php (Korean)

commit 5c70727c11
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Oct 16 13:42:10 2020 +0100

    New translations settings.php (Korean)

commit 9d66a04a2e
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Oct 16 13:42:09 2020 +0100

    New translations entities.php (Korean)

commit 4fcc18cd5a
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Oct 16 13:42:07 2020 +0100

    New translations common.php (Korean)
2021-01-02 17:49:57 +00:00
Dan Brown
024b0d8a64 Fixed restore revision save order, Added restore summary testing
Found during review of #2353, A revision would be stored before a
restore which would result with a duplicate revision and the new summary
would be assigned against the wrong content.
This change saves the revison after restore and adds test to check the
content and summary text.
2021-01-02 16:42:05 +00:00
Dan Brown
83d77d5166 Merge branch 'master' of git://github.com/rondaa/BookStack into rondaa-master 2021-01-02 16:25:59 +00:00
Dan Brown
e53e4f85c7 Aligned norwegian lang with others and used correct locale 2021-01-02 15:58:23 +00:00
Dan Brown
a04a800258 Merge branch 'master' of git://github.com/Swoy/BookStack into Swoy-master 2021-01-02 15:45:18 +00:00
Dan Brown
e6ea53b3e6 Merge pull request #2416 from shubhamosmosys/master
Fix issue with viewing export dropdown list
2021-01-02 15:36:35 +00:00
Dan Brown
fd67f61b43 Merge branch 'master' of github.com:BookStackApp/BookStack 2021-01-02 02:46:25 +00:00
Dan Brown
92922288dd Added iframe CSP, improved session cookie security
Added iframe CSP headers with configuration via .env.
Updated session cookies to be lax by default, dynamically changing to
none when iframes configured to allow third-party control.
Updated cookie security to be auto-secure if a https APP_URL is set.

Related to #2427 and #2207.
2021-01-02 02:43:50 +00:00
Dan Brown
280f1a0a5b Create FUNDING.yml 2021-01-02 01:25:49 +00:00
Dan Brown
588fd7d165 Fixed short editor in firefox and optimised some queries
Optimised permission fetching so that it won't initialise a bunch
of models for the role permissions and instead does a manual
query to get the data directly.
2021-01-02 01:22:41 +00:00
Dan Brown
857d9ed3f1 Merge pull request #2436 from BookStackApp/ownership_system
Entity Ownership System
2021-01-02 00:29:22 +00:00
Dan Brown
d27875bad1 Added owner field to DummyContentSeeder 2021-01-02 00:09:29 +00:00
Dan Brown
de989ffa9a Tested new ownership + (delete/change) systems 2021-01-01 23:58:53 +00:00
Dan Brown
b43f997dab Added manual type conversion to fix failing tests 2021-01-01 18:38:54 +00:00
Dan Brown
5e686bb624 Added user ownership migrate to delete screen. 2021-01-01 18:31:01 +00:00
Dan Brown
99b14621f9 Moved permission updating to its own tool
And added support for owner changing.
2021-01-01 17:49:48 +00:00
Dan Brown
da9083bf1f Fixed view path 2020-12-31 17:27:23 +00:00
Dan Brown
8833b5bc3b Added user-select input 2020-12-31 17:25:20 +00:00
Dan Brown
33e35c9a8a Converted breadcrumb-listing to new component system 2020-12-31 15:27:25 +00:00
Dan Brown
e408067b10 Fixed test helper method signature 2020-12-30 22:25:10 +00:00
Dan Brown
4c580d1571 Added owners to entity creation and updated tests 2020-12-30 22:18:28 +00:00
Dan Brown
b493becadf Started change for entities to have concept of owners 2020-12-30 18:25:35 +00:00
Dan Brown
c71f00b2ec Updated readme newsletter links 2020-12-30 16:51:55 +00:00
James Geiger
e458411f91 Create Open Graph meta tags for book/page/chapter/shelf 2020-12-21 23:20:13 -06:00
Shubham Tiwari
564f4f7c74 Remove unnecessary changes 2020-12-21 11:53:33 +05:30
Dan Brown
4e82d93350 Updated wording of image cleanup option
As per #2352
2020-12-18 22:59:47 +00:00
Dan Brown
f1e1a745b0 Fixed failing home test after changes in last commit
Also made a restriction test more reliable.
Also renamed restrictionstest to entitypermissionstest to be more
consistent with newer app wording.
2020-12-18 21:44:35 +00:00
Dan Brown
4b4642c8ea Aligned book and shelf grid item views
Updated the titles so they are limited via CSS rather than by a
estimated hardcoded limit.

For #1469
2020-12-18 21:26:22 +00:00
Dan Brown
2b603b0488 Updated deps based on changes done for php8 readiness
Commit cherry-picked from branch then made further changes.
Updates min php version.
2020-12-18 20:29:33 +00:00
Dan Brown
20bb76afdb Fixed changed namespaces for merged test 2020-12-18 20:04:48 +00:00
Dan Brown
cf04a0d818 Merge branch 'v0.30.x' 2020-12-18 14:16:13 +00:00
Dan Brown
66a746e297 Updated version for release v0.30.7 2020-12-18 14:13:40 +00:00
Dan Brown
a4d43ee24b Merge branch 'v0.30.x' into release 2020-12-18 14:13:19 +00:00
Dan Brown
2acef3c2ec Fixed issue where restricted page content in plaintext export
The content of pages made non-viewable to a user via permissions, within a visible parent, could be seen via the plaintext export option. Before v0.30.6 this would have applied only to scenarios where all pages within the chapter were made non-visible. In v0.30.6 this would make all pages within the chapter visible.

As per #2414
2020-12-18 13:56:00 +00:00
Dan Brown
9884cca00c Merge branch 'v0.30.x' 2020-12-17 21:47:59 +00:00
Dan Brown
f7793a70a9 Updated version for release v0.30.6 2020-12-17 21:07:06 +00:00
Dan Brown
ceba3d31fb Merge branch 'v0.30.x' into release 2020-12-17 21:03:20 +00:00
Dan Brown
3f3fad7113 Fixed book-tree-gen page visibility issue
When book trees were generated, pages in chapters where ALL pages within
were not supposed to be visibile, would be visible due to the code
falling back on the raw relation which would not account for
permissions.

This has now been changed so that a custom 'visible_pages' attribute is set and used by any book tree structures, to ensure it does not fall back to the raw relation.

Added an extra test to cover.

For #2414
2020-12-17 17:31:18 +00:00
shubhamosmosys
d7e0d3e2d6 Fix issue with viewing export dropdown list
There is issue with viewing all the export list
2020-12-17 19:47:15 +05:30
Dan Brown
5ab0db9690 Updated chapter delete wording to fit with new logic 2020-12-17 02:29:53 +00:00
Dan Brown
00308ad4ab Cleaned up some user/image areas of the app
Further cleanup of docblocks and standardisation of repos.
2020-12-08 23:46:38 +00:00
Dan Brown
6c09334ba0 Fixed issue where page export contain system would miss images 2020-12-06 22:23:21 +00:00
Dan Brown
65b2c90522 Merge branch 'v0.30.x' 2020-12-06 21:32:01 +00:00
Dan Brown
eecc08edde Updated version for release v0.30.5 2020-12-06 21:05:43 +00:00
Dan Brown
eb19aadc75 Merge branch 'v0.30.x' into release 2020-12-06 21:05:11 +00:00
Dan Brown
884664bfe9 Ensured base64 images are read from image upload folder
Also removed unused storage systems and updated testing.
2020-12-06 15:34:18 +00:00
Dan Brown
8911e3f441 Removed http fetching from image base64 generation 2020-12-06 14:24:22 +00:00
Dan Brown
7d38c96a23 Removed generic "UploadService" which was doing very little 2020-12-06 12:58:40 +00:00
Dan Brown
162d893143 Updated .env.example to encorage use of setting APP_URL
For the purposes of secure URL generation and to avoid common problems
found when people are using reverse proxies.
2020-12-06 12:31:36 +00:00
James Geiger
4b36df08a8 Merge pull request #1 from BookStackApp/master
Update from base/master
2020-12-03 11:39:06 -06:00
Dan Brown
0b01a77c16 Swapped out HTML diff implementation for own, removes tidy depdendancy 2020-11-29 19:08:13 +00:00
Dan Brown
bf8716bb22 Fixed bad collection/array mixing causing error on seed 2020-11-28 16:42:12 +00:00
Dan Brown
d56e7e7c79 Merge pull request #2382 from BookStackApp/pages_api
Pages API
2020-11-28 16:31:35 +00:00
Dan Brown
57754c8211 Added testing to cover the pages API 2020-11-28 16:30:30 +00:00
Dan Brown
8aedba14a3 Added page export API controller 2020-11-28 15:39:40 +00:00
Dan Brown
875a8bdaff Made docs sidebar a slight bit easier to scroll
Now it easily goes off the page, made it indapentally scrollable.
Will probably do something different in future as it grows more.
2020-11-28 15:28:44 +00:00
Dan Brown
53bcfe528d Added pages API doc examples
Made some tweaks to related content and other examples while there.
2020-11-28 15:21:54 +00:00
Dan Brown
1c8102bb89 Started pages API 2020-11-22 14:56:19 +00:00
Dan Brown
ebeca256f0 Updated old exportService name in controllers 2020-11-22 01:26:14 +00:00
Dan Brown
a042e22481 Focused base Entity class cleanup
Removed some common functions from other entities.
Aligned implementation of getUrl()
Cleaned phpdocs and added typehinting.
Also extracted sibling search logic out of controller.
2020-11-22 01:20:38 +00:00
Dan Brown
ef1b98019a Fixed some mis-refactoring and split search service
Search service broken into index and runner tools.
2020-11-22 00:17:45 +00:00
Dan Brown
c7a2d568bf Moved models to folder, renamed managers to tools
Tools seems to fit better since the classes were a bit of a mixed bunch
and did not always manage.
Also simplified the structure of the SlugGenerator class.
Also focused EntityContext on shelves and simplified to use session
helper.
2020-11-21 23:20:54 +00:00
Dan Brown
66917520cb Service provider and other cleanup
- Removed old 'exposeTranslations' system to instead use new component
 option system.
- Extracted validation rules into their own service provider.
- Cleaned up some formatting/comments in the repos.
2020-11-21 17:52:49 +00:00
Dan Brown
5e01c30882 Aligned constructors across controller classes
Since they no longer needed to run the parent contructor
since the parent constructor was no longer needed.
2020-11-21 17:08:37 +00:00
Dan Brown
f76a2a69f7 Cleaned up api docs implementation, added missing titles 2020-11-21 17:03:24 +00:00
Dan Brown
65ddd16532 Merge pull request #2360 from BookStackApp/activity_revamp
Tracked activity update
2020-11-21 16:12:25 +00:00
Dan Brown
c0680d5717 Added latest activity into users list view 2020-11-20 20:10:18 +00:00
Dan Brown
bd6a1a66d1 Implemented remainder of activity types
Also fixed audit log to work for non-entity items.
2020-11-20 19:33:11 +00:00
Dan Brown
da37700ac2 Implemented user, api_tokem & role activity logging
Also refactored some role content, primarily updating the permission
controller to be RoleController since it only dealt with roles.
2020-11-20 18:53:01 +00:00
Dan Brown
3f7180fa99 Started widening of activity logging
In progress, Need to implement much of the logging in controllers.
Also cleaned up base controller along the way.
2020-11-18 23:40:39 +00:00
Boddy4
20f9a50cee LDAP: Added TLS support 2020-11-18 01:05:29 +01:00
Dan Brown
712ccd23c4 Updated activities table format
Renamed some columns to be more generic and applicable.
Removed now redundant book_id column.
Allowed nullable entity morph columns for non-entity activity.

Ran tests and made required changes.
2020-11-08 00:03:19 +00:00
Dan Brown
ee7e1122d3 Removed use of book_id in activity 2020-11-07 23:15:13 +00:00
Dan Brown
c157dc3490 Organised activity types and moved most to repos
Repos are generally better since otherwise we end up duplicating
things between front-end and API.

Types moved to by CONST values within a class for better visibilty
of usage and listing of types.
2020-11-07 22:37:27 +00:00
Dan Brown
4824ef2760 Merge pull request #2283 from BookStackApp/recycle_bin
Recycle Bin Implementation
2020-11-07 15:10:17 +00:00
Dan Brown
b4da081552 Checked over recycle bin parent/child flows 2020-11-07 15:05:13 +00:00
Dan Brown
df10b508d8 Enhanced how activities are shown on items in recycle bin 2020-11-07 14:28:50 +00:00
Dan Brown
ec3aeb3315 Added recycle bin auto-clear lifetime functionality 2020-11-07 13:58:23 +00:00
Dan Brown
68b1d87ebe Added test coverage of recycle bin actions 2020-11-07 13:19:23 +00:00
Dan Brown
483cb41665 Started testing work for recycle bin implementation 2020-11-06 12:54:39 +00:00
Anthony Ronda
34dc4a1b6d Automatic Restored Revision Changelog Summary Text 2020-11-03 20:46:47 -05:00
Dan Brown
3e70c661a1 Cleaned up duplicate code in recycle-bin restore 2020-11-02 22:54:00 +00:00
Dan Brown
9e033709a7 Added per-item recycle-bin delete and restore 2020-11-02 22:47:48 +00:00
Dan Brown
82e671a06d Re-aligned init files with Laravel default
Removed the custom init elements that we added in 2017 to
custom load the helpers file and instead load via composer.

Also removed laravel-microscope package due to not running due to
helpers file.
2020-10-31 23:05:48 +00:00
Dan Brown
474770af51 Merge branch 'fixes' of git://github.com/imanghafoori1/BookStack into imanghafoori1-fixes 2020-10-31 22:11:27 +00:00
Dan Brown
78be644332 Merge pull request #2298 from timoschwarzer/composer-install-in-entrypoint
Install composer dependencies in Docker entrypoint
2020-10-31 21:56:48 +00:00
Dan Brown
06c81e69b9 Updated version and assets for release v0.30.4 2020-10-31 16:52:33 +00:00
Dan Brown
3dc3d4a639 Merge branch 'master' into release 2020-10-31 16:51:54 +00:00
Dan Brown
6d8b0605a0 Merge branch 'xss_and_redir_patch' of git://github.com/PercussiveElbow/BookStack into xss_and_redirect 2020-10-31 15:19:33 +00:00
Dan Brown
349162ea13 Prevented possible XSS via link attachments
This filters out potentially malicious javascript: or data: uri's coming
through to be attached to attachments.
Added tests to cover.

Thanks to Yassine ABOUKIR (@yassineaboukir on twitter) for reporting this
vulnerability.
2020-10-31 15:01:52 +00:00
PercussiveElbow
bbd1384acb XSS and redirect fixes with test cases 2020-10-27 01:34:51 +00:00
Ole Aldric
36daa09441 Update Localization.php in Middleware with "no" tag for estimate. 2020-10-19 12:43:41 +02:00
Ole Aldric
4c5566755f updated config to also include Norwegian 2020-10-19 12:35:05 +02:00
Ole Aldric
461977cf9a added missing comma that caused the testprocess to fail. 2020-10-19 12:26:18 +02:00
Ole Aldric
837cccd4d4 Added translation for Norwegian (Bokmål)
This will add translations for Norwegian to BookStack. It is identified by the langID no_NB
2020-10-19 11:43:43 +02:00
imanghafoori
7a5442e81b Adds laravel-microscope package 2020-10-16 18:40:44 +03:30
imanghafoori
704b808e9e fixes from laravel-microscope 2020-10-16 18:40:10 +03:30
Dan Brown
6aa2bf9e27 Merge pull request #2296 from timoschwarzer/esbuild-watch-first-time-fix
Fix build:js:watch not building at first launch in Docker
2020-10-13 23:17:23 +01:00
Dan Brown
94c59c1e3d Updated version and assets for release v0.30.3 2020-10-13 22:50:52 +01:00
Dan Brown
4d2205853a Merge branch 'master' into release 2020-10-13 22:50:30 +01:00
Dan Brown
18bcafaee4 Updated translator attribution before release v0.30.3 2020-10-13 22:49:55 +01:00
Dan Brown
8d07b7cf1c Added alias for vbscript 2020-10-13 22:44:33 +01:00
Dan Brown
080f9c3025 Merge pull request #2302 from nutsflag/master
Add VBScript Codemirror
2020-10-13 22:41:09 +01:00
Dan Brown
617fe6bc8c Merge pull request #2303 from BookStackApp/l10n_master
New Crowdin updates
2020-10-13 22:39:52 +01:00
Dan Brown
bb1f1a9ecd Fixed error on drawing edit on markdown editor
Was preventing save of drawings.
For #2313
2020-10-13 22:36:07 +01:00
Jason Houle
a192b600fc Missed a variable when updating LdapService. 2020-10-12 12:47:36 -04:00
Jason Houle
b714652e10 Import thumbnail photos when LDAP users are created. 2020-10-12 12:33:55 -04:00
Dan Brown
d688e43197 New translations settings.php (Chinese Simplified) 2020-10-05 06:26:38 +01:00
Dan Brown
ff7cbd14fc Added recycle bin empty notification response with count 2020-10-03 18:53:09 +01:00
Dan Brown
04197e393a Started work on the recycle bin interface 2020-10-03 18:44:12 +01:00
Dan Brown
c82c3023c5 New translations settings.php (Spanish) 2020-10-02 17:18:27 +01:00
Dan Brown
d0d75afc66 New translations settings.php (Chinese Simplified) 2020-10-02 15:55:46 +01:00
nutsflag
467176ee78 Update code.js 2020-10-02 15:14:29 +02:00
nutsflag
521a002001 Update code-editor.blade.php 2020-10-02 15:13:31 +02:00
Timo Schwarzer
a74d551bd6 Install composer dependencies in Docker entrypoint 2020-10-01 11:34:56 +02:00
Timo Schwarzer
aca37b8784 Fix build:js:watch not building at first launch in Docker 2020-10-01 11:25:22 +02:00
Dan Brown
751772b87a Updated version and assets for release v0.30.2 2020-09-30 22:44:58 +01:00
Dan Brown
76e30869e1 Merge branch 'master' into release 2020-09-30 22:44:17 +01:00
Dan Brown
f3ee8f2d4c Updated http service to not read 204 response data 2020-09-30 22:32:03 +01:00
Dan Brown
ea406690f5 Updated esbuild options and version & updated npm deps
Had to change way sortable is imported due to changes, Still
seemed to have functioning multi-select.
2020-09-30 22:28:53 +01:00
Dan Brown
465d405926 Updated page content related links on content id changes
For #2278
2020-09-28 22:26:50 +01:00
Dan Brown
1097c61d6d Fixed duplicate requests in attachment manager issue
Closes #2286
2020-09-28 21:55:24 +01:00
Dan Brown
def2d61ad8 Merge pull request #2272 from jakubboucek/feature/fix-invalid-canonical-redirect
Fixed canonical redirects on non-root url app instances
2020-09-28 21:15:23 +01:00
Dan Brown
8b0f5e7000 Updated draw.io references to diagrams.net
Related to #2044
2020-09-28 20:45:38 +01:00
Dan Brown
691027a522 Started implementation of recycle bin functionality 2020-09-27 23:24:33 +01:00
Jakub Bouček
1e88e8086f Fixed canonical redirects on non-root url app instances
If BookStack instance is deployed to any non-root path, e.g. http://example.com/wiki/,
requests for http://example.com/wiki/shelves/
was redirected to http://example.com/shelves
instead of http://example.com/wiki/shelves

Synced with: https://github.com/laravel/laravel/blob/master/public/.htaccess
2020-09-27 02:50:37 +02:00
Dan Brown
d48ac0a37d Removed redundant test
Now replaced in recent commit by one that checks actual message gets
displayed on the redirect page.
Redirect page changed to login page.
2020-09-26 18:24:05 +01:00
Dan Brown
3edc9fe9eb Updated version and assets for release v0.30.1 2020-09-26 17:51:37 +01:00
Dan Brown
616c62703e Merge branch 'master' into release 2020-09-26 17:50:25 +01:00
Dan Brown
3eeb1e7d08 Updated translators fiel with latest 2020-09-26 17:48:02 +01:00
Dan Brown
0d43b50f9d New Crowdin updates (#2262)
* New translations entities.php (Russian)

* New translations settings.php (Russian)

* New translations entities.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations entities.php (Czech)

* New translations common.php (Czech)

* New translations components.php (Czech)

* New translations settings.php (Czech)

* New translations errors.php (Czech)

* New translations settings.php (Czech)

* New translations settings.php (Czech)

* New translations settings.php (Czech)

* New translations settings.php (German)

* New translations settings.php (German)

* New translations entities.php (German)

* New translations validation.php (Czech)

* New translations entities.php (Spanish, Argentina)

* New translations entities.php (German Informal)

* New translations settings.php (German Informal)

* New translations auth.php (Czech)
2020-09-26 17:46:32 +01:00
Dan Brown
6bcfac6751 Updated codemirror and updated codemirror base styles
Aligns styles with current release, since was causing overflow
with scrollbars.

Fixes #2267
2020-09-26 17:33:43 +01:00
Dan Brown
68489e5b44 Updated PR code to use isA and updated that function definition
Related to #2227
2020-09-26 17:00:17 +01:00
Dan Brown
fe0e307313 Merge branch 'renderpages' of git://github.com/mr-vinn/BookStack into mr-vinn-renderpages 2020-09-26 16:55:05 +01:00
Dan Brown
9985046685 Added test for includes on book export
Related to #2227
2020-09-26 16:54:24 +01:00
Dan Brown
53ec794e53 Fixed issue where SAML login not notifiy on existing user
Added testing to cover

Fixes #2263
2020-09-26 16:43:06 +01:00
Dan Brown
328d2514c4 Updated settings nav to be more flexible
Uses flexbox layout, flexed to content instead of rigid thirds like
before. Also extracted row into own file
2020-09-26 16:26:30 +01:00
Dan Brown
de2756dd95 Updated callout links to be correct colors
- Also updated to be underlined instead of bold
2020-09-26 15:40:51 +01:00
Dan Brown
1f97047799 Merge branch 'master' of git://github.com/alexmannuk/BookStack into alexmannuk-master 2020-09-26 15:35:13 +01:00
Dan Brown
c870c10e38 Merge pull request #2270 from gertjankrol/feature/test-migrations-workflow
Add `test-migrations` workflow
2020-09-26 15:25:17 +01:00
Dan Brown
49fa21c1e2 Merge pull request #2268 from gertjankrol/master
Fix the `AddActivityIndexes` migration's `down()` method
2020-09-26 15:21:21 +01:00
Dan Brown
9f87423584 Merge pull request #2274 from abulgatz/patch-1
Fixed "Ubunto Mono" $mono type misspelling
2020-09-26 12:11:53 +01:00
Dan Brown
08fbd39fcb Fixed markdown iframe loading and content alignment
Fixes #2280
2020-09-26 12:01:01 +01:00
Adam
5f75a9f32c Fix "Ubunto Mono" $mono type misspelling 2020-09-23 16:19:30 -05:00
Gertjan Krol
3750922c3e Added the test-migrations workflow 2020-09-22 19:53:45 +02:00
Gertjan Krol
4b0d1ddf39 Fixed the AddActivityIndexes migration's down() method 2020-09-22 19:22:27 +02:00
Dan Brown
ecd56917e7 Updated version and assets for release v0.30.0 2020-09-20 10:33:18 +01:00
Dan Brown
e22c9cae91 Merge branch 'master' into release 2020-09-20 10:30:10 +01:00
Dan Brown
a6c20c321f Merged latest translation changes 2020-09-20 10:28:01 +01:00
Dan Brown
e12012a6fc Updated translation contributors 2020-09-20 09:15:02 +01:00
Dan Brown
73b4c6d947 Fixed some wording in example env 2020-09-19 23:09:08 +01:00
Dan Brown
9e11fc33fa Updated example env with helpful info
- Added comments to explain the use of the file.
- Added comments to advise that space/hash containing values would need
to be quoted.

Related to #2258
2020-09-19 16:09:43 +01:00
Dan Brown
ff46d81681 Merge branch 'jb-l10n-fix-czech' of git://github.com/jakubboucek/BookStack into jakubboucek-jb-l10n-fix-czech 2020-09-19 15:44:18 +01:00
Dan Brown
1f202f6dbc Updated locale lists for Bulgarian 2020-09-19 15:36:17 +01:00
Dan Brown
bccf4653cb New Crowdin translations (#2077)
* New translations entities.php (Portuguese, Brazilian)

* New translations entities.php (Persian)

* New translations entities.php (Spanish, Argentina)

* New translations entities.php (Thai)

* New translations errors.php (German Informal)

* New translations entities.php (Spanish)

* New translations entities.php (French)

* New translations entities.php (Arabic)

* New translations entities.php (Arabic)

* New translations components.php (Portuguese, Brazilian)

* New translations entities.php (Portuguese, Brazilian)

* New translations auth.php (Italian)

* New translations common.php (Italian)

* New translations components.php (Italian)

* New translations entities.php (Italian)

* New translations settings.php (Italian)

* New translations components.php (Chinese Simplified)

* New translations entities.php (Chinese Simplified)

* New translations settings.php (Spanish)

* New translations components.php (German)

* New translations components.php (Japanese)

* New translations components.php (Dutch)

* New translations components.php (German Informal)

* New translations components.php (Portuguese, Brazilian)

* New translations common.php (Ukrainian)

* New translations components.php (Portuguese)

* New translations common.php (Russian)

* New translations components.php (Russian)

* New translations common.php (Slovak)

* New translations components.php (Slovak)

* New translations common.php (Slovenian)

* New translations components.php (Slovenian)

* New translations common.php (Swedish)

* New translations components.php (Swedish)

* New translations common.php (Turkish)

* New translations components.php (Turkish)

* New translations components.php (Ukrainian)

* New translations components.php (Polish)

* New translations common.php (Chinese Simplified)

* New translations common.php (Chinese Traditional)

* New translations components.php (Chinese Traditional)

* New translations common.php (Vietnamese)

* New translations components.php (Vietnamese)

* New translations common.php (Portuguese, Brazilian)

* New translations common.php (Persian)

* New translations components.php (Persian)

* New translations common.php (Spanish, Argentina)

* New translations components.php (Spanish, Argentina)

* New translations common.php (Thai)

* New translations components.php (Thai)

* New translations common.php (Portuguese)

* New translations common.php (Polish)

* New translations common.php (Italian)

* New translations common.php (Bulgarian)

* New translations components.php (Italian)

* New translations components.php (Chinese Simplified)

* New translations components.php (German)

* New translations components.php (Japanese)

* New translations components.php (Dutch)

* New translations components.php (German Informal)

* New translations common.php (French)

* New translations components.php (French)

* New translations common.php (Spanish)

* New translations components.php (Spanish)

* New translations common.php (Arabic)

* New translations components.php (Arabic)

* New translations components.php (Bulgarian)

* New translations common.php (Dutch)

* New translations common.php (Czech)

* New translations components.php (Czech)

* New translations common.php (Danish)

* New translations components.php (Danish)

* New translations common.php (German)

* New translations common.php (Hebrew)

* New translations components.php (Hebrew)

* New translations common.php (Hungarian)

* New translations components.php (Hungarian)

* New translations common.php (Japanese)

* New translations common.php (Korean)

* New translations components.php (Korean)

* New translations common.php (German Informal)

* New translations components.php (German)

* New translations common.php (German)

* New translations entities.php (German)

* New translations common.php (French)

* New translations components.php (French)

* New translations common.php (Spanish)

* New translations components.php (Spanish)

* New translations components.php (Chinese Simplified)

* New translations common.php (Chinese Simplified)

* New translations common.php (Polish)

* New translations components.php (Polish)

* New translations auth.php (Polish)

* New translations entities.php (Polish)

* New translations errors.php (Polish)

* New translations passwords.php (Polish)

* New translations settings.php (Polish)

* New translations settings.php (Polish)

* New translations common.php (Spanish, Argentina)

* New translations components.php (Spanish, Argentina)

* New translations auth.php (Spanish, Argentina)

* New translations entities.php (Spanish, Argentina)

* New translations passwords.php (Spanish, Argentina)

* New translations settings.php (Spanish, Argentina)

* New translations entities.php (German)

* New translations components.php (German Informal)

* New translations common.php (German Informal)

* New translations entities.php (German Informal)

* New translations settings.php (Italian)

* New translations settings.php (Dutch)

* New translations settings.php (Thai)

* New translations settings.php (Persian)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Vietnamese)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Ukrainian)

* New translations settings.php (Turkish)

* New translations settings.php (Swedish)

* New translations settings.php (Slovenian)

* New translations settings.php (Slovak)

* New translations settings.php (Russian)

* New translations settings.php (Portuguese)

* New translations settings.php (Korean)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Japanese)

* New translations settings.php (Hungarian)

* New translations settings.php (Hebrew)

* New translations settings.php (German)

* New translations settings.php (Danish)

* New translations settings.php (Czech)

* New translations settings.php (Bulgarian)

* New translations settings.php (Arabic)

* New translations settings.php (French)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Polish)

* New translations settings.php (Spanish)

* New translations settings.php (German Informal)

* New translations settings.php (Spanish)

* New translations settings.php (French)

* New translations components.php (Turkish)

* New translations settings.php (Turkish)

* New translations entities.php (Turkish)

* New translations common.php (Turkish)

* New translations components.php (Portuguese, Brazilian)

* New translations common.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Chinese Simplified)

* New translations activities.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations activities.php (Chinese Traditional)

* New translations auth.php (Chinese Traditional)

* New translations common.php (Chinese Traditional)

* New translations components.php (Chinese Traditional)

* New translations errors.php (Chinese Traditional)

* New translations passwords.php (Chinese Traditional)

* New translations settings.php (German)

* New translations settings.php (German Informal)

* New translations activities.php (Slovak)

* New translations auth.php (Slovak)

* New translations auth.php (Slovak)

* New translations common.php (Slovak)

* New translations components.php (Slovak)

* New translations components.php (Slovak)

* New translations entities.php (Slovak)

* New translations common.php (Slovak)

* New translations entities.php (Slovak)

* New translations passwords.php (Slovak)

* New translations settings.php (Dutch)

* New translations components.php (Dutch)

* New translations entities.php (Dutch)

* New translations passwords.php (Dutch)

* New translations activities.php (Arabic)

* New translations entities.php (French)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations auth.php (Chinese Traditional)

* New translations errors.php (Chinese Traditional)

* New translations activities.php (Japanese)

* New translations auth.php (Japanese)

* New translations entities.php (Chinese Traditional)

* New translations validation.php (Chinese Traditional)

* New translations common.php (Russian)

* New translations components.php (Russian)

* New translations entities.php (Russian)

* New translations settings.php (Russian)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Polish)

* New translations settings.php (Polish)

* New translations settings.php (Polish)

* New translations entities.php (Russian)

* New translations entities.php (Portuguese)

* New translations entities.php (Thai)

* New translations entities.php (Spanish, Argentina)

* New translations entities.php (Persian)

* New translations entities.php (Portuguese, Brazilian)

* New translations entities.php (Vietnamese)

* New translations entities.php (Chinese Traditional)

* New translations entities.php (Chinese Simplified)

* New translations entities.php (Ukrainian)

* New translations entities.php (Turkish)

* New translations entities.php (Swedish)

* New translations entities.php (Slovenian)

* New translations entities.php (Slovak)

* New translations entities.php (Polish)

* New translations entities.php (French)

* New translations entities.php (Dutch)

* New translations entities.php (Korean)

* New translations entities.php (Japanese)

* New translations entities.php (Italian)

* New translations entities.php (Hungarian)

* New translations entities.php (Hebrew)

* New translations entities.php (German)

* New translations entities.php (Danish)

* New translations entities.php (Czech)

* New translations entities.php (Bulgarian)

* New translations entities.php (Arabic)

* New translations entities.php (Spanish)

* New translations entities.php (German Informal)

* New translations entities.php (French)

* New translations settings.php (Russian)

* New translations settings.php (Portuguese)

* New translations settings.php (Thai)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Persian)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Vietnamese)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Ukrainian)

* New translations settings.php (Turkish)

* New translations settings.php (Swedish)

* New translations settings.php (Slovenian)

* New translations settings.php (Slovak)

* New translations settings.php (Polish)

* New translations settings.php (French)

* New translations settings.php (Dutch)

* New translations settings.php (Korean)

* New translations settings.php (Japanese)

* New translations settings.php (Italian)

* New translations settings.php (Hungarian)

* New translations settings.php (Hebrew)

* New translations settings.php (German)

* New translations settings.php (Danish)

* New translations settings.php (Czech)

* New translations settings.php (Bulgarian)

* New translations settings.php (Arabic)

* New translations settings.php (Spanish)

* New translations settings.php (German Informal)

* New translations entities.php (Spanish)

* New translations settings.php (Spanish)
2020-09-19 15:22:32 +01:00
Dan Brown
31eec34b5d Moved decode and updated page plaintext decode test 2020-09-19 15:13:18 +01:00
Dan Brown
44f3508171 Merge branch 'preview-entities' of git://github.com/mr-vinn/BookStack into mr-vinn-preview-entities 2020-09-19 14:58:56 +01:00
Dan Brown
2e39e45886 Added test to check text gen decodes HTML entities 2020-09-19 14:58:18 +01:00
Dan Brown
458aa72c2f Updated composer deps 2020-09-19 12:12:48 +01:00
Dan Brown
78bf044a7a Added audit log interface
- Displays the currently tracked activities in the system.

Related to #2173 and #1167
2020-09-19 12:06:45 +01:00
Dan Brown
e5f0b4dd85 Split out Maintenance to separate controller 2020-09-19 09:24:58 +01:00
Vinnie Okada
311a12b7ef Decode HTML entities
Decode HTML entities in page text before saving it to the database.
2020-09-18 06:54:30 -06:00
Dan Brown
d9e2bddee4 Added some robustness to page draft saving
- Updated so that a warning is always shown on error, Not just on first
in chain.
- Added last-resort localStorage content saving.
2020-09-13 19:32:45 +01:00
Dan Brown
6578ac0b4a Fixed visible revision delete menu 2020-09-13 19:12:15 +01:00
Dan Brown
09c6d6c722 Added button for inserting attachment link to a page
For #1460
2020-09-13 18:58:05 +01:00
Dan Brown
ad48cd3e48 Continued implementation of attachment drag+drop
Cannot get working in chrome reliably due to conflicting handling of
events and drag+drop API. Getting attachment drop working breaks other
parts of TinyMCE.
Implementing current work as should still work for MD editor and within
FireFox.

Related to #1460
2020-09-13 18:31:14 +01:00
Dan Brown
e305ba14d9 Merge branch 'master' into attachment_drag_drop 2020-09-13 16:33:31 +01:00
Vinnie Okada
2c3f453c1f Implement the renderPages parameter
Render page content when getTree() is called with a true $renderPages
argument.
2020-09-07 09:05:51 -06:00
Dan Brown
b87e97f99e Added punnycode since its reuquired by markdownit
Is a native, although depricated, nodejs module. Have installed manually
since esbuild could not resolve the nodejs module
2020-09-05 20:37:23 +01:00
Dan Brown
e5377d5f46 Updated saml2 slo config so url is used if no repsonse url
Updated config to change empty string to null since the empty string was
hitting an isset check which caused an empty string to be used instead
of the slo url as a backup option.

Closes #2002
2020-09-05 19:26:47 +01:00
Dan Brown
ff1ee2d71f Updated flow to ensure /register/confirm route is used where needed
Was accidentally skipped during previous updates. Will now be used on
saml, ldap & standard registration where required.
Uses session to know if the email was just sent and, if so, show the
confirmation route.
2020-09-05 17:26:48 +01:00
Dan Brown
c029741a17 Updated npm deps 2020-09-05 16:54:25 +01:00
Dan Brown
ac83c349da Migrated from webpack to esbuild 2020-09-05 16:50:20 +01:00
Jakub Bouček
fefcaa21e7 Fix English translations
- Fix obvious bug
- Reunite capitalisation
2020-08-31 20:45:09 +02:00
Jakub Bouček
6a36db3cde Czech translations: Fix broken labels 2020-08-31 20:45:09 +02:00
Jakub Bouček
c9352bfd42 Czech translations: Add new translations to cs, improve existing 2020-08-31 20:45:09 +02:00
Jakub Bouček
9c457d9ffe Fix Czech translations (email -> e-mail)
In Czech language "email" does not means "email" but "enamel paint", correct is "e-mail".
See in Wikipedia:
- https://cs.wikipedia.org/wiki/E-mail
- https://cs.wikipedia.org/wiki/Email_(barva)
2020-08-31 17:34:46 +02:00
alexmannuk
7837b8c4ee Updated callout link formatting
Updated callout links to use font colouring based on type, with bold text to denote link, instead of using the theme link colour per issue #303.
2020-08-24 20:03:08 +01:00
Dan Brown
87a5340a05 Prevented email confirmation exception throw on registration
Was preventing any other registration actions from taking place such as
LDAP/SAML group sync. Email confirmation should be actioned by
middleware on post-registration redirect.

Added testing to cover.
Tested for LDAP, SAML and normal registration with email confirmation
required to ensure flows work as expected.

Fixes #2082
2020-08-04 17:54:50 +01:00
Dan Brown
c076ca408c Fixed non-visible horizontal rules in dark mode
Fixes #2209
2020-08-04 15:39:07 +01:00
Dan Brown
1ac11c1852 Added warning to role screen for important permissions
Warning related to permissions that could allow a person to promote
their own permissions to gain more privileges than expected.

For #2105.
2020-08-04 15:26:13 +01:00
Dan Brown
5f1ee5fb0e Removed role 'name' field from database
The 'name' field was really redundant and caused confusion in the
codebase, since the 'Display' name is often used and we have a
'system_name' for the admin and public role.

This fixes #2032, Where external auth group matching has confusing
behaviour as matching was done against the display_name, if no
external_auth field is set, but only roles with a match 'name' field
would be considered.

This also fixes and error where the role users migration, on role
delete, would not actually fire due to mis-matching http body keys.
Looks like this has been an issue from the start. Added some testing to
cover. Fixes #2211.

Also converted phpdoc to typehints in many areas of the reviewed code
during the above.
2020-08-04 14:55:01 +01:00
Dan Brown
a9f02550f0 Removed joint_permissions auto_increment id
Removed auto_incrementing id and set a primary key of the [role_id,
entity_type, entity_id, action] instead since this table could recieve a
lot of activity, especially when permission regeneration was automated,
leading to very high auto_increment counts which could max out the
integer limit.

Also updated some RolesTest comment endpoints to align with
recent route changes.

Should fix #2091
2020-08-04 13:02:31 +01:00
Dan Brown
7590ecd37c Updated some comment elements and standardised more JS
- Updated comment routes to be simpler.
- Updated comments JS to align better with updated component system.
- Documented available global JS functions/services.
- Removed redundant controller method.
- Added window.$events helpers for validation messages and
success/error.
- Updated JS events system to not be class based for simplicity.
- Added window.trans_plural method to handle pluralisation/replacements
where you already have the translation string itself.

Fixes #1836
2020-07-28 18:19:18 +01:00
Dan Brown
2c0fdf83c1 Updated public-login redirect to check url
Direct links to the login pages for public instances could lead to a
redirect back to an external page upon login.
This adds a check to ensure the URL is a URL expected from the current
bookstack instance, or at least under the same domain.

Fixes #2073
2020-07-28 16:29:06 +01:00
Dan Brown
2ed0317129 Updated functionality for logging failed access
- Added testing to cover.
- Linked logging into Laravel's monolog logging system and made log
channel configurable.
- Updated env var names to be specific to login access.
- Added extra locations as to where failed logins would be captured.

Related to #1881 and #728
2020-07-28 12:59:43 +01:00
Dan Brown
2f6ff07347 Merge branch 'auth' of git://github.com/benrubson/BookStack into benrubson-auth 2020-07-28 10:46:40 +01:00
Dan Brown
18f406d97b Started attachment drag/drop
Currently fighting between sortable and tinymce mechanisms which prevent
this working due to the different events stopping the drop event while
needing the dragover for cursor placement.
2020-07-28 10:45:28 +01:00
Dan Brown
76fcbd3752 Removed default anchor CSS filtering in dark mode
Due to causing content images to be rendered in unexpected ways.

- Also removed CSS filters from other image usage.
- Tweaked header CSS filtering to not be so aggressive.
- Forced WYSIWYG editor to be on its own layer since that would allow
massive larger performance increases in Safari, especially when using
dark mode.

Closes #2045.
Closes #2154.
2020-07-26 16:36:15 +01:00
Dan Brown
6e4132121c Updated pagination colors for visibility
Fixes #1839
2020-07-26 15:07:47 +01:00
Dan Brown
f5fefbdb06 Removed a few remaining vue references 2020-07-26 14:49:05 +01:00
Dan Brown
a46b248cf4 Fixed some image manager behaviour
fixed:
- Double click not working after tab usage.
- Synced edit form with select button.
2020-07-25 11:47:12 +01:00
Dan Brown
8213ea9a71 Fixed issue where URL params in image names would cause loading failure
Updated file name handling to route through str:slug to be cleaned up
a little.
Added testing to cover.

Fixes #2161
2020-07-25 11:18:40 +01:00
Dan Brown
03211ebea6 Removed unused tinymce imagetools plugin 2020-07-25 01:09:35 +01:00
Dan Brown
2bacc3c967 Removed vuejs from the project 2020-07-25 00:25:30 +01:00
Dan Brown
02dc3154e3 Converted image-manager to be component/HTML based
Instead of vue based.
2020-07-25 00:20:58 +01:00
Dan Brown
b6aa232205 Fixed issue where more images than expected could be deleted
When deleting images, images within the same directory, that have
a suffix of the delete image name, would also be deleted.

Added test to cover.
2020-07-24 23:41:59 +01:00
Dan Brown
b383f5776d Tweaked dropdown shadows a tad 2020-07-05 21:23:57 +01:00
Dan Brown
3bfd26bf86 Converted the page editor from vue to component 2020-07-05 21:18:17 +01:00
Dan Brown
9d6f574494 Updated attachment tests to align with front-end changes 2020-07-04 17:04:26 +01:00
Dan Brown
d41452f39c Finished breakdown of attachment vue into components 2020-07-04 16:53:02 +01:00
Dan Brown
14b6cd1091 Started migration of attachment manager from vue
- Created new dropzone component.
- Added standard component event system using custom DOM events.
- Added tabs component.
- Added ajax-delete-row component.
2020-06-30 22:12:45 +01:00
Dan Brown
8dc9689c6d Removed tests for removed ajax tag route 2020-06-29 23:46:08 +01:00
Dan Brown
181ae6d055 Fixed tag-manager loading on entity-creation 2020-06-29 23:40:34 +01:00
Dan Brown
573c4e26d5 Finished moving tag-manager from a vue to a component
Now tags load with the page, not via AJAX.
2020-06-29 22:11:03 +01:00
Dan Brown
4e107b9160 Started migrating tag manager JS to HTML-first component 2020-06-28 23:15:05 +01:00
Dan Brown
10305a4446 Converted entity-dash from vue to a component 2020-06-28 21:15:00 +01:00
Dan Brown
a5fa745749 Moved overlay component, migrated code-editor & added features
- Moved Code-editor from vue to component.
- Updated popup code so it background click only hides if the click
originated on the same background. Clicks within the popup will no
longer cause it to hide.
- Added session-level history tracking to code editor.
2020-06-28 00:06:47 +01:00
Dan Brown
9023f78cdc Merge branch 'master' of github.com:BookStackApp/BookStack 2020-06-27 17:19:05 +01:00
Dan Brown
8bc3e0f31a Merge branch 'master' of git://github.com/drzippie/BookStack into drzippie-master 2020-06-27 17:11:11 +01:00
Dan Brown
afed379c5c Merge pull request #2157 from Honvid/fix/lang_error
fix the translate error
2020-06-27 17:06:38 +01:00
Dan Brown
540119f133 Moved sass build out of webpack, updated npm deps
Moving sass out of webpack cleans the setup quite considerably and
brings a good speed improvement.
Made use of npm-run-all so the previous commands still run like before.
2020-06-27 16:52:26 +01:00
Dan Brown
d5de28c444 Merge branch 'use-dart-sass' of git://github.com/timoschwarzer/BookStack into timoschwarzer-use-dart-sass 2020-06-27 15:59:38 +01:00
Dan Brown
7a2e39212e Fixed empty search scenario 2020-06-27 13:37:18 +01:00
Dan Brown
715dee2d0e Converted search filters to not be vue based 2020-06-27 13:29:00 +01:00
Timo Schwarzer
0f55d776a6 Replace node-sass with dart-sass 2020-06-26 12:44:41 +02:00
Antonio Cortés (DrZippie)
d617dba61c removed test_slug_multi_byte_lower_casing and added new test test_slug_multi_byte_url_safe 2020-06-25 18:42:28 +02:00
Antonio Cortés (DrZippie)
ca202c1819 Added Illuminate\Support\Str::slug to generate slug from text to improve the creation of slugs with non-English characters 2020-06-25 18:08:13 +02:00
Dan Brown
76d02cd472 Started attempt at formalising component system used in BookStack
Added a document to try to define things.
Updated the loading so components are registed dynamically.
Added some standardised ways to reference other elems & define options
2020-06-24 20:38:08 +01:00
Honvid
118e31608a fix the bug for lang's extra letter. 2020-06-16 11:44:08 +08:00
Honvid
418fd9037f Merge pull request #1 from BookStackApp/master
sync the remote master
2020-06-10 07:46:06 +08:00
benrubson
9d7ce59b18 Move logFailedAccess into Activity 2020-05-23 15:37:38 +02:00
Dan Brown
71e7dd5894 Removed failing URL test
- Was found that the test was not testing the actual situation anyway.
- A work-around in the request creation, within testing, just happened
 to result in the desired outcome.

For reference: https://github.com/laravel/framework/pull/32345
2020-05-23 12:56:31 +01:00
Dan Brown
3502abdd49 Fixed revision issues caused by page fillable changes 2020-05-23 12:28:14 +01:00
Dan Brown
31514bae06 Updated framework and other deps 2020-05-23 11:50:44 +01:00
Dan Brown
19bfc8ad37 Prevented entity "Not Found" events from being logged
- Added testing to cover, which was more hassle than thought
  since Laravel did not have built in log test helpers, so:
- Added Log testing helper.

Related to #2110
2020-05-23 11:28:59 +01:00
benrubson
8f1f73defa Properly use env/config functions 2020-05-23 12:06:37 +02:00
Dan Brown
bf4a3b73f8 Updated listing endpoints to be clickable in api docs 2020-05-23 00:53:13 +01:00
Dan Brown
00c0815808 Fixed issue where updated page content would not be indexed
- Also updated html field of pages to not be fillable.
   (Since HTML should always go through app id parsing)

Related to #2042
2020-05-23 00:46:13 +01:00
Dan Brown
b61f950560 Incremented version number 2020-05-23 00:29:09 +01:00
Dan Brown
8a6cf0cdec Added chapters to the API 2020-05-23 00:28:41 +01:00
Dan Brown
24bad5034a Updated API auth to allow public user if given permission 2020-05-22 22:34:18 +01:00
Nikhil Jha
e287d965f5 move zip export into exportservice 2020-05-13 20:07:19 -07:00
Nikhil Jha
ea82c2f61b support exporting books as zip files 2020-05-13 19:57:59 -07:00
Nikhil Jha
a7d9646b19 support exporting WYSIWYG pages as Markdown 2020-05-13 18:34:22 -07:00
Nikhil Jha
a34a07c610 basic markdown export 2020-05-12 21:12:26 -07:00
Dan Brown
29ddb6e1b9 Updated version and assets for release v0.29.3 2020-05-12 22:34:01 +01:00
Dan Brown
2ff90e2ff0 Merge branch 'master' into release 2020-05-12 22:33:27 +01:00
Dan Brown
9666c8c0f7 Updated shelf-list view to enforce view permissions for child books
- Aligned shelf-homepage behaviour to match
- Updated testing to cover.

For #2111
2020-05-12 22:21:45 +01:00
benrubson
58df3ad956 Log failed accesses option 2020-05-03 16:20:02 +02:00
Dan Brown
04ecc128a2 Updated version and assets for release v0.29.2 2020-05-02 11:49:21 +01:00
Dan Brown
87d1d3423b Merge branch 'master' into release 2020-05-02 11:48:48 +01:00
Dan Brown
d3ec38bee3 Removed unused function in registration service 2020-05-02 01:07:30 +01:00
Dan Brown
413cac23ae Added command to regenerate comment content 2020-05-01 23:41:47 +01:00
Dan Brown
3c26e7b727 Updated comment md rendering to be server-side 2020-05-01 23:24:11 +01:00
Dan Brown
2a2d0aa15b Fixed incorrect color code causing yellow/orange code blocks 2020-04-29 18:28:26 +01:00
Dan Brown
4818192a2a Updated version and assets for release v0.29.1 2020-04-28 12:30:31 +01:00
Dan Brown
965dd97f54 Merge branch 'master' into release 2020-04-28 12:30:09 +01:00
Dan Brown
dfceab7cfa Updated translator attribution before release v0.29.1 2020-04-28 12:30:02 +01:00
Dan Brown
00c77e494b Updated ci with php7.4, update locale array 2020-04-28 12:28:19 +01:00
Dan Brown
ce8cea6a9f New Crowdin translations (#2071)
* New translations common.php (Korean)

* New translations settings.php (Korean)
2020-04-28 12:25:15 +01:00
Dan Brown
6f2a2c05bf New Crowdin translations (#2028)
* New translations settings.php (Chinese Simplified)

* New translations common.php (Spanish)

* New translations common.php (Spanish, Argentina)

* New translations common.php (Turkish)

* New translations common.php (French)

* New translations auth.php (Dutch)

* New translations common.php (Dutch)

* New translations entities.php (Dutch)

* New translations activities.php (Thai)

* New translations auth.php (Thai)

* New translations common.php (Thai)

* New translations components.php (Thai)

* New translations entities.php (Thai)

* New translations errors.php (Thai)

* New translations pagination.php (Thai)

* New translations passwords.php (Thai)

* New translations settings.php (Thai)

* New translations validation.php (Thai)
2020-04-28 10:19:42 +01:00
Dan Brown
898d0b5817 Added multi-select to book-sort interface
As discussed in #2064

Closes #2067
2020-04-27 16:53:27 +01:00
Dan Brown
4ef362143b Added auto-focus behaviour to page editor
- Will focus on title if the value of the field matches the default text
for the current user's language.
- Otherwise will focus on the editor body.
- Added and tested on both editors.

For #2036
2020-04-27 15:54:39 +01:00
Dan Brown
8ce38d2158 Fixed not shown existing-email warning on new ldap user
- Reduced the amount of different exceptions from LDAP attempt so they
can be handled more consistently.
- Added test to cover.
- Also cleaned up LDAP tests to reduce boilterplate mocks.

Fixes #2048
2020-04-26 12:13:00 +01:00
Dan Brown
468fec80de Updated WYSIWYG callout shortcut to handle child elems
- Will now search for a callout on/above the selected node rather than
only using the selected node.
- Issues previously where callout shortcut would not cycle if called
when child formatting was currently selected inside the callout.

For #2061
2020-04-26 09:26:41 +01:00
Dan Brown
2ec4ad1181 Tweaked ListingResponseBuilder to help avoid future issues
- Updated so none of the method mutate the query throughout the function
so that the query can be handled in a sane way, Since we were already
encountering issues due to internal method call order.
2020-04-25 22:15:59 +01:00
Dan Brown
a17b82bdde Fixed api query total not taking filters into account 2020-04-25 21:37:52 +01:00
Dan Brown
8fb1f7c361 Fixed floated content extending past page body
As shown in #2055
2020-04-25 19:59:23 +01:00
Dan Brown
c20110b6ae Fixed issue where callout and quotes overlap floated images
For #2055
2020-04-25 19:55:16 +01:00
Dan Brown
a880b1d5c5 Fixed selection not visible - dark theme codemirror
Fixes #2060
2020-04-25 19:19:41 +01:00
Dan Brown
07831df2d3 Updated user-create endpoint so saml and ldap is consistent. 2020-04-25 18:28:07 +01:00
Dan Brown
519283e643 Authenticated admins on all guards upon login
For #2031
2020-04-25 18:19:22 +01:00
Dan Brown
79a949836b Fixed incorrect API listing total when offset set
Fixes #2043
2020-04-25 16:38:11 +01:00
Dan Brown
195b74926c Updated version and assets for release v0.29.0 2020-04-13 16:10:23 +01:00
Dan Brown
2120db12b2 Merge branch 'master' into release 2020-04-13 16:10:11 +01:00
Dan Brown
0883b0533b Merge branch 'master' of github.com:BookStackApp/BookStack 2020-04-13 15:43:53 +01:00
Dan Brown
d030620846 Updated translator contributor file from crowdin 2020-04-13 15:43:20 +01:00
Dan Brown
687c4247ae New Crowdin translations (#2005)
* New translations settings.php (Portuguese)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Russian)

* New translations settings.php (Korean)

* New translations settings.php (Persian)

* New translations settings.php (Polish)

* New translations settings.php (Swedish)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Turkish)

* New translations settings.php (Slovak)

* New translations settings.php (Slovenian)

* New translations settings.php (Spanish)

* New translations settings.php (Czech)

* New translations settings.php (Danish)

* New translations settings.php (Dutch)

* New translations settings.php (Arabic)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Italian)

* New translations settings.php (Hungarian)

* New translations settings.php (Japanese)

* New translations settings.php (French)

* New translations settings.php (German)

* New translations settings.php (Hebrew)

* New translations settings.php (German Informal)

* New translations settings.php (Vietnamese)

* New translations settings.php (Ukrainian)

* New translations activities.php (Turkish)

* New translations activities.php (Turkish)

* New translations auth.php (Turkish)

* New translations common.php (Turkish)

* New translations auth.php (Turkish)

* New translations components.php (Turkish)

* New translations common.php (Turkish)

* New translations components.php (Turkish)

* New translations entities.php (Turkish)

* New translations entities.php (Turkish)

* New translations errors.php (Turkish)

* New translations entities.php (Turkish)

* New translations passwords.php (Turkish)

* New translations settings.php (Turkish)

* New translations errors.php (Turkish)

* New translations settings.php (Turkish)

* New translations settings.php (Turkish)

* New translations validation.php (Turkish)

* New translations settings.php (Turkish)

* New translations validation.php (Turkish)

* New translations common.php (Turkish)

* New translations components.php (Turkish)

* New translations validation.php (Turkish)

* New translations components.php (Turkish)

* New translations entities.php (Turkish)

* New translations errors.php (Turkish)

* New translations settings.php (Turkish)

* New translations validation.php (Turkish)

* New translations passwords.php (Arabic)

* New translations auth.php (Arabic)

* New translations auth.php (Slovak)

* New translations passwords.php (Russian)

* New translations passwords.php (Slovak)

* New translations auth.php (Slovenian)

* New translations passwords.php (Slovenian)

* New translations auth.php (Spanish)

* New translations passwords.php (Portuguese, Brazilian)

* New translations passwords.php (Polish)

* New translations auth.php (Portuguese)

* New translations auth.php (Russian)

* New translations passwords.php (Portuguese)

* New translations auth.php (Portuguese, Brazilian)

* New translations auth.php (Ukrainian)

* New translations passwords.php (Ukrainian)

* New translations auth.php (Vietnamese)

* New translations passwords.php (Vietnamese)

* New translations auth.php (German Informal)

* New translations passwords.php (German Informal)

* New translations passwords.php (Turkish)

* New translations passwords.php (Spanish)

* New translations auth.php (Spanish, Argentina)

* New translations passwords.php (Spanish, Argentina)

* New translations auth.php (Swedish)

* New translations passwords.php (Swedish)

* New translations auth.php (Turkish)

* New translations components.php (Turkish)

* New translations entities.php (Turkish)

* New translations auth.php (Polish)

* New translations passwords.php (Danish)

* New translations auth.php (Dutch)

* New translations passwords.php (Dutch)

* New translations auth.php (Danish)

* New translations auth.php (French)

* New translations passwords.php (French)

* New translations auth.php (Chinese Simplified)

* New translations passwords.php (Chinese Simplified)

* New translations auth.php (Chinese Traditional)

* New translations passwords.php (Chinese Traditional)

* New translations auth.php (Czech)

* New translations passwords.php (Czech)

* New translations auth.php (German)

* New translations auth.php (Korean)

* New translations auth.php (Japanese)

* New translations passwords.php (Japanese)

* New translations passwords.php (Korean)

* New translations auth.php (Persian)

* New translations passwords.php (Persian)

* New translations passwords.php (Italian)

* New translations passwords.php (German)

* New translations auth.php (Hebrew)

* New translations passwords.php (Hebrew)

* New translations auth.php (Hungarian)

* New translations passwords.php (Hungarian)

* New translations auth.php (Italian)

* New translations entities.php (Turkish)

* New translations settings.php (Turkish)

* New translations validation.php (Turkish)

* New translations passwords.php (Turkish)

* New translations entities.php (Turkish)

* New translations errors.php (Turkish)

* New translations validation.php (Turkish)

* New translations auth.php (Turkish)

* New translations auth.php (Spanish)

* New translations passwords.php (Spanish)

* New translations settings.php (Spanish)

* New translations auth.php (Spanish, Argentina)

* New translations passwords.php (Spanish, Argentina)

* New translations entities.php (Turkish)

* New translations auth.php (French)

* New translations passwords.php (French)

* New translations settings.php (French)

* New translations common.php (Russian)

* New translations common.php (Slovak)

* New translations common.php (Slovenian)

* New translations common.php (Spanish)

* New translations common.php (Portuguese)

* New translations common.php (Polish)

* New translations common.php (Portuguese, Brazilian)

* New translations common.php (Ukrainian)

* New translations common.php (Vietnamese)

* New translations common.php (German Informal)

* New translations common.php (Spanish, Argentina)

* New translations common.php (Swedish)

* New translations common.php (Turkish)

* New translations common.php (Danish)

* New translations common.php (Dutch)

* New translations common.php (French)

* New translations common.php (Arabic)

* New translations common.php (Chinese Simplified)

* New translations common.php (Czech)

* New translations common.php (Chinese Traditional)

* New translations common.php (Japanese)

* New translations common.php (Italian)

* New translations common.php (Korean)

* New translations common.php (Persian)

* New translations common.php (German)

* New translations common.php (Hebrew)

* New translations common.php (Hungarian)

* New translations auth.php (Russian)

* New translations common.php (Russian)

* New translations passwords.php (Russian)

* New translations passwords.php (German)

* New translations settings.php (German)

* New translations auth.php (German)

* New translations common.php (German)

* New translations settings.php (German Informal)

* New translations passwords.php (German Informal)

* New translations common.php (German Informal)

* New translations auth.php (German Informal)
2020-04-13 15:31:35 +01:00
Dan Brown
3a70e9d49c Merge pull request #2023 from jzoy/master
fix Chinese translation error
2020-04-12 19:15:00 +01:00
Dan Brown
88dfb40c63 Some further dark-mode fixes, added toggle to homepage
- Homepage toggle especially useful for not-logged-in users since they
do not have a dropdown.
2020-04-12 19:06:34 +01:00
Dan Brown
b80b6ed942 Merge pull request #2022 from BookStackApp/dark-mode
Addition of a user-selectable dark-mode option
2020-04-11 20:52:19 +01:00
Dan Brown
50669e3f4a Added tests and translations for dark-mode components 2020-04-11 20:44:23 +01:00
Dan Brown
573c848d51 Added dark/light mode toggle to profile dropdown menu
- Also fixed some remaining areas which needed dark mode support.
2020-04-11 20:37:51 +01:00
Dan Brown
d4b0e4acad Removed throttling from web-end requests
Generally seems to cause issues when secure images are in use.
Was added during laravel upgrade but laravel does not use this directly
for its web middleware anyway.
2020-04-11 20:02:07 +01:00
Dan Brown
b0b28e7b5e Rolled dark mode out to the editors
- Updated editor, and other area, styles to look okay in dark mode.
- Used tinyMCE theme generator to create dark mode theme.
- Updated tinymce to latest 4x version.
2020-04-11 15:48:08 +01:00
jzoy
eb94500dca Update settings.php 2020-04-11 21:29:09 +08:00
jzoy
df8ea0b81d fix Chinese translation error 2020-04-11 21:26:13 +08:00
Dan Brown
067cb9c5b7 Merge branch 'master' into dark-mode 2020-04-11 14:22:41 +01:00
jzoy
7673a2bd6c Merge pull request #2 from BookStackApp/master
fetch upstream
2020-04-11 21:18:17 +08:00
Dan Brown
627720c5af Fixed incorrect []Activity -> array conversion 2020-04-10 22:49:52 +01:00
Dan Brown
1ba5a1274c Started work on supporting a dark-mode
- Most elements done, but still need to do editors, tables and final
pass.
- Toggled only by quick js check at the moment, checking via css media
query. Need to make into user-preference toggle.

For #1234
2020-04-10 22:38:29 +01:00
Dan Brown
d4df18098f Cleaned up the activity service
- Added test to ensure activity on entity delete works as expected.
2020-04-10 20:55:33 +01:00
Dan Brown
7b8fe5fbc6 Added book-export endpoints to the API 2020-04-10 16:05:17 +01:00
Dan Brown
29705a25ce Reviewed and added testing for BookShelf API implementation
- Tweaked how books are passed on update to prevent unassignment if
parameter is not provided.
- Added books to validation so they show in docs.
- Added request/response examples.
- Added tests to cover.
- Added child book info to shelf info.

Review of #1908
2020-04-10 15:19:18 +01:00
Dan Brown
da1cea06ca Merge branch 'master' of git://github.com/osmansorkar/BookStack into osmansorkar-master 2020-04-10 13:49:28 +01:00
Dan Brown
ba1be9d710 Updated password reset process not to indicate if email exists
- Intended to prevent enumeration to check if a user exists.
- Updated messages on both the reqest-reset and set-password elements.
- Also updated notification auto-hide to be dynamic based upon the
amount of words within the notification.
- Added tests to cover.

For #2016
2020-04-10 13:38:08 +01:00
Dan Brown
053cbbd5b6 Updated view-change endpoints to be clearer, separated books and shelf
- Separated books-list and shelf-show view types to be saved separately.

During review of #1755
2020-04-10 12:49:16 +01:00
Dan Brown
b8c16b15a9 Merge branch 'feature_change_view_in_shelves_show' of git://github.com/philjak/BookStack into philjak-feature_change_view_in_shelves_show 2020-04-10 12:21:56 +01:00
Dan Brown
47e645909e Reviewed #1688, Show parent shelves on books page
- Moved list to the left of the page to align with other navigational
items.
- Hid list of no shelves, to help hide shelf references if not in use.
- Tweaked test to ensure it wasn't finding shelf name in breadcrumb
rather than list being tested.
2020-04-09 17:29:22 +01:00
Dan Brown
898cedf536 Merge branch 'feature/#1598' of git://github.com/cw1998/BookStack into cw1998-feature/#1598 2020-04-09 17:18:37 +01:00
Dan Brown
e83d2eedbb Added "update-url" command to find/replace url in the database
- Also aligned format of command descriptions.

Targeted most common columns.
Have not done revisions for the sake of keeping that
content true to how it was originally stored but could
cause unexpected behaviour.

For #1225
2020-04-09 16:59:26 +01:00
Dan Brown
1962c81742 Updated WYSIWYG entity link selector to set link display text
- Sets as entity name if the input is currently empty.

For #2014
2020-04-09 15:28:44 +01:00
Dan Brown
642db1387e Updated wysiwyg code-block insert flow to be mouseless
- Can now save a code block with Ctrl+Enter.
- Codemirror will be in focus on popup show.
- TinyMCE will get back focus on code save.

For #1972
2020-04-05 21:55:31 +01:00
Dan Brown
02f7ffe53c Removed overflow hidden from all lists
- Was causing ol list numbers to be cut off.

Fixes #1978
2020-04-05 18:05:51 +01:00
Dan Brown
5f61620cc2 Added support for changing the draw.io instance URL
- Allowed DRAWIO env option to be passed as URL to point to instance.
- Updated tests to check URL gets passed to pages correctly.
- Update default URL to be the default theme.

For #826
2020-04-05 17:27:16 +01:00
Dan Brown
ea9e9565ef Removed bmp and tiff support from uploaded images.
Fixes #1990
2020-04-05 16:15:05 +01:00
Dan Brown
feab756b9f Merge pull request #2003 from BookStackApp/rtl_styles_update
Updated styles to use logical properties/values, for improved RTL support
2020-04-05 14:15:23 +01:00
Dan Brown
fb08194af1 New Crowdin translations (#2004)
* New translations errors.php (Russian)

* New translations settings.php (Portuguese, Brazilian)

* New translations auth.php (Russian)

* New translations entities.php (Russian)

* New translations settings.php (Russian)

* New translations settings.php (Slovak)

* New translations settings.php (Persian)

* New translations settings.php (Portuguese)

* New translations settings.php (Polish)

* New translations settings.php (Korean)

* New translations settings.php (Swedish)

* New translations validation.php (Swedish)

* New translations errors.php (Turkish)

* New translations settings.php (Turkish)

* New translations entities.php (Swedish)

* New translations settings.php (Ukrainian)

* New translations errors.php (Swedish)

* New translations entities.php (Slovenian)

* New translations errors.php (Slovenian)

* New translations pagination.php (Slovenian)

* New translations passwords.php (Slovenian)

* New translations settings.php (Slovenian)

* New translations validation.php (Slovenian)

* New translations settings.php (Spanish)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Czech)

* New translations pagination.php (Danish)

* New translations settings.php (Danish)

* New translations settings.php (Dutch)

* New translations settings.php (Arabic)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Hungarian)

* New translations errors.php (French)

* New translations errors.php (Italian)

* New translations settings.php (Italian)

* New translations settings.php (Japanese)

* New translations settings.php (French)

* New translations errors.php (German)

* New translations settings.php (German)

* New translations settings.php (Hebrew)

* New translations auth.php (Hebrew)

* New translations validation.php (Hebrew)

* New translations errors.php (Hebrew)

* New translations entities.php (Hebrew)

* New translations common.php (Hebrew)

* New translations settings.php (German Informal)

* New translations errors.php (German Informal)

* New translations settings.php (Vietnamese)
2020-04-05 14:12:23 +01:00
Dan Brown
f94fd44ff6 Updated styles to use logical properties/values
- Intended to improve RTL support in the interface.
- Also adds hebrew to language dropdown since that was missing.

Related to #1794
2020-04-05 13:07:19 +01:00
Dan Brown
f84bf8e883 Updated test files to be PSR-4 compliant
Closes #1924
2020-04-04 01:16:05 +01:00
Dan Brown
3500182c5f Updated drawing uploads to use user id in image name
- Instead of user name.
- Due to issues with advanced charts like emoji zero-width-joiners.
- Could also have security concerns on untrusted instances with certain
webserver config due to double extension possibilities.

Closes #1993
2020-04-04 00:48:32 +01:00
Dan Brown
ef416d3e86 Fixed editor JavaScript error in TemplateManager
- Caused when loading the editor with no templates in the system.
- Tried to init a search box that did not exist.
2020-04-04 00:09:58 +01:00
Dan Brown
c1fe068ffc Bumped npm packages up and ran audit-fix 2020-04-04 00:03:26 +01:00
Dan Brown
b0610d85da Updated socialite to fix deprecated GitHub auth method
- Also updated composer dependancies to cover symfony/http-foundation
security issue.

Fixes #1879
Related to #1989
2020-04-04 00:00:19 +01:00
Jan Mareš
034478409e Add support Windows Authentication via SAML 2020-04-03 14:05:07 +02:00
James Geiger
fe438bdb45 Add footer element, styles, and associated settings 2020-03-18 22:28:06 -05:00
Dan Brown
ed563fef28 Updated version and assets for release v0.28.3 2020-03-14 22:31:42 +00:00
Dan Brown
0d31a8e3f1 Merge branch 'master' into release 2020-03-14 22:31:11 +00:00
Dan Brown
64942268b8 Added Slovenian to available language options
Related to #1946
2020-03-14 22:24:27 +00:00
Dan Brown
b670ab61d6 Updated translations from crowdin
Squashed commit of the following:

commit 23861a31bb2398ca61655c584bd8c75ee9bccdad
Merge: d44acf4b 1c6287f2
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 22:18:50 2020 +0000

    Merge branch 'master' into l10n_master

commit d44acf4b64
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 19:39:46 2020 +0000

    New translations errors.php (Portuguese, Brazilian)

commit c1a4cc5d12
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 19:14:49 2020 +0000

    New translations errors.php (Spanish, Argentina)

commit fb3c5dcffc
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 19:14:48 2020 +0000

    New translations errors.php (Spanish)

commit f65c84635d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:42:05 2020 +0000

    New translations errors.php (German Informal)

commit 99fba6932a
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:57 2020 +0000

    New translations errors.php (French)

commit bc4c9684b5
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:55 2020 +0000

    New translations errors.php (Portuguese, Brazilian)

commit 0afce79807
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:43 2020 +0000

    New translations errors.php (Russian)

commit f3daf77b95
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:41 2020 +0000

    New translations errors.php (Hungarian)

commit 63848278a5
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:40 2020 +0000

    New translations errors.php (Italian)

commit 53b5fce93c
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:38 2020 +0000

    New translations errors.php (Japanese)

commit 2638f7a663
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:37 2020 +0000

    New translations errors.php (Korean)

commit f19ffa468c
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:36 2020 +0000

    New translations errors.php (Persian)

commit 477ae0b845
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:34 2020 +0000

    New translations errors.php (Polish)

commit 56beebe12c
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:33 2020 +0000

    New translations errors.php (German)

commit 2b6540654a
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:32 2020 +0000

    New translations errors.php (Portuguese)

commit 80f7275011
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:30 2020 +0000

    New translations errors.php (Spanish)

commit 74c65f90ab
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:28 2020 +0000

    New translations errors.php (Spanish, Argentina)

commit 3bd9e4fb86
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:27 2020 +0000

    New translations errors.php (Swedish)

commit a698db00e3
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:26 2020 +0000

    New translations errors.php (Turkish)

commit f3cfc63b5c
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:25 2020 +0000

    New translations errors.php (Ukrainian)

commit 61eb76ac89
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:23 2020 +0000

    New translations errors.php (Vietnamese)

commit cfda94e2a8
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:22 2020 +0000

    New translations errors.php (Slovak)

commit f0659025a9
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:20 2020 +0000

    New translations errors.php (Dutch)

commit 27ac377ed6
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:19 2020 +0000

    New translations errors.php (Chinese Traditional)

commit 04bf21a325
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:18 2020 +0000

    New translations errors.php (Chinese Simplified)

commit 4dd5802979
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:16 2020 +0000

    New translations errors.php (Arabic)

commit 368cf2d248
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:11 2020 +0000

    New translations errors.php (Slovenian)

commit 52381df7be
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:08 2020 +0000

    New translations errors.php (Czech)

commit 7e8330510f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 14 18:41:07 2020 +0000

    New translations errors.php (Danish)

commit 1bf07c6acf
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Wed Mar 11 22:57:41 2020 +0000

    New translations entities.php (Slovenian)

commit 4d2d120b57
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Wed Mar 11 22:27:35 2020 +0000

    New translations entities.php (Slovenian)

commit edfc88eb8e
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Wed Mar 11 21:55:51 2020 +0000

    New translations entities.php (Slovenian)

commit 840ed35d34
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Wed Mar 11 21:22:08 2020 +0000

    New translations entities.php (Slovenian)

commit aa130af285
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Wed Mar 11 14:02:50 2020 +0000

    New translations common.php (Czech)

commit 5007fee528
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Wed Mar 11 14:02:25 2020 +0000

    New translations entities.php (Slovenian)

commit 1ad8874e6b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Wed Mar 11 13:30:21 2020 +0000

    New translations auth.php (Czech)

commit 56f17ff7d4
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Wed Mar 11 13:29:57 2020 +0000

    New translations entities.php (Slovenian)

commit 33789962cc
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Wed Mar 11 11:09:18 2020 +0000

    New translations components.php (Slovenian)

commit 1002cf9e3b
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Wed Mar 11 10:08:48 2020 +0000

    New translations components.php (Slovenian)

commit d5a6083ae8
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Wed Mar 11 09:37:23 2020 +0000

    New translations components.php (Slovenian)

commit 0d8df3a72e
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Wed Mar 11 09:07:01 2020 +0000

    New translations components.php (Slovenian)

commit 22337688f9
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Wed Mar 11 09:07:00 2020 +0000

    New translations common.php (Slovenian)

commit ff812694e2
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Wed Mar 11 08:20:44 2020 +0000

    New translations common.php (Slovenian)

commit 57b9e04927
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Wed Mar 11 06:17:11 2020 +0000

    New translations auth.php (Spanish)

commit 25343baac1
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Wed Mar 11 06:16:52 2020 +0000

    New translations activities.php (Spanish)

commit a5c72ee5f1
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Wed Mar 11 05:37:55 2020 +0000

    New translations activities.php (Spanish)

commit 6a6f28d095
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Mar 10 15:49:14 2020 +0000

    New translations auth.php (Slovenian)

commit 33f30876e1
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Mar 10 15:18:30 2020 +0000

    New translations auth.php (Slovenian)

commit 8bf8bc0fe5
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Mar 10 14:48:46 2020 +0000

    New translations auth.php (Slovenian)

commit 303dc07704
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Mar 10 14:48:44 2020 +0000

    New translations activities.php (Slovenian)

commit c219fb67aa
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Mar 10 09:59:45 2020 +0000

    New translations activities.php (Slovenian)

commit f45b6c6c82
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Mar 10 08:34:32 2020 +0000

    New translations activities.php (Slovenian)

commit 7d690eb13f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Mar 10 02:56:48 2020 +0000

    New translations entities.php (Russian)

commit 86aab0529e
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Tue Mar 10 02:56:43 2020 +0000

    New translations common.php (Russian)

commit 4fc1945543
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Mar 9 20:37:26 2020 +0000

    New translations errors.php (Russian)

commit 09791b736d
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Mar 9 20:07:52 2020 +0000

    New translations settings.php (Russian)

commit 9cb04bea4c
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Mar 9 18:49:50 2020 +0000

    New translations validation.php (Slovenian)

commit 7964a5a2a0
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Mar 9 18:49:34 2020 +0000

    New translations settings.php (Slovenian)

commit 361be13ff7
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Mar 9 18:49:32 2020 +0000

    New translations passwords.php (Slovenian)

commit 9b6a7f0f64
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Mar 9 18:49:31 2020 +0000

    New translations pagination.php (Slovenian)

commit a815adc24f
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Mar 9 18:49:30 2020 +0000

    New translations errors.php (Slovenian)

commit ae6040af3a
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Mar 9 18:49:28 2020 +0000

    New translations entities.php (Slovenian)

commit f1d0177dce
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Mar 9 18:49:26 2020 +0000

    New translations components.php (Slovenian)

commit 16ba9f1fe1
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Mar 9 18:49:24 2020 +0000

    New translations common.php (Slovenian)

commit caa47464ba
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Mar 9 18:49:23 2020 +0000

    New translations auth.php (Slovenian)

commit 4b9a78aef8
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Mon Mar 9 18:49:21 2020 +0000

    New translations activities.php (Slovenian)

commit 6a55161fe9
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sun Mar 8 01:36:31 2020 +0000

    New translations common.php (French)

commit 94235393fa
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 7 18:49:01 2020 +0000

    New translations errors.php (Portuguese, Brazilian)

commit a0f75e7724
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 7 10:24:26 2020 +0000

    New translations settings.php (Russian)

commit 65437712a2
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 7 09:37:34 2020 +0000

    New translations auth.php (Russian)

commit f7f6a92dcf
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 7 00:01:07 2020 +0000

    New translations entities.php (Russian)

commit ac8819edd3
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Sat Mar 7 00:00:57 2020 +0000

    New translations settings.php (Russian)

commit f1290f2b87
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Mar 6 23:23:44 2020 +0000

    New translations entities.php (Russian)

commit 8efb9bd571
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Mar 6 22:45:53 2020 +0000

    New translations entities.php (Russian)

commit 4fd31df14e
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Mar 6 22:45:44 2020 +0000

    New translations settings.php (Russian)

commit 262a2b3e4e
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Mar 6 22:11:41 2020 +0000

    New translations entities.php (Russian)

commit 15c98a64b8
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Mar 6 15:10:54 2020 +0000

    New translations errors.php (French)

commit 7a274db381
Author: Dan Brown <ssddanbrown@googlemail.com>
Date:   Fri Mar 6 15:10:43 2020 +0000

    New translations settings.php (French)
2020-03-14 22:20:01 +00:00
Dan Brown
1c6287f245 Updated translator list from Crowdin 2020-03-14 22:15:01 +00:00
Dan Brown
775ee1bde3 Merge branch 'patch-1' of git://github.com/MikeyMJCO/BookStack into MikeyMJCO-patch-1 2020-03-14 20:53:28 +00:00
Dan Brown
82278bd0f4 Updated readme
- Updated dev details to be current.
- Added warning for auto-fixing via phpcbf.
- Added warning that existing issue does not mean accepted pull request.
2020-03-14 18:56:49 +00:00
Dan Brown
8a4e75ef32 Added a "Start Database" step to github action flow
https://github.blog/changelog/2020-02-21-github-actions-breaking-change-ubuntu-virtual-environments-will-no-longer-start-the-mysql-service-automatically/
2020-03-14 18:44:02 +00:00
Dan Brown
7f6cbead33 Performed review of "public intended" functionality provided in #1817
- Updated logic to take url from referrer rather than pass as a query parameter.
- Added tests to cover functionality.
- Updated 404 page with login action button if not signed in.
- Updated 404 page with text to indicate permissions may be affecting visibility.

Related to #1817 and #1706
2020-03-14 18:29:31 +00:00
Dan Brown
a95588dc2e Merge branch 'feature/public-login-redirect' of git://github.com/Xiphoseer/BookStack into Xiphoseer-feature/public-login-redirect 2020-03-14 17:46:30 +00:00
Dan Brown
217954694c Updated npm dependancies 2020-03-14 17:38:39 +00:00
Dan Brown
17da30aa29 Updated default mail options 2020-03-14 17:32:11 +00:00
Dan Brown
aa12e48d73 Merge branch 'TBK-validation_fixes' 2020-03-14 12:46:01 +00:00
Dan Brown
200772da72 Merge branch 'validation_fixes' of git://github.com/TBK/BookStack into TBK-validation_fixes 2020-03-14 12:42:59 +00:00
dependabot[bot]
d7760b1b25 Bump acorn from 6.4.0 to 6.4.1
Bumps [acorn](https://github.com/acornjs/acorn) from 6.4.0 to 6.4.1.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/6.4.0...6.4.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-03-14 11:31:01 +00:00
Dan Brown
a5f972043b Updated primary color action text to be consistent
- With other similar picker components on the page.

As reported in #1930
2020-03-11 21:51:43 +00:00
Dan Brown
ae1f237a1f Merge branch 'Statium-master' 2020-03-11 21:43:16 +00:00
Statium
8a681fd796 Update entities.php
More accurate translation, error correction.
2020-03-11 21:40:50 +00:00
Statium
fa9944610d Update common.php
More accurate translation, error correction.
2020-03-11 21:38:29 +00:00
Statium
bebda6ff1a Update auth.php
More accurate translation, error correction.
2020-03-11 21:38:29 +00:00
Statium
991f6da9f4 Update activities.php
More accurate translation, error correction.
2020-03-11 21:35:31 +00:00
Dan Brown
c6ff6db784 Merge branch 'Statium-patch-1' 2020-03-11 21:28:09 +00:00
Statium
b58110000d Code refactoring
Removed extra spaces displayed in the header of the login and registration link.
2020-03-11 21:27:22 +00:00
Statium
f87c3b2660 Update setting-entity-color-picker.blade.php
Reducing indentation to one look in the application settings.
2020-03-11 21:23:04 +00:00
Dan Brown
59aefe5371 Updated social auth to take name from email if empty
- Added tests to cover.

Fixes #1853
2020-03-10 19:09:22 +00:00
Dan Brown
ccf92331c2 Updated readme with extra discord and issue list links 2020-03-06 20:26:11 +00:00
Dan Brown
30db8af460 Merge branch 'master' of git://github.com/ch0wm3in/BookStack into ch0wm3in-master 2020-03-06 20:10:57 +00:00
Dan Brown
56be10f1cd Merge branch 'perl_syntax_highlight' of git://github.com/Iyeyasu/BookStack into Iyeyasu-perl_syntax_highlight 2020-03-06 19:54:15 +00:00
Dan Brown
4b2654598c Merge branch 'master' of git://github.com/JHenneberg/BookStack into JHenneberg-master 2020-03-06 19:49:16 +00:00
Dan Brown
dbf5a87adb Lang setting list changes via Crowdin
* New translations settings.php (Italian)

* New translations settings.php (Vietnamese)

* New translations settings.php (Ukrainian)

* New translations settings.php (Turkish)

* New translations settings.php (Swedish)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Spanish)

* New translations settings.php (Slovak)

* New translations settings.php (Portuguese)

* New translations settings.php (Polish)

* New translations settings.php (Persian)

* New translations settings.php (Korean)

* New translations settings.php (Japanese)

* New translations settings.php (German)

* New translations settings.php (Russian)

* New translations settings.php (French)

* New translations settings.php (Dutch)

* New translations settings.php (Czech)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Arabic)

* New translations settings.php (Danish)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Hungarian)

* New translations settings.php (German Informal)
2020-03-04 22:43:30 +00:00
Dan Brown
b94b945fb0 Merge branch 'master' of git://github.com/Binternet/BookStack into Binternet-master 2020-03-04 22:22:08 +00:00
Dan Brown
34616ac195 Updated lanauge lists to match latest translations 2020-03-04 22:14:25 +00:00
Dan Brown
6303c788ed New Crowdin translations (#1868)
* New translations settings.php (Spanish)

* New translations errors.php (Japanese)

* New translations errors.php (Japanese)

* New translations components.php (Japanese)

* New translations settings.php (German)

* New translations settings.php (German)

* New translations auth.php (German Informal)

* New translations errors.php (German Informal)

* New translations settings.php (German Informal)

* New translations entities.php (German Informal)

* New translations activities.php (Persian)

* New translations auth.php (Persian)

* New translations common.php (Persian)

* New translations components.php (Persian)

* New translations entities.php (Persian)

* New translations errors.php (Persian)

* New translations pagination.php (Persian)

* New translations passwords.php (Persian)

* New translations settings.php (Persian)

* New translations validation.php (Persian)

* New translations settings.php (German Informal)

* New translations validation.php (German Informal)

* New translations settings.php (French)

* New translations errors.php (French)

* New translations settings.php (French)

* New translations settings.php (Hungarian)

* New translations activities.php (Portuguese)

* New translations auth.php (Vietnamese)

* New translations settings.php (Vietnamese)

* New translations passwords.php (Vietnamese)

* New translations pagination.php (Vietnamese)

* New translations errors.php (Vietnamese)

* New translations entities.php (Vietnamese)

* New translations components.php (Vietnamese)

* New translations common.php (Vietnamese)

* New translations activities.php (Vietnamese)

* New translations auth.php (Portuguese)

* New translations validation.php (Portuguese)

* New translations settings.php (Portuguese)

* New translations passwords.php (Portuguese)

* New translations pagination.php (Portuguese)

* New translations errors.php (Portuguese)

* New translations entities.php (Portuguese)

* New translations components.php (Portuguese)

* New translations common.php (Portuguese)

* New translations validation.php (Vietnamese)

* New translations components.php (Vietnamese)

* New translations auth.php (Vietnamese)

* New translations components.php (Vietnamese)

* New translations auth.php (Vietnamese)

* New translations activities.php (Vietnamese)

* New translations auth.php (Vietnamese)

* New translations entities.php (Vietnamese)

* New translations pagination.php (Vietnamese)

* New translations passwords.php (Vietnamese)

* New translations common.php (Vietnamese)

* New translations entities.php (Vietnamese)

* New translations common.php (Vietnamese)

* New translations settings.php (Vietnamese)

* New translations validation.php (Vietnamese)

* New translations validation.php (Vietnamese)

* New translations validation.php (Vietnamese)

* New translations errors.php (Vietnamese)

* New translations errors.php (Vietnamese)

* New translations errors.php (Vietnamese)

* New translations errors.php (Vietnamese)

* New translations errors.php (Vietnamese)

* New translations settings.php (Vietnamese)

* New translations settings.php (Vietnamese)

* New translations settings.php (Vietnamese)

* New translations settings.php (Vietnamese)

* New translations entities.php (Vietnamese)

* New translations settings.php (Vietnamese)

* New translations entities.php (Vietnamese)

* New translations settings.php (Vietnamese)

* New translations entities.php (Vietnamese)

* New translations entities.php (Vietnamese)

* New translations entities.php (Vietnamese)

* New translations errors.php (Chinese Simplified)

* New translations errors.php (French)

* New translations errors.php (German)

* New translations errors.php (Arabic)

* New translations errors.php (Czech)

* New translations errors.php (Danish)

* New translations errors.php (Dutch)

* New translations errors.php (Hungarian)

* New translations errors.php (Italian)

* New translations errors.php (Chinese Traditional)

* New translations errors.php (Swedish)

* New translations errors.php (Portuguese)

* New translations errors.php (Persian)

* New translations errors.php (German Informal)

* New translations errors.php (Ukrainian)

* New translations errors.php (Turkish)

* New translations errors.php (Korean)

* New translations errors.php (Spanish, Argentina)

* New translations errors.php (Spanish)

* New translations errors.php (Slovak)

* New translations errors.php (Russian)

* New translations errors.php (Polish)

* New translations errors.php (Japanese)

* New translations errors.php (Portuguese, Brazilian)

* New translations errors.php (Vietnamese)

* New translations errors.php (Spanish)

* New translations entities.php (Vietnamese)

* New translations entities.php (Vietnamese)

* New translations entities.php (Vietnamese)

* New translations entities.php (Vietnamese)

* New translations entities.php (Vietnamese)

* New translations entities.php (Vietnamese)

* New translations entities.php (Vietnamese)

* New translations entities.php (Vietnamese)

* New translations entities.php (Vietnamese)

* New translations errors.php (Vietnamese)

* New translations auth.php (Swedish)

* New translations common.php (Swedish)

* New translations entities.php (Swedish)

* New translations settings.php (Swedish)

* New translations errors.php (Chinese Simplified)

* New translations errors.php (Russian)

* New translations errors.php (Russian)

* New translations common.php (Russian)

* New translations settings.php (Russian)

* New translations settings.php (Russian)

* New translations errors.php (Hungarian)

* New translations settings.php (Hungarian)

* New translations settings.php (Russian)

* New translations errors.php (Russian)

* New translations settings.php (Russian)

* New translations activities.php (Russian)

* New translations auth.php (Russian)

* New translations components.php (Russian)

* New translations entities.php (Russian)

* New translations validation.php (Russian)

* New translations errors.php (Russian)

* New translations common.php (Russian)

* New translations entities.php (Russian)

* New translations errors.php (Russian)

* New translations settings.php (Russian)

* New translations settings.php (Portuguese, Brazilian)

* New translations auth.php (Russian)

* New translations components.php (Russian)

* New translations entities.php (Russian)

* New translations errors.php (Russian)

* New translations errors.php (Russian)

* New translations settings.php (Russian)

* New translations passwords.php (Russian)

* New translations auth.php (Danish)

* New translations auth.php (Danish)

* New translations common.php (Danish)

* New translations components.php (Danish)

* New translations entities.php (Danish)

* New translations entities.php (Danish)

* New translations entities.php (Danish)

* New translations errors.php (Danish)

* New translations errors.php (Russian)

* New translations settings.php (Russian)

* New translations settings.php (Russian)

* New translations validation.php (Russian)

* New translations errors.php (Danish)

* New translations errors.php (Danish)

* New translations settings.php (Danish)

* New translations settings.php (Danish)

* New translations settings.php (Danish)

* New translations validation.php (Danish)

* New translations validation.php (Danish)

* New translations settings.php (Danish)

* New translations settings.php (Danish)

* New translations auth.php (Russian)

* New translations settings.php (Russian)

* New translations errors.php (Russian)

* New translations settings.php (Russian)

* New translations validation.php (Russian)

* New translations settings.php (Russian)
2020-03-04 21:58:04 +00:00
TBK
57f587a78b Allow book, shelf, settings & profile form input validation to skip image 2020-03-04 00:17:53 +01:00
TBK
d3737d5a87 Remove redundant getImageValidationRules method 2020-03-04 00:17:49 +01:00
TBK
5cd56f63ff Change check to verify that request is present and contains a file 2020-03-04 00:17:45 +01:00
osmansorkar
1859c7917f added api functionality to handle book Shelves 2020-02-23 11:41:49 +06:00
Mikey O'Toole
65c4985710 Resolve issue #1911 (Additional margin/padding present in nested lists)
Optionally we could consider removing the rule at line 274. This doesn't handle multiple layers of nested lists and would be better covered by the generic rule which checks for an `ol` or `ul` nested inside a `li` which is how MarkDown renders nested lists as HTML.
2020-02-20 14:25:23 +00:00
osmansorkar
01adf39be8 added Handle Authorization Header on .htaccess to solve Authorization problem get from laravel orginal github ripo 2020-02-19 12:44:23 +06:00
jzoy
27191d1a2c Merge pull request #1 from BookStackApp/master
同步作者更新内容
2020-02-18 22:30:53 +08:00
Dan Brown
b8354b974b Updated version and assets for release v0.28.2 2020-02-15 22:36:08 +00:00
Dan Brown
034c1e289d Merge branch 'master' into release 2020-02-15 22:35:46 +00:00
Dan Brown
01b95d91ba Fixed side-effect in binary LDAP handling
- Was not stripping prefix when sending value to LDAP server in search.
- Updated test to cover.
2020-02-15 22:35:15 +00:00
Dan Brown
f31605a3de Updated version and assets for release v0.28.1 2020-02-15 22:08:06 +00:00
Dan Brown
e7cc75c74d Merge branch 'master' into release 2020-02-15 22:07:17 +00:00
Dan Brown
54a4c6e678 Fixed code-block drag+drop handling
- Added custom handling, Tracks if contenteditable blocks are being dragged. On drop the selection location will be roughly checked to put the block above or below the cursor block root element.
2020-02-15 21:37:41 +00:00
Dan Brown
29cc35a304 Added dump_user_details option to LDAP and added binary attribute decode option
Related to #1872
2020-02-15 20:31:23 +00:00
Dan Brown
6caedc7a37 Fixed issues preventing breadcrumb navigation menus from opening
- Added tests to cover endpoint

Fixes #1884
2020-02-15 19:09:33 +00:00
Dan Brown
5978d9a0d3 Updated cover image methods so image parameter is not optional but still nullable 2020-02-15 18:38:36 +00:00
Dan Brown
98ab3c1ffb Merge branch 'new_bookshelf_cover_fix' of git://github.com/TBK/BookStack into TBK-new_bookshelf_cover_fix 2020-02-15 18:34:45 +00:00
Dan Brown
ea3c3cde5a Added test to ensure shelf cover image gets set on create
Related to #1897
2020-02-15 18:34:02 +00:00
Dan Brown
e9d879bcc5 Made some updates to project readme and license 2020-02-15 15:47:17 +00:00
Dan Brown
ccd50fe918 Aligned export styles a little better and fixed potential DOMPDF css error
- Removed different PDF template used on pages.
- Updated export view files to have the intended format passed.
- Shared the export CSS amoung the export templates.

Should hopefully address #1886
2020-02-15 15:34:06 +00:00
Dan Brown
14363edb73 Fixed LDAP error thrown by not found user details
- Added testing to cover.

Related to #1876
2020-02-15 14:44:36 +00:00
Dan Brown
e8cfb4f2be Removed unintended extra lines in code blocks
Fixes #1877
2020-02-15 14:24:55 +00:00
Dan Brown
49386b42da Updated email test send to show error on failure
- Added test to cover
- Closes #1874
2020-02-15 14:13:15 +00:00
TBK
9533e0646e Fix for missing cover on create new shelf 2020-02-14 20:33:07 +01:00
ch0wm3in
c1fe81466f Fixed 'interaction_required' response for azure
Azure Conditional Access policy 2FA returns 'interaction_required' 400 response https://github.com/SocialiteProviders/Providers/issues/208
2020-02-12 15:03:55 +01:00
benrubson
12a9a45747 Log failed accesses 2020-02-09 10:01:33 +01:00
JHenneberg
0df0227ad4 Added support for Fortran language
sorted import alphabetically
2020-02-07 13:45:19 +01:00
Dan Brown
4b79d5e4e8 Updated version and assets for release v0.28.0 2020-02-03 22:44:45 +00:00
Dan Brown
34854915b3 Merge branch 'master' into release 2020-02-03 22:43:58 +00:00
Dan Brown
33ef1cd4fa Updated translators file 2020-02-03 22:25:17 +00:00
Dan Brown
d8072cbef2 New Crowdin translations (#1850)
* New translations settings.php (Korean)

* New translations settings.php (Polish)

* New translations settings.php (Ukrainian)

* New translations settings.php (Turkish)

* New translations settings.php (Swedish)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Spanish)

* New translations errors.php (Spanish)

* New translations settings.php (Slovak)

* New translations settings.php (Russian)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Japanese)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Italian)

* New translations settings.php (Hungarian)

* New translations settings.php (German)

* New translations settings.php (French)

* New translations settings.php (Dutch)

* New translations settings.php (Danish)

* New translations settings.php (Czech)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Arabic)

* New translations settings.php (German Informal)

* New translations common.php (Dutch)

* New translations settings.php (Spanish)

* New translations errors.php (Hungarian)

* New translations settings.php (Hungarian)

* New translations common.php (Hungarian)

* New translations errors.php (Hungarian)

* New translations settings.php (Hungarian)

* New translations validation.php (Hungarian)

* New translations errors.php (Portuguese, Brazilian)

* New translations errors.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations auth.php (Chinese Traditional)

* New translations common.php (Chinese Traditional)

* New translations entities.php (Chinese Traditional)

* New translations errors.php (Chinese Traditional)

* New translations entities.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Chinese Traditional)

* New translations validation.php (Chinese Traditional)

* New translations validation.php (Chinese Traditional)

* New translations errors.php (German)

* New translations errors.php (German)

* New translations settings.php (German)

* New translations settings.php (German Informal)

* New translations errors.php (French)

* New translations settings.php (French)

* New translations errors.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Hungarian)

* New translations settings.php (Hungarian)

* New translations validation.php (Hungarian)

* New translations errors.php (Chinese Simplified)

* New translations errors.php (Spanish)

* New translations errors.php (Korean)

* New translations settings.php (Korean)

* New translations errors.php (Polish)

* New translations settings.php (Polish)

* New translations errors.php (Russian)

* New translations settings.php (Russian)

* New translations errors.php (Slovak)

* New translations settings.php (Slovak)

* New translations settings.php (Spanish)

* New translations errors.php (Japanese)

* New translations errors.php (Spanish, Argentina)

* New translations settings.php (Spanish, Argentina)

* New translations errors.php (Swedish)

* New translations settings.php (Swedish)

* New translations errors.php (Turkish)

* New translations settings.php (Turkish)

* New translations errors.php (Ukrainian)

* New translations settings.php (Ukrainian)

* New translations settings.php (Japanese)

* New translations settings.php (Italian)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Portuguese, Brazilian)

* New translations errors.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations errors.php (French)

* New translations settings.php (French)

* New translations errors.php (German)

* New translations settings.php (German)

* New translations settings.php (Hungarian)

* New translations errors.php (Portuguese, Brazilian)

* New translations settings.php (German Informal)

* New translations errors.php (Italian)

* New translations errors.php (Arabic)

* New translations settings.php (Arabic)

* New translations errors.php (Czech)

* New translations settings.php (Czech)

* New translations errors.php (Danish)

* New translations settings.php (Danish)

* New translations errors.php (Dutch)

* New translations settings.php (Dutch)

* New translations errors.php (Hungarian)

* New translations errors.php (German Informal)

* New translations settings.php (Spanish)

* New translations settings.php (French)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Japanese)

* New translations settings.php (Turkish)

* New translations settings.php (Swedish)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Spanish)

* New translations settings.php (Slovak)

* New translations settings.php (Russian)

* New translations settings.php (Polish)

* New translations settings.php (Korean)

* New translations settings.php (Italian)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Dutch)

* New translations settings.php (Danish)

* New translations settings.php (Czech)

* New translations settings.php (Arabic)

* New translations settings.php (German Informal)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Hungarian)

* New translations settings.php (German)

* New translations settings.php (French)

* New translations settings.php (Ukrainian)
2020-02-03 21:00:17 +00:00
Dan Brown
718a97537e Added app theme setting to complete env and fixed text error 2020-02-03 20:33:10 +00:00
Dan Brown
dea8343bc8 Made docs sidebar sticky, changed theme to default
- MDN theme appeared fairly bad for markdown use, and the geometric
background was a bit much. Swapped out to default theme.
- Rough-added stickiness to docs sidebar, will need more work once it
starts to expand possible screen height.
2020-02-02 21:59:51 +00:00
Dan Brown
5ce3b861a9 Improved styling of the 500 error page 2020-02-02 21:04:43 +00:00
Dan Brown
e15fcf5b50 Merge pull request #1866 from BookStackApp/auth_alignment
Auth service alignment
2020-02-02 18:06:15 +00:00
Dan Brown
9d77cca734 Cleaned setting section redirect path 2020-02-02 17:57:21 +00:00
Dan Brown
b4f2b73590 Updated settings-save action to return to the same section 2020-02-02 17:35:16 +00:00
Dan Brown
3991fbe726 Checked over and aligned registration option behavior across all auth options
- Added tests to cover
2020-02-02 17:31:00 +00:00
Dan Brown
e6c6de0848 Simplified guard names and rolled out guard route checks
- Included tests to cover for LDAP and SAML
- Updated wording for external auth id option.
- Updated 'assertPermissionError' test case to be usable in BrowserKitTests
2020-02-02 13:10:21 +00:00
Dan Brown
5d08ec3cef Fixed failing tests caused by auth changes 2020-02-02 12:00:41 +00:00
Dan Brown
e743cd3f60 Added files missed in previous commit 2020-02-02 10:59:03 +00:00
Dan Brown
3470a6a140 Aligned SAML2 system with LDAP implementation in terms of guards and UI 2020-02-01 16:11:56 +00:00
Dan Brown
7728931f15 Set more appropriate login validation and broken up LDAP guide a bit 2020-02-01 14:30:23 +00:00
Dan Brown
575b85021d Started alignment of auth services
- Removed LDAP specific logic from login controller, placed in Guard.
- Created safer base user provider for ldap login, to be used for SAML
soon.
- Moved LDAP auth work from user provider to guard.
2020-02-01 11:42:22 +00:00
Dan Brown
92690d1ae9 Moved socal auth routes to their own controller
Also cleaned some phpdocs and extracted register actions to their own
service.
2020-01-26 14:42:50 +00:00
Dan Brown
fb5df49fd4 Updated laravel version and moved flare to non-dev 2020-01-26 13:27:28 +00:00
Dan Brown
82a8db3739 Merge pull request #1845 from SoarinFerret/add-close-icon-to-notifications
Add close icon to notifications
2020-01-19 16:07:08 +00:00
D4rt
b059744fb5 Add Perl syntax higlighting to code editor 2020-01-19 07:41:18 +02:00
Dan Brown
5ff89a1abb Added danish to language arrays 2020-01-18 16:10:16 +00:00
Dan Brown
7a2404d5e0 New Crowdin translations (#1825)
* New translations common.php (Turkish)

* New translations errors.php (Turkish)

* New translations settings.php (Turkish)

* New translations common.php (Italian)

* New translations settings.php (Italian)

* New translations auth.php (Portuguese, Brazilian)

* New translations auth.php (Portuguese, Brazilian)

* New translations auth.php (Portuguese, Brazilian)

* New translations common.php (Portuguese, Brazilian)

* New translations validation.php (Portuguese, Brazilian)

* New translations activities.php (Portuguese, Brazilian)

* New translations auth.php (Portuguese, Brazilian)

* New translations common.php (Portuguese, Brazilian)

* New translations activities.php (Portuguese, Brazilian)

* New translations components.php (Portuguese, Brazilian)

* New translations entities.php (Portuguese, Brazilian)

* New translations entities.php (Portuguese, Brazilian)

* New translations activities.php (Portuguese, Brazilian)

* New translations activities.php (Portuguese, Brazilian)

* New translations activities.php (Portuguese, Brazilian)

* New translations common.php (Portuguese, Brazilian)

* New translations components.php (Portuguese, Brazilian)

* New translations passwords.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese, Brazilian)

* New translations auth.php (Dutch)

* New translations auth.php (Dutch)

* New translations common.php (Dutch)

* New translations settings.php (Dutch)

* New translations common.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese, Brazilian)

* New translations validation.php (Dutch)

* New translations settings.php (Portuguese, Brazilian)

* New translations components.php (Dutch)

* New translations errors.php (Dutch)

* New translations settings.php (Dutch)

* New translations validation.php (Dutch)

* New translations settings.php (Dutch)

* New translations validation.php (Dutch)

* New translations entities.php (Portuguese, Brazilian)

* New translations entities.php (Portuguese, Brazilian)

* New translations errors.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese, Brazilian)

* New translations auth.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese, Brazilian)

* New translations auth.php (Portuguese, Brazilian)

* New translations auth.php (Portuguese, Brazilian)

* New translations components.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese, Brazilian)

* New translations errors.php (Portuguese, Brazilian)

* New translations entities.php (Portuguese, Brazilian)

* New translations errors.php (Portuguese, Brazilian)

* New translations entities.php (Portuguese, Brazilian)

* New translations entities.php (Portuguese, Brazilian)

* New translations validation.php (Portuguese, Brazilian)

* New translations validation.php (Portuguese, Brazilian)

* New translations validation.php (Portuguese, Brazilian)

* New translations errors.php (Danish)

* New translations errors.php (Danish)

* New translations activities.php (Danish)

* New translations common.php (Danish)

* New translations auth.php (Danish)

* New translations auth.php (Danish)

* New translations passwords.php (Danish)

* New translations common.php (Korean)

* New translations settings.php (Korean)

* New translations settings.php (Korean)

* New translations errors.php (Korean)

* New translations common.php (Chinese Simplified)

* New translations entities.php (Chinese Simplified)

* New translations errors.php (Chinese Simplified)

* New translations errors.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Korean)

* New translations settings.php (Spanish)

* New translations settings.php (Polish)

* New translations errors.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese, Brazilian)

* New translations errors.php (Russian)

* New translations settings.php (Russian)

* New translations errors.php (Slovak)

* New translations settings.php (Slovak)

* New translations errors.php (Spanish)

* New translations errors.php (Spanish, Argentina)

* New translations settings.php (Japanese)

* New translations settings.php (Spanish, Argentina)

* New translations errors.php (Swedish)

* New translations settings.php (Swedish)

* New translations errors.php (Turkish)

* New translations settings.php (Turkish)

* New translations errors.php (Ukrainian)

* New translations settings.php (Ukrainian)

* New translations errors.php (German Informal)

* New translations errors.php (Polish)

* New translations errors.php (Japanese)

* New translations errors.php (Korean)

* New translations errors.php (Danish)

* New translations errors.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations errors.php (Arabic)

* New translations settings.php (Arabic)

* New translations errors.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations errors.php (Czech)

* New translations settings.php (Czech)

* New translations settings.php (Danish)

* New translations settings.php (Italian)

* New translations errors.php (Dutch)

* New translations settings.php (Dutch)

* New translations errors.php (French)

* New translations settings.php (French)

* New translations errors.php (German)

* New translations settings.php (German)

* New translations errors.php (Hungarian)

* New translations settings.php (Hungarian)

* New translations errors.php (Italian)

* New translations settings.php (German Informal)
2020-01-18 16:03:27 +00:00
Dan Brown
0ba75713e1 Fixed github action workflow 2020-01-18 15:30:54 +00:00
Dan Brown
281200e212 Further updated github actions config
- Added composer caching based off github docs.
- Focused when actions run so they're not running unneccessarily.
2020-01-18 15:27:57 +00:00
Dan Brown
4ed23b0187 Added caching to github action workflow 2020-01-18 15:17:21 +00:00
Dan Brown
517687669c Merge pull request #1826 from BookStackApp/api_origins
Baseline API Implementation
2020-01-18 15:10:35 +00:00
Dan Brown
be554b9c79 Added configurable API throttling, Handled API errors standardly 2020-01-18 15:03:28 +00:00
Dan Brown
1350136ca3 Fixed bad test class name 2020-01-18 14:07:43 +00:00
Dan Brown
b9fb655b60 Added "Getting Started" API docs 2020-01-18 14:03:11 +00:00
Dan Brown
64455307b1 Added a few test to cover api docs pages 2020-01-18 10:04:13 +00:00
Dan Brown
8ead596067 Updated default codemirror theme
- To mdn-like theme, to have better default legibility and contrast
2020-01-18 09:55:02 +00:00
Dan Brown
8016f1121e Refined docs view, Added example requests 2020-01-18 09:48:30 +00:00
Dan Brown
45b5e631e2 Added a view for the API docs 2020-01-15 20:18:02 +00:00
SoarinFerret
4297d64e29 Add close icon to notifications 2020-01-14 13:50:29 -06:00
Dan Brown
bed2498667 Started work on generating API docs 2020-01-12 16:25:14 +00:00
Dan Brown
04a8614136 Filled out base Book API endpoints, added example responses 2020-01-12 14:45:54 +00:00
Dan Brown
a8595d8aaf Fixed test class names + add perm. check to api session auth 2020-01-01 17:01:36 +00:00
Dan Brown
a7a97a53f1 Added API listing filtering & cleaned ApiAuthenticate returns
API listing endpoint filter can be found via &filter[name]=my+book query
parameters. There are a range of operators that can be used such as
&filter[id:gte]=4
2020-01-01 16:33:47 +00:00
Dan Brown
55abf7be24 Added tests to cover API config and listing code 2019-12-30 20:48:23 +00:00
Dan Brown
3cacda6762 Added expiry checking to API token auth
- Added test to cover to ensure its checked going forward
2019-12-30 19:51:41 +00:00
Dan Brown
3d11cba223 Added testing coverage to API token auth 2019-12-30 19:42:46 +00:00
Dan Brown
6f1b88a6a6 Change email confirmation from own middle to trait
Email confirmation middleware caused more mess than good, As caused
priority issues and it depended on auth actions. Instead its now a trai
used on auth middlewares.

Also used 'EncryptCookies' middleware on API instead of custom
decryption in custom middleware since we'd need to do replicate all the
same actions anyway. Shouldn't have too much effect since it only
actions over cookies that exist, of which none should be there for most
API requests.

Also split out some large guard functions to be a little more readable
and appease codeclimate.
2019-12-30 15:49:20 +00:00
Dan Brown
349b4629be Extracted API auth into guard
Also implemented more elegant solution to allowing session auth for API
routes; A new 'StartSessionIfCookieExists' middleware, which wraps the
default 'StartSession' middleware will run for API routes which only
sets up the session if a session cookie is found on the request. Also
decrypts only the session cookie.

Also cleaned some TokenController codeclimate warnings.
2019-12-30 14:51:28 +00:00
Dan Brown
3de55ee645 Linked new API token system into middleware
Base logic in place but needs review and refactor to see if can better
fit into Laravel using 'Guard' system. Currently has issues due to
cookies in use from active session on API.
2019-12-30 02:16:07 +00:00
Lior Broshi
80a50f1ecb added rtl support for hebrew + added to localMap 2019-12-29 23:06:54 +02:00
Lior Broshi
23ad8024ec resolved conflict 2019-12-29 23:03:10 +02:00
Lior Broshi
da03e34c67 added he locale to configuration 2019-12-29 23:01:45 +02:00
Lior Broshi
5f333eebf0 validation 2019-12-29 22:53:42 +02:00
Dan Brown
2cfa37399c Fixed some empty-expiry conditions of token ui flows 2019-12-29 20:18:37 +00:00
Dan Brown
692fc46c7d Removed token 'client' text, avoid confusion w/ oAuth
- Instead have a token_id and a secret.
   - Displayed a 'Token ID' and 'Token Secret'.
2019-12-29 20:07:28 +00:00
Dan Brown
832fbd65af Added testing coverage to user API token interfaces 2019-12-29 19:46:46 +00:00
Dan Brown
dccb279c84 Built out interfaces & endpoints for API token managment 2019-12-29 17:03:52 +00:00
Dan Brown
d336ba6874 Started work on API token controls
- Added access-api permission.
- Started user profile UI work.
- Created database table and model for tokens.
- Fixed incorrect templates down migration :(
2019-12-29 13:02:26 +00:00
Dan Brown
04137e7c98 Started core API route work 2019-12-28 14:58:07 +00:00
Dan Brown
c055310507 Updated to latest laravel 6 version 2019-12-28 13:01:42 +00:00
Dan Brown
5c040bf2b7 Merge branch 'albergoniSivaf-master' 2019-12-27 17:15:45 +00:00
Dan Brown
cf743370a8 Updated code block lang order and added extra pascal option
- Fixed modal window sizing/positioning to be properly center and
responsive.

Related to #1730
2019-12-27 17:14:34 +00:00
Dan Brown
891dbfe085 Merge branch 'master' of git://github.com/albergoniSivaf/BookStack into albergoniSivaf-master 2019-12-27 17:03:10 +00:00
Dan Brown
6f9cad2106 Merge pull request #1793 from abublihi/master
Fix An Exception
2019-12-27 16:52:07 +00:00
Dan Brown
a433cde3b7 Merge pull request #1824 from BookStackApp/l10n_master
New Crowdin translations
2019-12-27 16:46:02 +00:00
Dan Brown
91081a0d72 New translations validation.php (German Informal) 2019-12-27 16:40:44 +00:00
Dan Brown
77c2b2ef64 New translations common.php (Slovak) 2019-12-27 16:40:43 +00:00
Dan Brown
426440d552 New translations errors.php (Slovak) 2019-12-27 16:40:40 +00:00
Dan Brown
a8ebcfaef6 New translations settings.php (Slovak) 2019-12-27 16:40:38 +00:00
Dan Brown
4db8c1279a New translations entities.php (Spanish) 2019-12-27 16:40:35 +00:00
Dan Brown
0ec4ca033c New translations errors.php (Spanish) 2019-12-27 16:40:33 +00:00
Dan Brown
0c446800a6 New translations settings.php (Spanish) 2019-12-27 16:40:31 +00:00
Dan Brown
2246b468bc New translations validation.php (Spanish) 2019-12-27 16:40:30 +00:00
Dan Brown
d7673c6a7b New translations common.php (Spanish) 2019-12-27 16:40:28 +00:00
Dan Brown
8269f99114 New translations common.php (Spanish, Argentina) 2019-12-27 16:40:27 +00:00
Dan Brown
9798fa8ba7 New translations settings.php (Russian) 2019-12-27 16:40:25 +00:00
Dan Brown
420baa2f65 New translations settings.php (Polish) 2019-12-27 16:40:24 +00:00
Dan Brown
f259bc2f15 New translations validation.php (Polish) 2019-12-27 16:40:22 +00:00
Dan Brown
312153befc New translations common.php (Portuguese, Brazilian) 2019-12-27 16:40:20 +00:00
Dan Brown
f85bf94c80 New translations errors.php (Portuguese, Brazilian) 2019-12-27 16:40:17 +00:00
Dan Brown
971c0b1b88 New translations activities.php (Russian) 2019-12-27 16:40:15 +00:00
Dan Brown
eff87696bc New translations auth.php (Russian) 2019-12-27 16:40:14 +00:00
Dan Brown
b44c27ba81 New translations common.php (Russian) 2019-12-27 16:40:13 +00:00
Dan Brown
f978ba3033 New translations entities.php (Russian) 2019-12-27 16:40:11 +00:00
Dan Brown
c163863b03 New translations passwords.php (Russian) 2019-12-27 16:40:08 +00:00
Dan Brown
ce70738c93 New translations settings.php (Portuguese, Brazilian) 2019-12-27 16:40:07 +00:00
Dan Brown
96f1fd534a New translations errors.php (Russian) 2019-12-27 16:40:05 +00:00
Dan Brown
5800bd82fb New translations errors.php (Spanish, Argentina) 2019-12-27 16:40:04 +00:00
Dan Brown
20ba63ce0e New translations validation.php (Turkish) 2019-12-27 16:40:03 +00:00
Dan Brown
026247be99 New translations activities.php (Ukrainian) 2019-12-27 16:40:01 +00:00
Dan Brown
303f4164f0 New translations auth.php (Ukrainian) 2019-12-27 16:40:00 +00:00
Dan Brown
3cb0742918 New translations common.php (Ukrainian) 2019-12-27 16:39:59 +00:00
Dan Brown
d7d634a3d7 New translations entities.php (Ukrainian) 2019-12-27 16:39:58 +00:00
Dan Brown
d957e72047 New translations errors.php (Ukrainian) 2019-12-27 16:39:56 +00:00
Dan Brown
6a0627e1d1 New translations passwords.php (Ukrainian) 2019-12-27 16:39:54 +00:00
Dan Brown
063a7af846 New translations settings.php (Turkish) 2019-12-27 16:39:53 +00:00
Dan Brown
dc5cc8c3ec New translations settings.php (Ukrainian) 2019-12-27 16:39:52 +00:00
Dan Brown
f39f2ca487 New translations auth.php (German Informal) 2019-12-27 16:39:50 +00:00
Dan Brown
b5d1b611b1 New translations common.php (German Informal) 2019-12-27 16:39:49 +00:00
Dan Brown
e9e6f11c2f New translations entities.php (German Informal) 2019-12-27 16:39:48 +00:00
Dan Brown
e634391fd7 New translations errors.php (German Informal) 2019-12-27 16:39:46 +00:00
Dan Brown
6ffb283014 New translations settings.php (German Informal) 2019-12-27 16:39:45 +00:00
Dan Brown
0105d4d5dd New translations validation.php (Ukrainian) 2019-12-27 16:39:42 +00:00
Dan Brown
63f9391f53 New translations errors.php (Turkish) 2019-12-27 16:39:40 +00:00
Dan Brown
51dd11410f New translations settings.php (Spanish, Argentina) 2019-12-27 16:39:38 +00:00
Dan Brown
475a1f4dff New translations common.php (Swedish) 2019-12-27 16:39:37 +00:00
Dan Brown
ed38be9672 New translations errors.php (Swedish) 2019-12-27 16:39:35 +00:00
Dan Brown
f55acc7cf1 New translations settings.php (Swedish) 2019-12-27 16:39:33 +00:00
Dan Brown
e6a1b2ea97 New translations auth.php (Turkish) 2019-12-27 16:39:30 +00:00
Dan Brown
8e4f331674 New translations common.php (Turkish) 2019-12-27 16:39:29 +00:00
Dan Brown
5ab6ad0526 New translations entities.php (Turkish) 2019-12-27 16:39:27 +00:00
Dan Brown
1568f953b6 New translations common.php (Dutch) 2019-12-27 16:39:25 +00:00
Dan Brown
68750b5da4 New translations settings.php (Czech) 2019-12-27 16:39:23 +00:00
Dan Brown
7cf2fd72ab New translations errors.php (Czech) 2019-12-27 16:39:21 +00:00
Dan Brown
c24905f606 New translations common.php (Czech) 2019-12-27 16:39:20 +00:00
Dan Brown
740543d32d New translations settings.php (Dutch) 2019-12-27 16:39:16 +00:00
Dan Brown
dd4feb4f3d New translations common.php (French) 2019-12-27 16:39:14 +00:00
Dan Brown
c58214c6fd New translations entities.php (French) 2019-12-27 16:39:12 +00:00
Dan Brown
3d187627d0 New translations errors.php (French) 2019-12-27 16:39:10 +00:00
Dan Brown
601126ba2e New translations errors.php (Dutch) 2019-12-27 16:39:07 +00:00
Dan Brown
003eb6ea26 New translations settings.php (Arabic) 2019-12-27 16:39:06 +00:00
Dan Brown
e4d847ab51 New translations settings.php (Chinese Traditional) 2019-12-27 16:39:05 +00:00
Dan Brown
82e344166e New translations settings.php (French) 2019-12-27 16:39:03 +00:00
Dan Brown
9e6f208dec New translations common.php (Arabic) 2019-12-27 16:39:02 +00:00
Dan Brown
5856998c60 New translations errors.php (Arabic) 2019-12-27 16:38:59 +00:00
Dan Brown
0d9be20af8 New translations auth.php (Chinese Simplified) 2019-12-27 16:38:57 +00:00
Dan Brown
f6816db615 New translations common.php (Chinese Simplified) 2019-12-27 16:38:56 +00:00
Dan Brown
faf455e78c New translations entities.php (Chinese Simplified) 2019-12-27 16:38:54 +00:00
Dan Brown
3534082c8c New translations settings.php (Chinese Simplified) 2019-12-27 16:38:52 +00:00
Dan Brown
8240295c86 New translations common.php (Chinese Traditional) 2019-12-27 16:38:50 +00:00
Dan Brown
bbb379919f New translations entities.php (Chinese Traditional) 2019-12-27 16:38:48 +00:00
Dan Brown
d1a9ddf3db New translations errors.php (Chinese Traditional) 2019-12-27 16:38:47 +00:00
Dan Brown
ee9c53325d New translations errors.php (Chinese Simplified) 2019-12-27 16:38:45 +00:00
Dan Brown
7c5488f318 New translations errors.php (Korean) 2019-12-27 16:38:44 +00:00
Dan Brown
f9969978a5 New translations auth.php (German) 2019-12-27 16:38:43 +00:00
Dan Brown
85c2e3bc8e New translations common.php (Japanese) 2019-12-27 16:38:41 +00:00
Dan Brown
f10808f6a0 New translations errors.php (Japanese) 2019-12-27 16:38:39 +00:00
Dan Brown
5d214b184d New translations settings.php (Japanese) 2019-12-27 16:38:38 +00:00
Dan Brown
f5a83eccb7 New translations auth.php (Korean) 2019-12-27 16:38:35 +00:00
Dan Brown
cf473edcbd New translations common.php (Korean) 2019-12-27 16:38:34 +00:00
Dan Brown
58b14d9e89 New translations entities.php (Korean) 2019-12-27 16:38:32 +00:00
Dan Brown
7cf60afe14 New translations passwords.php (Korean) 2019-12-27 16:38:30 +00:00
Dan Brown
78bd482931 New translations settings.php (Korean) 2019-12-27 16:38:29 +00:00
Dan Brown
83e946f146 New translations common.php (Polish) 2019-12-27 16:38:26 +00:00
Dan Brown
8d3220c98a New translations entities.php (Polish) 2019-12-27 16:38:25 +00:00
Dan Brown
9b0d1f1328 New translations errors.php (Polish) 2019-12-27 16:38:23 +00:00
Dan Brown
433d66e406 New translations activities.php (German) 2019-12-27 16:38:21 +00:00
Dan Brown
e2fec5cb4f New translations settings.php (Italian) 2019-12-27 16:38:20 +00:00
Dan Brown
702ad28a9a New translations common.php (German) 2019-12-27 16:38:18 +00:00
Dan Brown
8c224a57f0 New translations entities.php (German) 2019-12-27 16:38:17 +00:00
Dan Brown
a260279463 New translations errors.php (German) 2019-12-27 16:38:15 +00:00
Dan Brown
76f43b95d4 New translations settings.php (German) 2019-12-27 16:38:13 +00:00
Dan Brown
4b19ba9ed1 New translations validation.php (German) 2019-12-27 16:38:12 +00:00
Dan Brown
f1777280c3 New translations auth.php (Hungarian) 2019-12-27 16:38:10 +00:00
Dan Brown
4df112661f New translations common.php (Hungarian) 2019-12-27 16:38:09 +00:00
Dan Brown
33e17aed6e New translations entities.php (Hungarian) 2019-12-27 16:38:07 +00:00
Dan Brown
047b711fc4 New translations settings.php (Hungarian) 2019-12-27 16:38:04 +00:00
Dan Brown
15df902a32 New translations validation.php (Hungarian) 2019-12-27 16:38:02 +00:00
Dan Brown
5e2908c996 New translations common.php (Italian) 2019-12-27 16:38:01 +00:00
Dan Brown
6c9e162821 New translations entities.php (Italian) 2019-12-27 16:37:59 +00:00
Dan Brown
8235677b31 New translations errors.php (Italian) 2019-12-27 16:37:58 +00:00
Dan Brown
a4eb5c3268 New translations errors.php (Hungarian) 2019-12-27 16:37:56 +00:00
Dan Brown
4613dbfb8f Merge branch 'qianmengnet-master' 2019-12-27 16:29:06 +00:00
Dan Brown
8144887e4c Merge branch 'master' of git://github.com/qianmengnet/BookStack into qianmengnet-master 2019-12-27 16:28:56 +00:00
Dan Brown
d9f0d46d20 Merge pull request #1819 from johnroyer/translate
update translation
2019-12-27 16:22:59 +00:00
Dan Brown
611cb29073 Merge pull request #1804 from artskoczylas/master
Update of polish language
2019-12-27 16:21:23 +00:00
Dan Brown
84af59bbe6 Merge pull request #1791 from jzoy/master
Simplified Chinese Translation Update
2019-12-27 16:19:00 +00:00
Dan Brown
a3cf45cfb6 Merge pull request #1762 from dellamina/updateItalianTranslation
Update Italian translation
2019-12-27 16:18:04 +00:00
Dan Brown
dabe79a438 Merge pull request #1734 from ististudio/master
Update Korean translation
2019-12-27 16:16:55 +00:00
ezzra
a82d9fdba5 fix translate for "actions" 2019-12-27 15:47:03 +00:00
Lior Broshi
8794f62ad8 settings 2019-12-24 23:36:35 +02:00
Lior Broshi
290610b77e more heb 2019-12-23 22:04:15 +02:00
Dan Brown
865e8d4ec5 Improved markdown mobile editor experience
- Updated styles of codemirror area to be a bit more forefull in taking
up space.
- Added a fullscreen toggle as a backup option.

For #1675
2019-12-22 14:22:38 +00:00
Dan Brown
e06f9f7fe3 Removed setting override system due to confusing behaviour
- Was only used to disable registration when LDAP was enabled.
- Caused saved option not to show on settings page causing confusion.
- Extended setting logic where used to take ldap into account instead of
global override.
- Added warning on setting page to show registration enable setting is
not used while ldap is active.

For #1541
2019-12-22 13:19:17 +00:00
Dan Brown
32e7f0a2e6 Made display thumbnail generation use original data if smaller
Thumbnail generation would sometimes create a file larger than the
original, if the original was already well optimized, therefore making
the thumbnail counter-productive. This change compares the sizes of the
original and the generated thumbnail, and uses the smaller of the two if
the thumbnail does not change the aspect ratio of the image.

Fixes #1751
2019-12-22 12:44:49 +00:00
Lior Broshi
b65d4cda0e pagination, passwords and part of settings 2019-12-21 22:34:50 +02:00
Dan Brown
a83a7f34f4 Better standardised and fixes areas of image pasting
- Extracted logic to get images from paste/drop event into own file to
align usage in both events for both editors.
- Fixed non-ability to drag+drop into WYSIWYG editor.
- Updated check for table data to look for table specific rich-text
instead of just any text since some the old check was too general and
was preventing some legitimate image paste events.

Tested on Chrome and FireFox on Ubuntu.
Attempted to test on Safari via browserstack but environment was
unreliable and could not access folders to test drag/drop of files.

Relates to #1651 and #1697
2019-12-21 15:48:03 +00:00
Dan Brown
5491bd62a2 Fixed test failing due to redirect changes
- Also set APP_THEME param during testing to avoid local conflicts
2019-12-21 13:48:44 +00:00
Dan Brown
ceeb9d35a0 Updated JS dependancies 2019-12-21 13:30:41 +00:00
Zero
50ed56f65d update translation 2019-12-17 16:52:39 +08:00
Dan Brown
b93f8a4d46 Auto-expand collapsible sections if containing error
For #1693
2019-12-16 13:27:17 +00:00
Dan Brown
a9634b6b66 Set a default outline color and width
- Applied since the browser defaults caused outlines to appear very
large in some cases.
- Set default color to use app primary color, to help them blend into
the design a little.

For #1738
2019-12-16 13:15:11 +00:00
Dan Brown
f9fa6904b9 Made LDAP auth ID attribute configurable
- Allows the field that gets stored as the "External Authentication ID"
to be configurable. Defined as LDAP_ID_ATTRIBUTE=uid in .env.
- Added test to cover usage.
- Also now auto-lowercases when searching for attributes in LDAP
response since PHP always provides them as lower case.

Closes #592.
2019-12-16 12:40:21 +00:00
Dan Brown
017703ff1a Updated page delete to return to chapter if within one
- Added test to cover

Closes #1715
2019-12-16 11:54:53 +00:00
Dan Brown
f122bebae7 Prevented whitespace in codeblocks being trimmed
For #1771
2019-12-16 11:44:28 +00:00
Daniel Seiler
afa501e75b Recall previous route when manually clicking login 2019-12-14 08:41:22 +01:00
Dan Brown
02af69ddf2 Added command to copy shelf permissions
Has options to run for all or to specify a slug for a specific shelf.

Closes #1091
2019-12-11 21:22:03 +00:00
jzoy
7f0dbf350e Update entities.php 2019-12-11 20:03:32 +08:00
jzoy
b3889c380a Update entities.php 2019-12-11 19:24:18 +08:00
Dan Brown
cee4dccc55 Compacted entity color options in settings view
- Also extracted the view code into it's own blade template
- Made smaller color input styles
2019-12-07 21:23:15 +00:00
Dan Brown
615a050856 Merge branch 'settings-color-selector' of git://github.com/james-geiger/BookStack into james-geiger-settings-color-selector 2019-12-07 20:36:39 +00:00
Dan Brown
5a533fff8b Updated codeblock editor to work with fade animation
- Added fadeIn to animation JS service.
- Updated overlay to use anim service and to recieve a callback for
after-anim actions.
- Updated code editor popup to refresh Codemirror instance layout after
animation has completed.

Fixes #1672
2019-12-07 16:54:34 +00:00
Dan Brown
a6bbe46987 Updated code system to dynamically set php codemirror mode
- Codemirror mode mapping value can now be a function to dynamically set
mode depending on actual code content.
- Used above system to set php mode type, depending on if '<?php' tags
exist in content.

Closes #1557
2019-12-07 16:23:44 +00:00
Dan Brown
7af6fe4917 Standardised issue template name casing 2019-12-07 15:57:58 +00:00
Dan Brown
1746f2c249 Fixed issue template wording 2019-12-07 15:57:07 +00:00
Dan Brown
701d105b9e Updated details and attribution for translators 2019-12-07 15:54:25 +00:00
Artur Skoczylas
6bc6543402 consistent of book translation 2019-11-28 15:55:18 +01:00
Artur Skoczylas
000059f6cf Update polish language 2019-11-28 15:39:54 +01:00
Dan Brown
1bcb24a921 Added in the github translators that didn't save in the last comit 2019-11-22 22:41:00 +00:00
Dan Brown
abb5cc1852 Added a translator attriubtion file
Added list of users that have provided translations along with the
languages they have provided.

Github users, starting with an '@', were added via manually going
through past pull requests and inspecting the user and language.
2019-11-22 22:23:22 +00:00
qianmengnet
9bed57e40e Modify Chinese language pack
Modify Chinese language pack
2019-11-22 16:35:47 +08:00
abublihi
23a716a3ac Fix "Declaration of Middleware\TrustProxies::handle should be compatible with Fideloper\Proxy\TrustProxies::handle" 2019-11-20 14:00:20 +03:00
jzoy
f8279384a6 Simplified Chinese Translation Update 2019-11-19 18:22:23 +08:00
Dan Brown
4e09656c78 Merge pull request #1787 from BookStackApp/saml2_auth
SAML2 Authentication
2019-11-17 19:20:37 +00:00
Dan Brown
c33ef4b9b2 Added tests to cover saml and added controller middleware 2019-11-17 19:15:37 +00:00
Dan Brown
ebb3724892 Added onelogin attribution and tweaks after testing saml with onelogin 2019-11-17 17:00:42 +00:00
Dan Brown
6d899f3b17 Added icon for saml, added saml to register page, updated complete env 2019-11-17 16:07:06 +00:00
Dan Brown
aef6eb81e4 Added SAML singleLogoutService capabilities 2019-11-17 15:40:36 +00:00
Dan Brown
488325f459 Added the ability to auto-load config from metadata url 2019-11-17 14:44:26 +00:00
Dan Brown
3a17ba2cb9 Started using OneLogin SAML lib directly
- Aligned and formatted config options.
- Provided way to override onelogin lib options if required.
- Added endpoints in core bookstack routes.
- Provided way to debug details provided by idp and formatted by
bookstack.
- Started on test work
- Handled case of email address already in use.
2019-11-17 13:26:43 +00:00
Dan Brown
9bba84684f Appeased codeclimate by extracting out external_auth_id group matching 2019-11-16 15:24:09 +00:00
Dan Brown
8169c725d5 Started review of SAML implementation
- Updated PHPdoc of SAML service to use type hinting instead.
- Updated groups to only sync if enabled.
- Updated names of some config props.
- Removed a couple of unused config props.
- Added exception to handle no email on SAML response.
2019-11-16 14:42:51 +00:00
Dan Brown
bb1f43cbd8 Merge branch 'feature/saml' of git://github.com/Xiphoseer/BookStack into Xiphoseer-feature/saml 2019-11-16 12:42:45 +00:00
User
7c7098b601 Update some postpositional particles 2019-11-07 16:54:38 +09:00
User
ffd05f1584 Update some terms 2019-11-07 15:19:15 +09:00
Mattia Della Mina
b8a7ef15bd improve italian translation 2019-10-31 22:04:04 +01:00
jakob
6acd958927 Add the "Create Shelf" resp. "Create Book" to the home view 2019-10-30 11:42:37 +01:00
jakob
6cd26e23a8 Allow toggling between grid and list view in shelf view (shelves.show) 2019-10-30 11:23:42 +01:00
Dan Brown
189a598d56 Merge branch 'master' of github.com:BookStackApp/BookStack 2019-10-29 22:34:12 +00:00
Dan Brown
90f9240be4 Merge branch 'philjak-feature_move_page_into_chapter' 2019-10-29 22:33:53 +00:00
Dan Brown
d64c358c4f Updated sort logic to handle chapter to book scenario
- Extended tests out to cover
2019-10-29 22:33:09 +00:00
Dan Brown
e108808a32 Merge branch 'feature_move_page_into_chapter' of git://github.com/philjak/BookStack into philjak-feature_move_page_into_chapter 2019-10-29 22:26:11 +00:00
Dan Brown
6a1b6a97f9 Added test for page move into chapter 2019-10-29 22:25:53 +00:00
jakob
bea983ab85 Download and assign avatar when creating LDAP user in database. Fixes issue #1161 2019-10-29 22:18:02 +00:00
jakob
7368ff3e6a No need to save page 2019-10-28 16:53:48 +01:00
jakob
4daeb9daa6 Check if parent is a chapter. If so, move into Book and assing page to chapter. 2019-10-28 15:33:28 +01:00
Dan Brown
b80aa2350f Merge branch 'philjak-feature_bugfix_save_book_cover' 2019-10-27 17:05:34 +00:00
Dan Brown
e26474f233 Merge branch 'feature_bugfix_save_book_cover' of git://github.com/philjak/BookStack into philjak-feature_bugfix_save_book_cover 2019-10-27 17:03:02 +00:00
Dan Brown
1b350d622d Merge branch 'cw1998-fix/#1662' 2019-10-27 16:57:00 +00:00
Dan Brown
4b9618cd21 Update book form so cancel URL is explicitly passed in
- Added to prevent future possibility of 'shelf' var being introduced in
scope and therefore causing a side-effect of redirect logic.
2019-10-27 16:55:05 +00:00
Dan Brown
28184c6bfc Merge branch 'fix/#1662' of git://github.com/cw1998/BookStack into cw1998-fix/#1662 2019-10-27 16:44:41 +00:00
Dan Brown
99ce3067c7 Added test to check custom theme lang items 2019-10-26 18:07:14 +01:00
Dan Brown
4763b899b6 Made it possible to override translations via theme system 2019-10-26 18:07:14 +01:00
Dan Brown
1366fc45ce Added tests to cover test email sends
- Also tweaked wording of 'E-mail' to 'Email' to remain consistent with
the rest of the app.

Related to #1696 and #1719
2019-10-23 20:25:51 +01:00
Dan Brown
a2370f7c9d Merge branch 'feature-send-test-email' of git://github.com/timoschwarzer/BookStack into timoschwarzer-feature-send-test-email 2019-10-23 19:53:51 +01:00
jakob
bc38fd3ac4 entity needs to be saved after image upload and associate 2019-10-22 11:18:08 +02:00
istist
5ae0e127df Update auth.php
Edit for  'Must be over 7 characters'.
2019-10-21 04:17:52 +09:00
User
2eb6f178c2 Banish .DS_Store 2019-10-21 03:51:55 +09:00
User
19ce6da0d3 Update Korean translation 2019-10-21 03:44:38 +09:00
Dan Brown
99ae592ae9 New Crowdin translations (#1732)
* New translations auth.php (Ukrainian)

* New translations common.php (Ukrainian)

* New translations entities.php (Ukrainian)

* New translations entities.php (Ukrainian)

* New translations settings.php (Ukrainian)

* New translations validation.php (Ukrainian)

* New translations settings.php (French)

* New translations settings.php (Russian)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Ukrainian)

* New translations settings.php (Turkish)

* New translations settings.php (Swedish)

* New translations settings.php (Slovak)

* New translations settings.php (Polish)

* New translations settings.php (Spanish)

* New translations settings.php (Dutch)

* New translations settings.php (Korean)

* New translations settings.php (Japanese)

* New translations settings.php (Italian)

* New translations settings.php (Hungarian)

* New translations settings.php (German)

* New translations settings.php (Czech)

* New translations settings.php (Arabic)

* New translations settings.php (German Informal)
2019-10-19 00:13:00 +01:00
Dan Brown
f37131a5bf Removed old Translation Service + Provider
Was no longer needed due to only being there to perform
language extension for de_informal but now this is done by crowdin
instead so it's redundant. Same goes for checking and formatting
scripts.

Also removed comment advising deletion form settings.php language list
since this is now auto-copied to languages anyway.

Related to #1261
2019-10-19 00:04:49 +01:00
Dan Brown
f3a7d58816 Initial Crowdin Translation Integration Merge (#1731)
* New translations activities.php (French)

* New translations entities.php (Turkish)

* New translations entities.php (Swedish)

* New translations errors.php (Swedish)

* New translations pagination.php (Swedish)

* New translations passwords.php (Swedish)

* New translations settings.php (Swedish)

* New translations validation.php (Swedish)

* New translations auth.php (Turkish)

* New translations common.php (Turkish)

* New translations errors.php (Turkish)

* New translations common.php (Swedish)

* New translations settings.php (Turkish)

* New translations validation.php (Turkish)

* New translations activities.php (Ukrainian)

* New translations auth.php (Ukrainian)

* New translations common.php (Ukrainian)

* New translations components.php (Ukrainian)

* New translations entities.php (Ukrainian)

* New translations errors.php (Ukrainian)

* New translations components.php (Swedish)

* New translations auth.php (Swedish)

* New translations passwords.php (Ukrainian)

* New translations settings.php (Russian)

* New translations settings.php (Polish)

* New translations validation.php (Polish)

* New translations activities.php (Russian)

* New translations auth.php (Russian)

* New translations common.php (Russian)

* New translations components.php (Russian)

* New translations entities.php (Russian)

* New translations errors.php (Russian)

* New translations passwords.php (Russian)

* New translations validation.php (Russian)

* New translations activities.php (Swedish)

* New translations activities.php (Slovak)

* New translations auth.php (Slovak)

* New translations common.php (Slovak)

* New translations components.php (Slovak)

* New translations entities.php (Slovak)

* New translations errors.php (Slovak)

* New translations pagination.php (Slovak)

* New translations passwords.php (Slovak)

* New translations settings.php (Slovak)

* New translations validation.php (Slovak)

* New translations pagination.php (Ukrainian)

* New translations settings.php (Ukrainian)

* New translations pagination.php (Polish)

* New translations passwords.php (Spanish, Argentina)

* New translations settings.php (Portuguese, Brazilian)

* New translations validation.php (Portuguese, Brazilian)

* New translations activities.php (Spanish, Argentina)

* New translations auth.php (Spanish, Argentina)

* New translations common.php (Spanish, Argentina)

* New translations components.php (Spanish, Argentina)

* New translations entities.php (Spanish, Argentina)

* New translations errors.php (Spanish, Argentina)

* New translations pagination.php (Spanish, Argentina)

* New translations settings.php (Spanish, Argentina)

* New translations errors.php (Portuguese, Brazilian)

* New translations validation.php (Spanish, Argentina)

* New translations activities.php (German Informal)

* New translations auth.php (German Informal)

* New translations common.php (German Informal)

* New translations components.php (German Informal)

* New translations entities.php (German Informal)

* New translations errors.php (German Informal)

* New translations pagination.php (German Informal)

* New translations passwords.php (German Informal)

* New translations settings.php (German Informal)

* New translations entities.php (Portuguese, Brazilian)

* New translations validation.php (Ukrainian)

* New translations activities.php (Chinese Traditional)

* New translations activities.php (Chinese Simplified)

* New translations auth.php (Chinese Simplified)

* New translations common.php (Chinese Simplified)

* New translations components.php (Chinese Simplified)

* New translations entities.php (Chinese Simplified)

* New translations errors.php (Chinese Simplified)

* New translations pagination.php (Chinese Simplified)

* New translations passwords.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations validation.php (Chinese Simplified)

* New translations auth.php (Chinese Traditional)

* New translations components.php (Portuguese, Brazilian)

* New translations common.php (Chinese Traditional)

* New translations components.php (Chinese Traditional)

* New translations entities.php (Chinese Traditional)

* New translations errors.php (Chinese Traditional)

* New translations pagination.php (Chinese Traditional)

* New translations passwords.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations validation.php (Chinese Traditional)

* New translations activities.php (Portuguese, Brazilian)

* New translations auth.php (Portuguese, Brazilian)

* New translations common.php (Portuguese, Brazilian)

* New translations passwords.php (Polish)

* New translations errors.php (Polish)

* New translations auth.php (French)

* New translations validation.php (Czech)

* New translations validation.php (Arabic)

* New translations auth.php (Czech)

* New translations common.php (Czech)

* New translations entities.php (Czech)

* New translations errors.php (Czech)

* New translations pagination.php (Czech)

* New translations settings.php (Czech)

* New translations activities.php (German)

* New translations passwords.php (Arabic)

* New translations auth.php (German)

* New translations common.php (German)

* New translations components.php (German)

* New translations entities.php (German)

* New translations errors.php (German)

* New translations pagination.php (German)

* New translations passwords.php (German)

* New translations settings.php (German)

* New translations validation.php (German)

* New translations settings.php (Arabic)

* New translations pagination.php (Arabic)

* New translations common.php (Hungarian)

* New translations common.php (Spanish)

* New translations common.php (French)

* New translations components.php (French)

* New translations entities.php (French)

* New translations errors.php (French)

* New translations pagination.php (French)

* New translations passwords.php (French)

* New translations settings.php (French)

* New translations validation.php (French)

* New translations errors.php (Arabic)

* New translations settings.php (Spanish)

* New translations validation.php (Spanish)

* New translations activities.php (Arabic)

* New translations auth.php (Arabic)

* New translations common.php (Arabic)

* New translations components.php (Arabic)

* New translations entities.php (Arabic)

* New translations auth.php (Hungarian)

* New translations entities.php (Polish)

* New translations common.php (Dutch)

* New translations common.php (Korean)

* New translations components.php (Korean)

* New translations entities.php (Korean)

* New translations errors.php (Korean)

* New translations pagination.php (Korean)

* New translations passwords.php (Korean)

* New translations settings.php (Korean)

* New translations validation.php (Korean)

* New translations activities.php (Dutch)

* New translations auth.php (Dutch)

* New translations components.php (Dutch)

* New translations activities.php (Korean)

* New translations entities.php (Dutch)

* New translations errors.php (Dutch)

* New translations pagination.php (Dutch)

* New translations passwords.php (Dutch)

* New translations settings.php (Dutch)

* New translations validation.php (Dutch)

* New translations activities.php (Polish)

* New translations auth.php (Polish)

* New translations common.php (Polish)

* New translations components.php (Polish)

* New translations auth.php (Korean)

* New translations validation.php (Japanese)

* New translations entities.php (Hungarian)

* New translations errors.php (Italian)

* New translations errors.php (Hungarian)

* New translations settings.php (Hungarian)

* New translations validation.php (Hungarian)

* New translations activities.php (Italian)

* New translations auth.php (Italian)

* New translations common.php (Italian)

* New translations components.php (Italian)

* New translations entities.php (Italian)

* New translations pagination.php (Italian)

* New translations settings.php (Japanese)

* New translations passwords.php (Italian)

* New translations settings.php (Italian)

* New translations validation.php (Italian)

* New translations activities.php (Japanese)

* New translations auth.php (Japanese)

* New translations common.php (Japanese)

* New translations components.php (Japanese)

* New translations entities.php (Japanese)

* New translations errors.php (Japanese)

* New translations pagination.php (Japanese)

* New translations passwords.php (Japanese)

* New translations validation.php (German Informal)
2019-10-18 17:08:22 +01:00
Albergoni Andrea
48c44958f5 Added support for Pascal language 2019-10-18 16:34:38 +02:00
Dan Brown
f1d7699df5 Updated Korean to be correct country code 2019-10-18 14:27:41 +01:00
Dan Brown
37560a3f8c Fixed crowdin translation path 2019-10-18 02:09:12 +01:00
Dan Brown
5f3caf3643 Update Crowdin configuration file 2019-10-18 01:46:30 +01:00
Dan Brown
c8d90791ff Moved crownin config file 2019-10-18 01:45:25 +01:00
Dan Brown
c108c16419 Added crowdin config file 2019-10-18 01:40:50 +01:00
Dan Brown
b09ea76b8d Renamed properties input option as INI
- Also made INI be recognised as the codemirror "Properties" format.
2019-10-17 21:16:55 +01:00
Dan Brown
8b4bfa4d78 Merge branch 'master' of git://github.com/c0shea/BookStack into c0shea-master 2019-10-17 21:09:05 +01:00
James Geiger
e6fe299c4f added additional color settings into UI
Adds new options in the customization section of the settings to change the shelf, book, chapter, page, and draft colors.
2019-10-17 13:46:18 -05:00
James Geiger
ae19658b50 Placeholder for allowing colors to be changed in settings UI. 2019-10-17 09:44:20 -05:00
Dan Brown
d7557befe2 Copied release page link to normal settings page
- Also updated link to not leak referrer info
2019-10-17 15:06:55 +01:00
Dan Brown
5c7262673a Merge branch 'patch-1' of git://github.com/DeftNerd/BookStack into DeftNerd-patch-1 2019-10-17 14:58:20 +01:00
Dan Brown
ef762e851a Reverted changes to codemirror line wrapping 2019-10-17 14:41:39 +01:00
Dan Brown
e91ef54cc9 Merge branch 'fix-1575' of git://github.com/james-geiger/BookStack into james-geiger-fix-1575 2019-10-17 14:32:39 +01:00
Dan Brown
3959841dbc Added back in some tabindex that shouldn't have been removed 2019-10-17 14:21:13 +01:00
Dan Brown
e48d7d59cc Removed tabindexes where found to be not required 2019-10-17 14:19:35 +01:00
Dan Brown
5a887e31da Merge branch 'master' of git://github.com/almandin/BookStack into almandin-master 2019-10-17 14:09:07 +01:00
Dan Brown
df98deb59d Added Turkish to locale system 2019-10-17 14:01:19 +01:00
Dan Brown
ddb7f33868 Merge branch 'master' of git://github.com/oykenfurkan/BookStack into oykenfurkan-master 2019-10-17 13:56:53 +01:00
Dan Brown
076cf59a41 Merge pull request #1695 from qligier/master
French translation update
2019-10-17 13:46:33 +01:00
Dan Brown
4ab6a25893 Merge pull request #1681 from leomartinez/master
Updated 'Spanish Argentina' translation.
2019-10-17 13:44:28 +01:00
Dan Brown
f413fc528a Merge pull request #1646 from kostefun/patch-15
Update settings.php
2019-10-17 13:43:27 +01:00
Dan Brown
76bd0fdfa6 Added editor instance event hooks
As per #1721
2019-10-16 18:01:35 +01:00
Dan Brown
b24279cc12 Merge branch 'patching-v0.27' 2019-10-16 16:37:29 +01:00
Dan Brown
af6f34b529 Updated version and assets for release v0.27.5 2019-10-16 16:35:50 +01:00
Dan Brown
fb82a2b896 Merge branch 'patching-v0.27' into release 2019-10-16 16:35:10 +01:00
Timo Schwarzer
61a9139bf0 Add feature to send test e-mails 2019-10-16 08:24:33 +02:00
Dan Brown
d6456e961a Fixed issue causing text overlap in sort select box
Updated grid columns to be more adaptable to content, with a min-width
of the old value.
Fixes #1654
2019-10-07 21:06:15 +01:00
Dan Brown
d4c62265ca Made JS animation cleanup process more reliable
Fixes #1643
2019-10-07 20:57:25 +01:00
Dan Brown
b6c0baf44d Updated comment delete action to be a button
Fixes issue that causes code error when an anchor tag.

Closes #1650
2019-10-07 20:21:04 +01:00
Dan Brown
ccec991f6c Added zip/unzip to docker dev setup for composer to use 2019-10-05 13:21:38 +01:00
Dan Brown
6736779eff Merge pull request #1698 from 3mmarg97/master
Fixing composer install inside docker `app` container
2019-10-05 13:13:29 +01:00
Dan Brown
31f5786e01 Entity Repo & Controller Refactor (#1690)
* Started mass-refactoring of the current entity repos

* Rewrote book tree logic

- Now does two simple queries instead of one really complex one.
- Extracted logic into its own class.
- Remove model-level akward union field listing.
- Logic now more readable than being large separate query and
compilation functions.

* Extracted and split book sort logic

* Finished up Book controller/repo organisation

* Refactored bookshelves controllers and repo parts

* Fixed issues found via phpunit

* Refactored Chapter controller

* Updated Chapter export controller

* Started Page controller/repo refactor

* Refactored another chunk of PageController

* Completed initial pagecontroller refactor pass

* Fixed tests and continued reduction of old repos

* Removed old page remove and further reduced entity repo

* Removed old entity repo, split out page controller

* Ran phpcbf and split out some page content methods

* Tidied up some EntityProvider elements

* Fixed issued caused by viewservice change
2019-10-05 12:55:01 +01:00
Ammar Al-Khawaldeh
3f025f69cf Add git to the apt-get install packages. 2019-10-03 20:46:49 +03:00
Quentin Ligier
593933c84e French translation update 2019-10-01 20:34:54 +02:00
Christopher Wilkinson
4ad4dfa55a Show bookshelves that a book belongs to on a book view
Closes #1598
2019-09-27 00:45:22 +01:00
Christopher Wilkinson
2f94f078e3 Fix Book form (create) returning to the full books list on cancel
Fixes #1662
Added a small block of logic to determine the correct URL to attribute to the cancel button on a given page create form.
If adding a book from a bookshelf, return to the bookshelf. If editing a book, return to the book. In all other cases, return to the full books list.
2019-09-26 22:51:24 +01:00
Leonardo
0fa4ef072f Updated 'Spanish Argentina' translation. 2019-09-24 22:36:08 -03:00
Dan Brown
7cd956b24b Removed some unused parameters and fixed env test logic 2019-09-20 01:18:59 +01:00
Dan Brown
8b550991a4 Refactored some core entity actions
- Created BookChild class to share some page/chapter logic.
- Gave entities the power to generate their own permissions and slugs.
- Moved bits out of BaseController constructor since it was overly
sticky.
- Moved slug generation logic into its own class.
- Created a facade for permissions due to high use.
- Fixed failing test issues from last commits
2019-09-20 00:18:28 +01:00
Dan Brown
f7a5a0705b Moved shelf book append logic 2019-09-19 18:20:09 +01:00
Dan Brown
615b2de433 Simplified activity facade interface
Also cleaned up any other bits along the way.
2019-09-19 18:03:17 +01:00
Dan Brown
2a2cc858f0 Refactored notification showing and global view data 2019-09-19 15:12:10 +01:00
Connor O'Shea
fca69643db Normalize ini and properties values 2019-09-15 20:24:47 -04:00
Connor O'Shea
4ad43b1a1f Add support for properties 2019-09-15 20:22:26 -04:00
Connor O'Shea
228aa4740b Add support for properties (INI) 2019-09-15 20:20:11 -04:00
Dan Brown
60d0f96cd7 Extracted some methods into a BookRepo 2019-09-15 23:28:23 +01:00
Dan Brown
d28abf24d4 Split out export actions into own controllers 2019-09-15 22:33:27 +01:00
Dan Brown
3281925375 Standardised how request is injected into controller methods
Puts it in-line with how Laravel recommend.
2019-09-15 18:53:30 +01:00
Dan Brown
be08dc1588 Ran phpcbf and updated helpers typehinting 2019-09-15 18:29:51 +01:00
Dan Brown
b1566099a3 Added laravel stats package and enabled debugbar models 2019-09-15 18:07:00 +01:00
Dan Brown
e81f90d9bd Updated twitch provider 2019-09-15 17:50:08 +01:00
Dan Brown
8e212bdeab Ran NPM audit fix 2019-09-15 17:39:07 +01:00
Dan Brown
2ab5df75dd Updated version and removed travis 2019-09-14 14:23:16 +01:00
Dan Brown
ab91e245fb Merge branch 'master' of github.com:BookStackApp/BookStack 2019-09-14 14:21:35 +01:00
Dan Brown
1ee3e779e4 Merge branch 'laravel-upgrade' 2019-09-14 14:21:24 +01:00
Dan Brown
58a79fcb19 Removed old str_random functions from seeders 2019-09-14 14:17:55 +01:00
Dan Brown
cbf9d701af Updated to laravel 6 2019-09-14 14:12:39 +01:00
Dan Brown
140298bd96 Updated to Laravel 5.8 2019-09-13 23:58:40 +01:00
Furkan
84c36f6032 Added Turkish translations. 2019-09-13 15:45:38 +03:00
oykenfurkan
ec29c08beb Delete tr 2019-09-13 15:32:54 +03:00
oykenfurkan
9e8e5b2ca0 Create tr
Adding Turkish translations
2019-09-13 15:32:40 +03:00
Dan Brown
f311635de6 Add testing via GitHub actions (#1657)
To replace Travis CI. Travis to be removed after migration to Laravel 6.
2019-09-12 21:19:05 +01:00
kostefun
339d3849b8 Update settings.php
fix rus
2019-09-09 10:07:16 +07:00
Lior Broshi
974e52be5c errors.php 2019-09-08 23:08:49 +03:00
Lior Broshi
d84de86b40 entities.php 2019-09-07 22:46:30 +03:00
Dan Brown
5b464938b6 Updated version and assets for release v0.27.4 2019-09-07 13:30:08 +01:00
Dan Brown
81f954890d Merge branch 'patching-v0.27' into release 2019-09-07 13:29:53 +01:00
Dan Brown
23db81f2cc Merge pull request #1637 from kostefun/patch-14
Update validation.php
2019-09-07 13:22:12 +01:00
Dan Brown
a35c1bfb13 Merge pull request #1636 from kostefun/patch-13
Update passwords.php
2019-09-07 13:21:56 +01:00
Dan Brown
0b75b33044 Merge pull request #1635 from kostefun/patch-12
Update pagination.php
2019-09-07 13:21:37 +01:00
Dan Brown
b8617eb3d1 Merge pull request #1630 from kostefun/patch-11
Update errors.php
2019-09-07 13:21:11 +01:00
Dan Brown
1bf3666d6b Merge pull request #1629 from kostefun/patch-10
Update entities.php
2019-09-07 13:20:50 +01:00
Dan Brown
caaed849d5 Merge pull request #1628 from kostefun/patch-9
Update components.php
2019-09-07 13:20:10 +01:00
Dan Brown
e98986fc2d Merge pull request #1626 from kostefun/patch-7
Update auth.php
2019-09-07 13:19:39 +01:00
Dan Brown
c764208b25 Merge pull request #1624 from kostefun/patch-6
Update settings.php
2019-09-07 13:18:55 +01:00
Dan Brown
8fbe677975 Merge pull request #1627 from kostefun/patch-8
Update common.php
2019-09-07 13:18:01 +01:00
Dan Brown
d6e27af14a Merge pull request #1633 from moucho/master
Updated Spanish translation
2019-09-07 13:16:24 +01:00
Dan Brown
0b55e52e4e Merge pull request #1623 from leomartinez/master
Updated 'Spanish Argentina' translation.
2019-09-07 13:14:27 +01:00
Dan Brown
0345ece890 Fixed issue that caused quick-sort buttons to not be clickable
Fixes #1639
2019-09-07 13:08:55 +01:00
Dan Brown
58f5508b05 Added mysql service for travis 2019-09-07 00:14:19 +01:00
Dan Brown
de8a1a372d Updated travis-ci php versions 2019-09-07 00:10:03 +01:00
Dan Brown
6917ea088f Upgraded app to Laravel 5.7 2019-09-06 23:36:16 +01:00
Dan Brown
213e9d2941 Upgraded to Laravel 5.6 2019-09-06 22:14:39 +01:00
kostefun
739efdb0e2 Update entities.php
fix
2019-09-05 10:25:17 +07:00
kostefun
ac5784d0d0 Update entities.php 2019-09-05 10:20:22 +07:00
kostefun
e1aa212db8 Update validation.php
Fix & add Ru
2019-09-05 10:10:15 +07:00
kostefun
6758a42f80 Update passwords.php
Corresponds to the English version
2019-09-05 09:52:24 +07:00
kostefun
10199d684e Update pagination.php
Corresponds to the English version
2019-09-05 09:46:45 +07:00
moucho
21e5685816 Update Spanish translation 2019-09-04 15:40:25 +02:00
kostefun
746ad01ebb Update errors.php
update ru
2019-09-04 16:42:04 +07:00
kostefun
26b42b6414 Update entities.php
Update ru
2019-09-04 16:35:44 +07:00
kostefun
22a665a942 Update components.php
update ru
2019-09-04 16:07:10 +07:00
kostefun
7a5fc800b5 Update common.php
update ru
2019-09-04 16:05:20 +07:00
kostefun
3148b316cf Update auth.php
update ru
2019-09-04 15:57:29 +07:00
kostefun
1c2f43b3a6 Update settings.php 2019-09-04 15:41:08 +07:00
Leonardo
1bb1b568af Updated 'Spanish Argentina' translation. 2019-09-03 21:33:37 -03:00
Dan Brown
0e2bbcec62 Updated version and assets for release v0.27.3 2019-09-03 21:50:12 +01:00
Dan Brown
fdd339f525 Merge branch 'master' into release 2019-09-03 21:49:46 +01:00
Dan Brown
16d8a667b1 Fixed issue preventing FormData posting correctly
- Due to migration from Axios, Instances where we were sending FormData
were not considered and always converted to JSON which resulted in empty
JSON bodies.

Related to #1621
2019-09-03 21:46:46 +01:00
Leonardo
a1f89ad589 Merge remote-tracking branch 'upstream/master' 2019-09-02 17:04:11 -03:00
Dan Brown
8cf7d6a83d Updated version and assets for release v0.27.2 2019-09-01 12:12:23 +01:00
Dan Brown
58a5008718 Merge branch 'master' into release 2019-09-01 12:12:10 +01:00
Dan Brown
7a4425473b Fixed URL gen issue causing incorrect scheme to be used
For #1613
2019-09-01 12:07:51 +01:00
Dan Brown
c44a8df55d Updated version and assets for release v0.27.1 2019-09-01 11:13:50 +01:00
Dan Brown
ff1494c519 Merge branch 'master' into release 2019-09-01 11:13:18 +01:00
Dan Brown
f421a2e1d6 Updated pointer button styles so icon not hidden
Related to #1616
2019-09-01 11:06:19 +01:00
Dan Brown
79f1e87cd0 Updated export styles to remove grey bg 2019-09-01 10:55:00 +01:00
Dan Brown
e9d42a2e8c Fixed no md editor preview in FireFox 2019-09-01 10:51:52 +01:00
Dan Brown
712ea21efe Added mailhog to the docker-compose setup 2019-08-31 18:09:40 +01:00
Dan Brown
b8ce8fd852 Updated assets for release v0.27 2019-08-31 14:16:14 +01:00
Dan Brown
75e7454a5f Merge branch 'master' into release and set version 2019-08-31 14:15:18 +01:00
Dan Brown
36195c94df Merge branch 'timoschwarzer-docker-development-environment' 2019-08-26 22:01:19 +01:00
Dan Brown
21f09a5920 Added ldap and moved compose for docker-dev setup
- Also tweaked readme a little to fit this is with more recent changes.
2019-08-26 22:01:10 +01:00
Dan Brown
aea5319256 Merge branch 'docker-development-environment' of git://github.com/timoschwarzer/BookStack into timoschwarzer-docker-development-environment 2019-08-26 21:24:56 +01:00
Dan Brown
444a23a419 Merge pull request #1573 from miles75/lang-hu
Typo fix
2019-08-26 16:07:45 +01:00
Dan Brown
fde3867313 Made it possible to drag in template content 2019-08-26 15:34:03 +01:00
Dan Brown
5979f6667b Tweaked entity color palette for accessibility
Also converted entity colors to CSS variables for easier
instance customization.

Related to #1320
2019-08-26 14:38:50 +01:00
Dan Brown
64abe10dc4 Improved accessibility for many editor page components
Related to #1320
2019-08-26 12:47:04 +01:00
Dan Brown
7cc17934a8 Made MD editor display a sandboxed iframe
- Also added escaping of srcdoc elements in escape logic.

Related to #1531
2019-08-26 12:16:50 +01:00
Dan Brown
2dfe6c2d56 Fixed failing test and added more accessibility improvements
- Updated linked images to have obvious focus styles
- Added proper role to notifications
- Made dropdown list focus styles a bit nicer.
- Updated book list chapter child slide down to be keyboard activatable.

Related to #1320
2019-08-25 17:21:25 +01:00
Dan Brown
9fbef8cd1b Re-orged readme and added a11y info
- Also tweaked default theme color a tad to better fit in Level A
standard.
2019-08-25 16:19:56 +01:00
Dan Brown
cf5d51e7b8 Made another mass of accessibility improvements
- Set proper semantic tags for main parts of content.
- Removed focus-trap from tag manager/autosuggest.
- Set better accessibility labelling on tag manager.
- Updated collapsible sections to be keyboard navigatable.
- Improved input focus styling to better fit theme.
- Updated custom styled file picker to be accessible via keyboard.

Related to #1320
2019-08-25 15:44:51 +01:00
Dan Brown
ae93a6ed07 Converted primary color use to css variable
- Removed all existing SCSS usage of primary color.
- Cut down custom styles injection to just be css vars.
- Reduced button styles so default button is primary.
- Updated button styles to lighten/brighten on hover & active states even
when a custom color is set.
- Removed unused scss color vars.
- Updated default BookStack blue to achieve better accessibility.
2019-08-25 12:40:04 +01:00
Dan Brown
b792108bc1 Updated print css for recent redesign
Fixes #1472
2019-08-25 11:30:26 +01:00
Dan Brown
4bf77f67dd Set comment add box to show with correct permissions
- Also fixed const assignment issue in translations.js
2019-08-25 11:02:58 +01:00
Dan Brown
88e076a12a Removed console.log 2019-08-24 18:39:38 +01:00
Dan Brown
b27a5c7fb8 Made a mass of accessibility improvements
- Changed default focus styles
- Updated dropdowns with keyboard navigation
- Updated modals with esc exiting
- Added accessibility attirbutes where needed
- Made many more elements focusable
- Updated hover effects of many items to also apply when focused within

Related to #1320 and #1198
2019-08-24 18:29:02 +01:00
Dan Brown
1b33a0c5b9 Added labels and tweaked muted colors for accessibility
Home now passing automated checks in accessibility insights for web.
2019-08-18 19:17:43 +01:00
Dan Brown
78f8a51664 Merge branch 'kostasdizas-unicode' 2019-08-18 18:58:06 +01:00
Dan Brown
666213a4d4 Removed html dir tag for now, Updated lang format 2019-08-18 18:57:35 +01:00
Dan Brown
3acea12f1c Merge branch 'unicode' of git://github.com/kostasdizas/BookStack into kostasdizas-unicode 2019-08-18 18:51:20 +01:00
Dan Brown
eab0ca9648 Covered new invite system with testing
Closes #316
2019-08-18 13:55:28 +01:00
Dan Brown
42d8548960 Finished new user invite flow 2019-08-18 13:11:30 +01:00
Dan Brown
e5155a5dcb Refactored confirm actions to their own controller 2019-08-18 10:47:59 +01:00
Dan Brown
44330bdd24 Start user invite system 2019-08-17 15:52:33 +01:00
Lior Broshi
019085071a entities, not done yet 2019-08-15 23:24:45 +03:00
James Geiger
c14611d14b Fixed inline code overflowing off of page in issue #1575. 2019-08-14 23:45:48 -05:00
James Geiger
fccc112cc1 Merge pull request #1 from BookStackApp/master
merge aug. 11 commits
2019-08-14 06:10:43 +00:00
Virgile
3bcfe2a460 Adds autofocus on the email field of the standard login page. 2019-08-13 17:30:29 +02:00
Timo Schwarzer
c6b1f36412 Alter docker paths 2019-08-12 22:19:58 +02:00
Timo Schwarzer
b608bb8859 Remove additional database connections and seeders in docker env 2019-08-12 16:59:51 +02:00
Timo Schwarzer
9357620d55 Add docker development environment 2019-08-12 16:43:39 +02:00
Dan Brown
4de432b50d Removed console.log & added readme discord badge 2019-08-11 20:30:51 +01:00
Dan Brown
20c36d58a6 Merge pull request #1527 from BookStackApp/129-page-templates
Page Templates Implementation
2019-08-11 20:21:17 +01:00
Dan Brown
5fdab3b8af Updated template test to be more stable 2019-08-11 20:10:27 +01:00
Dan Brown
de3e9ab094 Added ability to use templates
- Added replace, append and prepend actions for template content into
both the WYSIWYG editor and markdown editor.
- Added further testing to cover.
2019-08-11 20:04:43 +01:00
Daniel Seiler
8e723f10dc Add error messages, fix LDAP error 2019-08-07 15:31:10 +02:00
Daniel Seiler
03dbe32f99 Refactor for codestyle 2019-08-07 12:07:21 +02:00
Daniel Seiler
bda0082461 Add login and automatic registration; Prepare Group sync 2019-08-06 23:42:46 +02:00
Dan Brown
421dd93ffd Merge branch 'v0.26' 2019-08-06 21:50:56 +01:00
Dan Brown
2558ea8931 Updated version for release v0.26.4 2019-08-06 21:42:09 +01:00
Dan Brown
ac0f47a4b2 Merge branch 'v0.26' into release 2019-08-06 21:41:06 +01:00
Dan Brown
f417675b1d Prevented normal users from changing own email
To address #1542

Updates to only allow email changes by users with the users-manage role
permission.
2019-08-06 21:29:42 +01:00
Dan Brown
2955f414dd Added iframe JS and data url escaping
Related to #1531
2019-08-06 21:08:24 +01:00
Dan Brown
4de719b325 Prevented potential apache image dir listing
Closes #1545
2019-08-06 20:35:27 +01:00
Daniel Seiler
3c41b15be6 Initial work on SAML integration 2019-08-05 20:06:39 +02:00
miles
518d9df961 Typo fix 2019-08-05 10:43:48 +02:00
Dan Brown
2ebbc6b658 Merge branch 'master' into 129-page-templates 2019-08-04 16:26:38 +01:00
Dan Brown
0b1ece664d Updated editor z-indexing to not hide app menu
Closes #1556
2019-08-04 16:21:16 +01:00
Dan Brown
83ef086470 Added missing locale option 2019-08-04 16:10:04 +01:00
Dan Brown
1b8a164412 Merge pull request #1561 from danielroehrig-mm/task/updateGermanTranslation
German translation extended
2019-08-04 16:08:48 +01:00
Dan Brown
84a387cf5b Merge pull request #1554 from miles75/lang-hu
Hungarian translation
2019-08-04 16:07:19 +01:00
Dan Brown
71ebb9df8b Removed unused config item
Left in by mistake during development
2019-08-04 14:41:08 +01:00
Dan Brown
0ac50c0e50 Updated phpunit instructions to composer phpunit
Closes #1555
2019-08-04 14:34:02 +01:00
Dan Brown
4b0c4e621a Replaced use of custom 'baseUrl' helper with 'url'
Also changed up how base URL setting was being done
by manipulating incoming request URLs instead of
altering then on generation.
2019-08-04 14:26:39 +01:00
Daniel Röhrig
fbf8378ae5 German translation extended 2019-07-31 13:44:28 +02:00
miles
d63157175b Hungarian translation 2019-07-27 14:03:01 +02:00
Lior Broshi
6c7e74f475 components 2019-07-22 22:57:00 +03:00
Lior Broshi
b153ffd019 common 2019-07-22 22:35:29 +03:00
Lior Broshi
9cfa391ab6 auth 2019-07-22 22:31:01 +03:00
Dan Brown
30da105812 Started refactor of URL system to better extend Laravel 2019-07-21 21:32:08 +01:00
Dan Brown
1e7df28238 Set export service to set correct svg image mimetype
For #1538
2019-07-17 22:37:19 +01:00
Dan Brown
629b7a674e Merge pull request #1534 from DeehSlash/pt_BR
Fix pt_BR translations
2019-07-15 20:11:03 +01:00
Dan Brown
ce1c70084e Merge pull request #1485 from lucaguindani/update-fr-lang
Updated the french lang files
2019-07-15 20:02:13 +01:00
André Luiz da Silva
94f610d040 Fix pt_BR translations 2019-07-11 19:30:00 -03:00
Dan Brown
8fcb0e6820 Merge branch 'v0.26' 2019-07-10 20:30:36 +01:00
Dan Brown
4f16129869 Updated version for release v0.26.3 2019-07-10 20:21:22 +01:00
Dan Brown
64a8037fdd Merge branch 'v0.26' into release 2019-07-10 20:19:54 +01:00
Dan Brown
c732970f6e Hardened page content script escaping
Increased range of tests to cover.

Fixes #1531
2019-07-10 20:17:22 +01:00
Lior Broshi
de140ab5a5 started Hebrew translation, not done yet 2019-07-09 22:40:35 +03:00
Dan Brown
94441832c5 Removed old translation endpoint tests 2019-07-07 13:54:17 +01:00
Dan Brown
71167426bb Started implementation of page template 2019-07-07 13:45:46 +01:00
Dan Brown
f7f7cd464c Removed jquery from dropzone
Also added fadeout to custom animation lib
2019-07-06 15:08:26 +01:00
Dan Brown
15c39c1976 Updated JS translations to be inserted from back-end
Removes old awkward JS translations endpoint.
New system still a little akward in code but not now in process.

Also extracted out page editors into their own files.

Closes #1258
2019-07-06 14:52:25 +01:00
Dan Brown
6fa093d9d0 Merge branch 'master' of github.com:BookStackApp/BookStack 2019-07-06 13:45:31 +01:00
Dan Brown
97fdfa6ebe Moved config dir into app dir
Closes #1506
2019-07-06 13:44:50 +01:00
Dan Brown
5c43a5a59a Merge pull request #1517 from bjubes/patch-1
Fix missing word in users_social_accounts_info string
2019-07-03 19:54:26 +01:00
Brian Jubelirer
e7508689de fix missing word 2019-07-02 09:14:42 -04:00
Dan Brown
5c70413784 Fixed incorrect testing vars and reset env vars in config test 2019-06-25 22:52:07 +01:00
Dan Brown
52b4c81aff Merge pull request #1505 from timoschwarzer/hide-permissions-table-unless-enabled
Hide permissions table unless custom permissions are enabled
2019-06-25 21:52:52 +01:00
Dan Brown
9a080da29f Added debugbar config
- Set debugbar support for APP_URL
- Set debugbar to not show by default in debug mode.

Closes #1508
2019-06-24 20:24:24 +01:00
Dan Brown
762d1d7595 Allowed different storage types for images and attachments
- Added new env and config vars to allow this.
- Also added tests for awkward config logic including fallback for new
env vars.

Closes #1302
2019-06-23 16:01:15 +01:00
Timo Schwarzer
6504a6f599 Hide permissions table unless custom permissions are enabled 2019-06-23 14:29:58 +02:00
Dan Brown
bf1371d04c Fixed firefox tri-layout grid issue and added tablet sticky sidebar
- Fixed issue with original left-sidebar content being placed halfway
down the page.
- Added sticky sidebar to mid-size tablet layout, only for original left
sidebar items.

Fixes #1434.
2019-06-16 12:46:23 +01:00
Dan Brown
f08668706f Updated page-nav to show more title content
Will now be truncated using CSS instead of being truncated on PHP side.
Closes #1206.
2019-06-16 12:08:07 +01:00
Dan Brown
7b506447c7 Updated WYSIWYG edtitor to be iOS scrollable
Fixes #1058
2019-06-16 11:55:01 +01:00
Dan Brown
fbb2b7ac6a Updated page nav header shift logic to be accurate
Added tests to cover.
Fixes #542
2019-06-16 11:32:38 +01:00
Dan Brown
56e31a5df7 Cleaned some page pointer layout/styles up 2019-06-16 11:17:15 +01:00
Kostas Dizas
86f56dd22b Added locale and text direction to html templates 2019-06-11 23:01:08 +01:00
Dan Brown
282c45f088 Updated roadmap & dev version, removed dupe locale mappings 2019-06-11 22:45:41 +01:00
Dan Brown
214c09c2b2 Changed translation key for last commit 2019-06-10 21:21:27 +01:00
Dan Brown
dda0200a94 Added note to custom HTML head input
To warn of being inactive while viewing the settings page.
Closes #1144
2019-06-10 19:54:22 +01:00
Dan Brown
53ba5b7e33 Removed jQuery and replaced axios with fetch 2019-06-08 00:02:51 +01:00
Dan Brown
b532ed0f86 Removed jquery usage from wysiwyg editor JS 2019-06-07 19:21:38 +01:00
Dan Brown
fdd34a74ed Removed jquery usage from page-display 2019-06-07 17:46:19 +01:00
Luca Guindani
239b3c8c2b Updated french translation files 2019-06-07 17:06:54 +02:00
Dan Brown
7634a84334 Converted existing custom slideup/down implementations 2019-06-07 16:00:34 +01:00
Dan Brown
2b929f5d95 Added custom slideUp/slideDown animations using plain JS 2019-06-07 15:51:01 +01:00
Dan Brown
ff841cff2e Removed "Toggle Header" option in page editor
Somewhat overlaps with the editor fullscreen button and is using jQuery
2019-06-06 14:14:32 +01:00
Dan Brown
9e397a57a9 Removed tiny color picker library 2019-06-06 14:05:06 +01:00
Dan Brown
d87eb277dd Replaced jquery sortable with sortablejs 2019-06-06 13:09:58 +01:00
Dan Brown
2eba8c611e Updated shelf-sort to use sortablejs 2019-06-06 11:49:51 +01:00
Dan Brown
f12a7540c9 Removed babel & auto-prefixer from build system
Closes #1468
2019-06-04 12:19:34 +01:00
Dan Brown
fe64248e86 Added keyboard navigation to breadcrumb dropdowns 2019-06-04 11:25:19 +01:00
Dan Brown
a9f983f156 Added focus and a11y attributes/functionality to custom checkboxes
Closes #1476
2019-06-04 10:47:09 +01:00
Dan Brown
7502ba1bc8 Updated version and assets for release v0.26.2 2019-05-27 13:48:20 +01:00
Dan Brown
33a04697ef Merge branch 'master' into release 2019-05-27 13:47:47 +01:00
Dan Brown
a602cdf401 Fixed some body card horizontal scroll and column collapse issues
As mentoined in #1441
2019-05-27 13:10:48 +01:00
Dan Brown
5aa741cb60 Prevented tri-layout sidebars being faded on mobile
As mentoined in #1441
2019-05-27 12:56:31 +01:00
Dan Brown
3ad1b42a74 Updated page delete to handle inactive custom homepage correctly
Fixes #1447
2019-05-27 12:40:19 +01:00
Dan Brown
2b7362fa94 Added highlighting to current book-tree item
Related to #1435
2019-05-25 16:52:44 +01:00
Dan Brown
35f35bcba5 Updated custom home views to use tri-layout
Closes #1423
2019-05-25 16:35:27 +01:00
Dan Brown
13c0386e84 Updated string functions to use mulitbyte versions where needed
Fixes #816
2019-05-25 16:15:19 +01:00
Dan Brown
78f5f44460 Updated page navigation click to show content tab on mobile
Fixes #1454
2019-05-25 15:37:49 +01:00
Dan Brown
35e6635379 Fixed chapter description not showing in book exports
Closes #1465
2019-05-25 15:21:02 +01:00
Leonardo Martinez
e42d90a5b6 Updated 'Spanish Argentina' translation. 2019-05-24 15:07:24 -03:00
Adam Brown
47a107ac5b Update maintenance.php
* Added a link to the Github releases page when someone clicks the current release version (to look for changelog information, or to see if there are new updates)
* Removed unnecessary BR tag by fixing the CSS class for the version display so it is properly aligned with the rest of the menu
2019-05-23 10:45:15 -04:00
Dan Brown
8ae35f645a Fixed faulty baseUrl rewrites
Fixes #1452
May help #1377
2019-05-19 16:25:05 +01:00
Dan Brown
5470a9e035 Merge branch 'kostefun-patch-1' 2019-05-19 15:43:11 +01:00
Dan Brown
dbfe63ccf6 Fixed missing comma in RU translation array 2019-05-19 15:42:46 +01:00
Dan Brown
114f10d5ca Merge branch 'patch-1' of git://github.com/kostefun/BookStack into kostefun-patch-1 2019-05-19 15:41:48 +01:00
Dan Brown
5226ddd959 Merge pull request #1446 from kostefun/patch-5
Update common.php
2019-05-19 15:41:21 +01:00
Dan Brown
60013f776a Merge branch 'master' into patch-5 2019-05-19 15:40:54 +01:00
Dan Brown
ac0a070fc8 Merge pull request #1445 from kostefun/patch-4
Update entities.php
2019-05-19 15:40:15 +01:00
Dan Brown
b05659d7a3 Merge pull request #1443 from kostefun/patch-3
Update common.php
2019-05-19 15:39:48 +01:00
Dan Brown
3af4648dc3 Merge pull request #1437 from NootoNooto/patch-2
Added Dutch translations for some new texts
2019-05-19 15:36:05 +01:00
Dan Brown
e1e1ea6099 Amended page save button layout to fix z-index issues
- Added a new mobile save button instead of trying to reposition the
original.
- Also recuced the point where the editor top toolbar will collapse to
become x-scrollable.

Fixes #1424
2019-05-19 15:30:58 +01:00
Dan Brown
0c3dc50cd9 Added mobile search bar on search page
Since the header one hides on mobile devices.
Fixes #1450
2019-05-19 15:06:52 +01:00
Dan Brown
0a0ceb382e Doubled image upload display thumb size
Related to #1108
2019-05-19 14:52:17 +01:00
Dan Brown
896f88174a Updated page navigation logic to ignore empty headers
Fixes #1429
2019-05-15 21:02:11 +01:00
Dan Brown
0ee9e5c4db Updated both editors to ignore image paste if text data apparent
Designed to ignore image data when copying from a spreadsheet.
Fixes #987
2019-05-15 20:23:09 +01:00
kostefun
112f73c91c Update settings.php
Ru locale fix
2019-05-14 17:50:23 +07:00
kostefun
b47dc046e0 Update common.php 2019-05-13 17:40:09 +07:00
kostefun
215d84d705 Update entities.php 2019-05-13 17:31:19 +07:00
kostefun
c459d86b58 Update common.php 2019-05-13 17:21:05 +07:00
kostefun
adf0d5fce2 Update settings.php 2019-05-13 17:09:50 +07:00
Nooto
cb355c8aad Modified Bookshelf texts 2019-05-08 23:57:44 +02:00
Nooto
d0e351b942 Added translations for Bookshelves 2019-05-08 23:51:34 +02:00
Nooto
e3d570e928 Update activities.php 2019-05-08 23:25:13 +02:00
Nooto
e00c170d85 Update common.php 2019-05-08 23:24:22 +02:00
Nooto
e430dad38c Added translations for View All, Copy, Reply, etc 2019-05-08 23:05:30 +02:00
Dan Brown
b70a5c0cdb Updated version and assets for release v0.26.1 2019-05-07 23:05:47 +01:00
Dan Brown
9443ae9f40 Merge branch 'master' into release 2019-05-07 23:05:10 +01:00
Dan Brown
d62d2384cb Updated guest settings system to format value as per non-guest
Fixes #1431
2019-05-07 22:56:48 +01:00
Dan Brown
a981dc41cb Merge pull request #1433 from Hambern/master
Updated the Swedish language files
2019-05-07 22:45:42 +01:00
Dan Brown
97ffbaa740 Fixed issue where books titles could be leaked via shelf home view
- Also added test to cover
Fixes #1425
2019-05-07 22:42:48 +01:00
vagrant
8051558d3a Updated the Swedish language files 2019-05-07 21:29:30 +00:00
Dan Brown
7ef059e254 Fixed some editor image/drawing upload endpoints
Fixes #1428
2019-05-07 22:23:44 +01:00
Dan Brown
4329fee2c9 Fixed 404 card header fonts
Fixes #1427
2019-05-07 22:10:54 +01:00
Dan Brown
b1cf5ab309 Standardised login tab order and evened card padding
Closes #1418
2019-05-07 22:07:50 +01:00
Dan Brown
b67d9f4036 Updated verison for 0.26 dev path 2019-05-07 21:55:41 +01:00
Dan Brown
224d9e7a7d Merge pull request #1420 from moucho/master
Spanish translation
2019-05-07 21:52:02 +01:00
Dan Brown
31419c3913 Merge pull request #1419 from Mant1kor/master
Ukrainian translation update
2019-05-07 21:51:15 +01:00
moucho
ba36d36597 Spanish 2019-05-07 01:28:00 +02:00
Mantikor
ac7d6b8737 Update validation.php 2019-05-06 23:11:23 +03:00
Mantikor
e52dab825a Update settings.php 2019-05-06 23:05:48 +03:00
Mantikor
33f51d5b78 Update passwords.php 2019-05-06 22:27:17 +03:00
Mantikor
ae7529376b Update pagination.php 2019-05-06 22:26:43 +03:00
Mantikor
aefd4d423c Update errors.php 2019-05-06 22:25:40 +03:00
Mantikor
bad44391d4 Update auth.php 2019-05-06 22:21:29 +03:00
Mantikor
1880633be3 Update common.php 2019-05-06 22:21:15 +03:00
Mantikor
8273f8b16e Update entities.php 2019-05-06 22:20:31 +03:00
Mantikor
0600f752eb Update components.php 2019-05-06 21:57:22 +03:00
Mantikor
342dc8948c Update common.php 2019-05-06 21:56:10 +03:00
Mantikor
3e24e44106 Update auth.php 2019-05-06 21:45:16 +03:00
Mantikor
404d11d0eb Update activities.php 2019-05-06 21:40:04 +03:00
Mantikor
07b889547d Merge pull request #1 from BookStackApp/master
merge changes
2019-05-06 21:33:09 +03:00
Dan Brown
220c2a4102 Updated version and assets for release v0.26.0 2019-05-06 18:58:56 +01:00
Dan Brown
e9914eb301 Merge branch 'master' into release 2019-05-06 18:57:58 +01:00
Dan Brown
e47a7e0b97 Merge pull request #1417 from Hambern/master
Updated the swedish lang files
2019-05-06 18:44:51 +01:00
vagrant
989309fdff Updated the swedish lang files 2019-05-06 17:19:51 +00:00
Dan Brown
6797c91eeb Updated dropdowns to close all others before opening 2019-05-06 17:59:17 +01:00
Dan Brown
b9ad3f9f65 Fixed intersection observer check on iOS 2019-05-06 16:08:08 +01:00
Dan Brown
7a8678e5f7 Tweaked colors for accessibility, applied fixes found during testing
- Fixed overriding h3 content header style.
- Updated notification styling to be less overwhelming.
- Increased floated image margin.
- Adjusted callout icon placement.
- Fixed tinymce fullscreen zindex issue.
2019-05-06 00:15:03 +01:00
Dan Brown
ba09dad1fe Fixed shelf activity display & updated book sort operation 2019-05-05 15:54:22 +01:00
Dan Brown
5910e00fb8 Made app core timezone configurable via env
Related to #1407
2019-05-05 15:09:04 +01:00
Dan Brown
3f83c548f8 Ran phpcbf 2019-05-05 14:54:37 +01:00
Dan Brown
adc866cb3d Added ability for dropdown menu to be bottom of dom body
- Used when a dropdown is within a scrollable section such as editor
toolbar on mobile.
- Also made mobile page save button more obvious by increasing size and
inverting color.
2019-05-05 14:43:26 +01:00
Dan Brown
ad542f0407 Prevented potential inline JS event usage
- Removes 'on*' attributes from elements.
- Also updated script logic to remove scripts instead of escaping.
- All JS injection removal now uses DomDocument + xpath parsing.
2019-05-05 13:53:37 +01:00
Dan Brown
15786e2630 Merge pull request #1410 from BookStackApp/image_management_rewrite
Image management rewrite
2019-05-04 18:16:58 +01:00
Dan Brown
8c190324ac Updated existing image tests to reflect changes
- Also added some new tests
2019-05-04 18:11:19 +01:00
Dan Brown
79f6dc00a3 Change image-selector to not use manager
- Now changes the images directly for user, system & cover.
- Extra permission checks added to edit & delete actions.
2019-05-04 15:50:29 +01:00
Dan Brown
cb832a2c10 Started diversion to not using image manager for cover/system/user 2019-04-27 14:55:23 +01:00
Dan Brown
a87ae16010 Started extraction of image controller to separate controllers 2019-04-27 14:18:00 +01:00
Dan Brown
aeb1fc4d49 Started rewriting back-end image managment 2019-04-21 15:52:29 +01:00
Dan Brown
6428f32483 Prevented invalid form inputs having incorrect padding 2019-04-21 14:11:49 +01:00
Dan Brown
884e20cc5e Updated TinyMCE to version 4.9.4 2019-04-21 13:49:46 +01:00
Dan Brown
fc761784a1 Merge branch 'cw1998-fix/registraion-form-validation' 2019-04-21 12:52:11 +01:00
Dan Brown
e0c229114f Updated register link text/placement on login card
- Also extracted "Already have account?" text to translation files.
2019-04-21 12:45:09 +01:00
Dan Brown
4e49d06182 Merge branch 'fix/registraion-form-validation' of git://github.com/cw1998/BookStack into cw1998-fix/registraion-form-validation 2019-04-21 12:24:39 +01:00
Dan Brown
2bb06463d5 Added deeper content id de-duplication
Closes #1393
2019-04-21 12:22:41 +01:00
Dan Brown
4d6df37963 Merge branch 'XVilka-patch-1' 2019-04-20 13:32:03 +01:00
Dan Brown
553d3ce861 Merge branch 'patch-1' of git://github.com/XVilka/BookStack into XVilka-patch-1 2019-04-20 13:30:50 +01:00
Dan Brown
0bc5ccba32 Add revision restore confirm and changed http method
Closes #1321
2019-04-20 13:25:16 +01:00
Dan Brown
ed330f246c Updated md drawing mngr shortcut to work on mac cmd key
Closes #1228
2019-04-20 13:12:35 +01:00
Dan Brown
6c66a8935a Added test to check page HTML id de-duplication
Relates to #1393
2019-04-20 13:01:56 +01:00
Dan Brown
c653618eab Merge branch 'cw1998-fix/dot-in-role-names' 2019-04-20 11:26:48 +01:00
Dan Brown
efc034bd8d Merge branch 'fix/dot-in-role-names' of git://github.com/cw1998/BookStack into cw1998-fix/dot-in-role-names 2019-04-16 23:08:23 +01:00
Dan Brown
c24764018a Updated ldap server option parsing to work with protocol and port
- Aligns with PHP behaviour where ports is ignore for full LDAP URI.
- Added tests to check format being passed to LDAP is as expected.
- May be related to #1220
- Related to #1386 and #1278
2019-04-16 22:47:53 +01:00
Christopher Wilkinson
c8cf6731e2 Add min length validation on name on register form & add sign up link 2019-04-16 12:18:51 +01:00
Dan Brown
d0db0f8e26 Reduced markup for books icon 2019-04-15 21:21:54 +01:00
Dan Brown
c380c10d54 Prevented bad duplicate IDs causing major exception
Related to #1393
2019-04-15 21:20:32 +01:00
Dan Brown
95d4149d5e Merge branch 'cw1998-feature/create-book-button-on-shelves' 2019-04-15 20:45:14 +01:00
Dan Brown
7f3f6e65b9 Aligned item creation wording and updated shelf-book-add logic 2019-04-15 20:45:04 +01:00
Christopher Wilkinson
29f17fd154 Replace dots with something else on user create and edit screens 2019-04-15 15:42:18 +01:00
Christopher Wilkinson
84419005e7 Update create new book button on shelves to 2019 design 2019-04-15 10:56:21 +01:00
Christopher Wilkinson
d3cd369247 Fix phpcs issues 2019-04-15 09:27:17 +01:00
Christopher Wilkinson
50a9c71de0 Add tests for creating a book and adding directly to a shelf 2019-04-15 09:27:17 +01:00
Christopher Wilkinson
faa3a8b842 Add button to add a book directly from a shelf view 2019-04-15 09:27:17 +01:00
Dan Brown
c836862d89 Tweaked header font size to fit redesign better 2019-04-14 14:20:53 +01:00
Dan Brown
03073dd9e4 Merge pull request #1153 from BookStackApp/2019-design
WIP: 2019 design
2019-04-14 13:54:36 +01:00
Dan Brown
ee58bea8b7 Updated user references to be app-default-supporting functions 2019-04-14 13:19:33 +01:00
Dan Brown
9406b4d4c9 Updated view toggle to store date
Also added test for user list order preferences
2019-04-14 13:01:51 +01:00
Dan Brown
01be72d5e2 Updated markdown editor for mobile
Also tweaked padding and responsivness on many common elements
2019-04-14 12:04:20 +01:00
Dan Brown
21e1123d12 Updated editor usability on mobile 2019-04-13 18:30:11 +01:00
Dan Brown
8d358e4894 Updated tri-layout on mobile to be tab based 2019-04-13 17:36:27 +01:00
Dan Brown
f797d2da20 Added column select-all to role permission table 2019-04-13 13:16:18 +01:00
Dan Brown
d3cc261320 Fixed "Add comment" layout when no comments exist 2019-04-13 12:58:57 +01:00
Dan Brown
cc24d478aa Organised entity action buttons a little more 2019-04-13 12:46:15 +01:00
Dan Brown
07adfb2ff1 Added select-all helpers to permission tables 2019-04-13 12:07:27 +01:00
Dan Brown
36481bb73f Updated guest page-create intermediate page 2019-04-13 11:30:19 +01:00
Dan Brown
4d5e47a2d2 Updated empty container item states 2019-04-13 11:24:41 +01:00
Dan Brown
d66fab8bee Updated and aligned entity dashboard elements 2019-04-13 11:09:17 +01:00
Dan Brown
2694bb8fab Updated the design of the comments section 2019-04-13 10:50:24 +01:00
Dan Brown
b12ae6d11b Added bookshelves to breadcrumbs
- Updated breadcrumb dropdown switchers and back-end sibling code to handle new breadcrumbs.
- Added breadcrumb view composer and EntityContext system to mangage
tracking if in the context of a bookshelf.
2019-04-07 18:28:11 +01:00
Dan Brown
221a483b40 Standardised view referencing to dot-notation 2019-04-07 12:00:09 +01:00
Dan Brown
4a127c29a5 Removed important color overrides to a tags 2019-04-07 11:36:50 +01:00
Dan Brown
8c21b5345d Cleaned up usage of some core scss files 2019-04-07 11:34:40 +01:00
Dan Brown
0a06e2bce3 Actioned some todo items, Cleaned old grid css 2019-04-07 09:57:48 +01:00
Dan Brown
d9cde4123d Fixed entity excerpt function signature misalignment 2019-04-06 18:47:27 +01:00
Dan Brown
7cda9b026e Updated tests to suit layout changes, Updated 404 page
- Also replaced 'or' usage in templates with null coalescing operator
2019-04-06 18:36:17 +01:00
Dan Brown
67ed4710b6 Cleaned up old toolbar usage 2019-04-06 17:43:44 +01:00
Dan Brown
745a0bb98d Updated custom homepage views 2019-04-06 17:31:59 +01:00
Dan Brown
aedff7dc6d Added book selector to books sort
Now more efficient rather than listing all books in the system.
2019-04-06 16:59:04 +01:00
Dan Brown
17969c0bbf Added shelves and search shortcuts to profile page 2019-04-06 16:21:20 +01:00
Dan Brown
666ced9c3b Fixed tri-layout overflow in some scenarios 2019-03-30 17:07:01 +00:00
Dan Brown
37bf7f11e4 Implemented new design in entity selector
- Also showed entity path in search.
- Cleaned popular entity fetch logic.
- Cleaned entity selector JS code a little
2019-03-30 16:54:15 +00:00
Dan Brown
bda8aa414b Fixed up edit views to use new layout
- Also updated chapter pages in books view to show detail
2019-03-30 15:49:14 +00:00
Dan Brown
60d175a9b9 Cleaned up sidebar book tree and moved details
- Also made top-spacing more consistent
2019-03-30 15:15:01 +00:00
Dan Brown
42e908c7f0 Cleaned up some existing tri-column views 2019-03-30 14:27:00 +00:00
Dan Brown
53a26a365c Merge branch 'master' into 2019-design 2019-03-30 13:17:29 +00:00
Dan Brown
4ee0fde0ac Updated readme with security info 2019-03-24 20:42:52 +00:00
Dan Brown
934512d09c Updated version and assets for release v0.25.5 2019-03-24 19:45:17 +00:00
Dan Brown
9102c90986 Merge branch 'master' into release 2019-03-24 19:45:00 +00:00
Dan Brown
9879a0d12c Added helper text for no_double_extension validation 2019-03-24 19:40:45 +00:00
Dan Brown
5d2e80bff3 Merge pull request #1348 from agvol/master
Russian translation
2019-03-24 19:14:53 +00:00
Dan Brown
83818234c8 Merge pull request #1347 from cima/czech-translation
Czech translation
2019-03-24 19:13:48 +00:00
Dan Brown
5c00187138 Merge pull request #1327 from leomartinez/master
Updated 'Spanish Argentina' translation.
2019-03-24 19:11:01 +00:00
Dan Brown
193e2ffebe Prevent dbl exts. on img upload, Randomized attachment upload names 2019-03-24 19:08:21 +00:00
agvol
b2a5d07787 Update russian lang 2019-03-23 10:22:54 +03:00
agvol
15cf9f8b32 Update russian lang 2019-03-23 10:18:44 +03:00
agvol
f9adfee47a Update russian lang 2019-03-23 10:04:50 +03:00
Martin Šimek
2e988277f0 Czech translation
+ Unit test repair
2019-03-23 00:35:42 +01:00
Martin Šimek
4e8e28c35f Czech translation
+ Typos
+ errors.php
2019-03-22 22:52:26 +01:00
Anton Kochkov
4cbfb2bf13 Enable syntax highlight for OCaml, Haskell, Rust 2019-03-22 16:42:02 +08:00
Dan Brown
c3e74219c4 Updated version and assets for release v0.25.4 2019-03-21 19:46:19 +00:00
Dan Brown
13c9d7bc2d Merge branch 'master' into release 2019-03-21 19:43:48 +00:00
Dan Brown
f5fe524e6c Added extension whitelist for image uploads
- A continuation of the security issues addressed in v0.25.3
2019-03-21 19:43:15 +00:00
Dan Brown
119b539586 Updated version and assets for release v0.25.3 2019-03-21 00:03:26 +00:00
Dan Brown
29a5c180f0 Merge branch 'master' into release 2019-03-21 00:02:33 +00:00
Dan Brown
37b91b6b0e Hardened image file validation by removing custom validation
- Added test to check PHP files cannot be uploaded as an image.
2019-03-20 23:59:55 +00:00
Martin Šimek
b3a4d8af2a Czech translation
+ Czech language (cs)
+ settings.php in english populated by new option
Note: validation php taken from  lavarel official translation (https://github.com/caouecs/Laravel-lang/blob/master/src/cs/validation.php)
2019-03-19 22:45:14 +01:00
Dan Brown
8b7bee7c67 Updated standard entity lists 2019-03-17 15:07:03 +00:00
Dan Brown
837d2bc582 Improved login, Fixed breadcrumbs & improved grid thumbnails 2019-03-16 16:00:41 +00:00
Leonardo Martinez
64cd499542 Updated 'Spanish Argentina' translation. 2019-03-12 11:46:02 -03:00
Dan Brown
5f2d226f09 Merge branch 'master' into 2019-design 2019-03-10 21:40:02 +00:00
Dan Brown
7906602291 Updated version and assets for release v0.25.2 2019-03-10 13:45:21 +00:00
Dan Brown
6dafe773ff Merge branch 'master' into release 2019-03-10 13:44:29 +00:00
Dan Brown
00703fa817 Merge branch 'dfanara-feature-ldap-attributes' 2019-03-10 10:55:36 +00:00
Dan Brown
44c537de1a Performed some LDAP service/test cleanup 2019-03-10 10:54:19 +00:00
Dan Brown
6bccf0e64a Merge branch 'feature-ldap-attributes' of git://github.com/dfanara/BookStack into dfanara-feature-ldap-attributes 2019-03-10 10:31:09 +00:00
Dan Brown
042a6f9760 Updated shelf menu item to show on custom permission
- Extended new 'userCanOnAny' helper to take a entity class for
filtering.

Closes #1201
2019-03-09 21:15:45 +00:00
Dan Brown
04287745e4 Merge branch 'mark-james-Copy-For-View-Only' 2019-03-09 16:52:47 +00:00
Dan Brown
5c9b528517 Abstracted userCanCreatePage helper to work for any permisison
- Added test to cover scenario where someone with create-own permission
would want to copy a viewable item into a container entity that they
own.
2019-03-09 16:50:22 +00:00
Dan Brown
6be2d3f28c Merge branch 'Copy-For-View-Only' of git://github.com/mark-james/BookStack into mark-james-Copy-For-View-Only 2019-03-09 16:12:12 +00:00
Daniel Fanara
6d20bdc1fb Preserve original display_name_attribute configuration values. 2019-03-09 01:13:30 -05:00
Daniel Fanara
502ea608bf Issue #1306 - Unit Tests for LdapService Changes 2019-03-09 01:08:49 -05:00
Daniel Fanara
55b07c7076 Issue #1306 - Specify display name attribute from LDAP 2019-03-08 23:55:11 -05:00
Dan Brown
33e999909f Merge branch 'fix-1186' 2019-03-08 22:57:57 +00:00
Dan Brown
6be95cd2ac Re-centered dropzone error arrow 2019-03-08 22:57:24 +00:00
Dan Brown
f467185e86 Merge branch 'master' into fix-1186 2019-03-08 22:47:31 +00:00
Dan Brown
646fd822c5 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
2019-03-08 22:42:48 +00:00
Dan Brown
d96baf2d4a Set 'uploaded_to' parameters for editor-pasted/dragged images
Allows image-listing permission system to work as intended.
Fixes #1287
2019-03-08 21:32:31 +00:00
Dan Brown
1c312906bc Added a configurable upload size limit
Closes #1293
2019-03-08 21:06:37 +00:00
Dan Brown
9126c87f2b Merge pull request #1272 from Xiphoseer/patch-1
Add german translations for shelves
2019-03-07 22:14:35 +00:00
Dan Brown
579d98a908 Merge pull request #1314 from maantje/patch-2
Update Dutch password_hint translation to correspond with validation
2019-03-07 21:53:08 +00:00
Dan Brown
98a4359198 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
2019-03-07 21:09:23 +00:00
Jamie Schouten
6f710225b5 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',
        ]);
    }
```
2019-03-06 17:10:15 +01:00
Dan Brown
b273b9d6d0 Improved alignment classes used by WYSIWYG editor
- Fixed table cells being floated, Fixes #1284.
- Made it possible to easily center linked images.
2019-03-02 09:08:01 +00:00
Dan Brown
e471d0c52a Added lua to code languages
Closes #1223
2019-03-02 08:52:14 +00:00
Dan Brown
0a431e3223 Merge pull request #1263 from christophert/add-powershellmarkup
Add Powershell Code Markup
2019-03-02 08:45:08 +00:00
Dan Brown
035a0d8efb Added experimental breadcrumb traversal 2019-02-24 15:57:35 +00:00
Dan Brown
e70423c73f Standardized breadcrumbs a little further with icons 2019-02-17 17:52:42 +00:00
Dan Brown
8445304fe9 Added book sort helper buttons 2019-02-17 11:44:02 +00:00
Dan Brown
f1e571a57c Made shelf listing more unique & efficient
- Now includes listing of all books within.
2019-02-16 17:13:01 +00:00
Dan Brown
e9be2b7174 Standardized setting casing 2019-02-16 15:39:23 +00:00
Dan Brown
352cbbd074 Updated design of page navigation box 2019-02-16 15:39:11 +00:00
Dan Brown
b00b319e83 Re-arranged some list items to flexbox instead of grid
Since flexbox is better supported on a wider range of elements
2019-02-16 15:05:18 +00:00
Dan Brown
a112c11df8 Re-ordered and updated main settings page 2019-02-16 14:17:35 +00:00
Xiphoseer
058cc2cbd6 Update entities.php 2019-02-12 12:30:43 +01:00
Xiphoseer
edd98c00e5 Update entities.php 2019-02-12 12:30:12 +01:00
Xiphoseer
19bb11a1c9 Update entities.php
Add informal german shelve localisations
2019-02-12 12:28:48 +01:00
Xiphoseer
9511d10ec8 Update entities.php
Add german shelve localizations
2019-02-12 12:24:01 +01:00
Dan Brown
3286f29a61 Merge branch 'master' into 2019-design 2019-02-09 14:58:38 +00:00
Christopher Tran
77d3bd31a6 add powershell code block link 2019-02-06 01:06:59 -05:00
Dan Brown
56004abdf4 Added high-level release and roadmap info to readme
Closes #1259
2019-02-06 00:09:39 +00:00
Dan Brown
df6f6e2d77 Merge branch 'master' of github.com:BookStackApp/BookStack 2019-02-04 19:57:43 +00:00
Dan Brown
ba1b3fc181 Made some readme tweaks 2019-02-04 19:57:21 +00:00
Dan Brown
67d4fa0c65 Updated npm packages and migrated webpack css plugin 2019-02-03 18:21:21 +00:00
Dan Brown
49deab3a02 Fixed page edit to have white background 2019-02-03 17:53:54 +00:00
Dan Brown
5325870271 Updated auth pages to new design, Removed public layout 2019-02-03 17:34:15 +00:00
Dan Brown
138f5d5c4f Updated user and shelf views to new design 2019-02-03 13:45:45 +00:00
Dan Brown
880d4f35da Started the migration of the setting views 2019-02-02 15:49:57 +00:00
Dan Brown
20988962fe Migrated a whole load more page/chapter/shelf views 2019-02-02 11:41:41 +00:00
Dan Brown
32603362a6 Updated a bunch of book views 2019-01-31 20:37:12 +00:00
abijeet
9dba9ca178 Fixes tooltip on the image manager.
Fixes #1186
2019-01-27 19:43:31 +05:30
Abijeet Patro
8a4a81629f Merge pull request #1237 from BookStackApp/phpcs-fixes
PHPCS related fixes.
2019-01-27 16:04:30 +05:30
abijeet
5ef0992d5b PHPCS related fixes. 2019-01-27 15:59:23 +05:30
Dan Brown
25bc28a1be Updated version and assets for release v0.25.1 2019-01-20 15:42:32 +00:00
Dan Brown
4c561c7fa0 Merge branch 'master' into release 2019-01-20 15:41:24 +00:00
Dan Brown
12be7d0086 Added extra s3 config parameters for use s3-like service compatibility
For #1192 and #1195
2019-01-20 15:23:49 +00:00
Dan Brown
ba0af9214e Updated socialite to work around google+ API shutdown
Fixes #1190
Will require docs update
2019-01-20 14:58:06 +00:00
Dan Brown
36424a24b5 Added ability for date format strings to be localized by back-end
Requires the locale to be installed on the system-side.
Closes #1214
2019-01-19 12:11:18 +00:00
Dan Brown
a70ee9664a Fixed firefox page print view and removed comments from prints
Closes #1211
2019-01-19 11:33:27 +00:00
Dan Brown
156c0a88e9 Updated sidebar to prevent rubber-banding with comments disabled
Fixes #1218
2019-01-19 11:10:46 +00:00
Dan Brown
0efed43389 Converted more views to new layout and made breadcrumbs more flexible 2019-01-13 15:54:55 +00:00
Dan Brown
163a57cf70 Merge branch 'master' into 2019-design 2019-01-13 14:10:27 +00:00
Dan Brown
95b3e78573 Updated version and assets for release v0.25.0 2019-01-12 22:48:53 +00:00
Dan Brown
63a345bc93 Merge branch 'master' into release 2019-01-12 22:47:07 +00:00
Dan Brown
a3ccde8698 Updated TinyMCE and fixed TinyMCE/Codemirror cursor jumping
For #1162
2019-01-12 19:23:18 +00:00
Dan Brown
9700b7ccea Merge pull request #1205 from BookStackApp/env-cleanup
Simplified example env and created full example copy
2019-01-06 16:05:51 +00:00
Dan Brown
54c428c375 Commented APP_URL by default to prevent upgrade path issues 2019-01-06 16:01:24 +00:00
Dan Brown
ebe5d643f3 Simplified example env and created full example copy 2019-01-06 15:46:16 +00:00
Dan Brown
e66ddbc17b Merge pull request #1197 from moucho/master
Spanish update
2019-01-06 14:37:11 +00:00
Dan Brown
0e0a17cc30 Prevented page text content includes
Avoids possible permission issues where included content shown in search or preview
where the user would not normally have permission to view the included content.

Closes #1178
2019-01-05 17:18:40 +00:00
Dan Brown
ffceb4092e Merge branch 'cw1998-fix/#1110' 2019-01-05 15:22:59 +00:00
Dan Brown
50e5527483 Added test to cover "users" header link in correct permission conditions 2019-01-05 15:22:47 +00:00
Dan Brown
f63fd4beca Merge branch 'fix/#1110' of git://github.com/cw1998/BookStack into cw1998-fix/#1110 2019-01-05 15:12:33 +00:00
Dan Brown
d682a0157f Merge branch 'qianmengnet-master' 2019-01-05 15:01:38 +00:00
Dan Brown
70ad707c3c Tweaked profile page anchor links and swapped register/login links
Also added test for login/register links on non-auth app view
Relates to #1146
2019-01-05 15:01:16 +00:00
Dan Brown
3062bf1876 Merge branch 'master' of git://github.com/qianmengnet/BookStack into qianmengnet-master 2019-01-05 14:47:47 +00:00
Dan Brown
a2087fe3ff Made delete permissions a requirement for move operations
Closes #1200
2019-01-05 14:39:40 +00:00
Mark James
19770d2792 Use joint_permissions to determine is a user has an available page or chapter to copy. 2019-01-02 16:55:28 +11:00
Mark James
99c6d70c51 Initial updates to allow for page copy when the user can read the page but can't update it. 2018-12-31 17:01:49 +11:00
mark-james
0830521e60 Merge pull request #1 from BookStackApp/master
Update From Bookstack
2018-12-31 09:00:19 +11:00
Dan Brown
2317bf2350 Added check for last admin on role change
Will show error message if last admin and admin role is removed.
Closes #1124
Also cleaned up user controller a little.
2018-12-30 16:11:58 +00:00
moucho
2c48f4f7e8 Format update 2018-12-24 12:41:42 +01:00
Dan Brown
456afdcd4c Updated configuration files
Added a notice to the top of each to explain they should not be normally modified.
Standardised comment format used for each item.
Better aligned some files with laravel 5.5 options.
2018-12-23 16:26:39 +00:00
Dan Brown
68017e2553 Added testing for avatar fetching systems & config
Abstracts imageservice http interaction.
Closes #1193
2018-12-23 15:34:38 +00:00
Dan Brown
866187830a Merge branch 'Vinrobot-custom-avatar-provider' 2018-12-22 19:29:35 +00:00
Dan Brown
b56fc21aaf Abstracted user avatar fetching away from gravatar
Still uses gravatar as a default.
Updated URL placeholders to follow LDAP format.
Potential breaking config change: `GRAVATAR=false` replaced by `AVATAR_URL=false`
Builds upon #1111
2018-12-22 19:29:19 +00:00
Dan Brown
d673bf61c2 Merge branch 'custom-avatar-provider' of git://github.com/Vinrobot/BookStack into Vinrobot-custom-avatar-provider 2018-12-22 18:18:14 +00:00
Dan Brown
18b10153e5 Updated composer with bumped php version and extra extensions 2018-12-22 16:49:09 +00:00
Dan Brown
7c8edf5673 Merge pull request #1096 from christophert/add-ldaptlsinsecure
Add option to disable LDAPS Certificate Validation
2018-12-22 16:38:50 +00:00
Dan Brown
f4ea5f1f55 Updated page exports to use absolute time format
For #1065
2018-12-22 16:35:04 +00:00
Dan Brown
f62843c861 Updated DZ upload timeout var name and error handling
For #1133 & #876
Concerns BookStackApp/website#31
2018-12-22 15:45:13 +00:00
Dan Brown
5fe630b8d2 Merge branch 'master' into dropzone-timeout 2018-12-22 15:08:54 +00:00
Dan Brown
d910defbfd Merge pull request #1183 from Mant1kor/master
Add Ukrainian translate
2018-12-22 15:00:56 +00:00
Dan Brown
153adb055c Merge pull request #1180 from vasiliev123/update-pl-language
Updates for PL language
2018-12-22 14:58:30 +00:00
Dan Brown
26ec1cc3dc Added proper escaping to LDAP filter operations
To cover #1163
2018-12-20 20:04:09 +00:00
Mantikor
d476e30df0 Added 'uk' locale 2018-12-18 10:03:10 +02:00
Mantikor
37ab97af8c Add files via upload 2018-12-18 10:01:50 +02:00
Mantikor
7fcd7a5d91 Rename resources/lang/activities.php to resources/lang/uk/activities.php 2018-12-18 10:01:18 +02:00
Mantikor
c67f76f776 Add files via upload 2018-12-18 10:00:45 +02:00
Mantikor
9a444b4a04 Update settings.php
added 'uk' language
2018-12-17 18:16:43 +02:00
Mantikor
106f32591d Update app.php
added 'uk' locale
2018-12-17 14:10:54 +02:00
Dan Brown
7f6929d716 Re-enabled plaintext view for email notifications
Updated mail notifications to set the HTML and plaintext views since before
no plaintext version was being created.

Closes #1182
2018-12-16 20:44:57 +00:00
Dan Brown
651ae2f3be Fixed failing language test after addition of formatter 2018-12-16 15:46:02 +00:00
Dan Brown
101a7b40b9 Updated codemirror SQL mode name
Now will highlight a lot more SQL syntax.
Closes #1181.
2018-12-16 15:38:49 +00:00
Dan Brown
1930ed4d6a Made some further fixes to the formatting script
Takes into account single and double quotes.
Ignores //! comments and the 'language_select' array.

Language files may need some cleaning up and may encounter some other bugs when running.
2018-12-16 14:04:04 +00:00
Dan Brown
2753629dbe Cleaned up script and formatted remaining EN files 2018-12-16 13:12:13 +00:00
Dan Brown
86a00a59d4 Created sketchy translation formatter script
Compares a translation file to a EN version to
place translations on matching line numbers and matches
up comments.
2018-12-14 21:23:05 +00:00
Jurij Vasiliev
d6dd96e7fc 1. Fixed translation for Copy and Reply 2018-12-13 13:58:08 +01:00
Jurij Vasiliev
1b1ddb6794 Major updates on polish language
1. Changed Book translation from księga => podręcznik (księga is very old word, and thus not fit to the app. Podręcznik is word for book used in school and fits much more to the documentation site)
2. Changed Entity transaltion from encja => obiekt (encja is word used in IT world, common people doesn't know what it is. Obiekt (object) fits better for no IT geeks and explains them more than word encja)
3. Added Shelf/Bookshelf transaltion. Now they are named Półka/Półki
4. Changed Draft translation from szkic => wersja robocza (in every system like wordpress/wiki etc. the word for draft is wersja robocza. Szkic is word for draft of an image)
5. Fixed typos
6. Fixed unfit plural words when they were not needed
2018-12-13 13:39:26 +01:00
Dan Brown
f65ff3a9a8 Merge branch 'ezzra-german_informal' 2018-12-12 20:47:03 +00:00
Dan Brown
323bff7d6d Extended translations system for arrays & extension
Extended the base Laravel translation system to
allow a locale to be based upon another.

Also adds functionality to take base & fallback locales into account when fetching
an array of translations.

Related to work done in #1159
2018-12-12 20:46:27 +00:00
Dan Brown
0e3d507ec2 Merge branch 'german_informal' of git://github.com/ezzra/BookStack into ezzra-german_informal 2018-12-12 19:02:16 +00:00
ezzra
f943f0d401 de_informal - remove comments from unused lines 2018-12-12 10:37:24 +01:00
Dan Brown
1b01d65965 Updated readme with phpunit version, removed old translations line 2018-12-11 23:26:43 +00:00
ezzra
a2acd063f3 add german informal language 2018-12-11 19:39:16 +01:00
Dan Brown
e9e3e8b6b1 Added npm install details
Closes #1174
2018-12-11 14:54:34 +00:00
Dan Brown
7f95b51b00 Rolled tri-layout to page edit and book-create 2018-12-09 16:51:31 +00:00
Dan Brown
ff0b9004bc Cleaned existing grid view up a little 2018-12-09 14:04:28 +00:00
Dan Brown
8fd8652bbf Added tri-layout desktop sticky-scroll 2018-12-09 13:42:35 +00:00
Dan Brown
e1474194db Added responsive functionality to tri-layout view. 2018-12-08 23:34:06 +00:00
Dan Brown
4c574c22a8 Implemented functionality to make books sort function
Also changed public user settings to be stored in session rather than DB.
Cleaned existing list view type logic.
2018-12-07 18:33:53 +00:00
Dan Brown
0b976d9f91 Added list sorting styles, Yet to add functionality 2018-12-01 21:28:21 +00:00
Dan Brown
2a882a43ff Updated books listing to three column layout design 2018-12-01 20:28:17 +00:00
Dan Brown
aabd4c0412 Started looking at the books listing design 2018-12-01 16:29:57 +00:00
Dan Brown
d39fc84301 Merge branch 'master' into 2019-design 2018-12-01 13:57:23 +00:00
Dan Brown
e093a172cb Updated assets and version for release v0.24.3 2018-11-27 21:52:20 +00:00
Dan Brown
4b01f8934b Merge branch 'master' into release 2018-11-27 21:51:32 +00:00
Dan Brown
75ca430fd4 Updated NPM dependancies 2018-11-27 21:50:29 +00:00
Dan Brown
4cf43f67d6 Merge pull request #1072 from CliffyPrime/german_update
Update german translation
2018-11-27 21:26:18 +00:00
Dan Brown
86899864dd Merge pull request #1117 from leomartinez/master
Updated 'Spanish Argentina' translation.
2018-11-27 21:24:01 +00:00
qianmengnet
3c796b1ae7 Add "register" to nav.
Add "register" to nav.You need to click "login" to find register, which is not convenient for people who are not familiar with the app.
2018-11-26 09:05:38 +08:00
qianmengnet
b7915cc7b0 Add anchor link to "Created Content" on the "View Profile"
Add 3 anchor link to "Created Content" on the "View Profile" page and click to jump to the page section
2018-11-26 08:47:49 +08:00
Abijeet
eac82c47a5 Fixes image deletion failing in subdirectory.
Fixes #1092

Signed-off-by: Abijeet <abijeetpatro@gmail.com>
2018-11-25 00:46:04 +05:30
Abijeet
d3d3e2ad3e Added a default timeout of 60 seconds to dropzone.
Fixes #876
2018-11-18 00:22:08 +05:30
Christopher Wilkinson
54b36cd305 Show users link in top nav if user is signed in and only manages users 2018-11-13 13:43:20 +00:00
Leonardo Martinez
f8396d3632 Updated 'Spanish Argentina' translation. 2018-11-12 10:15:06 -03:00
Dan Brown
4df11701e7 Updated book-tree design and abstracted breadcrumb template 2018-11-11 13:11:36 +00:00
Dan Brown
4a872012c5 Merge branch 'master' into 2019-design 2018-11-11 11:44:35 +00:00
Dan Brown
bc116b45b5 Re-updated assets for release v0.24.2 2018-11-10 16:10:22 +00:00
Dan Brown
a059960b9e Merge branch 'master' into release 2018-11-10 16:09:14 +00:00
Dan Brown
302b53562d Fixed clipboard imports 2018-11-10 16:08:33 +00:00
Dan Brown
7770966fed Updated assets for release v0.24.2 2018-11-10 16:01:55 +00:00
Dan Brown
d7adcf6c69 Merge branch 'master' into release 2018-11-10 16:01:01 +00:00
Dan Brown
ebd4c3327d Merge branch 'thomasjsn-master' 2018-11-10 15:35:35 +00:00
Dan Brown
d0c166c207 Added linked images to markdown paste insert 2018-11-10 15:35:13 +00:00
Dan Brown
321b53c827 Merge branch 'master' of git://github.com/thomasjsn/BookStack into thomasjsn-master 2018-11-10 15:23:29 +00:00
Vinrobot
5e6c039b08 Added config to change Gravatar URL 2018-11-10 16:11:11 +01:00
Dan Brown
178b5af83a Added google select_account test
Also cleaned the function naming a little to be more descriptive of the
work they do.
2018-11-10 14:52:43 +00:00
Dan Brown
4be0c567cc Merge pull request #1063 from justein230/master
Add select account parameter for google authorization
2018-11-10 14:32:28 +00:00
Dan Brown
0724ae3640 Merge pull request #1098 from TheLastOperator/master
Update french translations
2018-11-10 13:58:56 +00:00
Dan Brown
62a475e464 Merge branch 'qianmengnet-master' 2018-11-10 13:55:48 +00:00
Dan Brown
cfc1a2f045 Removed settings that had been copied from en 2018-11-10 13:55:13 +00:00
Dan Brown
b012f27ae3 Merge branch 'master' of git://github.com/qianmengnet/BookStack into qianmengnet-master 2018-11-10 13:54:35 +00:00
Dan Brown
58bec7287f Merge pull request #1088 from kejjang/zh_TW_update
Update zh_TW translation
2018-11-10 13:52:23 +00:00
Dan Brown
9341ae4910 Merge pull request #1066 from limkukhyun/codev-kuk-master
completed the Korean translation. Please accept the pull request
2018-11-10 13:50:39 +00:00
Dan Brown
1328755f95 Merge pull request #1034 from DeehSlash/pt_br_translations
Adds missing pt_BR translation
2018-11-10 13:47:38 +00:00
Dan Brown
038b2418f7 Fixed baseURL helper when no app url is set
Also cleaned variable naming to be more obvious
2018-11-09 21:29:30 +00:00
Dan Brown
e3230f8f21 Standardised module loading system & fixed build system
Fixed broken build system in broken webpack version.
Also updates module system to standardise on ES6 import/exports,
Especially since babel has changed it's 'default' logic for the old
module system.
2018-11-09 21:17:35 +00:00
qianmengnet
fd37d95ffc Chinese translation update for v0.24.1
0.24.1
2018-11-08 08:10:04 +08:00
Justin Stein
3abde8bfe2 Added config entry for select account 2018-11-04 11:15:58 -08:00
Justin Stein
2ca8038df2 Removed return from documentation for function redirectToSocialProvider 2018-11-04 11:07:04 -08:00
Justin Stein
89de328439 Merge branch 'master' of https://github.com/BookStackApp/BookStack 2018-11-04 11:04:30 -08:00
Justin Stein
c37e73b626 Moved redirect functionality back to start register and log in functions 2018-11-04 10:48:55 -08:00
Justin Stein
0283ab11b5 Added function for redirect with parameters for Socialite 2018-11-04 10:40:06 -08:00
Dan Brown
5b36ddb12f Updated npm dependancies 2018-11-04 15:40:10 +00:00
Dan Brown
ffc1aa873e Merge branch 'v0.24-dev' 2018-11-04 15:36:40 +00:00
Dan Brown
19b7093438 Fixed redirect issue when custom app url in use
Fixes #956 & #1048
Also added tests to cover this url logic.
Also removed debugbar during tests to maybe improve test speed.
2018-11-04 15:18:27 +00:00
Dan Brown
7799ba5c79 Updated composer dependancies including laravel minor version
Updated larvel 5.5 to latest version to bring in latest fixes.
Fixes #1095
2018-11-04 14:53:13 +00:00
Dan Brown
c356612612 Added sidebar layout size tweaks 2018-11-04 14:41:52 +00:00
Florian PREVOST
1c89fcd20a Update french translasion 2018-10-30 15:13:17 +01:00
Christopher Tran
730cb78b45 switch spaces to tabs 2018-10-27 17:05:46 -04:00
Christopher Tran
8e7f703af7 fix how the option is set, change handle to NULL 2018-10-27 16:58:10 -04:00
Christopher Tran
6c14c09880 Add ability to disable LDAP certificate validation 2018-10-27 16:14:19 -04:00
Kej
773ab9d7ff Update zh_TW translation 2018-10-25 11:38:49 +08:00
Dan Brown
0e395b1e21 Started reworking of page-show design
- Updated core toolbar & breadcrumb design
2018-10-21 20:05:11 +01:00
CliffyPrime
6c7d87c836 Update german translation
Started working on updating / completing the german translation files, as some recent changes (shelves etc.) are not yet translated. Also changed some wordings to better fit into the flow and word order of the german language. Started with two small files, will do more soon...
2018-10-17 23:44:13 +02:00
Dan Brown
89be30ff0e Started on a design update
- Added base of new grid system.
- Added new margin/padding/visiblity helpers.
- Made header collapse to overflow menu on mobile.
2018-10-16 18:49:56 +01:00
codev-kuk-mac
e8ab4fd91f change config/app.php to add korean 2018-10-15 16:39:16 +09:00
codev-kuk-mac
5d1162fb64 translate complate 2018-10-15 16:36:11 +09:00
Justin Stein
216358c6e4 Added Google select account functionality to login 2018-10-13 15:14:06 -07:00
Justin Stein
57d99130ee Added environment variable for google select account option. 2018-10-13 14:50:58 -07:00
Justin Stein
79afec9737 Revert "Added else clause"
This reverts commit 77d7f764f1.
2018-10-13 14:31:29 -07:00
Thomas Jensen
90929baa52 Wrap images inserted with markdown editor with anchor tag to original file ref #1062 2018-10-13 21:43:35 +02:00
Dan Brown
85f330c79a Extracted many page-specific repo methods into page-specific repo 2018-10-13 11:27:55 +01:00
justein230
77d7f764f1 Added else clause 2018-10-12 22:50:02 -07:00
Justin Stein
a76599bd2a Add select account parameter for google authorization
Useful for choosing an account if a default account is outside the scope of a G Suite organization.
2018-10-12 11:52:13 -07:00
codev-kuk-mac
4afc67a962 settings - completed
entities - Some edits done
2018-10-12 17:22:29 +09:00
codev-kuk-mac
042d8b3274 translate entities, setting 2018-10-12 16:06:08 +09:00
codev-kuk-mac
1c0a196b9d Include Korean in settings 2018-10-12 16:05:28 +09:00
codev-kuk-mac
a1fda37896 done validation 2018-10-12 16:04:57 +09:00
codev-kuk-mac
43758a7d60 3개 번역 2018-10-12 15:13:27 +09:00
codev-kuk-mac
c7d3db9751 translate kr 50/100 2018-10-05 11:24:24 +09:00
codev-kuk-mac
fca7689e1a translate to kr 20/100 2018-10-05 10:24:37 +09:00
André Luiz da Silva
18bac4e673 Fixes "bookshelf" pt_BR translation in "activities" 2018-09-28 16:27:26 -03:00
André Luiz da Silva
ca2a9fbf1c Adds missing "settings" pt_BR translations 2018-09-28 16:26:01 -03:00
André Luiz da Silva
cbebe7c8de Adds missing "errors" pt_BR translations 2018-09-28 16:19:06 -03:00
André Luiz da Silva
0943221902 Adds missing "entities" pt_BR translations 2018-09-28 16:18:14 -03:00
André Luiz da Silva
17ed1b7faf Adds missing "common" pt_BR translations 2018-09-26 21:54:16 -03:00
André Luiz da Silva
36d18f28ee Adds missing "activities" pt_BR translations 2018-09-26 21:51:34 -03:00
Dan Brown
495d18814a Updated various classes to take EntityProvider instead of separate entities 2018-09-25 18:00:40 +01:00
Dan Brown
257a5a23ec Fleshed out entity provided and optimized imports 2018-09-25 16:58:03 +01:00
Dan Brown
919660678b Re-structured the app code to be feature based rather than code type based 2018-09-25 12:30:50 +01:00
Dan Brown
19751ed1cb Incremented dev version 2018-09-25 10:00:09 +01:00
Dan Brown
04a364dcc3 Incremented version for v0.24.1 2018-09-24 16:34:16 +01:00
Dan Brown
db83ac7eaa Merge branch 'master' into release 2018-09-24 16:32:30 +01:00
Dan Brown
818c02ed44 Added null role check to migrate path
Also added check for existing bookshelf role_permissions
in the event the user got that for.
Also related to #1027
2018-09-24 16:30:08 +01:00
Dan Brown
3ca9dddf61 Merge branch 'master' into release 2018-09-24 15:59:39 +01:00
Dan Brown
9abdab3991 Updated migration to convert MyISAM tables to InnoDB
New bookshelves_books tables requires foreign constraints which error on MyISAM.
For #1027
2018-09-24 15:58:40 +01:00
Dan Brown
bf74f53ca7 Updated assets for release and incremented version 2018-09-24 12:18:27 +01:00
Dan Brown
9d67efb4a4 Merge branch 'master' into release 2018-09-24 12:08:21 +01:00
Dan Brown
43122f86e8 Merge pull request #1026 from vriic/master
Update german translation
2018-09-24 10:35:22 +01:00
Nikolai Nikolajevic
935337862c Update german translation 2018-09-24 09:55:37 +02:00
Dan Brown
dd671524f8 Merge pull request #1025 from moucho/master
Spanish translation
2018-09-23 17:18:41 +01:00
Marcos
1cac3d43d3 Spanish translation 2018-09-23 17:31:41 +02:00
Dan Brown
9243c635f2 Made search test a little more consistent 2018-09-23 15:15:44 +01:00
Dan Brown
93f820d9da Updated TinyMCE config to end containers on empty blocks
Makes it easier to escape out of blockquote sections.
Fixes #961
2018-09-23 14:07:50 +01:00
Dan Brown
b62afcad1f Removed search indexing from migration path to prevent Bookshelf issue 2018-09-23 13:25:12 +01:00
Dan Brown
7b32aa163f Added Bookshelves to search system.
Also cleaned up and made search indexing system a little more efficient.
Closes #1023
2018-09-23 12:34:30 +01:00
Dan Brown
eebfd8904e Removed old fulltext indexes from migrations
Prevents forcing of MyISAM for some databases
Removed old code to add indexes and added checks for existing indexes before removal.
Should still allow upgrades, rollbacks to old bookstack versions may be funky but
should not be high use-case.
2018-09-23 00:30:48 +01:00
Dan Brown
0d84a0b976 Extracted search sidebar text to translation file
Closes #864
2018-09-22 23:40:04 +01:00
Dan Brown
88ac636c00 Made it possible to scroll past the end of the markdown editor
Closes #1020
2018-09-22 23:24:51 +01:00
Dan Brown
9dc26a8c52 Prevented TinyMCE clear-color option having scrollbar
Was covering the option if showing and prevented the option being pressed.
Fixes #999
2018-09-22 23:12:39 +01:00
Dan Brown
6543020fd2 Updated tinymce to v4.8.3 2018-09-22 22:58:06 +01:00
Dan Brown
be4f3d62cd Merge branch 'fix/ru-locale' of git://github.com/mullinsmikey/BookStack into mullinsmikey-fix/ru-locale 2018-09-22 22:29:03 +01:00
Dan Brown
da58c41ab6 Prevented attachDefaultRole from trying to re-attach if already existing
Fixes #1003
Added test to cover
2018-09-22 22:09:34 +01:00
Dan Brown
10d08e641c Merge pull request #1021 from moucho/master
Spanish translation
2018-09-22 21:43:19 +01:00
Dan Brown
3a39b9f440 Merge pull request #1022 from BookStackApp/revert-983-master
Revert "Update german translation"
2018-09-22 18:33:29 +01:00
Dan Brown
27f7aab375 Revert "Update german translation" 2018-09-22 18:33:15 +01:00
Dan Brown
337da0c467 Merge pull request #983 from vriic/master
Update german translation
2018-09-22 18:27:04 +01:00
Marcos
c4e4cebf14 Spanish translation 2018-09-22 18:36:52 +02:00
Dan Brown
3f58800ed1 Added ability to configure revision limit 2018-09-22 17:30:42 +01:00
Dan Brown
0931ff38e9 Tried to make chapter toggles a little smoother in FF 2018-09-22 16:36:35 +01:00
Dan Brown
07bc0612c0 Merge branch 'master' into fix/#960 2018-09-22 15:57:53 +01:00
Dan Brown
6dec485b45 Fixed sidebar rubber-banding when content is expanded
Hopefully for #905
Ideally layout needs to be re-thought
2018-09-22 15:52:09 +01:00
Dan Brown
a441faf65c Only show codeblock copy icon on hover
Fixes #980
2018-09-22 14:55:33 +01:00
Dan Brown
50ee1462ad Merge pull request #986 from DeehSlash/fix/pt_br_locale
Adds and fixes pt_BR strings
2018-09-22 14:40:23 +01:00
Dan Brown
1cb6ae39c8 Added base RTL support
For #939

- Adds way to check if current language is RTL via config system.
- Made TinyMCE default direction be based on current language text
direction.
- Fixed bullet points to be RTL compatible.
- Set page content body to have direction based on content.
2018-09-22 13:18:26 +01:00
Dan Brown
c667c6e235 Merge branch 'master' of git://github.com/kmoj86/BookStack into kmoj86-master 2018-09-22 12:23:17 +01:00
Dan Brown
e3e484e561 Added custom head content to exports
Closes #981

Also fixed incorrect download tests.
2018-09-22 11:53:40 +01:00
Dan Brown
73fa18a128 Made bookstack cookie name configurable
Closes #1018
2018-09-22 11:42:02 +01:00
Dan Brown
5c2e3f4e56 Extracted download response logic into controller method
Fixes incorrect 'Content-Disposition' header value.
Fixes #581
2018-09-22 11:34:09 +01:00
Dan Brown
c47b578599 Fixed formatting via phpcbf 2018-09-21 18:48:47 +01:00
Dan Brown
e60d11ee04 Altered social auto-reg to be configurable per service
- Added {$service}_AUTO_REGISTER and {$service}_AUTO_CONFIRM_EMAIL env
options for each social auth system.
- Auto-register will allow registration from login, even if registration
is disabled.
- Auto-confirm-email indicates trust and will mark new registrants as
'email_confirmed' and skip 'confirmation email' flow.
- Also added covering tests.
2018-09-21 18:05:06 +01:00
Dan Brown
7ad8314bd7 Merge branch 'feature/autoregistration_social_login' of git://github.com/ibrahimennafaa/BookStack into ibrahimennafaa-feature/autoregistration_social_login 2018-09-21 16:14:52 +01:00
Dan Brown
131fcae4c7 Merge pull request #947 from BookStackApp/bookshelves
Bookshelves
2018-09-21 15:29:52 +01:00
Dan Brown
c8d893fac7 Updated 404 test to not fail based on random long name 2018-09-21 15:24:29 +01:00
Dan Brown
b59e5942c8 Added testing coverage for Bookshelves
Created modified TestResponse so we can use DOM operations in new
Testcases as we move away from the BrowserKit tests.
2018-09-21 15:15:16 +01:00
Dan Brown
8ff969dd17 Updated so permission effect admins more
Asset permissions can now be configured for admins.
joint_permissions will now effect admins more often.
Made so shelves header link will hide if you have no bookshelves view
permission.
2018-09-20 19:48:08 +01:00
Dan Brown
6eead437d8 Added bookshelf permission control UI and copy-down ability 2018-09-20 19:16:11 +01:00
Dan Brown
0b6f83837b Removed joint_permission generation in older migration 2018-09-20 16:03:01 +01:00
Dan Brown
81eb642f75 Added bookshelves homepage options
- Updated homepage selection UI to be more scalable
- Cleaned homepage selection logic in code
- Added seed test data for bookshelves
- Added bookshelves to permission system
2018-09-20 15:27:30 +01:00
Dan Brown
47b08888ba Added bookshelf view, update, delete
- Enabled proper ordering of Books in a shelf.
- Improved related item destroy for all entities.
2018-09-16 19:34:09 +01:00
Abijeet Patro
32e34f10ff Merge pull request #1008 from BookStackApp/revision-deletion
#784 - Adds ability to remove particular revision.
2018-09-16 21:30:04 +05:30
Dan Brown
f455b317ec Added ability to click books in shelf-sort 2018-09-16 16:59:01 +01:00
Abijeet
08b967607f Changes as per code review, and fixes failing test cases.
Signed-off-by: Abijeet <abijeetpatro@gmail.com>
2018-09-16 20:44:09 +05:30
Abijeet
90883bb22b Fixes issue wth the dropdown list upon double clicking.
Closes #960

Signed-off-by: Abijeet <abijeetpatro@gmail.com>
2018-09-16 13:09:21 +05:30
Abijeet
0c8b6b7324 Final tweaks after code review and fixing failing test cases. 2018-09-16 01:12:36 +05:30
Abijeet
81d3bdc168 Removes the BadRequestException class added earlier.
Signed-off-by: Abijeet <abijeetpatro@gmail.com>
2018-09-15 21:08:00 +05:30
Abijeet
54ca4487fa Adds tests and few fixes.
Signed-off-by: Abijeet <abijeetpatro@gmail.com>
2018-09-15 21:05:51 +05:30
Abijeet
25da4d9a8b Added a success message on deletion of revision.
Signed-off-by: Abijeet <abijeetpatro@gmail.com>
2018-09-15 16:08:20 +05:30
Abijeet
f0add69b61 Adding languages for the revision deletion. 2018-09-15 15:16:04 +05:30
Abijeet
714c7bbd3a Adds code to delete the revision.
Signed-off-by: Abijeet <abijeetpatro@gmail.com>
2018-09-15 15:15:42 +05:30
Michael Mullins
e0b479efef UTF-8 slugs & UI fixes 2018-09-11 22:42:25 +04:00
Michael Mullins
9d09c4c7b0 Ru locale fix
Fixed russian translations, added several missing strings
2018-09-10 22:28:47 +04:00
Dan Brown
b89411c108 Copied book content, Added create routes
Added view control
Added pivot table for books relation
Added control to assign books
2018-08-27 14:18:09 +01:00
André Luiz da Silva
c472b82ee3 Adds and fixes pt_BR strings 2018-08-24 16:03:04 -03:00
Nikolai Nikolajevic
f56b3560c4 Update german translation 2018-08-23 16:17:46 +02:00
Ibrahim Ennafaa
d2f5313f92 add missing @param in method comment 2018-08-21 12:44:42 -04:00
Ibrahim Ennafaa
572e75b783 Update UserRepo.php 2018-08-20 21:19:25 -04:00
Ibrahim Ennafaa
b224a2c8a0 attempt to fix unit test error for admin creation 2018-08-16 21:52:16 +00:00
Dan Brown
fe6dfcedf9 implement social auto registration feature 2018-08-16 21:26:54 +00:00
Dan Brown
c3986cedfc Added shelve icon, improved migration, added role permission
Icon is placeholder for now
Migration will now copy permissions from Books to apply to shelves.
Role view updated with visibility on shelve permission
2018-08-04 12:45:45 +01:00
Dan Brown
b5a2d3c1c4 Merge remote-tracking branch 'origin' into bookshelves 2018-08-04 11:35:01 +01:00
Khalid
a6862362c1 added Arabic to locales 2018-08-03 19:00:51 +03:00
Khalid
7d4ec0d633 added Arabic language to drop-down list. 2018-08-03 18:58:27 +03:00
Khalid
85544c04a9 translated 2018-08-03 18:51:18 +03:00
Khalid
0a8ff6ffad translated 2018-08-03 18:34:39 +03:00
Khalid
04274078c4 translated 2018-08-02 06:38:33 +03:00
Khalid
aac9fbf236 translated 2018-08-01 18:25:44 +03:00
Khalid
08e290f3ea translated 2018-07-30 12:58:12 +03:00
Khalid
86602854ac translated 2018-07-30 12:54:32 +03:00
Khalid
6eb63a1e03 translated 2018-07-28 14:13:12 +03:00
Khalid
8774f1a320 translated 2018-07-28 13:02:19 +03:00
Khalid
6ca8ccd330 translated 2018-07-28 12:47:35 +03:00
Khalid
df88ffa159 translated 2018-07-28 00:13:33 +03:00
Khalid
dcbb8ad960 translated 2018-07-24 21:40:49 +03:00
Khalid
0f2ffa9545 translated to Arabic 2018-07-24 21:36:12 +03:00
Khalid
6bae16f7e9 fully translated "common" and partially translated "entities" 2018-07-24 18:11:55 +03:00
kmoj86
f5ca7ab1c8 Update entities.php 2018-07-23 18:19:17 +03:00
Khalid
7dd11decb8 partial file translation 2018-07-23 13:08:07 +03:00
Dan Brown
4948b443b6 Started work on bookshelves 2018-06-24 13:38:19 +01:00
1406 changed files with 94040 additions and 45413 deletions

View File

@@ -1,2 +0,0 @@
>0.25%
not op_mini all

View File

@@ -1,11 +1,24 @@
# Environment
APP_ENV=production
APP_DEBUG=false
# This file, when named as ".env" in the root of your BookStack install
# folder, is used for the core configuration of the application.
# By default this file contains the most common required options but
# a full list of options can be found in the '.env.example.complete' file.
# NOTE: If any of your values contain a space or a hash you will need to
# wrap the entire value in quotes. (eg. MAIL_FROM_NAME="BookStack Mailer")
# Application key
# Used for encryption where needed.
# Run `php artisan key:generate` to generate a valid key.
APP_KEY=SomeRandomString
# The below url has to be set if using social auth options
# or if you are not using BookStack at the root path of your domain.
# APP_URL=http://bookstack.dev
# Application URL
# This must be the root URL that you want to host BookStack on.
# All URLs in BookStack will be generated using this value
# to ensure URLs generated are consistent and secure.
# If you change this in the future you may need to run a command
# to update stored URLs in the database. Command example:
# php artisan bookstack:update-url https://old.example.com https://new.example.com
APP_URL=https://example.com
# Database details
DB_HOST=localhost
@@ -13,76 +26,19 @@ DB_DATABASE=database_database
DB_USERNAME=database_username
DB_PASSWORD=database_user_password
# Cache and session
CACHE_DRIVER=file
SESSION_DRIVER=file
# If using Memcached, comment the above and uncomment these
#CACHE_DRIVER=memcached
#SESSION_DRIVER=memcached
QUEUE_DRIVER=sync
# A different prefix is useful when multiple BookStack instances use the same caching server
CACHE_PREFIX=bookstack
# Memcached settings
# If using a UNIX socket path for the host, set the port to 0
# This follows the following format: HOST:PORT:WEIGHT
# For multiple servers separate with a comma
MEMCACHED_SERVERS=127.0.0.1:11211:100
# Storage
STORAGE_TYPE=local
# Amazon S3 Config
STORAGE_S3_KEY=false
STORAGE_S3_SECRET=false
STORAGE_S3_REGION=false
STORAGE_S3_BUCKET=false
# Storage URL
# Used to prefix image urls for when using custom domains/cdns
STORAGE_URL=false
# General auth
AUTH_METHOD=standard
# Social Authentication information. Defaults as off.
GITHUB_APP_ID=false
GITHUB_APP_SECRET=false
GOOGLE_APP_ID=false
GOOGLE_APP_SECRET=false
OKTA_BASE_URL=false
OKTA_APP_ID=false
OKTA_APP_SECRET=false
TWITCH_APP_ID=false
TWITCH_APP_SECRET=false
GITLAB_APP_ID=false
GITLAB_APP_SECRET=false
GITLAB_BASE_URI=false
DISCORD_APP_ID=false
DISCORD_APP_SECRET=false
# External services such as Gravatar and Draw.IO
DISABLE_EXTERNAL_SERVICES=false
# LDAP Settings
LDAP_SERVER=false
LDAP_BASE_DN=false
LDAP_DN=false
LDAP_PASS=false
LDAP_USER_FILTER=false
LDAP_VERSION=false
# Do you want to sync LDAP groups to BookStack roles for a user
LDAP_USER_TO_GROUPS=false
# What is the LDAP attribute for group memberships
LDAP_GROUP_ATTRIBUTE="memberOf"
# Would you like to remove users from roles on BookStack if they do not match on LDAP
# If false, the ldap groups-roles sync will only add users to roles
LDAP_REMOVE_FROM_GROUPS=false
# Mail settings
# Mail system to use
# Can be 'smtp' or 'sendmail'
MAIL_DRIVER=smtp
# Mail sender details
MAIL_FROM_NAME="BookStack"
MAIL_FROM=bookstack@example.com
# SMTP mail options
# These settings can be checked using the "Send a Test Email"
# feature found in the "Settings > Maintenance" area of the system.
MAIL_HOST=localhost
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM=null
MAIL_FROM_NAME=null
MAIL_ENCRYPTION=null

309
.env.example.complete Normal file
View File

@@ -0,0 +1,309 @@
# Full list of environment variables that can be used with BookStack.
# Selectively copy these to your '.env' file as required.
# Each option is shown with it's default value.
# Do not copy this whole file to use as your '.env' file.
# Application environment
# Can be 'production', 'development', 'testing' or 'demo'
APP_ENV=production
# Enable debug mode
# Shows advanced debug information and errors.
# CAN EXPOSE OTHER VARIABLES, LEAVE DISABLED
APP_DEBUG=false
# Application key
# Used for encryption where needed.
# Run `php artisan key:generate` to generate a valid key.
APP_KEY=SomeRandomString
# Application URL
# This must be the root URL that you want to host BookStack on.
# All URL's in BookStack will be generated using this value.
APP_URL=https://example.com
# Application default language
# The default language choice to show.
# May be overridden by user-preference or visitor browser settings.
APP_LANG=en
# Auto-detect language for public visitors.
# Uses browser-sent headers to infer a language.
# APP_LANG will be used if such a header is not provided.
APP_AUTO_LANG_PUBLIC=true
# Application timezone
# Used where dates are displayed such as on exported content.
# Valid timezone values can be found here: https://www.php.net/manual/en/timezones.php
APP_TIMEZONE=UTC
# Application theme
# Used to specific a themes/<APP_THEME> folder where BookStack UI
# overrides can be made. Defaults to disabled.
APP_THEME=false
# Database details
# Host can contain a port (localhost:3306) or a separate DB_PORT option can be used.
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=database_database
DB_USERNAME=database_username
DB_PASSWORD=database_user_password
# Mail system to use
# Can be 'smtp' or 'sendmail'
MAIL_DRIVER=smtp
# Mail sending options
MAIL_FROM=mail@bookstackapp.com
MAIL_FROM_NAME=BookStack
# SMTP mail options
MAIL_HOST=localhost
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
# Cache & Session driver to use
# Can be 'file', 'database', 'memcached' or 'redis'
CACHE_DRIVER=file
SESSION_DRIVER=file
# Session configuration
SESSION_LIFETIME=120
SESSION_COOKIE_NAME=bookstack_session
SESSION_SECURE_COOKIE=false
# Cache key prefix
# Can be used to prevent conflicts multiple BookStack instances use the same store.
CACHE_PREFIX=bookstack
# Memcached server configuration
# If using a UNIX socket path for the host, set the port to 0
# This follows the following format: HOST:PORT:WEIGHT
# 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.
QUEUE_CONNECTION=sync
# Storage system to use
# Can be 'local', 'local_secure' or 's3'
STORAGE_TYPE=local
# Image storage system to use
# Defaults to the value of STORAGE_TYPE if unset.
# Accepts the same values as STORAGE_TYPE.
STORAGE_IMAGE_TYPE=local
# Attachment storage system to use
# Defaults to the value of STORAGE_TYPE if unset.
# Accepts the same values as STORAGE_TYPE although 'local' will be forced to 'local_secure'.
STORAGE_ATTACHMENT_TYPE=local_secure
# Amazon S3 storage configuration
STORAGE_S3_KEY=your-s3-key
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.
STORAGE_URL=false
# Authentication method to use
# Can be 'standard', 'ldap' or 'saml2'
AUTH_METHOD=standard
# Social authentication configuration
# All disabled by default.
# Refer to https://www.bookstackapp.com/docs/admin/third-party-auth/
AZURE_APP_ID=false
AZURE_APP_SECRET=false
AZURE_TENANT=false
AZURE_AUTO_REGISTER=false
AZURE_AUTO_CONFIRM_EMAIL=false
DISCORD_APP_ID=false
DISCORD_APP_SECRET=false
DISCORD_AUTO_REGISTER=false
DISCORD_AUTO_CONFIRM_EMAIL=false
FACEBOOK_APP_ID=false
FACEBOOK_APP_SECRET=false
FACEBOOK_AUTO_REGISTER=false
FACEBOOK_AUTO_CONFIRM_EMAIL=false
GITHUB_APP_ID=false
GITHUB_APP_SECRET=false
GITHUB_AUTO_REGISTER=false
GITHUB_AUTO_CONFIRM_EMAIL=false
GITLAB_APP_ID=false
GITLAB_APP_SECRET=false
GITLAB_BASE_URI=false
GITLAB_AUTO_REGISTER=false
GITLAB_AUTO_CONFIRM_EMAIL=false
GOOGLE_APP_ID=false
GOOGLE_APP_SECRET=false
GOOGLE_SELECT_ACCOUNT=false
GOOGLE_AUTO_REGISTER=false
GOOGLE_AUTO_CONFIRM_EMAIL=false
OKTA_BASE_URL=false
OKTA_APP_ID=false
OKTA_APP_SECRET=false
OKTA_AUTO_REGISTER=false
OKTA_AUTO_CONFIRM_EMAIL=false
SLACK_APP_ID=false
SLACK_APP_SECRET=false
SLACK_AUTO_REGISTER=false
SLACK_AUTO_CONFIRM_EMAIL=false
TWITCH_APP_ID=false
TWITCH_APP_SECRET=false
TWITCH_AUTO_REGISTER=false
TWITCH_AUTO_CONFIRM_EMAIL=false
TWITTER_APP_ID=false
TWITTER_APP_SECRET=false
TWITTER_AUTO_REGISTER=false
TWITTER_AUTO_CONFIRM_EMAIL=false
# LDAP authentication configuration
# Refer to https://www.bookstackapp.com/docs/admin/ldap-auth/
LDAP_SERVER=false
LDAP_BASE_DN=false
LDAP_DN=false
LDAP_PASS=false
LDAP_USER_FILTER=false
LDAP_VERSION=false
LDAP_START_TLS=false
LDAP_TLS_INSECURE=false
LDAP_ID_ATTRIBUTE=uid
LDAP_EMAIL_ATTRIBUTE=mail
LDAP_DISPLAY_NAME_ATTRIBUTE=cn
LDAP_THUMBNAIL_ATTRIBUTE=null
LDAP_FOLLOW_REFERRALS=true
LDAP_DUMP_USER_DETAILS=false
# LDAP group sync configuration
# Refer to https://www.bookstackapp.com/docs/admin/ldap-auth/
LDAP_USER_TO_GROUPS=false
LDAP_GROUP_ATTRIBUTE="memberOf"
LDAP_REMOVE_FROM_GROUPS=false
# SAML authentication configuration
# Refer to https://www.bookstackapp.com/docs/admin/saml2-auth/
SAML2_NAME=SSO
SAML2_EMAIL_ATTRIBUTE=email
SAML2_DISPLAY_NAME_ATTRIBUTES=username
SAML2_EXTERNAL_ID_ATTRIBUTE=null
SAML2_IDP_ENTITYID=null
SAML2_IDP_SSO=null
SAML2_IDP_SLO=null
SAML2_IDP_x509=null
SAML2_ONELOGIN_OVERRIDES=null
SAML2_DUMP_USER_DETAILS=false
SAML2_AUTOLOAD_METADATA=false
SAML2_IDP_AUTHNCONTEXT=true
# SAML group sync configuration
# Refer to https://www.bookstackapp.com/docs/admin/saml2-auth/
SAML2_USER_TO_GROUPS=false
SAML2_GROUP_ATTRIBUTE=group
SAML2_REMOVE_FROM_GROUPS=false
# Disable default third-party services such as Gravatar and Draw.IO
# Service-specific options will override this option
DISABLE_EXTERNAL_SERVICES=false
# Use custom avatar service, Sets fetch URL
# Possible placeholders: ${hash} ${size} ${email}
# If set, Avatars will be fetched regardless of DISABLE_EXTERNAL_SERVICES option.
# Example: AVATAR_URL=https://seccdn.libravatar.org/avatar/${hash}?s=${size}&d=identicon
AVATAR_URL=
# Enable diagrams.net integration
# Can simply be true/false to enable/disable the integration.
# Alternatively, It can be URL to the diagrams.net instance you want to use.
# For URLs, The following URL parameters should be included: embed=1&proto=json&spin=1
DRAWIO=true
# Default item listing view
# Used for public visitors and user's without a preference.
# Can be 'list' or 'grid'.
APP_VIEWS_BOOKS=list
APP_VIEWS_BOOKSHELVES=grid
APP_VIEWS_BOOKSHELF=grid
# Use dark mode by default
# Will be overriden by any user/session preference.
APP_DEFAULT_DARK_MODE=false
# Page revision limit
# Number of page revisions to keep in the system before deleting old revisions.
# If set to 'false' a limit will not be enforced.
REVISION_LIMIT=50
# Recycle Bin Lifetime
# The number of days that content will remain in the recycle bin before
# being considered for auto-removal. It is not a guarantee that content will
# be removed after this time.
# Set to 0 for no recycle bin functionality.
# Set to -1 for unlimited recycle bin lifetime.
RECYCLE_BIN_LIFETIME=30
# Allow <script> tags in page content
# Note, if set to 'true' the page editor may still escape scripts.
ALLOW_CONTENT_SCRIPTS=false
# Indicate if robots/crawlers should crawl your instance.
# Can be 'true', 'false' or 'null'.
# The behaviour of the default 'null' option will depend on the 'app-public' admin setting.
# Contents of the robots.txt file can be overridden, making this option obsolete.
ALLOW_ROBOTS=null
# Allow server-side fetches to be performed to potentially unknown
# and user-provided locations. Primarily used in exports when loading
# in externally referenced assets.
# Can be 'true' or 'false'.
ALLOW_UNTRUSTED_SERVER_FETCHING=false
# A list of hosts that BookStack can be iframed within.
# Space separated if multiple. BookStack host domain is auto-inferred.
# For Example: ALLOWED_IFRAME_HOSTS="https://example.com https://a.example.com"
# Setting this option will also auto-adjust cookies to be SameSite=None.
ALLOWED_IFRAME_HOSTS=null
# The default and maximum item-counts for listing API requests.
API_DEFAULT_ITEM_COUNT=100
API_MAX_ITEM_COUNT=500
# The number of API requests that can be made per minute by a single user.
API_REQUESTS_PER_MIN=180
# Enable the logging of failed email+password logins with the given message.
# The default log channel below uses the php 'error_log' function which commonly
# results in messages being output to the webserver error logs.
# The message can contain a %u parameter which will be replaced with the login
# user identifier (Username or email).
LOG_FAILED_LOGIN_MESSAGE=false
LOG_FAILED_LOGIN_CHANNEL=errorlog_plain_webserver

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
# These are supported funding model platforms
github: [ssddanbrown]

17
.github/ISSUE_TEMPLATE/api_request.md vendored Normal file
View File

@@ -0,0 +1,17 @@
---
name: New API Endpoint or Feature
about: Request a new endpoint or API feature be added
labels: ":nut_and_bolt: API Request"
---
#### API Endpoint or Feature
Clearly describe what you'd like to have added to the API.
#### Use-Case
Explain the use-case that you're working-on that requires the above request.
#### Additional Context
If required, add any other context about the feature request here.

View File

@@ -1,5 +1,5 @@
---
name: Bug report
name: Bug Report
about: Create a report to help us improve
---

9
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,9 @@
blank_issues_enabled: false
contact_links:
- name: Discord chat support
url: https://discord.gg/ztkBqR2
about: Realtime support / chat with the community and the team.
- name: Debugging & Common Issues
url: https://www.bookstackapp.com/docs/admin/debugging/
about: Find details on how to debug issues and view common issues with thier resolutions.

View File

@@ -1,5 +1,5 @@
---
name: Feature request
name: Feature Request
about: Suggest an idea for this project
---

View File

@@ -0,0 +1,13 @@
---
name: Language Request
about: Request a new language to be added to Crowdin for you to translate
---
### Language To Add
_Specify here the language you want to add._
----
_This issue template is to request a new language be added to our [Crowdin translation management project](https://crowdin.com/project/bookstack). Please don't use this template to request a new language that you are not prepared to provide translations for._

185
.github/translators.txt vendored Normal file
View File

@@ -0,0 +1,185 @@
Name :: Languages
@robertlandes :: German
@SergioMendolia :: French
@NakaharaL :: Portuguese, Brazilian
@ReeseSebastian :: German
@arietimmerman :: Dutch
@diegoseso :: Spanish
@S64 :: Japanese
@JachuPL :: Polish
@Joorem :: French
@timoschwarzer :: German
@sanderdw :: Dutch
@lbguilherme :: Portuguese, Brazilian
@marcusforsberg :: Swedish
@artur-trzesiok :: Polish
@Alwaysin :: French
@msaus :: Japanese
@moucho :: Spanish
@vriic :: German
@DeehSlash :: Portuguese, Brazilian
@alex2702 :: German
@nicobubulle :: French
@kmoj86 :: Arabic
@houbaron :: Chinese Traditional; Chinese Simplified
@mullinsmikey :: Russian
@limkukhyun :: Korean
@CliffyPrime :: German
@kejjang :: Chinese Traditional
@TheLastOperator :: French
@qianmengnet :: Simplified Chinese
@ezzra :: German; German Informal
@vasiliev123 :: Polish
@Mant1kor :: Ukrainian
@Xiphoseer :: German; German Informal
@maantje :: Dutch
@cima :: Czech
@agvol :: Russian
@Hambern :: Swedish
@NootoNooto :: Dutch
@kostefun :: Russian
@lucaguindani :: French
@miles75 :: Hungarian
@danielroehrig-mm :: German
@oykenfurkan :: Turkish
@qligier :: French
@johnroyer :: Traditional Chinese
@artskoczylas :: Polish
@dellamina :: Italian
@jzoy :: Simplified Chinese
@ististudio :: Korean
@leomartinez :: Spanish Argentina
@geins :: German
@Ereza :: Catalan
@benediktvolke :: German
@Baptistou :: French
@arcoai :: Spanish
@Jokuna :: Korean
cipi1965 :: Italian
Mykola Ronik (Mantikor) :: Ukrainian
furkanoyk :: Turkish
m0uch0 :: Spanish
Maxim Zalata (zlatin) :: Russian; Ukrainian
nutsflag :: French
Leonardo Mario Martinez (leonardo.m.martinez) :: Spanish, Argentina
Rodrigo Saczuk Niz (rodrigoniz) :: Portuguese, Brazilian
叫钦叔就好 (254351722) :: Chinese Traditional; Chinese Simplified
aekramer :: Dutch
JachuPL :: Polish
milesteg :: Hungarian
Beenbag :: German; German Informal
Lett3rs :: Danish
Julian (julian.henneberg) :: German; German Informal
3GNWn :: Danish
dbguichu :: Chinese Simplified
Randy Kim (hyunjun) :: Korean
Francesco M. Taurino (ftaurino) :: Italian
DanielFrederiksen :: Danish
Finn Wessel (19finnwessel6) :: German Informal; German
Gustav Kånåhols (Kurbitz) :: Swedish
Vuong Trung Hieu (fpooon) :: Vietnamese
Emil Petersen (emoyly) :: Danish
mrjaboozy :: Slovenian
Statium :: Russian
Mikkel Struntze (MStruntze) :: Danish
kostefun :: Russian
Tuyen.NG (tuyendev) :: Vietnamese
Ghost_chu (dbguichu) :: Chinese Simplified
Ziipen :: Danish
Samuel Schwarz (Guiph7quan) :: Czech
Aleph (toishoki) :: Turkish
Julio Alberto García (Yllelder) :: Spanish
Rafael (raribeir) :: Portuguese, Brazilian
Hiroyuki Odake (dakesan) :: Japanese
Alex Lee (qianmengnet) :: Chinese Simplified
swinn37 :: French
Hasan Özbey (the-turk) :: Turkish
rcy :: Swedish
Ali Yasir Yılmaz (ayyilmaz) :: Turkish
scureza :: Italian
Biepa :: German Informal; German
syecu :: Chinese Simplified
Lap1t0r :: French
Thinkverse (thinkverse) :: Swedish
alef (toishoki) :: Turkish
Robbert Feunekes (Muukuro) :: Dutch
seohyeon.joo :: Korean
Orenda (OREDNA) :: Bulgarian
Marek Pavelka (marapavelka) :: Czech
Venkinovec :: Czech
Tommy Ku (tommyku) :: Chinese Traditional; Japanese
Michał Bielejewski (bielej) :: Polish
jozefrebjak :: Slovak
Ikhwan Koo (Ikhwan.Koo) :: Korean
Whay (remkovdhoef) :: Dutch
jc7115 :: Chinese Traditional
주서현 (seohyeon.joo) :: Korean
ReadySystems :: Arabic
HFinch :: German; German Informal
brechtgijsens :: Dutch
Lowkey (v587ygq) :: Chinese Simplified
sdl-blue :: German Informal
sqlik :: Polish
Roy van Schaijk (royvanschaijk) :: Dutch
Simsimpicpic :: French
Zenahr Barzani (Zenahr) :: German; Japanese; Dutch; German Informal
tatsuya.info :: Japanese
fadiapp :: Arabic
Jakub Bouček (jakubboucek) :: Czech
Marco (cdrfun) :: German
10935336 :: Chinese Simplified
孟繁阳 (FanyangMeng) :: Chinese Simplified
Andrej Močan (andrejm) :: Slovenian
gilane9_ :: Arabic
Raed alnahdi (raednahdi) :: Arabic
Xiphoseer :: German
MerlinSVK (merlinsvk) :: Slovak
Kauê Sena (kaue.sena.ks) :: Portuguese, Brazilian
MatthieuParis :: French
Douradinho :: Portuguese, Brazilian
Gaku Yaguchi (tama11) :: Japanese
johnroyer :: Chinese Traditional
jackaaa :: Chinese Traditional
Irfan Hukama Arsyad (IrfanArsyad) :: Indonesian
Jeff Huang (s8321414) :: Chinese Traditional
Luís Tiago Favas (starkyller) :: Portuguese
semirte :: Bosnian
aarchijs :: Latvian
Martins Pilsetnieks (pilsetnieks) :: Latvian
Yonatan Magier (yonatanmgr) :: Hebrew
FastHogi :: German Informal; German
Ole Anders (Swoy) :: Norwegian Bokmal
Atlochowski (atlochowski) :: Polish
Simon (DefaultSimon) :: Slovenian
Reinis Mednis (Mednis) :: Latvian
toisho (toishoki) :: Turkish
nikservik :: Ukrainian; Russian; Polish
HenrijsS :: Latvian
Pascal R-B (pborgner) :: German
Boris (Ginfred) :: Russian
Jonas Anker Rasmussen (jonasanker) :: Danish
Gerwin de Keijzer (gdekeijzer) :: Dutch; German; German Informal
kometchtech :: Japanese
Auri (Atalonica) :: Catalan
Francesco Franchina (ffranchina) :: Italian
Aimrane Kds (aimrane.kds) :: Arabic
whenwesober :: Indonesian
Rem (remkovdhoef) :: Dutch
syn7ax69 :: Bulgarian; Turkish
Blaade :: French
Behzad HosseinPoor (behzad.hp) :: Persian
Ole Aldric (Swoy) :: Norwegian Bokmal
fharis arabia (raednahdi) :: Arabic
Alexander Predl (Harveyhase68) :: German
Rem (Rem9000) :: Dutch
Michał Stelmach (stelmach-web) :: Polish
arniom :: French
REMOVED_USER :: Turkish
林祖年 (contagion) :: Chinese Traditional
Siamak Guodarzi (siamakgoudarzi88) :: Persian
Lis Maestrelo (lismtrl) :: Portuguese, Brazilian
Nathanaël (nathanaelhoun) :: French
A Ibnu Hibban (abd.ibnuhibban) :: Indonesian
Frost-ZX :: Chinese Simplified
Kuzma Simonov (ovmach) :: Russian
Vojtěch Krystek (acantophis) :: Czech

57
.github/workflows/phpunit.yml vendored Normal file
View File

@@ -0,0 +1,57 @@
name: phpunit
on:
push:
branches-ignore:
- l10n_master
pull_request:
branches-ignore:
- l10n_master
jobs:
build:
runs-on: ubuntu-20.04
strategy:
matrix:
php: ['7.3', '7.4', '8.0']
steps:
- uses: actions/checkout@v1
- name: Setup PHP
uses: shivammathur/setup-php@b7d1d9c9a92d8d8463ce36d7f60da34d461724f8
with:
php-version: ${{ matrix.php }}
extensions: gd, mbstring, json, curl, xml, mysql, ldap
- name: Get Composer Cache Directory
id: composer-cache
run: |
echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache composer packages
uses: actions/cache@v1
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ matrix.php }}
- name: Start Database
run: |
sudo /etc/init.d/mysql start
- name: Setup Database
run: |
mysql -uroot -proot -e 'CREATE DATABASE IF NOT EXISTS `bookstack-test`;'
mysql -uroot -proot -e "CREATE USER 'bookstack-test'@'localhost' IDENTIFIED WITH mysql_native_password BY 'bookstack-test';"
mysql -uroot -proot -e "GRANT ALL ON \`bookstack-test\`.* TO 'bookstack-test'@'localhost';"
mysql -uroot -proot -e 'FLUSH PRIVILEGES;'
- name: Install composer dependencies & Test
run: composer install --prefer-dist --no-interaction --ansi
- name: Migrate and seed the database
run: |
php${{ matrix.php }} artisan migrate --force -n --database=mysql_testing
php${{ matrix.php }} artisan db:seed --force -n --class=DummyContentSeeder --database=mysql_testing
- name: phpunit
run: php${{ matrix.php }} ./vendor/bin/phpunit

61
.github/workflows/test-migrations.yml vendored Normal file
View File

@@ -0,0 +1,61 @@
name: test-migrations
on:
push:
branches-ignore:
- l10n_master
pull_request:
branches-ignore:
- l10n_master
jobs:
build:
runs-on: ubuntu-20.04
strategy:
matrix:
php: ['7.3', '7.4', '8.0']
steps:
- uses: actions/checkout@v1
- name: Setup PHP
uses: shivammathur/setup-php@b7d1d9c9a92d8d8463ce36d7f60da34d461724f8
with:
php-version: ${{ matrix.php }}
extensions: gd, mbstring, json, curl, xml, mysql, ldap
- name: Get Composer Cache Directory
id: composer-cache
run: |
echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache composer packages
uses: actions/cache@v1
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ matrix.php }}
- name: Start MySQL
run: |
sudo /etc/init.d/mysql start
- name: Create database & user
run: |
mysql -uroot -proot -e 'CREATE DATABASE IF NOT EXISTS `bookstack-test`;'
mysql -uroot -proot -e "CREATE USER 'bookstack-test'@'localhost' IDENTIFIED WITH mysql_native_password BY 'bookstack-test';"
mysql -uroot -proot -e "GRANT ALL ON \`bookstack-test\`.* TO 'bookstack-test'@'localhost';"
mysql -uroot -proot -e 'FLUSH PRIVILEGES;'
- name: Install composer dependencies
run: composer install --prefer-dist --no-interaction --ansi
- name: Start migration test
run: |
php${{ matrix.php }} artisan migrate --force -n --database=mysql_testing
- name: Start migration:rollback test
run: |
php${{ matrix.php }} artisan migrate:rollback --force -n --database=mysql_testing
- name: Start migration rerun test
run: |
php${{ matrix.php }} artisan migrate --force -n --database=mysql_testing

4
.gitignore vendored
View File

@@ -21,4 +21,6 @@ nbproject
.buildpath
.project
.settings/
webpack-stats.json
webpack-stats.json
.phpunit.result.cache
.DS_Store

View File

@@ -1,28 +0,0 @@
dist: trusty
sudo: false
language: php
php:
- 7.0.20
- 7.1.9
cache:
directories:
- $HOME/.composer/cache
before_script:
- mysql -u root -e 'create database `bookstack-test`;'
- mysql -u root -e "CREATE USER 'bookstack-test'@'localhost' IDENTIFIED BY 'bookstack-test';"
- mysql -u root -e "GRANT ALL ON \`bookstack-test\`.* TO 'bookstack-test'@'localhost';"
- mysql -u root -e "FLUSH PRIVILEGES;"
- phpenv config-rm xdebug.ini
- composer install --prefer-dist --no-interaction
- php artisan clear-compiled -n
- php artisan optimize -n
- php artisan migrate --force -n --database=mysql_testing
- php artisan db:seed --force -n --class=DummyContentSeeder --database=mysql_testing
after_failure:
- cat storage/logs/laravel.log
script:
- phpunit

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2018 Dan Brown and the BookStack Project contributors
Copyright (c) 2020 Dan Brown and the BookStack Project contributors
https://github.com/BookStackApp/BookStack/graphs/contributors
Permission is hereby granted, free of charge, to any person obtaining a copy

68
app/Actions/Activity.php Normal file
View File

@@ -0,0 +1,68 @@
<?php
namespace BookStack\Actions;
use BookStack\Auth\User;
use BookStack\Entities\Models\Entity;
use BookStack\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Support\Str;
/**
* @property string $type
* @property User $user
* @property Entity $entity
* @property string $detail
* @property string $entity_type
* @property int $entity_id
* @property int $user_id
*/
class Activity extends Model
{
/**
* Get the entity for this activity.
*/
public function entity(): MorphTo
{
if ($this->entity_type === '') {
$this->entity_type = null;
}
return $this->morphTo('entity');
}
/**
* Get the user this activity relates to.
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
/**
* Returns text from the language files, Looks up by using the activity key.
*/
public function getText(): string
{
return trans('activities.' . $this->type);
}
/**
* Check if this activity is intended to be for an entity.
*/
public function isForEntity(): bool
{
return Str::startsWith($this->type, [
'page_', 'chapter_', 'book_', 'bookshelf_',
]);
}
/**
* Checks if another Activity matches the general information of another.
*/
public function isSimilarTo(Activity $activityB): bool
{
return [$this->type, $this->entity_type, $this->entity_id] === [$activityB->type, $activityB->entity_type, $activityB->entity_id];
}
}

View File

@@ -0,0 +1,197 @@
<?php
namespace BookStack\Actions;
use BookStack\Auth\Permissions\PermissionService;
use BookStack\Auth\User;
use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Models\Entity;
use BookStack\Entities\Models\Page;
use BookStack\Interfaces\Loggable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Facades\Log;
class ActivityService
{
protected $activity;
protected $permissionService;
public function __construct(Activity $activity, PermissionService $permissionService)
{
$this->activity = $activity;
$this->permissionService = $permissionService;
}
/**
* Add activity data to database for an entity.
*/
public function addForEntity(Entity $entity, string $type)
{
$activity = $this->newActivityForUser($type);
$entity->activity()->save($activity);
$this->setNotification($type);
}
/**
* Add a generic activity event to the database.
*
* @param string|Loggable $detail
*/
public function add(string $type, $detail = '')
{
if ($detail instanceof Loggable) {
$detail = $detail->logDescriptor();
}
$activity = $this->newActivityForUser($type);
$activity->detail = $detail;
$activity->save();
$this->setNotification($type);
}
/**
* Get a new activity instance for the current user.
*/
protected function newActivityForUser(string $type): Activity
{
return $this->activity->newInstance()->forceFill([
'type' => strtolower($type),
'user_id' => user()->id,
]);
}
/**
* Removes the entity attachment from each of its activities
* and instead uses the 'extra' field with the entities name.
* Used when an entity is deleted.
*/
public function removeEntity(Entity $entity)
{
$entity->activity()->update([
'detail' => $entity->name,
'entity_id' => null,
'entity_type' => null,
]);
}
/**
* Gets the latest activity.
*/
public function latest(int $count = 20, int $page = 0): array
{
$activityList = $this->permissionService
->filterRestrictedEntityRelations($this->activity->newQuery(), 'activities', 'entity_id', 'entity_type')
->orderBy('created_at', 'desc')
->with(['user', 'entity'])
->skip($count * $page)
->take($count)
->get();
return $this->filterSimilar($activityList);
}
/**
* Gets the latest activity for an entity, Filtering out similar
* items to prevent a message activity list.
*/
public function entityActivity(Entity $entity, int $count = 20, int $page = 1): array
{
/** @var [string => int[]] $queryIds */
$queryIds = [$entity->getMorphClass() => [$entity->id]];
if ($entity->isA('book')) {
$queryIds[(new Chapter())->getMorphClass()] = $entity->chapters()->visible()->pluck('id');
}
if ($entity->isA('book') || $entity->isA('chapter')) {
$queryIds[(new Page())->getMorphClass()] = $entity->pages()->visible()->pluck('id');
}
$query = $this->activity->newQuery();
$query->where(function (Builder $query) use ($queryIds) {
foreach ($queryIds as $morphClass => $idArr) {
$query->orWhere(function (Builder $innerQuery) use ($morphClass, $idArr) {
$innerQuery->where('entity_type', '=', $morphClass)
->whereIn('entity_id', $idArr);
});
}
});
$activity = $query->orderBy('created_at', 'desc')
->with(['entity' => function (Relation $query) {
$query->withTrashed();
}, 'user.avatar'])
->skip($count * ($page - 1))
->take($count)
->get();
return $this->filterSimilar($activity);
}
/**
* Get latest activity for a user, Filtering out similar items.
*/
public function userActivity(User $user, int $count = 20, int $page = 0): array
{
$activityList = $this->permissionService
->filterRestrictedEntityRelations($this->activity->newQuery(), 'activities', 'entity_id', 'entity_type')
->orderBy('created_at', 'desc')
->where('user_id', '=', $user->id)
->skip($count * $page)
->take($count)
->get();
return $this->filterSimilar($activityList);
}
/**
* Filters out similar activity.
*
* @param Activity[] $activities
*
* @return array
*/
protected function filterSimilar(iterable $activities): array
{
$newActivity = [];
$previousItem = null;
foreach ($activities as $activityItem) {
if (!$previousItem || !$activityItem->isSimilarTo($previousItem)) {
$newActivity[] = $activityItem;
}
$previousItem = $activityItem;
}
return $newActivity;
}
/**
* Flashes a notification message to the session if an appropriate message is available.
*/
protected function setNotification(string $type)
{
$notificationTextKey = 'activities.' . $type . '_notification';
if (trans()->has($notificationTextKey)) {
$message = trans($notificationTextKey);
session()->flash('success', $message);
}
}
/**
* Log out a failed login attempt, Providing the given username
* as part of the message if the '%u' string is used.
*/
public function logFailedLogin(string $username)
{
$message = config('logging.failed_login.message');
if (!$message) {
return;
}
$message = str_replace('%u', $username, $message);
$channel = config('logging.failed_login.channel');
Log::channel($channel)->warning($message);
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace BookStack\Actions;
class ActivityType
{
const PAGE_CREATE = 'page_create';
const PAGE_UPDATE = 'page_update';
const PAGE_DELETE = 'page_delete';
const PAGE_RESTORE = 'page_restore';
const PAGE_MOVE = 'page_move';
const CHAPTER_CREATE = 'chapter_create';
const CHAPTER_UPDATE = 'chapter_update';
const CHAPTER_DELETE = 'chapter_delete';
const CHAPTER_MOVE = 'chapter_move';
const BOOK_CREATE = 'book_create';
const BOOK_UPDATE = 'book_update';
const BOOK_DELETE = 'book_delete';
const BOOK_SORT = 'book_sort';
const BOOKSHELF_CREATE = 'bookshelf_create';
const BOOKSHELF_UPDATE = 'bookshelf_update';
const BOOKSHELF_DELETE = 'bookshelf_delete';
const COMMENTED_ON = 'commented_on';
const PERMISSIONS_UPDATE = 'permissions_update';
const SETTINGS_UPDATE = 'settings_update';
const MAINTENANCE_ACTION_RUN = 'maintenance_action_run';
const RECYCLE_BIN_EMPTY = 'recycle_bin_empty';
const RECYCLE_BIN_RESTORE = 'recycle_bin_restore';
const RECYCLE_BIN_DESTROY = 'recycle_bin_destroy';
const USER_CREATE = 'user_create';
const USER_UPDATE = 'user_update';
const USER_DELETE = 'user_delete';
const API_TOKEN_CREATE = 'api_token_create';
const API_TOKEN_UPDATE = 'api_token_update';
const API_TOKEN_DELETE = 'api_token_delete';
const ROLE_CREATE = 'role_create';
const ROLE_UPDATE = 'role_update';
const ROLE_DELETE = 'role_delete';
const AUTH_PASSWORD_RESET = 'auth_password_reset_request';
const AUTH_PASSWORD_RESET_UPDATE = 'auth_password_reset_update';
const AUTH_LOGIN = 'auth_login';
const AUTH_REGISTER = 'auth_register';
const MFA_SETUP_METHOD = 'mfa_setup_method';
const MFA_REMOVE_METHOD = 'mfa_remove_method';
}

View File

@@ -1,30 +1,43 @@
<?php namespace BookStack;
<?php
class Comment extends Ownable
namespace BookStack\Actions;
use BookStack\Model;
use BookStack\Traits\HasCreatorAndUpdater;
use Illuminate\Database\Eloquent\Relations\MorphTo;
/**
* @property string text
* @property string html
* @property int|null parent_id
* @property int local_id
*/
class Comment extends Model
{
protected $fillable = ['text', 'html', 'parent_id'];
use HasCreatorAndUpdater;
protected $fillable = ['text', 'parent_id'];
protected $appends = ['created', 'updated'];
/**
* Get the entity that this comment belongs to
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
* Get the entity that this comment belongs to.
*/
public function entity()
public function entity(): MorphTo
{
return $this->morphTo('entity');
}
/**
* Check if a comment has been updated since creation.
* @return bool
*/
public function isUpdated()
public function isUpdated(): bool
{
return $this->updated_at->timestamp > $this->created_at->timestamp;
}
/**
* Get created date as a relative diff.
*
* @return mixed
*/
public function getCreatedAttribute()
@@ -34,6 +47,7 @@ class Comment extends Ownable
/**
* Get updated date as a relative diff.
*
* @return mixed
*/
public function getUpdatedAttribute()

View File

@@ -0,0 +1,97 @@
<?php
namespace BookStack\Actions;
use BookStack\Entities\Models\Entity;
use BookStack\Facades\Activity as ActivityService;
use League\CommonMark\CommonMarkConverter;
/**
* Class CommentRepo.
*/
class CommentRepo
{
/**
* @var Comment
*/
protected $comment;
public function __construct(Comment $comment)
{
$this->comment = $comment;
}
/**
* Get a comment by ID.
*/
public function getById(int $id): Comment
{
return $this->comment->newQuery()->findOrFail($id);
}
/**
* Create a new comment on an entity.
*/
public function create(Entity $entity, string $text, ?int $parent_id): Comment
{
$userId = user()->id;
$comment = $this->comment->newInstance();
$comment->text = $text;
$comment->html = $this->commentToHtml($text);
$comment->created_by = $userId;
$comment->updated_by = $userId;
$comment->local_id = $this->getNextLocalId($entity);
$comment->parent_id = $parent_id;
$entity->comments()->save($comment);
ActivityService::addForEntity($entity, ActivityType::COMMENTED_ON);
return $comment;
}
/**
* Update an existing comment.
*/
public function update(Comment $comment, string $text): Comment
{
$comment->updated_by = user()->id;
$comment->text = $text;
$comment->html = $this->commentToHtml($text);
$comment->save();
return $comment;
}
/**
* Delete a comment from the system.
*/
public function delete(Comment $comment)
{
$comment->delete();
}
/**
* Convert the given comment markdown text to HTML.
*/
public function commentToHtml(string $commentText): string
{
$converter = new CommonMarkConverter([
'html_input' => 'strip',
'max_nesting_level' => 10,
'allow_unsafe_links' => false,
]);
return $converter->convertToHtml($commentText);
}
/**
* Get the next local ID relative to the linked entity.
*/
protected function getNextLocalId(Entity $entity): int
{
$comments = $entity->comments(false)->orderBy('local_id', 'desc')->first();
return ($comments->local_id ?? 0) + 1;
}
}

19
app/Actions/Favourite.php Normal file
View File

@@ -0,0 +1,19 @@
<?php
namespace BookStack\Actions;
use BookStack\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;
class Favourite extends Model
{
protected $fillable = ['user_id'];
/**
* Get the related model that can be favourited.
*/
public function favouritable(): MorphTo
{
return $this->morphTo();
}
}

36
app/Actions/Tag.php Normal file
View File

@@ -0,0 +1,36 @@
<?php
namespace BookStack\Actions;
use BookStack\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;
class Tag extends Model
{
protected $fillable = ['name', 'value', 'order'];
protected $hidden = ['id', 'entity_id', 'entity_type', 'created_at', 'updated_at'];
/**
* Get the entity that this tag belongs to.
*/
public function entity(): MorphTo
{
return $this->morphTo('entity');
}
/**
* Get a full URL to start a tag name search for this tag name.
*/
public function nameUrl(): string
{
return url('/search?term=%5B' . urlencode($this->name) . '%5D');
}
/**
* Get a full URL to start a tag name and value search for this tag's values.
*/
public function valueUrl(): string
{
return url('/search?term=%5B' . urlencode($this->name) . '%3D' . urlencode($this->value) . '%5D');
}
}

98
app/Actions/TagRepo.php Normal file
View File

@@ -0,0 +1,98 @@
<?php
namespace BookStack\Actions;
use BookStack\Auth\Permissions\PermissionService;
use BookStack\Entities\Models\Entity;
use DB;
use Illuminate\Support\Collection;
class TagRepo
{
protected $tag;
protected $permissionService;
/**
* TagRepo constructor.
*/
public function __construct(Tag $tag, PermissionService $ps)
{
$this->tag = $tag;
$this->permissionService = $ps;
}
/**
* Get tag name suggestions from scanning existing tag names.
* If no search term is given the 50 most popular tag names are provided.
*/
public function getNameSuggestions(?string $searchTerm): Collection
{
$query = $this->tag->newQuery()
->select('*', DB::raw('count(*) as count'))
->groupBy('name');
if ($searchTerm) {
$query = $query->where('name', 'LIKE', $searchTerm . '%')->orderBy('name', 'desc');
} else {
$query = $query->orderBy('count', 'desc')->take(50);
}
$query = $this->permissionService->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type');
return $query->get(['name'])->pluck('name');
}
/**
* Get tag value suggestions from scanning existing tag values.
* If no search is given the 50 most popular values are provided.
* Passing a tagName will only find values for a tags with a particular name.
*/
public function getValueSuggestions(?string $searchTerm, ?string $tagName): Collection
{
$query = $this->tag->newQuery()
->select('*', DB::raw('count(*) as count'))
->groupBy('value');
if ($searchTerm) {
$query = $query->where('value', 'LIKE', $searchTerm . '%')->orderBy('value', 'desc');
} else {
$query = $query->orderBy('count', 'desc')->take(50);
}
if ($tagName) {
$query = $query->where('name', '=', $tagName);
}
$query = $this->permissionService->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type');
return $query->get(['value'])->pluck('value');
}
/**
* Save an array of tags to an entity.
*/
public function saveTagsToEntity(Entity $entity, array $tags = []): iterable
{
$entity->tags()->delete();
$newTags = collect($tags)->filter(function ($tag) {
return boolval(trim($tag['name']));
})->map(function ($tag) {
return $this->newInstanceFromInput($tag);
})->all();
return $entity->tags()->saveMany($newTags);
}
/**
* Create a new Tag instance from user input.
* Input must be an array with a 'name' and an optional 'value' key.
*/
protected function newInstanceFromInput(array $input): Tag
{
$name = trim($input['name']);
$value = isset($input['value']) ? trim($input['value']) : '';
return $this->tag->newInstance(['name' => $name, 'value' => $value]);
}
}

58
app/Actions/View.php Normal file
View File

@@ -0,0 +1,58 @@
<?php
namespace BookStack\Actions;
use BookStack\Interfaces\Viewable;
use BookStack\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;
/**
* Class View
* Views are stored per-item per-person within the database.
* They can be used to find popular items or recently viewed items
* at a per-person level. They do not record every view instance as an
* activity. Only the latest and original view times could be recognised.
*
* @property int $views
* @property int $user_id
*/
class View extends Model
{
protected $fillable = ['user_id', 'views'];
/**
* Get all owning viewable models.
*/
public function viewable(): MorphTo
{
return $this->morphTo();
}
/**
* Increment the current user's view count for the given viewable model.
*/
public static function incrementFor(Viewable $viewable): int
{
$user = user();
if (is_null($user) || $user->isDefault()) {
return 0;
}
/** @var View $view */
$view = $viewable->views()->firstOrNew([
'user_id' => $user->id,
], ['views' => 0]);
$view->forceFill(['views' => $view->views + 1])->save();
return $view->views;
}
/**
* Clear all views from the system.
*/
public static function clearAll()
{
static::query()->truncate();
}
}

View File

@@ -1,52 +0,0 @@
<?php
namespace BookStack;
/**
* @property string key
* @property \User user
* @property \Entity entity
* @property string extra
*/
class Activity extends Model
{
/**
* Get the entity for this activity.
*/
public function entity()
{
if ($this->entity_type === '') {
$this->entity_type = null;
}
return $this->morphTo('entity');
}
/**
* Get the user this activity relates to.
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo(User::class);
}
/**
* Returns text from the language files, Looks up by using the
* activity key.
*/
public function getText()
{
return trans('activities.' . $this->key);
}
/**
* Checks if another Activity matches the general information of another.
* @param $activityB
* @return bool
*/
public function isSimilarTo($activityB)
{
return [$this->key, $this->entity_type, $this->entity_id] === [$activityB->key, $activityB->entity_type, $activityB->entity_id];
}
}

View File

@@ -0,0 +1,155 @@
<?php
namespace BookStack\Api;
use BookStack\Http\Controllers\Api\ApiController;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Str;
use ReflectionClass;
use ReflectionException;
use ReflectionMethod;
class ApiDocsGenerator
{
protected $reflectionClasses = [];
protected $controllerClasses = [];
/**
* Load the docs form the cache if existing
* otherwise generate and store in the cache.
*/
public static function generateConsideringCache(): Collection
{
$appVersion = trim(file_get_contents(base_path('version')));
$cacheKey = 'api-docs::' . $appVersion;
if (Cache::has($cacheKey) && config('app.env') === 'production') {
$docs = Cache::get($cacheKey);
} else {
$docs = (new static())->generate();
Cache::put($cacheKey, $docs, 60 * 24);
}
return $docs;
}
/**
* Generate API documentation.
*/
protected function generate(): Collection
{
$apiRoutes = $this->getFlatApiRoutes();
$apiRoutes = $this->loadDetailsFromControllers($apiRoutes);
$apiRoutes = $this->loadDetailsFromFiles($apiRoutes);
$apiRoutes = $apiRoutes->groupBy('base_model');
return $apiRoutes;
}
/**
* Load any API details stored in static files.
*/
protected function loadDetailsFromFiles(Collection $routes): Collection
{
return $routes->map(function (array $route) {
$exampleTypes = ['request', 'response'];
foreach ($exampleTypes as $exampleType) {
$exampleFile = base_path("dev/api/{$exampleType}s/{$route['name']}.json");
$exampleContent = file_exists($exampleFile) ? file_get_contents($exampleFile) : null;
$route["example_{$exampleType}"] = $exampleContent;
}
return $route;
});
}
/**
* Load any details we can fetch from the controller and its methods.
*/
protected function loadDetailsFromControllers(Collection $routes): Collection
{
return $routes->map(function (array $route) {
$method = $this->getReflectionMethod($route['controller'], $route['controller_method']);
$comment = $method->getDocComment();
$route['description'] = $comment ? $this->parseDescriptionFromMethodComment($comment) : null;
$route['body_params'] = $this->getBodyParamsFromClass($route['controller'], $route['controller_method']);
return $route;
});
}
/**
* Load body params and their rules by inspecting the given class and method name.
*
* @throws BindingResolutionException
*/
protected function getBodyParamsFromClass(string $className, string $methodName): ?array
{
/** @var ApiController $class */
$class = $this->controllerClasses[$className] ?? null;
if ($class === null) {
$class = app()->make($className);
$this->controllerClasses[$className] = $class;
}
$rules = $class->getValdationRules()[$methodName] ?? [];
foreach ($rules as $param => $ruleString) {
$rules[$param] = explode('|', $ruleString);
}
return count($rules) > 0 ? $rules : null;
}
/**
* Parse out the description text from a class method comment.
*/
protected function parseDescriptionFromMethodComment(string $comment)
{
$matches = [];
preg_match_all('/^\s*?\*\s((?![@\s]).*?)$/m', $comment, $matches);
return implode(' ', $matches[1] ?? []);
}
/**
* Get a reflection method from the given class name and method name.
*
* @throws ReflectionException
*/
protected function getReflectionMethod(string $className, string $methodName): ReflectionMethod
{
$class = $this->reflectionClasses[$className] ?? null;
if ($class === null) {
$class = new ReflectionClass($className);
$this->reflectionClasses[$className] = $class;
}
return $class->getMethod($methodName);
}
/**
* Get the system API routes, formatted into a flat collection.
*/
protected function getFlatApiRoutes(): Collection
{
return collect(Route::getRoutes()->getRoutes())->filter(function ($route) {
return strpos($route->uri, 'api/') === 0;
})->map(function ($route) {
[$controller, $controllerMethod] = explode('@', $route->action['uses']);
$baseModelName = explode('.', explode('/', $route->uri)[1])[0];
$shortName = $baseModelName . '-' . $controllerMethod;
return [
'name' => $shortName,
'uri' => $route->uri,
'method' => $route->methods[0],
'controller' => $controller,
'controller_method' => $controllerMethod,
'controller_method_kebab' => Str::kebab($controllerMethod),
'base_model' => $baseModelName,
];
});
}
}

52
app/Api/ApiToken.php Normal file
View File

@@ -0,0 +1,52 @@
<?php
namespace BookStack\Api;
use BookStack\Auth\User;
use BookStack\Interfaces\Loggable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Carbon;
/**
* Class ApiToken.
*
* @property int $id
* @property string $token_id
* @property string $secret
* @property string $name
* @property Carbon $expires_at
* @property User $user
*/
class ApiToken extends Model implements Loggable
{
protected $fillable = ['name', 'expires_at'];
protected $casts = [
'expires_at' => 'date:Y-m-d',
];
/**
* Get the user that this token belongs to.
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
/**
* Get the default expiry value for an API token.
* Set to 100 years from now.
*/
public static function defaultExpiry(): string
{
return Carbon::now()->addYears(100)->format('Y-m-d');
}
/**
* @inheritdoc
*/
public function logDescriptor(): string
{
return "({$this->id}) {$this->name}; User: {$this->user->logDescriptor()}";
}
}

181
app/Api/ApiTokenGuard.php Normal file
View File

@@ -0,0 +1,181 @@
<?php
namespace BookStack\Api;
use BookStack\Auth\Access\LoginService;
use BookStack\Exceptions\ApiAuthException;
use Illuminate\Auth\GuardHelpers;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Hash;
use Symfony\Component\HttpFoundation\Request;
class ApiTokenGuard implements Guard
{
use GuardHelpers;
/**
* The request instance.
*/
protected $request;
/**
* @var LoginService
*/
protected $loginService;
/**
* The last auth exception thrown in this request.
*
* @var ApiAuthException
*/
protected $lastAuthException;
/**
* ApiTokenGuard constructor.
*/
public function __construct(Request $request, LoginService $loginService)
{
$this->request = $request;
$this->loginService = $loginService;
}
/**
* @inheritDoc
*/
public function user()
{
// Return the user if we've already retrieved them.
// Effectively a request-instance cache for this method.
if (!is_null($this->user)) {
return $this->user;
}
$user = null;
try {
$user = $this->getAuthorisedUserFromRequest();
} catch (ApiAuthException $exception) {
$this->lastAuthException = $exception;
}
$this->user = $user;
return $user;
}
/**
* Determine if current user is authenticated. If not, throw an exception.
*
* @throws ApiAuthException
*
* @return \Illuminate\Contracts\Auth\Authenticatable
*/
public function authenticate()
{
if (!is_null($user = $this->user())) {
return $user;
}
if ($this->lastAuthException) {
throw $this->lastAuthException;
}
throw new ApiAuthException('Unauthorized');
}
/**
* Check the API token in the request and fetch a valid authorised user.
*
* @throws ApiAuthException
*/
protected function getAuthorisedUserFromRequest(): Authenticatable
{
$authToken = trim($this->request->headers->get('Authorization', ''));
$this->validateTokenHeaderValue($authToken);
[$id, $secret] = explode(':', str_replace('Token ', '', $authToken));
$token = ApiToken::query()
->where('token_id', '=', $id)
->with(['user'])->first();
$this->validateToken($token, $secret);
if ($this->loginService->awaitingEmailConfirmation($token->user)) {
throw new ApiAuthException(trans('errors.email_confirmation_awaiting'));
}
return $token->user;
}
/**
* Validate the format of the token header value string.
*
* @throws ApiAuthException
*/
protected function validateTokenHeaderValue(string $authToken): void
{
if (empty($authToken)) {
throw new ApiAuthException(trans('errors.api_no_authorization_found'));
}
if (strpos($authToken, ':') === false || strpos($authToken, 'Token ') !== 0) {
throw new ApiAuthException(trans('errors.api_bad_authorization_format'));
}
}
/**
* Validate the given secret against the given token and ensure the token
* currently has access to the instance API.
*
* @throws ApiAuthException
*/
protected function validateToken(?ApiToken $token, string $secret): void
{
if ($token === null) {
throw new ApiAuthException(trans('errors.api_user_token_not_found'));
}
if (!Hash::check($secret, $token->secret)) {
throw new ApiAuthException(trans('errors.api_incorrect_token_secret'));
}
$now = Carbon::now();
if ($token->expires_at <= $now) {
throw new ApiAuthException(trans('errors.api_user_token_expired'), 403);
}
if (!$token->user->can('access-api')) {
throw new ApiAuthException(trans('errors.api_user_no_api_permission'), 403);
}
}
/**
* @inheritDoc
*/
public function validate(array $credentials = [])
{
if (empty($credentials['id']) || empty($credentials['secret'])) {
return false;
}
$token = ApiToken::query()
->where('token_id', '=', $credentials['id'])
->with(['user'])->first();
if ($token === null) {
return false;
}
return Hash::check($credentials['secret'], $token->secret);
}
/**
* "Log out" the currently authenticated user.
*/
public function logout()
{
$this->user = null;
}
}

View File

@@ -0,0 +1,141 @@
<?php
namespace BookStack\Api;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;
class ListingResponseBuilder
{
protected $query;
protected $request;
protected $fields;
protected $filterOperators = [
'eq' => '=',
'ne' => '!=',
'gt' => '>',
'lt' => '<',
'gte' => '>=',
'lte' => '<=',
'like' => 'like',
];
/**
* ListingResponseBuilder constructor.
*/
public function __construct(Builder $query, Request $request, array $fields)
{
$this->query = $query;
$this->request = $request;
$this->fields = $fields;
}
/**
* Get the response from this builder.
*/
public function toResponse()
{
$filteredQuery = $this->filterQuery($this->query);
$total = $filteredQuery->count();
$data = $this->fetchData($filteredQuery);
return response()->json([
'data' => $data,
'total' => $total,
]);
}
/**
* Fetch the data to return in the response.
*/
protected function fetchData(Builder $query): Collection
{
$query = $this->countAndOffsetQuery($query);
$query = $this->sortQuery($query);
return $query->get($this->fields);
}
/**
* Apply any filtering operations found in the request.
*/
protected function filterQuery(Builder $query): Builder
{
$query = clone $query;
$requestFilters = $this->request->get('filter', []);
if (!is_array($requestFilters)) {
return $query;
}
$queryFilters = collect($requestFilters)->map(function ($value, $key) {
return $this->requestFilterToQueryFilter($key, $value);
})->filter(function ($value) {
return !is_null($value);
})->values()->toArray();
return $query->where($queryFilters);
}
/**
* Convert a request filter query key/value pair into a [field, op, value] where condition.
*/
protected function requestFilterToQueryFilter($fieldKey, $value): ?array
{
$splitKey = explode(':', $fieldKey);
$field = $splitKey[0];
$filterOperator = $splitKey[1] ?? 'eq';
if (!in_array($field, $this->fields)) {
return null;
}
if (!in_array($filterOperator, array_keys($this->filterOperators))) {
$filterOperator = 'eq';
}
$queryOperator = $this->filterOperators[$filterOperator];
return [$field, $queryOperator, $value];
}
/**
* Apply sorting operations to the query from given parameters
* otherwise falling back to the first given field, ascending.
*/
protected function sortQuery(Builder $query): Builder
{
$query = clone $query;
$defaultSortName = $this->fields[0];
$direction = 'asc';
$sort = $this->request->get('sort', '');
if (strpos($sort, '-') === 0) {
$direction = 'desc';
}
$sortName = ltrim($sort, '+- ');
if (!in_array($sortName, $this->fields)) {
$sortName = $defaultSortName;
}
return $query->orderBy($sortName, $direction);
}
/**
* Apply count and offset for paging, based on params from the request while falling
* back to system defined default, taking the max limit into account.
*/
protected function countAndOffsetQuery(Builder $query): Builder
{
$query = clone $query;
$offset = max(0, $this->request->get('offset', 0));
$maxCount = config('api.max_item_count');
$count = $this->request->get('count', config('api.default_item_count'));
$count = max(min($maxCount, $count), 1);
return $query->skip($offset)->take($count);
}
}

23
app/Application.php Normal file
View File

@@ -0,0 +1,23 @@
<?php
namespace BookStack;
class Application extends \Illuminate\Foundation\Application
{
/**
* Get the path to the application configuration files.
*
* @param string $path Optionally, a path to append to the config path
*
* @return string
*/
public function configPath($path = '')
{
return $this->basePath
. DIRECTORY_SEPARATOR
. 'app'
. DIRECTORY_SEPARATOR
. 'Config'
. ($path ? DIRECTORY_SEPARATOR . $path : $path);
}
}

View File

@@ -1,39 +0,0 @@
<?php namespace BookStack;
class Attachment extends Ownable
{
protected $fillable = ['name', 'order'];
/**
* Get the downloadable file name for this upload.
* @return mixed|string
*/
public function getFileName()
{
if (str_contains($this->name, '.')) {
return $this->name;
}
return $this->name . '.' . $this->extension;
}
/**
* Get the page this file was uploaded to.
* @return Page
*/
public function page()
{
return $this->belongsTo(Page::class, 'uploaded_to');
}
/**
* Get the url of this file.
* @return string
*/
public function getUrl()
{
if ($this->external && strpos($this->path, 'http') !== 0) {
return $this->path;
}
return baseUrl('/attachments/' . $this->id);
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace BookStack\Auth\Access;
use BookStack\Auth\User;
use BookStack\Exceptions\ConfirmationEmailException;
use BookStack\Notifications\ConfirmEmail;
class EmailConfirmationService extends UserTokenService
{
protected $tokenTable = 'email_confirmations';
protected $expiryTime = 24;
/**
* Create new confirmation for a user,
* Also removes any existing old ones.
*
* @throws ConfirmationEmailException
*/
public function sendConfirmation(User $user)
{
if ($user->email_confirmed) {
throw new ConfirmationEmailException(trans('errors.email_already_confirmed'), '/login');
}
$this->deleteByUser($user);
$token = $this->createTokenForUser($user);
$user->notify(new ConfirmEmail($token));
}
/**
* Check if confirmation is required in this instance.
*/
public function confirmationRequired(): bool
{
return setting('registration-confirmation')
|| setting('registration-restrict');
}
}

View File

@@ -0,0 +1,76 @@
<?php
namespace BookStack\Auth\Access;
use BookStack\Auth\Role;
use BookStack\Auth\User;
use Illuminate\Support\Collection;
class ExternalAuthService
{
/**
* Check a role against an array of group names to see if it matches.
* Checked against role 'external_auth_id' if set otherwise the name of the role.
*/
protected function roleMatchesGroupNames(Role $role, array $groupNames): bool
{
if ($role->external_auth_id) {
return $this->externalIdMatchesGroupNames($role->external_auth_id, $groupNames);
}
$roleName = str_replace(' ', '-', trim(strtolower($role->display_name)));
return in_array($roleName, $groupNames);
}
/**
* Check if the given external auth ID string matches one of the given group names.
*/
protected function externalIdMatchesGroupNames(string $externalId, array $groupNames): bool
{
$externalAuthIds = explode(',', strtolower($externalId));
foreach ($externalAuthIds as $externalAuthId) {
if (in_array(trim($externalAuthId), $groupNames)) {
return true;
}
}
return false;
}
/**
* Match an array of group names to BookStack system roles.
* Formats group names to be lower-case and hyphenated.
*/
protected function matchGroupsToSystemsRoles(array $groupNames): Collection
{
foreach ($groupNames as $i => $groupName) {
$groupNames[$i] = str_replace(' ', '-', trim(strtolower($groupName)));
}
$roles = Role::query()->get(['id', 'external_auth_id', 'display_name']);
$matchedRoles = $roles->filter(function (Role $role) use ($groupNames) {
return $this->roleMatchesGroupNames($role, $groupNames);
});
return $matchedRoles->pluck('id');
}
/**
* Sync the groups to the user roles for the current user.
*/
public function syncWithGroups(User $user, array $userGroups): void
{
// Get the ids for the roles from the names
$groupsAsRoles = $this->matchGroupsToSystemsRoles($userGroups);
// Sync groups
if ($this->config['remove_from_groups']) {
$user->roles()->sync($groupsAsRoles);
$user->attachDefaultRole();
} else {
$user->roles()->syncWithoutDetaching($groupsAsRoles);
}
}
}

View File

@@ -0,0 +1,107 @@
<?php
namespace BookStack\Auth\Access;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\UserProvider;
class ExternalBaseUserProvider implements UserProvider
{
/**
* The user model.
*
* @var string
*/
protected $model;
/**
* LdapUserProvider constructor.
*
* @param $model
*/
public function __construct(string $model)
{
$this->model = $model;
}
/**
* Create a new instance of the model.
*
* @return \Illuminate\Database\Eloquent\Model
*/
public function createModel()
{
$class = '\\' . ltrim($this->model, '\\');
return new $class();
}
/**
* Retrieve a user by their unique identifier.
*
* @param mixed $identifier
*
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveById($identifier)
{
return $this->createModel()->newQuery()->find($identifier);
}
/**
* Retrieve a user by their unique identifier and "remember me" token.
*
* @param mixed $identifier
* @param string $token
*
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveByToken($identifier, $token)
{
return null;
}
/**
* Update the "remember me" token for the given user in storage.
*
* @param \Illuminate\Contracts\Auth\Authenticatable $user
* @param string $token
*
* @return void
*/
public function updateRememberToken(Authenticatable $user, $token)
{
//
}
/**
* Retrieve a user by the given credentials.
*
* @param array $credentials
*
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveByCredentials(array $credentials)
{
// Search current user base by looking up a uid
$model = $this->createModel();
return $model->newQuery()
->where('external_auth_id', $credentials['external_auth_id'])
->first();
}
/**
* Validate a user against the given credentials.
*
* @param \Illuminate\Contracts\Auth\Authenticatable $user
* @param array $credentials
*
* @return bool
*/
public function validateCredentials(Authenticatable $user, array $credentials)
{
// Should be done in the guard.
return false;
}
}

View File

@@ -0,0 +1,305 @@
<?php
namespace BookStack\Auth\Access\Guards;
use BookStack\Auth\Access\RegistrationService;
use Illuminate\Auth\GuardHelpers;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\StatefulGuard;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Session\Session;
/**
* Class BaseSessionGuard
* A base implementation of a session guard. Is a copy of the default Laravel
* guard with 'remember' functionality removed. Basic auth and event emission
* has also been removed to keep this simple. Designed to be extended by external
* Auth Guards.
*/
class ExternalBaseSessionGuard implements StatefulGuard
{
use GuardHelpers;
/**
* The name of the Guard. Typically "session".
*
* Corresponds to guard name in authentication configuration.
*
* @var string
*/
protected $name;
/**
* The user we last attempted to retrieve.
*
* @var \Illuminate\Contracts\Auth\Authenticatable
*/
protected $lastAttempted;
/**
* The session used by the guard.
*
* @var \Illuminate\Contracts\Session\Session
*/
protected $session;
/**
* Indicates if the logout method has been called.
*
* @var bool
*/
protected $loggedOut = false;
/**
* Service to handle common registration actions.
*
* @var RegistrationService
*/
protected $registrationService;
/**
* Create a new authentication guard.
*
* @return void
*/
public function __construct(string $name, UserProvider $provider, Session $session, RegistrationService $registrationService)
{
$this->name = $name;
$this->session = $session;
$this->provider = $provider;
$this->registrationService = $registrationService;
}
/**
* Get the currently authenticated user.
*
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function user()
{
if ($this->loggedOut) {
return;
}
// If we've already retrieved the user for the current request we can just
// return it back immediately. We do not want to fetch the user data on
// every call to this method because that would be tremendously slow.
if (!is_null($this->user)) {
return $this->user;
}
$id = $this->session->get($this->getName());
// First we will try to load the user using the
// identifier in the session if one exists.
if (!is_null($id)) {
$this->user = $this->provider->retrieveById($id);
}
return $this->user;
}
/**
* Get the ID for the currently authenticated user.
*
* @return int|null
*/
public function id()
{
if ($this->loggedOut) {
return;
}
return $this->user()
? $this->user()->getAuthIdentifier()
: $this->session->get($this->getName());
}
/**
* Log a user into the application without sessions or cookies.
*
* @param array $credentials
*
* @return bool
*/
public function once(array $credentials = [])
{
if ($this->validate($credentials)) {
$this->setUser($this->lastAttempted);
return true;
}
return false;
}
/**
* Log the given user ID into the application without sessions or cookies.
*
* @param mixed $id
*
* @return \Illuminate\Contracts\Auth\Authenticatable|false
*/
public function onceUsingId($id)
{
if (!is_null($user = $this->provider->retrieveById($id))) {
$this->setUser($user);
return $user;
}
return false;
}
/**
* Validate a user's credentials.
*
* @param array $credentials
*
* @return bool
*/
public function validate(array $credentials = [])
{
return false;
}
/**
* Attempt to authenticate a user using the given credentials.
*
* @param array $credentials
* @param bool $remember
*
* @return bool
*/
public function attempt(array $credentials = [], $remember = false)
{
return false;
}
/**
* Log the given user ID into the application.
*
* @param mixed $id
* @param bool $remember
*
* @return \Illuminate\Contracts\Auth\Authenticatable|false
*/
public function loginUsingId($id, $remember = false)
{
// Always return false as to disable this method,
// Logins should route through LoginService.
return false;
}
/**
* Log a user into the application.
*
* @param \Illuminate\Contracts\Auth\Authenticatable $user
* @param bool $remember
*
* @return void
*/
public function login(AuthenticatableContract $user, $remember = false)
{
$this->updateSession($user->getAuthIdentifier());
$this->setUser($user);
}
/**
* Update the session with the given ID.
*
* @param string $id
*
* @return void
*/
protected function updateSession($id)
{
$this->session->put($this->getName(), $id);
$this->session->migrate(true);
}
/**
* Log the user out of the application.
*
* @return void
*/
public function logout()
{
$this->clearUserDataFromStorage();
// Now we will clear the users out of memory so they are no longer available
// as the user is no longer considered as being signed into this
// application and should not be available here.
$this->user = null;
$this->loggedOut = true;
}
/**
* Remove the user data from the session and cookies.
*
* @return void
*/
protected function clearUserDataFromStorage()
{
$this->session->remove($this->getName());
}
/**
* Get the last user we attempted to authenticate.
*
* @return \Illuminate\Contracts\Auth\Authenticatable
*/
public function getLastAttempted()
{
return $this->lastAttempted;
}
/**
* Get a unique identifier for the auth session value.
*
* @return string
*/
public function getName()
{
return 'login_' . $this->name . '_' . sha1(static::class);
}
/**
* Determine if the user was authenticated via "remember me" cookie.
*
* @return bool
*/
public function viaRemember()
{
return false;
}
/**
* Return the currently cached user.
*
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function getUser()
{
return $this->user;
}
/**
* Set the current user.
*
* @param \Illuminate\Contracts\Auth\Authenticatable $user
*
* @return $this
*/
public function setUser(AuthenticatableContract $user)
{
$this->user = $user;
$this->loggedOut = false;
return $this;
}
}

View File

@@ -0,0 +1,133 @@
<?php
namespace BookStack\Auth\Access\Guards;
use BookStack\Auth\Access\LdapService;
use BookStack\Auth\Access\RegistrationService;
use BookStack\Auth\User;
use BookStack\Exceptions\LdapException;
use BookStack\Exceptions\LoginAttemptEmailNeededException;
use BookStack\Exceptions\LoginAttemptException;
use BookStack\Exceptions\UserRegistrationException;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Session\Session;
use Illuminate\Support\Str;
class LdapSessionGuard extends ExternalBaseSessionGuard
{
protected $ldapService;
/**
* LdapSessionGuard constructor.
*/
public function __construct(
$name,
UserProvider $provider,
Session $session,
LdapService $ldapService,
RegistrationService $registrationService
) {
$this->ldapService = $ldapService;
parent::__construct($name, $provider, $session, $registrationService);
}
/**
* Validate a user's credentials.
*
* @param array $credentials
*
* @throws LdapException
*
* @return bool
*/
public function validate(array $credentials = [])
{
$userDetails = $this->ldapService->getUserDetails($credentials['username']);
if (isset($userDetails['uid'])) {
$this->lastAttempted = $this->provider->retrieveByCredentials([
'external_auth_id' => $userDetails['uid'],
]);
}
return $this->ldapService->validateUserCredentials($userDetails, $credentials['password']);
}
/**
* Attempt to authenticate a user using the given credentials.
*
* @param array $credentials
* @param bool $remember
*
* @throws LoginAttemptException
* @throws LdapException
*
* @return bool
*/
public function attempt(array $credentials = [], $remember = false)
{
$username = $credentials['username'];
$userDetails = $this->ldapService->getUserDetails($username);
$user = null;
if (isset($userDetails['uid'])) {
$this->lastAttempted = $user = $this->provider->retrieveByCredentials([
'external_auth_id' => $userDetails['uid'],
]);
}
if (!$this->ldapService->validateUserCredentials($userDetails, $credentials['password'])) {
return false;
}
if (is_null($user)) {
try {
$user = $this->createNewFromLdapAndCreds($userDetails, $credentials);
} catch (UserRegistrationException $exception) {
throw new LoginAttemptException($exception->message);
}
}
// Sync LDAP groups if required
if ($this->ldapService->shouldSyncGroups()) {
$this->ldapService->syncGroups($user, $username);
}
// Attach avatar if non-existent
if (is_null($user->avatar)) {
$this->ldapService->saveAndAttachAvatar($user, $userDetails);
}
$this->login($user, $remember);
return true;
}
/**
* Create a new user from the given ldap credentials and login credentials.
*
* @throws LoginAttemptEmailNeededException
* @throws LoginAttemptException
* @throws UserRegistrationException
*/
protected function createNewFromLdapAndCreds(array $ldapUserDetails, array $credentials): User
{
$email = trim($ldapUserDetails['email'] ?: ($credentials['email'] ?? ''));
if (empty($email)) {
throw new LoginAttemptEmailNeededException();
}
$details = [
'name' => $ldapUserDetails['name'],
'email' => $ldapUserDetails['email'] ?: $credentials['email'],
'external_auth_id' => $ldapUserDetails['uid'],
'password' => Str::random(32),
];
$user = $this->registrationService->registerUser($details, null, false);
$this->ldapService->saveAndAttachAvatar($user, $ldapUserDetails);
return $user;
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace BookStack\Auth\Access\Guards;
/**
* Saml2 Session Guard.
*
* The saml2 login process is async in nature meaning it does not fit very well
* into the default laravel 'Guard' auth flow. Instead most of the logic is done
* via the Saml2 controller & Saml2Service. This class provides a safer, thin
* version of SessionGuard.
*/
class Saml2SessionGuard extends ExternalBaseSessionGuard
{
/**
* Validate a user's credentials.
*
* @param array $credentials
*
* @return bool
*/
public function validate(array $credentials = [])
{
return false;
}
/**
* Attempt to authenticate a user using the given credentials.
*
* @param array $credentials
* @param bool $remember
*
* @return bool
*/
public function attempt(array $credentials = [], $remember = false)
{
return false;
}
}

View File

@@ -1,18 +1,20 @@
<?php namespace BookStack\Services;
<?php
namespace BookStack\Auth\Access;
/**
* Class Ldap
* An object-orientated thin abstraction wrapper for common PHP LDAP functions.
* Allows the standard LDAP functions to be mocked for testing.
* @package BookStack\Services
*/
class Ldap
{
/**
* Connect to a LDAP server.
*
* @param string $hostName
* @param int $port
*
* @return resource
*/
public function connect($hostName, $port)
@@ -22,9 +24,11 @@ class Ldap
/**
* Set the value of a LDAP option for the given connection.
*
* @param resource $ldapConnection
* @param int $option
* @param mixed $value
* @param int $option
* @param mixed $value
*
* @return bool
*/
public function setOption($ldapConnection, $option, $value)
@@ -32,10 +36,20 @@ class Ldap
return ldap_set_option($ldapConnection, $option, $value);
}
/**
* Start TLS on the given LDAP connection.
*/
public function startTls($ldapConnection): bool
{
return ldap_start_tls($ldapConnection);
}
/**
* Set the version number for the given ldap connection.
*
* @param $ldapConnection
* @param $version
*
* @return bool
*/
public function setVersion($ldapConnection, $version)
@@ -45,10 +59,12 @@ class Ldap
/**
* Search LDAP tree using the provided filter.
*
* @param resource $ldapConnection
* @param string $baseDn
* @param string $filter
* @param array|null $attributes
*
* @return resource
*/
public function search($ldapConnection, $baseDn, $filter, array $attributes = null)
@@ -58,8 +74,10 @@ class Ldap
/**
* Get entries from an ldap search result.
*
* @param resource $ldapConnection
* @param resource $ldapSearchResult
*
* @return array
*/
public function getEntries($ldapConnection, $ldapSearchResult)
@@ -69,27 +87,59 @@ class Ldap
/**
* Search and get entries immediately.
*
* @param resource $ldapConnection
* @param string $baseDn
* @param string $filter
* @param array|null $attributes
*
* @return resource
*/
public function searchAndGetEntries($ldapConnection, $baseDn, $filter, array $attributes = null)
{
$search = $this->search($ldapConnection, $baseDn, $filter, $attributes);
return $this->getEntries($ldapConnection, $search);
}
/**
* Bind to LDAP directory.
*
* @param resource $ldapConnection
* @param string $bindRdn
* @param string $bindPassword
*
* @return bool
*/
public function bind($ldapConnection, $bindRdn = null, $bindPassword = null)
{
return ldap_bind($ldapConnection, $bindRdn, $bindPassword);
}
/**
* Explode a LDAP dn string into an array of components.
*
* @param string $dn
* @param int $withAttrib
*
* @return array
*/
public function explodeDn(string $dn, int $withAttrib)
{
return ldap_explode_dn($dn, $withAttrib);
}
/**
* Escape a string for use in an LDAP filter.
*
* @param string $value
* @param string $ignore
* @param int $flags
*
* @return string
*/
public function escape(string $value, string $ignore = '', int $flags = 0)
{
return ldap_escape($value, $ignore, $flags);
}
}

View File

@@ -0,0 +1,397 @@
<?php
namespace BookStack\Auth\Access;
use BookStack\Auth\User;
use BookStack\Exceptions\JsonDebugException;
use BookStack\Exceptions\LdapException;
use BookStack\Uploads\UserAvatars;
use ErrorException;
use Illuminate\Support\Facades\Log;
/**
* Class LdapService
* Handles any app-specific LDAP tasks.
*/
class LdapService extends ExternalAuthService
{
protected $ldap;
protected $ldapConnection;
protected $userAvatars;
protected $config;
protected $enabled;
/**
* LdapService constructor.
*/
public function __construct(Ldap $ldap, UserAvatars $userAvatars)
{
$this->ldap = $ldap;
$this->userAvatars = $userAvatars;
$this->config = config('services.ldap');
$this->enabled = config('auth.method') === 'ldap';
}
/**
* Check if groups should be synced.
*
* @return bool
*/
public function shouldSyncGroups()
{
return $this->enabled && $this->config['user_to_groups'] !== false;
}
/**
* Search for attributes for a specific user on the ldap.
*
* @throws LdapException
*/
private function getUserWithAttributes(string $userName, array $attributes): ?array
{
$ldapConnection = $this->getConnection();
$this->bindSystemUser($ldapConnection);
// Clean attributes
foreach ($attributes as $index => $attribute) {
if (strpos($attribute, 'BIN;') === 0) {
$attributes[$index] = substr($attribute, strlen('BIN;'));
}
}
// Find user
$userFilter = $this->buildFilter($this->config['user_filter'], ['user' => $userName]);
$baseDn = $this->config['base_dn'];
$followReferrals = $this->config['follow_referrals'] ? 1 : 0;
$this->ldap->setOption($ldapConnection, LDAP_OPT_REFERRALS, $followReferrals);
$users = $this->ldap->searchAndGetEntries($ldapConnection, $baseDn, $userFilter, $attributes);
if ($users['count'] === 0) {
return null;
}
return $users[0];
}
/**
* Get the details of a user from LDAP using the given username.
* User found via configurable user filter.
*
* @throws LdapException
*/
public function getUserDetails(string $userName): ?array
{
$idAttr = $this->config['id_attribute'];
$emailAttr = $this->config['email_attribute'];
$displayNameAttr = $this->config['display_name_attribute'];
$thumbnailAttr = $this->config['thumbnail_attribute'];
$user = $this->getUserWithAttributes($userName, array_filter([
'cn', 'dn', $idAttr, $emailAttr, $displayNameAttr, $thumbnailAttr,
]));
if (is_null($user)) {
return null;
}
$userCn = $this->getUserResponseProperty($user, 'cn', null);
$formatted = [
'uid' => $this->getUserResponseProperty($user, $idAttr, $user['dn']),
'name' => $this->getUserResponseProperty($user, $displayNameAttr, $userCn),
'dn' => $user['dn'],
'email' => $this->getUserResponseProperty($user, $emailAttr, null),
'avatar'=> $thumbnailAttr ? $this->getUserResponseProperty($user, $thumbnailAttr, null) : null,
];
if ($this->config['dump_user_details']) {
throw new JsonDebugException([
'details_from_ldap' => $user,
'details_bookstack_parsed' => $formatted,
]);
}
return $formatted;
}
/**
* Get a property from an LDAP user response fetch.
* Handles properties potentially being part of an array.
* If the given key is prefixed with 'BIN;', that indicator will be stripped
* from the key and any fetched values will be converted from binary to hex.
*/
protected function getUserResponseProperty(array $userDetails, string $propertyKey, $defaultValue)
{
$isBinary = strpos($propertyKey, 'BIN;') === 0;
$propertyKey = strtolower($propertyKey);
$value = $defaultValue;
if ($isBinary) {
$propertyKey = substr($propertyKey, strlen('BIN;'));
}
if (isset($userDetails[$propertyKey])) {
$value = (is_array($userDetails[$propertyKey]) ? $userDetails[$propertyKey][0] : $userDetails[$propertyKey]);
if ($isBinary) {
$value = bin2hex($value);
}
}
return $value;
}
/**
* Check if the given credentials are valid for the given user.
*
* @throws LdapException
*/
public function validateUserCredentials(?array $ldapUserDetails, string $password): bool
{
if (is_null($ldapUserDetails)) {
return false;
}
$ldapConnection = $this->getConnection();
try {
$ldapBind = $this->ldap->bind($ldapConnection, $ldapUserDetails['dn'], $password);
} catch (ErrorException $e) {
$ldapBind = false;
}
return $ldapBind;
}
/**
* Bind the system user to the LDAP connection using the given credentials
* otherwise anonymous access is attempted.
*
* @param $connection
*
* @throws LdapException
*/
protected function bindSystemUser($connection)
{
$ldapDn = $this->config['dn'];
$ldapPass = $this->config['pass'];
$isAnonymous = ($ldapDn === false || $ldapPass === false);
if ($isAnonymous) {
$ldapBind = $this->ldap->bind($connection);
} else {
$ldapBind = $this->ldap->bind($connection, $ldapDn, $ldapPass);
}
if (!$ldapBind) {
throw new LdapException(($isAnonymous ? trans('errors.ldap_fail_anonymous') : trans('errors.ldap_fail_authed')));
}
}
/**
* Get the connection to the LDAP server.
* Creates a new connection if one does not exist.
*
* @throws LdapException
*
* @return resource
*/
protected function getConnection()
{
if ($this->ldapConnection !== null) {
return $this->ldapConnection;
}
// Check LDAP extension in installed
if (!function_exists('ldap_connect') && config('app.env') !== 'testing') {
throw new LdapException(trans('errors.ldap_extension_not_installed'));
}
// Disable certificate verification.
// This option works globally and must be set before a connection is created.
if ($this->config['tls_insecure']) {
$this->ldap->setOption(null, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_NEVER);
}
$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'));
}
// Set any required options
if ($this->config['version']) {
$this->ldap->setVersion($ldapConnection, $this->config['version']);
}
// Start and verify TLS if it's enabled
if ($this->config['start_tls']) {
$started = $this->ldap->startTls($ldapConnection);
if (!$started) {
throw new LdapException('Could not start TLS connection');
}
}
$this->ldapConnection = $ldapConnection;
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'.
*/
protected function parseServerString(string $serverString): array
{
$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.
*/
protected function buildFilter(string $filterString, array $attrs): string
{
$newAttrs = [];
foreach ($attrs as $key => $attrText) {
$newKey = '${' . $key . '}';
$newAttrs[$newKey] = $this->ldap->escape($attrText);
}
return strtr($filterString, $newAttrs);
}
/**
* Get the groups a user is a part of on ldap.
*
* @throws LdapException
*/
public function getUserGroups(string $userName): array
{
$groupsAttr = $this->config['group_attribute'];
$user = $this->getUserWithAttributes($userName, [$groupsAttr]);
if ($user === null) {
return [];
}
$userGroups = $this->groupFilter($user);
$userGroups = $this->getGroupsRecursive($userGroups, []);
return $userGroups;
}
/**
* Get the parent groups of an array of groups.
*
* @throws LdapException
*/
private function getGroupsRecursive(array $groupsArray, array $checked): array
{
$groupsToAdd = [];
foreach ($groupsArray as $groupName) {
if (in_array($groupName, $checked)) {
continue;
}
$parentGroups = $this->getGroupGroups($groupName);
$groupsToAdd = array_merge($groupsToAdd, $parentGroups);
$checked[] = $groupName;
}
$groupsArray = array_unique(array_merge($groupsArray, $groupsToAdd), SORT_REGULAR);
if (empty($groupsToAdd)) {
return $groupsArray;
}
return $this->getGroupsRecursive($groupsArray, $checked);
}
/**
* Get the parent groups of a single group.
*
* @throws LdapException
*/
private function getGroupGroups(string $groupName): array
{
$ldapConnection = $this->getConnection();
$this->bindSystemUser($ldapConnection);
$followReferrals = $this->config['follow_referrals'] ? 1 : 0;
$this->ldap->setOption($ldapConnection, LDAP_OPT_REFERRALS, $followReferrals);
$baseDn = $this->config['base_dn'];
$groupsAttr = strtolower($this->config['group_attribute']);
$groupFilter = 'CN=' . $this->ldap->escape($groupName);
$groups = $this->ldap->searchAndGetEntries($ldapConnection, $baseDn, $groupFilter, [$groupsAttr]);
if ($groups['count'] === 0) {
return [];
}
return $this->groupFilter($groups[0]);
}
/**
* Filter out LDAP CN and DN language in a ldap search return.
* Gets the base CN (common name) of the string.
*/
protected function groupFilter(array $userGroupSearchResponse): array
{
$groupsAttr = strtolower($this->config['group_attribute']);
$ldapGroups = [];
$count = 0;
if (isset($userGroupSearchResponse[$groupsAttr]['count'])) {
$count = (int) $userGroupSearchResponse[$groupsAttr]['count'];
}
for ($i = 0; $i < $count; $i++) {
$dnComponents = $this->ldap->explodeDn($userGroupSearchResponse[$groupsAttr][$i], 1);
if (!in_array($dnComponents[0], $ldapGroups)) {
$ldapGroups[] = $dnComponents[0];
}
}
return $ldapGroups;
}
/**
* Sync the LDAP groups to the user roles for the current user.
*
* @throws LdapException
*/
public function syncGroups(User $user, string $username)
{
$userLdapGroups = $this->getUserGroups($username);
$this->syncWithGroups($user, $userLdapGroups);
}
/**
* Save and attach an avatar image, if found in the ldap details, and attach
* to the given user model.
*/
public function saveAndAttachAvatar(User $user, array $ldapUserDetails): void
{
if (is_null(config('services.ldap.thumbnail_attribute')) || is_null($ldapUserDetails['avatar'])) {
return;
}
try {
$imageData = $ldapUserDetails['avatar'];
$this->userAvatars->assignToUserFromExistingData($user, $imageData, 'jpg');
} catch (\Exception $exception) {
Log::info("Failed to use avatar image from LDAP data for user id {$user->id}");
}
}
}

View File

@@ -0,0 +1,164 @@
<?php
namespace BookStack\Auth\Access;
use BookStack\Actions\ActivityType;
use BookStack\Auth\Access\Mfa\MfaSession;
use BookStack\Auth\User;
use BookStack\Exceptions\StoppedAuthenticationException;
use BookStack\Facades\Activity;
use BookStack\Facades\Theme;
use BookStack\Theming\ThemeEvents;
use Exception;
class LoginService
{
protected const LAST_LOGIN_ATTEMPTED_SESSION_KEY = 'auth-login-last-attempted';
protected $mfaSession;
protected $emailConfirmationService;
public function __construct(MfaSession $mfaSession, EmailConfirmationService $emailConfirmationService)
{
$this->mfaSession = $mfaSession;
$this->emailConfirmationService = $emailConfirmationService;
}
/**
* Log the given user into the system.
* Will start a login of the given user but will prevent if there's
* a reason to (MFA or Unconfirmed Email).
* Returns a boolean to indicate the current login result.
*
* @throws StoppedAuthenticationException
*/
public function login(User $user, string $method, bool $remember = false): void
{
if ($this->awaitingEmailConfirmation($user) || $this->needsMfaVerification($user)) {
$this->setLastLoginAttemptedForUser($user, $method, $remember);
throw new StoppedAuthenticationException($user, $this);
}
$this->clearLastLoginAttempted();
auth()->login($user, $remember);
Activity::add(ActivityType::AUTH_LOGIN, "{$method}; {$user->logDescriptor()}");
Theme::dispatch(ThemeEvents::AUTH_LOGIN, $method, $user);
// Authenticate on all session guards if a likely admin
if ($user->can('users-manage') && $user->can('user-roles-manage')) {
$guards = ['standard', 'ldap', 'saml2'];
foreach ($guards as $guard) {
auth($guard)->login($user);
}
}
}
/**
* Reattempt a system login after a previous stopped attempt.
*
* @throws Exception
*/
public function reattemptLoginFor(User $user)
{
if ($user->id !== ($this->getLastLoginAttemptUser()->id ?? null)) {
throw new Exception('Login reattempt user does align with current session state');
}
$lastLoginDetails = $this->getLastLoginAttemptDetails();
$this->login($user, $lastLoginDetails['method'], $lastLoginDetails['remember'] ?? false);
}
/**
* Get the last user that was attempted to be logged in.
* Only exists if the last login attempt had correct credentials
* but had been prevented by a secondary factor.
*/
public function getLastLoginAttemptUser(): ?User
{
$id = $this->getLastLoginAttemptDetails()['user_id'];
return User::query()->where('id', '=', $id)->first();
}
/**
* Get the details of the last login attempt.
* Checks upon a ttl of about 1 hour since that last attempted login.
*
* @return array{user_id: ?string, method: ?string, remember: bool}
*/
protected function getLastLoginAttemptDetails(): array
{
$value = session()->get(self::LAST_LOGIN_ATTEMPTED_SESSION_KEY);
if (!$value) {
return ['user_id' => null, 'method' => null];
}
[$id, $method, $remember, $time] = explode(':', $value);
$hourAgo = time() - (60 * 60);
if ($time < $hourAgo) {
$this->clearLastLoginAttempted();
return ['user_id' => null, 'method' => null];
}
return ['user_id' => $id, 'method' => $method, 'remember' => boolval($remember)];
}
/**
* Set the last login attempted user.
* Must be only used when credentials are correct and a login could be
* achieved but a secondary factor has stopped the login.
*/
protected function setLastLoginAttemptedForUser(User $user, string $method, bool $remember)
{
session()->put(
self::LAST_LOGIN_ATTEMPTED_SESSION_KEY,
implode(':', [$user->id, $method, $remember, time()])
);
}
/**
* Clear the last login attempted session value.
*/
protected function clearLastLoginAttempted(): void
{
session()->remove(self::LAST_LOGIN_ATTEMPTED_SESSION_KEY);
}
/**
* Check if MFA verification is needed.
*/
public function needsMfaVerification(User $user): bool
{
return !$this->mfaSession->isVerifiedForUser($user) && $this->mfaSession->isRequiredForUser($user);
}
/**
* Check if the given user is awaiting email confirmation.
*/
public function awaitingEmailConfirmation(User $user): bool
{
return $this->emailConfirmationService->confirmationRequired() && !$user->email_confirmed;
}
/**
* Attempt the login of a user using the given credentials.
* Meant to mirror Laravel's default guard 'attempt' method
* but in a manner that always routes through our login system.
* May interrupt the flow if extra authentication requirements are imposed.
*
* @throws StoppedAuthenticationException
*/
public function attempt(array $credentials, string $method, bool $remember = false): bool
{
$result = auth()->attempt($credentials, $remember);
if ($result) {
$user = auth()->user();
auth()->logout();
$this->login($user, $method, $remember);
}
return $result;
}
}

View File

@@ -0,0 +1,62 @@
<?php
namespace BookStack\Auth\Access\Mfa;
use Illuminate\Support\Str;
class BackupCodeService
{
/**
* Generate a new set of 16 backup codes.
*/
public function generateNewSet(): array
{
$codes = [];
while (count($codes) < 16) {
$code = Str::random(5) . '-' . Str::random(5);
if (!in_array($code, $codes)) {
$codes[] = strtolower($code);
}
}
return $codes;
}
/**
* Check if the given code matches one of the available options.
*/
public function inputCodeExistsInSet(string $code, string $codeSet): bool
{
$cleanCode = $this->cleanInputCode($code);
$codes = json_decode($codeSet);
return in_array($cleanCode, $codes);
}
/**
* Remove the given input code from the given available options.
* Will return a JSON string containing the codes.
*/
public function removeInputCodeFromSet(string $code, string $codeSet): string
{
$cleanCode = $this->cleanInputCode($code);
$codes = json_decode($codeSet);
$pos = array_search($cleanCode, $codes, true);
array_splice($codes, $pos, 1);
return json_encode($codes);
}
/**
* Count the number of codes in the given set.
*/
public function countCodesInSet(string $codeSet): int
{
return count(json_decode($codeSet));
}
protected function cleanInputCode(string $code): string
{
return strtolower(str_replace(' ', '-', trim($code)));
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace BookStack\Auth\Access\Mfa;
use BookStack\Auth\User;
class MfaSession
{
/**
* Check if MFA is required for the given user.
*/
public function isRequiredForUser(User $user): bool
{
// TODO - Test both these cases
return $user->mfaValues()->exists() || $this->userRoleEnforcesMfa($user);
}
/**
* Check if the given user is pending MFA setup.
* (MFA required but not yet configured).
*/
public function isPendingMfaSetup(User $user): bool
{
return $this->isRequiredForUser($user) && !$user->mfaValues()->exists();
}
/**
* Check if a role of the given user enforces MFA.
*/
protected function userRoleEnforcesMfa(User $user): bool
{
return $user->roles()
->where('mfa_enforced', '=', true)
->exists();
}
/**
* Check if the current MFA session has already been verified for the given user.
*/
public function isVerifiedForUser(User $user): bool
{
return session()->get($this->getMfaVerifiedSessionKey($user)) === 'true';
}
/**
* Mark the current session as MFA-verified.
*/
public function markVerifiedForUser(User $user): void
{
session()->put($this->getMfaVerifiedSessionKey($user), 'true');
}
/**
* Get the session key in which the MFA verification status is stored.
*/
protected function getMfaVerifiedSessionKey(User $user): string
{
return 'mfa-verification-passed:' . $user->id;
}
}

View File

@@ -0,0 +1,76 @@
<?php
namespace BookStack\Auth\Access\Mfa;
use BookStack\Auth\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
/**
* @property int $id
* @property int $user_id
* @property string $method
* @property string $value
* @property Carbon $created_at
* @property Carbon $updated_at
*/
class MfaValue extends Model
{
protected static $unguarded = true;
const METHOD_TOTP = 'totp';
const METHOD_BACKUP_CODES = 'backup_codes';
/**
* Get all the MFA methods available.
*/
public static function allMethods(): array
{
return [self::METHOD_TOTP, self::METHOD_BACKUP_CODES];
}
/**
* Upsert a new MFA value for the given user and method
* using the provided value.
*/
public static function upsertWithValue(User $user, string $method, string $value): void
{
/** @var MfaValue $mfaVal */
$mfaVal = static::query()->firstOrNew([
'user_id' => $user->id,
'method' => $method,
]);
$mfaVal->setValue($value);
$mfaVal->save();
}
/**
* Easily get the decrypted MFA value for the given user and method.
*/
public static function getValueForUser(User $user, string $method): ?string
{
/** @var MfaValue $mfaVal */
$mfaVal = static::query()
->where('user_id', '=', $user->id)
->where('method', '=', $method)
->first();
return $mfaVal ? $mfaVal->getValue() : null;
}
/**
* Decrypt the value attribute upon access.
*/
protected function getValue(): string
{
return decrypt($this->value);
}
/**
* Encrypt the value attribute upon access.
*/
protected function setValue($value): void
{
$this->value = encrypt($value);
}
}

View File

@@ -0,0 +1,72 @@
<?php
namespace BookStack\Auth\Access\Mfa;
use BaconQrCode\Renderer\Color\Rgb;
use BaconQrCode\Renderer\Image\SvgImageBackEnd;
use BaconQrCode\Renderer\ImageRenderer;
use BaconQrCode\Renderer\RendererStyle\Fill;
use BaconQrCode\Renderer\RendererStyle\RendererStyle;
use BaconQrCode\Writer;
use PragmaRX\Google2FA\Google2FA;
use PragmaRX\Google2FA\Support\Constants;
class TotpService
{
protected $google2fa;
public function __construct(Google2FA $google2fa)
{
$this->google2fa = $google2fa;
// Use SHA1 as a default, Personal testing of other options in 2021 found
// many apps lack support for other algorithms yet still will scan
// the code causing a confusing UX.
$this->google2fa->setAlgorithm(Constants::SHA1);
}
/**
* Generate a new totp secret key.
*/
public function generateSecret(): string
{
/** @noinspection PhpUnhandledExceptionInspection */
return $this->google2fa->generateSecretKey();
}
/**
* Generate a TOTP URL from secret key.
*/
public function generateUrl(string $secret): string
{
return $this->google2fa->getQRCodeUrl(
setting('app-name'),
user()->email,
$secret
);
}
/**
* Generate a QR code to display a TOTP URL.
*/
public function generateQrCodeSvg(string $url): string
{
$color = Fill::uniformColor(new Rgb(255, 255, 255), new Rgb(32, 110, 167));
return (new Writer(
new ImageRenderer(
new RendererStyle(192, 0, null, null, $color),
new SvgImageBackEnd()
)
))->writeString($url);
}
/**
* Verify that the user provided code is valid for the secret.
* The secret must be known, not user-provided.
*/
public function verifyCode(string $code, string $secret): bool
{
/** @noinspection PhpUnhandledExceptionInspection */
return $this->google2fa->verifyKey($secret, $code);
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace BookStack\Auth\Access\Mfa;
use Illuminate\Contracts\Validation\Rule;
class TotpValidationRule implements Rule
{
protected $secret;
protected $totpService;
/**
* Create a new rule instance.
* Takes the TOTP secret that must be system provided, not user provided.
*/
public function __construct(string $secret)
{
$this->secret = $secret;
$this->totpService = app()->make(TotpService::class);
}
/**
* Determine if the validation rule passes.
*/
public function passes($attribute, $value)
{
return $this->totpService->verifyCode($value, $this->secret);
}
/**
* Get the validation error message.
*/
public function message()
{
return trans('validation.totp');
}
}

View File

@@ -0,0 +1,121 @@
<?php
namespace BookStack\Auth\Access;
use BookStack\Actions\ActivityType;
use BookStack\Auth\SocialAccount;
use BookStack\Auth\User;
use BookStack\Auth\UserRepo;
use BookStack\Exceptions\UserRegistrationException;
use BookStack\Facades\Activity;
use BookStack\Facades\Theme;
use BookStack\Theming\ThemeEvents;
use Exception;
class RegistrationService
{
protected $userRepo;
protected $emailConfirmationService;
/**
* RegistrationService constructor.
*/
public function __construct(UserRepo $userRepo, EmailConfirmationService $emailConfirmationService)
{
$this->userRepo = $userRepo;
$this->emailConfirmationService = $emailConfirmationService;
}
/**
* Check whether or not registrations are allowed in the app settings.
*
* @throws UserRegistrationException
*/
public function ensureRegistrationAllowed()
{
if (!$this->registrationAllowed()) {
throw new UserRegistrationException(trans('auth.registrations_disabled'), '/login');
}
}
/**
* Check if standard BookStack User registrations are currently allowed.
* Does not prevent external-auth based registration.
*/
protected function registrationAllowed(): bool
{
$authMethod = config('auth.method');
$authMethodsWithRegistration = ['standard'];
return in_array($authMethod, $authMethodsWithRegistration) && setting('registration-enabled');
}
/**
* The registrations flow for all users.
*
* @throws UserRegistrationException
*/
public function registerUser(array $userData, ?SocialAccount $socialAccount = null, bool $emailConfirmed = false): User
{
$userEmail = $userData['email'];
// Email restriction
$this->ensureEmailDomainAllowed($userEmail);
// Ensure user does not already exist
$alreadyUser = !is_null($this->userRepo->getByEmail($userEmail));
if ($alreadyUser) {
throw new UserRegistrationException(trans('errors.error_user_exists_different_creds', ['email' => $userEmail]), '/login');
}
// Create the user
$newUser = $this->userRepo->registerNew($userData, $emailConfirmed);
// Assign social account if given
if ($socialAccount) {
$newUser->socialAccounts()->save($socialAccount);
}
Activity::add(ActivityType::AUTH_REGISTER, $socialAccount ?? $newUser);
Theme::dispatch(ThemeEvents::AUTH_REGISTER, $socialAccount ? $socialAccount->driver : auth()->getDefaultDriver(), $newUser);
// Start email confirmation flow if required
if ($this->emailConfirmationService->confirmationRequired() && !$emailConfirmed) {
$newUser->save();
try {
$this->emailConfirmationService->sendConfirmation($newUser);
session()->flash('sent-email-confirmation', true);
} catch (Exception $e) {
$message = trans('auth.email_confirm_send_error');
throw new UserRegistrationException($message, '/register/confirm');
}
}
return $newUser;
}
/**
* Ensure that the given email meets any active email domain registration restrictions.
* Throws if restrictions are active and the email does not match an allowed domain.
*
* @throws UserRegistrationException
*/
protected function ensureEmailDomainAllowed(string $userEmail): void
{
$registrationRestrict = setting('registration-restrict');
if (!$registrationRestrict) {
return;
}
$restrictedEmailDomains = explode(',', str_replace(' ', '', $registrationRestrict));
$userEmailDomain = $domain = mb_substr(mb_strrchr($userEmail, '@'), 1);
if (!in_array($userEmailDomain, $restrictedEmailDomains)) {
$redirect = $this->registrationAllowed() ? '/register' : '/login';
throw new UserRegistrationException(trans('auth.registration_email_domain_invalid'), $redirect);
}
}
}

View File

@@ -0,0 +1,394 @@
<?php
namespace BookStack\Auth\Access;
use BookStack\Auth\User;
use BookStack\Exceptions\JsonDebugException;
use BookStack\Exceptions\SamlException;
use BookStack\Exceptions\StoppedAuthenticationException;
use BookStack\Exceptions\UserRegistrationException;
use Exception;
use Illuminate\Support\Str;
use OneLogin\Saml2\Auth;
use OneLogin\Saml2\Error;
use OneLogin\Saml2\IdPMetadataParser;
use OneLogin\Saml2\ValidationError;
/**
* Class Saml2Service
* Handles any app-specific SAML tasks.
*/
class Saml2Service extends ExternalAuthService
{
protected $config;
protected $registrationService;
protected $loginService;
/**
* Saml2Service constructor.
*/
public function __construct(RegistrationService $registrationService, LoginService $loginService)
{
$this->config = config('saml2');
$this->registrationService = $registrationService;
$this->loginService = $loginService;
}
/**
* Initiate a login flow.
*
* @throws Error
*/
public function login(): array
{
$toolKit = $this->getToolkit();
$returnRoute = url('/saml2/acs');
return [
'url' => $toolKit->login($returnRoute, [], false, false, true),
'id' => $toolKit->getLastRequestID(),
];
}
/**
* Initiate a logout flow.
*
* @throws Error
*/
public function logout(): array
{
$toolKit = $this->getToolkit();
$returnRoute = url('/');
try {
$url = $toolKit->logout($returnRoute, [], null, null, true);
$id = $toolKit->getLastRequestID();
} catch (Error $error) {
if ($error->getCode() !== Error::SAML_SINGLE_LOGOUT_NOT_SUPPORTED) {
throw $error;
}
$this->actionLogout();
$url = '/';
$id = null;
}
return ['url' => $url, 'id' => $id];
}
/**
* Process the ACS response from the idp and return the
* matching, or new if registration active, user matched to the idp.
* Returns null if not authenticated.
*
* @throws Error
* @throws SamlException
* @throws ValidationError
* @throws JsonDebugException
* @throws UserRegistrationException
*/
public function processAcsResponse(?string $requestId): ?User
{
$toolkit = $this->getToolkit();
$toolkit->processResponse($requestId);
$errors = $toolkit->getErrors();
if (!empty($errors)) {
throw new Error(
'Invalid ACS Response: ' . implode(', ', $errors)
);
}
if (!$toolkit->isAuthenticated()) {
return null;
}
$attrs = $toolkit->getAttributes();
$id = $toolkit->getNameId();
return $this->processLoginCallback($id, $attrs);
}
/**
* Process a response for the single logout service.
*
* @throws Error
*/
public function processSlsResponse(?string $requestId): ?string
{
$toolkit = $this->getToolkit();
$redirect = $toolkit->processSLO(true, $requestId, false, null, true);
$errors = $toolkit->getErrors();
if (!empty($errors)) {
throw new Error(
'Invalid SLS Response: ' . implode(', ', $errors)
);
}
$this->actionLogout();
return $redirect;
}
/**
* Do the required actions to log a user out.
*/
protected function actionLogout()
{
auth()->logout();
session()->invalidate();
}
/**
* Get the metadata for this service provider.
*
* @throws Error
*/
public function metadata(): string
{
$toolKit = $this->getToolkit();
$settings = $toolKit->getSettings();
$metadata = $settings->getSPMetadata();
$errors = $settings->validateMetadata($metadata);
if (!empty($errors)) {
throw new Error(
'Invalid SP metadata: ' . implode(', ', $errors),
Error::METADATA_SP_INVALID
);
}
return $metadata;
}
/**
* Load the underlying Onelogin SAML2 toolkit.
*
* @throws Error
* @throws Exception
*/
protected function getToolkit(): Auth
{
$settings = $this->config['onelogin'];
$overrides = $this->config['onelogin_overrides'] ?? [];
if ($overrides && is_string($overrides)) {
$overrides = json_decode($overrides, true);
}
$metaDataSettings = [];
if ($this->config['autoload_from_metadata']) {
$metaDataSettings = IdPMetadataParser::parseRemoteXML($settings['idp']['entityId']);
}
$spSettings = $this->loadOneloginServiceProviderDetails();
$settings = array_replace_recursive($settings, $spSettings, $metaDataSettings, $overrides);
return new Auth($settings);
}
/**
* Load dynamic service provider options required by the onelogin toolkit.
*/
protected function loadOneloginServiceProviderDetails(): array
{
$spDetails = [
'entityId' => url('/saml2/metadata'),
'assertionConsumerService' => [
'url' => url('/saml2/acs'),
],
'singleLogoutService' => [
'url' => url('/saml2/sls'),
],
];
return [
'baseurl' => url('/saml2'),
'sp' => $spDetails,
];
}
/**
* Check if groups should be synced.
*/
protected function shouldSyncGroups(): bool
{
return $this->config['user_to_groups'] !== false;
}
/**
* Calculate the display name.
*/
protected function getUserDisplayName(array $samlAttributes, string $defaultValue): string
{
$displayNameAttr = $this->config['display_name_attributes'];
$displayName = [];
foreach ($displayNameAttr as $dnAttr) {
$dnComponent = $this->getSamlResponseAttribute($samlAttributes, $dnAttr, null);
if ($dnComponent !== null) {
$displayName[] = $dnComponent;
}
}
if (count($displayName) == 0) {
$displayName = $defaultValue;
} else {
$displayName = implode(' ', $displayName);
}
return $displayName;
}
/**
* Get the value to use as the external id saved in BookStack
* used to link the user to an existing BookStack DB user.
*/
protected function getExternalId(array $samlAttributes, string $defaultValue)
{
$userNameAttr = $this->config['external_id_attribute'];
if ($userNameAttr === null) {
return $defaultValue;
}
return $this->getSamlResponseAttribute($samlAttributes, $userNameAttr, $defaultValue);
}
/**
* Extract the details of a user from a SAML response.
*/
protected function getUserDetails(string $samlID, $samlAttributes): array
{
$emailAttr = $this->config['email_attribute'];
$externalId = $this->getExternalId($samlAttributes, $samlID);
$defaultEmail = filter_var($samlID, FILTER_VALIDATE_EMAIL) ? $samlID : null;
$email = $this->getSamlResponseAttribute($samlAttributes, $emailAttr, $defaultEmail);
return [
'external_id' => $externalId,
'name' => $this->getUserDisplayName($samlAttributes, $externalId),
'email' => $email,
'saml_id' => $samlID,
];
}
/**
* Get the groups a user is a part of from the SAML response.
*/
public function getUserGroups(array $samlAttributes): array
{
$groupsAttr = $this->config['group_attribute'];
$userGroups = $samlAttributes[$groupsAttr] ?? null;
if (!is_array($userGroups)) {
$userGroups = [];
}
return $userGroups;
}
/**
* For an array of strings, return a default for an empty array,
* a string for an array with one element and the full array for
* more than one element.
*/
protected function simplifyValue(array $data, $defaultValue)
{
switch (count($data)) {
case 0:
$data = $defaultValue;
break;
case 1:
$data = $data[0];
break;
}
return $data;
}
/**
* Get a property from an SAML response.
* Handles properties potentially being an array.
*/
protected function getSamlResponseAttribute(array $samlAttributes, string $propertyKey, $defaultValue)
{
if (isset($samlAttributes[$propertyKey])) {
return $this->simplifyValue($samlAttributes[$propertyKey], $defaultValue);
}
return $defaultValue;
}
/**
* Get the user from the database for the specified details.
*
* @throws UserRegistrationException
*/
protected function getOrRegisterUser(array $userDetails): ?User
{
$user = User::query()
->where('external_auth_id', '=', $userDetails['external_id'])
->first();
if (is_null($user)) {
$userData = [
'name' => $userDetails['name'],
'email' => $userDetails['email'],
'password' => Str::random(32),
'external_auth_id' => $userDetails['external_id'],
];
$user = $this->registrationService->registerUser($userData, null, false);
}
return $user;
}
/**
* Process the SAML response for a user. Login the user when
* they exist, optionally registering them automatically.
*
* @throws SamlException
* @throws JsonDebugException
* @throws UserRegistrationException
* @throws StoppedAuthenticationException
*/
public function processLoginCallback(string $samlID, array $samlAttributes): User
{
$userDetails = $this->getUserDetails($samlID, $samlAttributes);
$isLoggedIn = auth()->check();
if ($this->config['dump_user_details']) {
throw new JsonDebugException([
'id_from_idp' => $samlID,
'attrs_from_idp' => $samlAttributes,
'attrs_after_parsing' => $userDetails,
]);
}
if ($userDetails['email'] === null) {
throw new SamlException(trans('errors.saml_no_email_address'));
}
if ($isLoggedIn) {
throw new SamlException(trans('errors.saml_already_logged_in'), '/login');
}
$user = $this->getOrRegisterUser($userDetails);
if ($user === null) {
throw new SamlException(trans('errors.saml_user_not_registered', ['name' => $userDetails['external_id']]), '/login');
}
if ($this->shouldSyncGroups()) {
$groups = $this->getUserGroups($samlAttributes);
$this->syncWithGroups($user, $groups);
}
$this->loginService->login($user, 'saml2');
return $user;
}
}

View File

@@ -0,0 +1,317 @@
<?php
namespace BookStack\Auth\Access;
use BookStack\Auth\SocialAccount;
use BookStack\Auth\User;
use BookStack\Exceptions\SocialDriverNotConfigured;
use BookStack\Exceptions\SocialSignInAccountNotUsed;
use BookStack\Exceptions\UserRegistrationException;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Str;
use Laravel\Socialite\Contracts\Factory as Socialite;
use Laravel\Socialite\Contracts\Provider;
use Laravel\Socialite\Contracts\User as SocialUser;
use SocialiteProviders\Manager\SocialiteWasCalled;
use Symfony\Component\HttpFoundation\RedirectResponse;
class SocialAuthService
{
/**
* The core socialite library used.
*
* @var Socialite
*/
protected $socialite;
/**
* @var LoginService
*/
protected $loginService;
/**
* The default built-in social drivers we support.
*
* @var string[]
*/
protected $validSocialDrivers = [
'google',
'github',
'facebook',
'slack',
'twitter',
'azure',
'okta',
'gitlab',
'twitch',
'discord',
];
/**
* Callbacks to run when configuring a social driver
* for an initial redirect action.
* Array is keyed by social driver name.
* Callbacks are passed an instance of the driver.
*
* @var array<string, callable>
*/
protected $configureForRedirectCallbacks = [];
/**
* SocialAuthService constructor.
*/
public function __construct(Socialite $socialite, LoginService $loginService)
{
$this->socialite = $socialite;
$this->loginService = $loginService;
}
/**
* Start the social login path.
*
* @throws SocialDriverNotConfigured
*/
public function startLogIn(string $socialDriver): RedirectResponse
{
$driver = $this->validateDriver($socialDriver);
return $this->getDriverForRedirect($driver)->redirect();
}
/**
* Start the social registration process.
*
* @throws SocialDriverNotConfigured
*/
public function startRegister(string $socialDriver): RedirectResponse
{
$driver = $this->validateDriver($socialDriver);
return $this->getDriverForRedirect($driver)->redirect();
}
/**
* Handle the social registration process on callback.
*
* @throws UserRegistrationException
*/
public function handleRegistrationCallback(string $socialDriver, SocialUser $socialUser): SocialUser
{
// Check social account has not already been used
if (SocialAccount::query()->where('driver_id', '=', $socialUser->getId())->exists()) {
throw new UserRegistrationException(trans('errors.social_account_in_use', ['socialAccount' => $socialDriver]), '/login');
}
if (User::query()->where('email', '=', $socialUser->getEmail())->exists()) {
$email = $socialUser->getEmail();
throw new UserRegistrationException(trans('errors.error_user_exists_different_creds', ['email' => $email]), '/login');
}
return $socialUser;
}
/**
* Get the social user details via the social driver.
*
* @throws SocialDriverNotConfigured
*/
public function getSocialUser(string $socialDriver): SocialUser
{
$driver = $this->validateDriver($socialDriver);
return $this->socialite->driver($driver)->user();
}
/**
* Handle the login process on a oAuth callback.
*
* @throws SocialSignInAccountNotUsed
*/
public function handleLoginCallback(string $socialDriver, SocialUser $socialUser)
{
$socialId = $socialUser->getId();
// Get any attached social accounts or users
$socialAccount = SocialAccount::query()->where('driver_id', '=', $socialId)->first();
$isLoggedIn = auth()->check();
$currentUser = user();
$titleCaseDriver = Str::title($socialDriver);
// When a user is not logged in and a matching SocialAccount exists,
// Simply log the user into the application.
if (!$isLoggedIn && $socialAccount !== null) {
$this->loginService->login($socialAccount->user, $socialAccount);
return redirect()->intended('/');
}
// When a user is logged in but the social account does not exist,
// Create the social account and attach it to the user & redirect to the profile page.
if ($isLoggedIn && $socialAccount === null) {
$account = $this->newSocialAccount($socialDriver, $socialUser);
$currentUser->socialAccounts()->save($account);
session()->flash('success', trans('settings.users_social_connected', ['socialAccount' => $titleCaseDriver]));
return redirect($currentUser->getEditUrl());
}
// When a user is logged in and the social account exists and is already linked to the current user.
if ($isLoggedIn && $socialAccount !== null && $socialAccount->user->id === $currentUser->id) {
session()->flash('error', trans('errors.social_account_existing', ['socialAccount' => $titleCaseDriver]));
return redirect($currentUser->getEditUrl());
}
// When a user is logged in, A social account exists but the users do not match.
if ($isLoggedIn && $socialAccount !== null && $socialAccount->user->id != $currentUser->id) {
session()->flash('error', trans('errors.social_account_already_used_existing', ['socialAccount' => $titleCaseDriver]));
return redirect($currentUser->getEditUrl());
}
// Otherwise let the user know this social account is not used by anyone.
$message = trans('errors.social_account_not_used', ['socialAccount' => $titleCaseDriver]);
if (setting('registration-enabled') && config('auth.method') !== 'ldap' && config('auth.method') !== 'saml2') {
$message .= trans('errors.social_account_register_instructions', ['socialAccount' => $titleCaseDriver]);
}
throw new SocialSignInAccountNotUsed($message, '/login');
}
/**
* Ensure the social driver is correct and supported.
*
* @throws SocialDriverNotConfigured
*/
protected function validateDriver(string $socialDriver): string
{
$driver = trim(strtolower($socialDriver));
if (!in_array($driver, $this->validSocialDrivers)) {
abort(404, trans('errors.social_driver_not_found'));
}
if (!$this->checkDriverConfigured($driver)) {
throw new SocialDriverNotConfigured(trans('errors.social_driver_not_configured', ['socialAccount' => Str::title($socialDriver)]));
}
return $driver;
}
/**
* Check a social driver has been configured correctly.
*/
protected function checkDriverConfigured(string $driver): bool
{
$lowerName = strtolower($driver);
$configPrefix = 'services.' . $lowerName . '.';
$config = [config($configPrefix . 'client_id'), config($configPrefix . 'client_secret'), config('services.callback_url')];
return !in_array(false, $config) && !in_array(null, $config);
}
/**
* Gets the names of the active social drivers.
*/
public function getActiveDrivers(): array
{
$activeDrivers = [];
foreach ($this->validSocialDrivers as $driverKey) {
if ($this->checkDriverConfigured($driverKey)) {
$activeDrivers[$driverKey] = $this->getDriverName($driverKey);
}
}
return $activeDrivers;
}
/**
* Get the presentational name for a driver.
*/
public function getDriverName(string $driver): string
{
return config('services.' . strtolower($driver) . '.name');
}
/**
* Check if the current config for the given driver allows auto-registration.
*/
public function driverAutoRegisterEnabled(string $driver): bool
{
return config('services.' . strtolower($driver) . '.auto_register') === true;
}
/**
* Check if the current config for the given driver allow email address auto-confirmation.
*/
public function driverAutoConfirmEmailEnabled(string $driver): bool
{
return config('services.' . strtolower($driver) . '.auto_confirm') === true;
}
/**
* Fill and return a SocialAccount from the given driver name and SocialUser.
*/
public function newSocialAccount(string $socialDriver, SocialUser $socialUser): SocialAccount
{
return new SocialAccount([
'driver' => $socialDriver,
'driver_id' => $socialUser->getId(),
'avatar' => $socialUser->getAvatar(),
]);
}
/**
* Detach a social account from a user.
*/
public function detachSocialAccount(string $socialDriver): void
{
user()->socialAccounts()->where('driver', '=', $socialDriver)->delete();
}
/**
* Provide redirect options per service for the Laravel Socialite driver.
*/
protected function getDriverForRedirect(string $driverName): Provider
{
$driver = $this->socialite->driver($driverName);
if ($driverName === 'google' && config('services.google.select_account')) {
$driver->with(['prompt' => 'select_account']);
}
if ($driverName === 'azure') {
$driver->with(['resource' => 'https://graph.windows.net']);
}
if (isset($this->configureForRedirectCallbacks[$driverName])) {
$this->configureForRedirectCallbacks[$driverName]($driver);
}
return $driver;
}
/**
* Add a custom socialite driver to be used.
* Driver name should be lower_snake_case.
* Config array should mirror the structure of a service
* within the `Config/services.php` file.
* Handler should be a Class@method handler to the SocialiteWasCalled event.
*/
public function addSocialDriver(
string $driverName,
array $config,
string $socialiteHandler,
callable $configureForRedirect = null
) {
$this->validSocialDrivers[] = $driverName;
config()->set('services.' . $driverName, $config);
config()->set('services.' . $driverName . '.redirect', url('/login/service/' . $driverName . '/callback'));
config()->set('services.' . $driverName . '.name', $config['name'] ?? $driverName);
Event::listen(SocialiteWasCalled::class, $socialiteHandler);
if (!is_null($configureForRedirect)) {
$this->configureForRedirectCallbacks[$driverName] = $configureForRedirect;
}
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace BookStack\Auth\Access;
use BookStack\Auth\User;
use BookStack\Notifications\UserInvite;
class UserInviteService extends UserTokenService
{
protected $tokenTable = 'user_invites';
protected $expiryTime = 336; // Two weeks
/**
* Send an invitation to a user to sign into BookStack
* Removes existing invitation tokens.
*
* @param User $user
*/
public function sendInvitation(User $user)
{
$this->deleteByUser($user);
$token = $this->createTokenForUser($user);
$user->notify(new UserInvite($token));
}
}

View File

@@ -0,0 +1,142 @@
<?php
namespace BookStack\Auth\Access;
use BookStack\Auth\User;
use BookStack\Exceptions\UserTokenExpiredException;
use BookStack\Exceptions\UserTokenNotFoundException;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use stdClass;
class UserTokenService
{
/**
* Name of table where user tokens are stored.
*
* @var string
*/
protected $tokenTable = 'user_tokens';
/**
* Token expiry time in hours.
*
* @var int
*/
protected $expiryTime = 24;
/**
* Delete all email confirmations that belong to a user.
*
* @param User $user
*
* @return mixed
*/
public function deleteByUser(User $user)
{
return DB::table($this->tokenTable)
->where('user_id', '=', $user->id)
->delete();
}
/**
* Get the user id from a token, while check the token exists and has not expired.
*
* @param string $token
*
* @throws UserTokenNotFoundException
* @throws UserTokenExpiredException
*
* @return int
*/
public function checkTokenAndGetUserId(string $token): int
{
$entry = $this->getEntryByToken($token);
if (is_null($entry)) {
throw new UserTokenNotFoundException('Token "' . $token . '" not found');
}
if ($this->entryExpired($entry)) {
throw new UserTokenExpiredException("Token of id {$entry->id} has expired.", $entry->user_id);
}
return $entry->user_id;
}
/**
* Creates a unique token within the email confirmation database.
*
* @return string
*/
protected function generateToken(): string
{
$token = Str::random(24);
while ($this->tokenExists($token)) {
$token = Str::random(25);
}
return $token;
}
/**
* Generate and store a token for the given user.
*
* @param User $user
*
* @return string
*/
protected function createTokenForUser(User $user): string
{
$token = $this->generateToken();
DB::table($this->tokenTable)->insert([
'user_id' => $user->id,
'token' => $token,
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
]);
return $token;
}
/**
* Check if the given token exists.
*
* @param string $token
*
* @return bool
*/
protected function tokenExists(string $token): bool
{
return DB::table($this->tokenTable)
->where('token', '=', $token)->exists();
}
/**
* Get a token entry for the given token.
*
* @param string $token
*
* @return object|null
*/
protected function getEntryByToken(string $token)
{
return DB::table($this->tokenTable)
->where('token', '=', $token)
->first();
}
/**
* Check if the given token entry has expired.
*
* @param stdClass $tokenEntry
*
* @return bool
*/
protected function entryExpired(stdClass $tokenEntry): bool
{
return Carbon::now()->subHours($this->expiryTime)
->gt(new Carbon($tokenEntry->created_at));
}
}

View File

@@ -1,13 +1,17 @@
<?php namespace BookStack;
<?php
namespace BookStack\Auth\Permissions;
use BookStack\Model;
class EntityPermission extends Model
{
protected $fillable = ['role_id', 'action'];
public $timestamps = false;
/**
* Get all this restriction's attached entity.
*
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
*/
public function restrictable()

View File

@@ -0,0 +1,31 @@
<?php
namespace BookStack\Auth\Permissions;
use BookStack\Auth\Role;
use BookStack\Entities\Models\Entity;
use BookStack\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphOne;
class JointPermission extends Model
{
protected $primaryKey = null;
public $timestamps = false;
/**
* Get the role that this points to.
*/
public function role(): BelongsTo
{
return $this->belongsTo(Role::class);
}
/**
* Get the entity this points to.
*/
public function entity(): MorphOne
{
return $this->morphOne(Entity::class, 'entity');
}
}

View File

@@ -0,0 +1,693 @@
<?php
namespace BookStack\Auth\Permissions;
use BookStack\Auth\Role;
use BookStack\Auth\User;
use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\BookChild;
use BookStack\Entities\Models\Bookshelf;
use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Models\Entity;
use BookStack\Entities\Models\Page;
use BookStack\Model;
use BookStack\Traits\HasCreatorAndUpdater;
use BookStack\Traits\HasOwner;
use Illuminate\Database\Connection;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Throwable;
class PermissionService
{
/**
* @var ?array
*/
protected $userRoles = null;
/**
* @var ?User
*/
protected $currentUserModel = null;
/**
* @var Connection
*/
protected $db;
/**
* @var array
*/
protected $entityCache;
/**
* PermissionService constructor.
*/
public function __construct(Connection $db)
{
$this->db = $db;
}
/**
* Set the database connection.
*/
public function setConnection(Connection $connection)
{
$this->db = $connection;
}
/**
* Prepare the local entity cache and ensure it's empty.
*
* @param Entity[] $entities
*/
protected function readyEntityCache(array $entities = [])
{
$this->entityCache = [];
foreach ($entities as $entity) {
$class = get_class($entity);
if (!isset($this->entityCache[$class])) {
$this->entityCache[$class] = collect();
}
$this->entityCache[$class]->put($entity->id, $entity);
}
}
/**
* Get a book via ID, Checks local cache.
*/
protected function getBook(int $bookId): ?Book
{
if (isset($this->entityCache[Book::class]) && $this->entityCache[Book::class]->has($bookId)) {
return $this->entityCache[Book::class]->get($bookId);
}
return Book::query()->withTrashed()->find($bookId);
}
/**
* Get a chapter via ID, Checks local cache.
*/
protected function getChapter(int $chapterId): ?Chapter
{
if (isset($this->entityCache[Chapter::class]) && $this->entityCache[Chapter::class]->has($chapterId)) {
return $this->entityCache[Chapter::class]->get($chapterId);
}
return Chapter::query()
->withTrashed()
->find($chapterId);
}
/**
* Get the roles for the current logged in user.
*/
protected function getCurrentUserRoles(): array
{
if (!is_null($this->userRoles)) {
return $this->userRoles;
}
if (auth()->guest()) {
$this->userRoles = [Role::getSystemRole('public')->id];
} else {
$this->userRoles = $this->currentUser()->roles->pluck('id')->values()->all();
}
return $this->userRoles;
}
/**
* Re-generate all entity permission from scratch.
*/
public function buildJointPermissions()
{
JointPermission::query()->truncate();
$this->readyEntityCache();
// Get all roles (Should be the most limited dimension)
$roles = Role::query()->with('permissions')->get()->all();
// Chunk through all books
$this->bookFetchQuery()->chunk(5, function (EloquentCollection $books) use ($roles) {
$this->buildJointPermissionsForBooks($books, $roles);
});
// Chunk through all bookshelves
Bookshelf::query()->withTrashed()->select(['id', 'restricted', 'owned_by'])
->chunk(50, function (EloquentCollection $shelves) use ($roles) {
$this->buildJointPermissionsForShelves($shelves, $roles);
});
}
/**
* Get a query for fetching a book with it's children.
*/
protected function bookFetchQuery(): Builder
{
return Book::query()->withTrashed()
->select(['id', 'restricted', 'owned_by'])->with([
'chapters' => function ($query) {
$query->withTrashed()->select(['id', 'restricted', 'owned_by', 'book_id']);
},
'pages' => function ($query) {
$query->withTrashed()->select(['id', 'restricted', 'owned_by', 'book_id', 'chapter_id']);
},
]);
}
/**
* Build joint permissions for the given shelf and role combinations.
*
* @throws Throwable
*/
protected function buildJointPermissionsForShelves(EloquentCollection $shelves, array $roles, bool $deleteOld = false)
{
if ($deleteOld) {
$this->deleteManyJointPermissionsForEntities($shelves->all());
}
$this->createManyJointPermissions($shelves->all(), $roles);
}
/**
* Build joint permissions for the given book and role combinations.
*
* @throws Throwable
*/
protected function buildJointPermissionsForBooks(EloquentCollection $books, array $roles, bool $deleteOld = false)
{
$entities = clone $books;
/** @var Book $book */
foreach ($books->all() as $book) {
foreach ($book->getRelation('chapters') as $chapter) {
$entities->push($chapter);
}
foreach ($book->getRelation('pages') as $page) {
$entities->push($page);
}
}
if ($deleteOld) {
$this->deleteManyJointPermissionsForEntities($entities->all());
}
$this->createManyJointPermissions($entities->all(), $roles);
}
/**
* Rebuild the entity jointPermissions for a particular entity.
*
* @throws Throwable
*/
public function buildJointPermissionsForEntity(Entity $entity)
{
$entities = [$entity];
if ($entity instanceof Book) {
$books = $this->bookFetchQuery()->where('id', '=', $entity->id)->get();
$this->buildJointPermissionsForBooks($books, Role::query()->get()->all(), true);
return;
}
/** @var BookChild $entity */
if ($entity->book) {
$entities[] = $entity->book;
}
if ($entity instanceof Page && $entity->chapter_id) {
$entities[] = $entity->chapter;
}
if ($entity instanceof Chapter) {
foreach ($entity->pages as $page) {
$entities[] = $page;
}
}
$this->buildJointPermissionsForEntities($entities);
}
/**
* Rebuild the entity jointPermissions for a collection of entities.
*
* @throws Throwable
*/
public function buildJointPermissionsForEntities(array $entities)
{
$roles = Role::query()->get()->values()->all();
$this->deleteManyJointPermissionsForEntities($entities);
$this->createManyJointPermissions($entities, $roles);
}
/**
* Build the entity jointPermissions for a particular role.
*/
public function buildJointPermissionForRole(Role $role)
{
$roles = [$role];
$this->deleteManyJointPermissionsForRoles($roles);
// Chunk through all books
$this->bookFetchQuery()->chunk(20, function ($books) use ($roles) {
$this->buildJointPermissionsForBooks($books, $roles);
});
// Chunk through all bookshelves
Bookshelf::query()->select(['id', 'restricted', 'owned_by'])
->chunk(50, function ($shelves) use ($roles) {
$this->buildJointPermissionsForShelves($shelves, $roles);
});
}
/**
* Delete the entity jointPermissions attached to a particular role.
*/
public function deleteJointPermissionsForRole(Role $role)
{
$this->deleteManyJointPermissionsForRoles([$role]);
}
/**
* Delete all of the entity jointPermissions for a list of entities.
*
* @param Role[] $roles
*/
protected function deleteManyJointPermissionsForRoles($roles)
{
$roleIds = array_map(function ($role) {
return $role->id;
}, $roles);
JointPermission::query()->whereIn('role_id', $roleIds)->delete();
}
/**
* Delete the entity jointPermissions for a particular entity.
*
* @param Entity $entity
*
* @throws Throwable
*/
public function deleteJointPermissionsForEntity(Entity $entity)
{
$this->deleteManyJointPermissionsForEntities([$entity]);
}
/**
* Delete all of the entity jointPermissions for a list of entities.
*
* @param Entity[] $entities
*
* @throws Throwable
*/
protected function deleteManyJointPermissionsForEntities(array $entities)
{
if (count($entities) === 0) {
return;
}
$this->db->transaction(function () use ($entities) {
foreach (array_chunk($entities, 1000) as $entityChunk) {
$query = $this->db->table('joint_permissions');
foreach ($entityChunk as $entity) {
$query->orWhere(function (QueryBuilder $query) use ($entity) {
$query->where('entity_id', '=', $entity->id)
->where('entity_type', '=', $entity->getMorphClass());
});
}
$query->delete();
}
});
}
/**
* Create & Save entity jointPermissions for many entities and roles.
*
* @param Entity[] $entities
* @param Role[] $roles
*
* @throws Throwable
*/
protected function createManyJointPermissions(array $entities, array $roles)
{
$this->readyEntityCache($entities);
$jointPermissions = [];
// Fetch Entity Permissions and create a mapping of entity restricted statuses
$entityRestrictedMap = [];
$permissionFetch = EntityPermission::query();
foreach ($entities as $entity) {
$entityRestrictedMap[$entity->getMorphClass() . ':' . $entity->id] = boolval($entity->getRawAttribute('restricted'));
$permissionFetch->orWhere(function ($query) use ($entity) {
$query->where('restrictable_id', '=', $entity->id)->where('restrictable_type', '=', $entity->getMorphClass());
});
}
$permissions = $permissionFetch->get();
// Create a mapping of explicit entity permissions
$permissionMap = [];
foreach ($permissions as $permission) {
$key = $permission->restrictable_type . ':' . $permission->restrictable_id . ':' . $permission->role_id . ':' . $permission->action;
$isRestricted = $entityRestrictedMap[$permission->restrictable_type . ':' . $permission->restrictable_id];
$permissionMap[$key] = $isRestricted;
}
// Create a mapping of role permissions
$rolePermissionMap = [];
foreach ($roles as $role) {
foreach ($role->permissions as $permission) {
$rolePermissionMap[$role->getRawAttribute('id') . ':' . $permission->getRawAttribute('name')] = true;
}
}
// Create Joint Permission Data
foreach ($entities as $entity) {
foreach ($roles as $role) {
foreach ($this->getActions($entity) as $action) {
$jointPermissions[] = $this->createJointPermissionData($entity, $role, $action, $permissionMap, $rolePermissionMap);
}
}
}
$this->db->transaction(function () use ($jointPermissions) {
foreach (array_chunk($jointPermissions, 1000) as $jointPermissionChunk) {
$this->db->table('joint_permissions')->insert($jointPermissionChunk);
}
});
}
/**
* Get the actions related to an entity.
*/
protected function getActions(Entity $entity): array
{
$baseActions = ['view', 'update', 'delete'];
if ($entity instanceof Chapter || $entity instanceof Book) {
$baseActions[] = 'page-create';
}
if ($entity instanceof Book) {
$baseActions[] = 'chapter-create';
}
return $baseActions;
}
/**
* Create entity permission data for an entity and role
* for a particular action.
*/
protected function createJointPermissionData(Entity $entity, Role $role, string $action, array $permissionMap, array $rolePermissionMap): array
{
$permissionPrefix = (strpos($action, '-') === false ? ($entity->getType() . '-') : '') . $action;
$roleHasPermission = isset($rolePermissionMap[$role->getRawAttribute('id') . ':' . $permissionPrefix . '-all']);
$roleHasPermissionOwn = isset($rolePermissionMap[$role->getRawAttribute('id') . ':' . $permissionPrefix . '-own']);
$explodedAction = explode('-', $action);
$restrictionAction = end($explodedAction);
if ($role->system_name === 'admin') {
return $this->createJointPermissionDataArray($entity, $role, $action, true, true);
}
if ($entity->restricted) {
$hasAccess = $this->mapHasActiveRestriction($permissionMap, $entity, $role, $restrictionAction);
return $this->createJointPermissionDataArray($entity, $role, $action, $hasAccess, $hasAccess);
}
if ($entity instanceof Book || $entity instanceof Bookshelf) {
return $this->createJointPermissionDataArray($entity, $role, $action, $roleHasPermission, $roleHasPermissionOwn);
}
// For chapters and pages, Check if explicit permissions are set on the Book.
$book = $this->getBook($entity->book_id);
$hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $book, $role, $restrictionAction);
$hasPermissiveAccessToParents = !$book->restricted;
// For pages with a chapter, Check if explicit permissions are set on the Chapter
if ($entity instanceof Page && intval($entity->chapter_id) !== 0) {
$chapter = $this->getChapter($entity->chapter_id);
$hasPermissiveAccessToParents = $hasPermissiveAccessToParents && !$chapter->restricted;
if ($chapter->restricted) {
$hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $chapter, $role, $restrictionAction);
}
}
return $this->createJointPermissionDataArray(
$entity,
$role,
$action,
($hasExplicitAccessToParents || ($roleHasPermission && $hasPermissiveAccessToParents)),
($hasExplicitAccessToParents || ($roleHasPermissionOwn && $hasPermissiveAccessToParents))
);
}
/**
* Check for an active restriction in an entity map.
*/
protected function mapHasActiveRestriction(array $entityMap, Entity $entity, Role $role, string $action): bool
{
$key = $entity->getMorphClass() . ':' . $entity->getRawAttribute('id') . ':' . $role->getRawAttribute('id') . ':' . $action;
return $entityMap[$key] ?? false;
}
/**
* Create an array of data with the information of an entity jointPermissions.
* Used to build data for bulk insertion.
*/
protected function createJointPermissionDataArray(Entity $entity, Role $role, string $action, bool $permissionAll, bool $permissionOwn): array
{
return [
'role_id' => $role->getRawAttribute('id'),
'entity_id' => $entity->getRawAttribute('id'),
'entity_type' => $entity->getMorphClass(),
'action' => $action,
'has_permission' => $permissionAll,
'has_permission_own' => $permissionOwn,
'owned_by' => $entity->getRawAttribute('owned_by'),
];
}
/**
* Checks if an entity has a restriction set upon it.
*
* @param HasCreatorAndUpdater|HasOwner $ownable
*/
public function checkOwnableUserAccess(Model $ownable, string $permission): bool
{
$explodedPermission = explode('-', $permission);
$baseQuery = $ownable->newQuery()->where('id', '=', $ownable->id);
$action = end($explodedPermission);
$user = $this->currentUser();
$nonJointPermissions = ['restrictions', 'image', 'attachment', 'comment'];
// Handle non entity specific jointPermissions
if (in_array($explodedPermission[0], $nonJointPermissions)) {
$allPermission = $user && $user->can($permission . '-all');
$ownPermission = $user && $user->can($permission . '-own');
$ownerField = ($ownable instanceof Entity) ? 'owned_by' : 'created_by';
$isOwner = $user && $user->id === $ownable->$ownerField;
return $allPermission || ($isOwner && $ownPermission);
}
// Handle abnormal create jointPermissions
if ($action === 'create') {
$action = $permission;
}
$hasAccess = $this->entityRestrictionQuery($baseQuery, $action)->count() > 0;
$this->clean();
return $hasAccess;
}
/**
* Checks if a user has the given permission for any items in the system.
* Can be passed an entity instance to filter on a specific type.
*/
public function checkUserHasPermissionOnAnything(string $permission, ?string $entityClass = null): bool
{
$userRoleIds = $this->currentUser()->roles()->select('id')->pluck('id')->toArray();
$userId = $this->currentUser()->id;
$permissionQuery = JointPermission::query()
->where('action', '=', $permission)
->whereIn('role_id', $userRoleIds)
->where(function (Builder $query) use ($userId) {
$this->addJointHasPermissionCheck($query, $userId);
});
if (!is_null($entityClass)) {
$entityInstance = app($entityClass);
$permissionQuery = $permissionQuery->where('entity_type', '=', $entityInstance->getMorphClass());
}
$hasPermission = $permissionQuery->count() > 0;
$this->clean();
return $hasPermission;
}
/**
* The general query filter to remove all entities
* that the current user does not have access to.
*/
protected function entityRestrictionQuery(Builder $query, string $action): Builder
{
$q = $query->where(function ($parentQuery) use ($action) {
$parentQuery->whereHas('jointPermissions', function ($permissionQuery) use ($action) {
$permissionQuery->whereIn('role_id', $this->getCurrentUserRoles())
->where('action', '=', $action)
->where(function (Builder $query) {
$this->addJointHasPermissionCheck($query, $this->currentUser()->id);
});
});
});
$this->clean();
return $q;
}
/**
* Limited the given entity query so that the query will only
* return items that the user has permission for the given ability.
*/
public function restrictEntityQuery(Builder $query, string $ability = 'view'): Builder
{
$this->clean();
return $query->where(function (Builder $parentQuery) use ($ability) {
$parentQuery->whereHas('jointPermissions', function (Builder $permissionQuery) use ($ability) {
$permissionQuery->whereIn('role_id', $this->getCurrentUserRoles())
->where('action', '=', $ability)
->where(function (Builder $query) {
$this->addJointHasPermissionCheck($query, $this->currentUser()->id);
});
});
});
}
/**
* Extend the given page query to ensure draft items are not visible
* unless created by the given user.
*/
public function enforceDraftVisibilityOnQuery(Builder $query): Builder
{
return $query->where(function (Builder $query) {
$query->where('draft', '=', false)
->orWhere(function (Builder $query) {
$query->where('draft', '=', true)
->where('owned_by', '=', $this->currentUser()->id);
});
});
}
/**
* Add restrictions for a generic entity.
*/
public function enforceEntityRestrictions(Entity $entity, Builder $query, string $action = 'view'): Builder
{
if ($entity instanceof Page) {
// Prevent drafts being visible to others.
$this->enforceDraftVisibilityOnQuery($query);
}
return $this->entityRestrictionQuery($query, $action);
}
/**
* Filter items that have entities set as a polymorphic relation.
*
* @param Builder|\Illuminate\Database\Query\Builder $query
*/
public function filterRestrictedEntityRelations($query, string $tableName, string $entityIdColumn, string $entityTypeColumn, string $action = 'view')
{
$tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn, 'entityTypeColumn' => $entityTypeColumn];
$q = $query->where(function ($query) use ($tableDetails, $action) {
$query->whereExists(function ($permissionQuery) use (&$tableDetails, $action) {
$permissionQuery->select(['role_id'])->from('joint_permissions')
->whereRaw('joint_permissions.entity_id=' . $tableDetails['tableName'] . '.' . $tableDetails['entityIdColumn'])
->whereRaw('joint_permissions.entity_type=' . $tableDetails['tableName'] . '.' . $tableDetails['entityTypeColumn'])
->where('action', '=', $action)
->whereIn('role_id', $this->getCurrentUserRoles())
->where(function (QueryBuilder $query) {
$this->addJointHasPermissionCheck($query, $this->currentUser()->id);
});
});
});
$this->clean();
return $q;
}
/**
* Add conditions to a query to filter the selection to related entities
* where view permissions are granted.
*/
public function filterRelatedEntity(string $entityClass, Builder $query, string $tableName, string $entityIdColumn): Builder
{
$tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn];
$morphClass = app($entityClass)->getMorphClass();
$q = $query->where(function ($query) use ($tableDetails, $morphClass) {
$query->where(function ($query) use (&$tableDetails, $morphClass) {
$query->whereExists(function ($permissionQuery) use (&$tableDetails, $morphClass) {
$permissionQuery->select('id')->from('joint_permissions')
->whereRaw('joint_permissions.entity_id=' . $tableDetails['tableName'] . '.' . $tableDetails['entityIdColumn'])
->where('entity_type', '=', $morphClass)
->where('action', '=', 'view')
->whereIn('role_id', $this->getCurrentUserRoles())
->where(function (QueryBuilder $query) {
$this->addJointHasPermissionCheck($query, $this->currentUser()->id);
});
});
})->orWhere($tableDetails['entityIdColumn'], '=', 0);
});
$this->clean();
return $q;
}
/**
* Add the query for checking the given user id has permission
* within the join_permissions table.
*
* @param QueryBuilder|Builder $query
*/
protected function addJointHasPermissionCheck($query, int $userIdToCheck)
{
$query->where('has_permission', '=', true)->orWhere(function ($query) use ($userIdToCheck) {
$query->where('has_permission_own', '=', true)
->where('owned_by', '=', $userIdToCheck);
});
}
/**
* Get the current user.
*/
private function currentUser(): User
{
if (is_null($this->currentUserModel)) {
$this->currentUserModel = user();
}
return $this->currentUserModel;
}
/**
* Clean the cached user elements.
*/
private function clean(): void
{
$this->currentUserModel = null;
$this->userRoles = null;
}
}

View File

@@ -1,14 +1,16 @@
<?php namespace BookStack\Repos;
<?php
namespace BookStack\Auth\Permissions;
use BookStack\Actions\ActivityType;
use BookStack\Auth\Role;
use BookStack\Exceptions\PermissionsException;
use BookStack\RolePermission;
use BookStack\Role;
use BookStack\Services\PermissionService;
use Setting;
use BookStack\Facades\Activity;
use Exception;
use Illuminate\Database\Eloquent\Collection;
class PermissionsRepo
{
protected $permission;
protected $role;
protected $permissionService;
@@ -17,9 +19,6 @@ class PermissionsRepo
/**
* PermissionsRepo constructor.
* @param RolePermission $permission
* @param Role $role
* @param PermissionService $permissionService
*/
public function __construct(RolePermission $permission, Role $role, PermissionService $permissionService)
{
@@ -30,90 +29,89 @@ class PermissionsRepo
/**
* Get all the user roles from the system.
* @return \Illuminate\Database\Eloquent\Collection|static[]
*/
public function getAllRoles()
public function getAllRoles(): Collection
{
return $this->role->all();
}
/**
* Get all the roles except for the provided one.
* @param Role $role
* @return mixed
*/
public function getAllRolesExcept(Role $role)
public function getAllRolesExcept(Role $role): Collection
{
return $this->role->where('id', '!=', $role->id)->get();
}
/**
* Get a role via its ID.
* @param $id
* @return mixed
*/
public function getRoleById($id)
public function getRoleById($id): Role
{
return $this->role->findOrFail($id);
return $this->role->newQuery()->findOrFail($id);
}
/**
* Save a new role into the system.
* @param array $roleData
* @return Role
*/
public function saveNewRole($roleData)
public function saveNewRole(array $roleData): Role
{
$role = $this->role->newInstance($roleData);
$role->name = str_replace(' ', '-', strtolower($roleData['display_name']));
// Prevent duplicate names
while ($this->role->where('name', '=', $role->name)->count() > 0) {
$role->name .= strtolower(str_random(2));
}
$role->mfa_enforced = ($roleData['mfa_enforced'] ?? 'false') === 'true';
$role->save();
$permissions = isset($roleData['permissions']) ? array_keys($roleData['permissions']) : [];
$this->assignRolePermissions($role, $permissions);
$this->permissionService->buildJointPermissionForRole($role);
Activity::add(ActivityType::ROLE_CREATE, $role);
return $role;
}
/**
* Updates an existing role.
* Ensure Admin role always has all permissions.
* @param $roleId
* @param $roleData
* @throws PermissionsException
* Ensure Admin role always have core permissions.
*/
public function updateRole($roleId, $roleData)
public function updateRole($roleId, array $roleData)
{
$role = $this->role->findOrFail($roleId);
/** @var Role $role */
$role = $this->role->newQuery()->findOrFail($roleId);
$permissions = isset($roleData['permissions']) ? array_keys($roleData['permissions']) : [];
$this->assignRolePermissions($role, $permissions);
if ($role->system_name === 'admin') {
$permissions = $this->permission->all()->pluck('id')->toArray();
$role->permissions()->sync($permissions);
$permissions = array_merge($permissions, [
'users-manage',
'user-roles-manage',
'restrictions-manage-all',
'restrictions-manage-own',
'settings-manage',
]);
}
$this->assignRolePermissions($role, $permissions);
$role->fill($roleData);
$role->mfa_enforced = ($roleData['mfa_enforced'] ?? 'false') === 'true';
$role->save();
$this->permissionService->buildJointPermissionForRole($role);
Activity::add(ActivityType::ROLE_UPDATE, $role);
}
/**
* Assign an list of permission names to an role.
* @param Role $role
* @param array $permissionNameArray
*/
public function assignRolePermissions(Role $role, $permissionNameArray = [])
protected function assignRolePermissions(Role $role, array $permissionNameArray = [])
{
$permissions = [];
$permissionNameArray = array_values($permissionNameArray);
if ($permissionNameArray && count($permissionNameArray) > 0) {
$permissions = $this->permission->whereIn('name', $permissionNameArray)->pluck('id')->toArray();
if ($permissionNameArray) {
$permissions = $this->permission->newQuery()
->whereIn('name', $permissionNameArray)
->pluck('id')
->toArray();
}
$role->permissions()->sync($permissions);
}
@@ -122,30 +120,32 @@ class PermissionsRepo
* Check it's not an admin role or set as default before deleting.
* If an migration Role ID is specified the users assign to the current role
* will be added to the role of the specified id.
* @param $roleId
* @param $migrateRoleId
*
* @throws PermissionsException
* @throws Exception
*/
public function deleteRole($roleId, $migrateRoleId)
{
$role = $this->role->findOrFail($roleId);
/** @var Role $role */
$role = $this->role->newQuery()->findOrFail($roleId);
// Prevent deleting admin role or default registration role.
if ($role->system_name && in_array($role->system_name, $this->systemRoles)) {
throw new PermissionsException(trans('errors.role_system_cannot_be_deleted'));
} else if ($role->id == setting('registration-role')) {
} elseif ($role->id === intval(setting('registration-role'))) {
throw new PermissionsException(trans('errors.role_registration_default_cannot_delete'));
}
if ($migrateRoleId) {
$newRole = $this->role->find($migrateRoleId);
$newRole = $this->role->newQuery()->find($migrateRoleId);
if ($newRole) {
$users = $role->users->pluck('id')->toArray();
$users = $role->users()->pluck('id')->toArray();
$newRole->users()->sync($users);
}
}
$this->permissionService->deleteJointPermissionsForRole($role);
Activity::add(ActivityType::ROLE_DELETE, $role);
$role->delete();
}
}

View File

@@ -1,5 +1,13 @@
<?php namespace BookStack;
<?php
namespace BookStack\Auth\Permissions;
use BookStack\Auth\Role;
use BookStack\Model;
/**
* @property int $id
*/
class RolePermission extends Model
{
/**
@@ -12,7 +20,9 @@ class RolePermission extends Model
/**
* Get the permission object by name.
*
* @param $name
*
* @return mixed
*/
public static function getByName($name)

124
app/Auth/Role.php Normal file
View File

@@ -0,0 +1,124 @@
<?php
namespace BookStack\Auth;
use BookStack\Auth\Permissions\JointPermission;
use BookStack\Auth\Permissions\RolePermission;
use BookStack\Interfaces\Loggable;
use BookStack\Model;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
/**
* Class Role.
*
* @property int $id
* @property string $display_name
* @property string $description
* @property string $external_auth_id
* @property string $system_name
* @property bool $mfa_enforced
*/
class Role extends Model implements Loggable
{
protected $fillable = ['display_name', 'description', 'external_auth_id'];
/**
* The roles that belong to the role.
*/
public function users(): BelongsToMany
{
return $this->belongsToMany(User::class)->orderBy('name', 'asc');
}
/**
* Get all related JointPermissions.
*/
public function jointPermissions(): HasMany
{
return $this->hasMany(JointPermission::class);
}
/**
* The RolePermissions that belong to the role.
*/
public function permissions(): BelongsToMany
{
return $this->belongsToMany(RolePermission::class, 'permission_role', 'role_id', 'permission_id');
}
/**
* Check if this role has a permission.
*/
public function hasPermission(string $permissionName): bool
{
$permissions = $this->getRelationValue('permissions');
foreach ($permissions as $permission) {
if ($permission->getRawAttribute('name') === $permissionName) {
return true;
}
}
return false;
}
/**
* Add a permission to this role.
*/
public function attachPermission(RolePermission $permission)
{
$this->permissions()->attach($permission->id);
}
/**
* Detach a single permission from this role.
*/
public function detachPermission(RolePermission $permission)
{
$this->permissions()->detach([$permission->id]);
}
/**
* Get the role of the specified display name.
*/
public static function getRole(string $displayName): ?Role
{
return static::query()->where('display_name', '=', $displayName)->first();
}
/**
* Get the role object for the specified system role.
*/
public static function getSystemRole(string $systemName): ?Role
{
return static::query()->where('system_name', '=', $systemName)->first();
}
/**
* Get all visible roles.
*/
public static function visible(): Collection
{
return static::query()->where('hidden', '=', false)->orderBy('name')->get();
}
/**
* Get the roles that can be restricted.
*/
public static function restrictable(): Collection
{
return static::query()
->where('system_name', '!=', 'admin')
->orderBy('display_name', 'asc')
->get();
}
/**
* @inheritdoc
*/
public function logDescriptor(): string
{
return "({$this->id}) {$this->display_name}";
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace BookStack\Auth;
use BookStack\Interfaces\Loggable;
use BookStack\Model;
/**
* Class SocialAccount.
*
* @property string $driver
* @property User $user
*/
class SocialAccount extends Model implements Loggable
{
protected $fillable = ['user_id', 'driver', 'driver_id', 'timestamps'];
public function user()
{
return $this->belongsTo(User::class);
}
/**
* @inheritDoc
*/
public function logDescriptor(): string
{
return "{$this->driver}; {$this->user->logDescriptor()}";
}
}

355
app/Auth/User.php Normal file
View File

@@ -0,0 +1,355 @@
<?php
namespace BookStack\Auth;
use BookStack\Actions\Favourite;
use BookStack\Api\ApiToken;
use BookStack\Auth\Access\Mfa\MfaValue;
use BookStack\Entities\Tools\SlugGenerator;
use BookStack\Interfaces\Loggable;
use BookStack\Interfaces\Sluggable;
use BookStack\Model;
use BookStack\Notifications\ResetPassword;
use BookStack\Uploads\Image;
use Carbon\Carbon;
use Exception;
use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Collection;
/**
* Class User.
*
* @property string $id
* @property string $name
* @property string $slug
* @property string $email
* @property string $password
* @property Carbon $created_at
* @property Carbon $updated_at
* @property bool $email_confirmed
* @property int $image_id
* @property string $external_auth_id
* @property string $system_name
* @property Collection $roles
* @property Collection $mfaValues
*/
class User extends Model implements AuthenticatableContract, CanResetPasswordContract, Loggable, Sluggable
{
use Authenticatable;
use CanResetPassword;
use Notifiable;
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['name', 'email'];
protected $casts = ['last_activity_at' => 'datetime'];
/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token', 'system_name', 'email_confirmed', 'external_auth_id', 'email',
'created_at', 'updated_at', 'image_id',
];
/**
* This holds the user's permissions when loaded.
*
* @var ?Collection
*/
protected $permissions;
/**
* This holds the default user when loaded.
*
* @var null|User
*/
protected static $defaultUser = null;
/**
* Returns the default public user.
*/
public static function getDefault(): User
{
if (!is_null(static::$defaultUser)) {
return static::$defaultUser;
}
static::$defaultUser = static::query()->where('system_name', '=', 'public')->first();
return static::$defaultUser;
}
/**
* Check if the user is the default public user.
*/
public function isDefault(): bool
{
return $this->system_name === 'public';
}
/**
* The roles that belong to the user.
*
* @return BelongsToMany
*/
public function roles()
{
if ($this->id === 0) {
return;
}
return $this->belongsToMany(Role::class);
}
/**
* Check if the user has a role.
*/
public function hasRole($roleId): bool
{
return $this->roles->pluck('id')->contains($roleId);
}
/**
* Check if the user has a role.
*/
public function hasSystemRole(string $roleSystemName): bool
{
return $this->roles->pluck('system_name')->contains($roleSystemName);
}
/**
* Attach the default system role to this user.
*/
public function attachDefaultRole(): void
{
$roleId = setting('registration-role');
if ($roleId && $this->roles()->where('id', '=', $roleId)->count() === 0) {
$this->roles()->attach($roleId);
}
}
/**
* Check if the user has a particular permission.
*/
public function can(string $permissionName): bool
{
if ($this->email === 'guest') {
return false;
}
return $this->permissions()->contains($permissionName);
}
/**
* Get all permissions belonging to a the current user.
*/
protected function permissions(): Collection
{
if (isset($this->permissions)) {
return $this->permissions;
}
$this->permissions = $this->newQuery()->getConnection()->table('role_user', 'ru')
->select('role_permissions.name as name')->distinct()
->leftJoin('permission_role', 'ru.role_id', '=', 'permission_role.role_id')
->leftJoin('role_permissions', 'permission_role.permission_id', '=', 'role_permissions.id')
->where('ru.user_id', '=', $this->id)
->get()
->pluck('name');
return $this->permissions;
}
/**
* Clear any cached permissions on this instance.
*/
public function clearPermissionCache()
{
$this->permissions = null;
}
/**
* Attach a role to this user.
*/
public function attachRole(Role $role)
{
$this->roles()->attach($role->id);
}
/**
* Get the social account associated with this user.
*/
public function socialAccounts(): HasMany
{
return $this->hasMany(SocialAccount::class);
}
/**
* Check if the user has a social account,
* If a driver is passed it checks for that single account type.
*
* @param bool|string $socialDriver
*
* @return bool
*/
public function hasSocialAccount($socialDriver = false)
{
if ($socialDriver === false) {
return $this->socialAccounts()->count() > 0;
}
return $this->socialAccounts()->where('driver', '=', $socialDriver)->exists();
}
/**
* Returns a URL to the user's avatar.
*/
public function getAvatar(int $size = 50): string
{
$default = url('/user_avatar.png');
$imageId = $this->image_id;
if ($imageId === 0 || $imageId === '0' || $imageId === null) {
return $default;
}
try {
$avatar = $this->avatar ? url($this->avatar->getThumb($size, $size, false)) : $default;
} catch (Exception $err) {
$avatar = $default;
}
return $avatar;
}
/**
* Get the avatar for the user.
*/
public function avatar(): BelongsTo
{
return $this->belongsTo(Image::class, 'image_id');
}
/**
* Get the API tokens assigned to this user.
*/
public function apiTokens(): HasMany
{
return $this->hasMany(ApiToken::class);
}
/**
* Get the favourite instances for this user.
*/
public function favourites(): HasMany
{
return $this->hasMany(Favourite::class);
}
/**
* Get the MFA values belonging to this use.
*/
public function mfaValues(): HasMany
{
return $this->hasMany(MfaValue::class);
}
/**
* Get the last activity time for this user.
*/
public function scopeWithLastActivityAt(Builder $query)
{
$query->addSelect(['activities.created_at as last_activity_at'])
->leftJoinSub(function (\Illuminate\Database\Query\Builder $query) {
$query->from('activities')->select('user_id')
->selectRaw('max(created_at) as created_at')
->groupBy('user_id');
}, 'activities', 'users.id', '=', 'activities.user_id');
}
/**
* Get the url for editing this user.
*/
public function getEditUrl(string $path = ''): string
{
$uri = '/settings/users/' . $this->id . '/' . trim($path, '/');
return url(rtrim($uri, '/'));
}
/**
* Get the url that links to this user's profile.
*/
public function getProfileUrl(): string
{
return url('/user/' . $this->slug);
}
/**
* Get a shortened version of the user's name.
*/
public function getShortName(int $chars = 8): string
{
if (mb_strlen($this->name) <= $chars) {
return $this->name;
}
$splitName = explode(' ', $this->name);
if (mb_strlen($splitName[0]) <= $chars) {
return $splitName[0];
}
return '';
}
/**
* Send the password reset notification.
*
* @param string $token
*
* @return void
*/
public function sendPasswordResetNotification($token)
{
$this->notify(new ResetPassword($token));
}
/**
* @inheritdoc
*/
public function logDescriptor(): string
{
return "({$this->id}) {$this->name}";
}
/**
* @inheritDoc
*/
public function refreshSlug(): string
{
$this->slug = app(SlugGenerator::class)->generate($this);
return $this->slug;
}
}

281
app/Auth/UserRepo.php Normal file
View File

@@ -0,0 +1,281 @@
<?php
namespace BookStack\Auth;
use Activity;
use BookStack\Entities\EntityProvider;
use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Bookshelf;
use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Models\Page;
use BookStack\Exceptions\NotFoundException;
use BookStack\Exceptions\UserUpdateException;
use BookStack\Uploads\UserAvatars;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Pagination\LengthAwarePaginator;
use Log;
class UserRepo
{
protected $userAvatar;
/**
* UserRepo constructor.
*/
public function __construct(UserAvatars $userAvatar)
{
$this->userAvatar = $userAvatar;
}
/**
* Get a user by their email address.
*/
public function getByEmail(string $email): ?User
{
return User::query()->where('email', '=', $email)->first();
}
/**
* Get a user by their ID.
*/
public function getById(int $id): User
{
return User::query()->findOrFail($id);
}
/**
* Get a user by their slug.
*/
public function getBySlug(string $slug): User
{
return User::query()->where('slug', '=', $slug)->firstOrFail();
}
/**
* Get all the users with their permissions.
*/
public function getAllUsers(): Collection
{
return User::query()->with('roles', 'avatar')->orderBy('name', 'asc')->get();
}
/**
* Get all the users with their permissions in a paginated format.
*/
public function getAllUsersPaginatedAndSorted(int $count, array $sortData): LengthAwarePaginator
{
$sort = $sortData['sort'];
$query = User::query()->select(['*'])
->withLastActivityAt()
->with(['roles', 'avatar'])
->withCount('mfaValues')
->orderBy($sort, $sortData['order']);
if ($sortData['search']) {
$term = '%' . $sortData['search'] . '%';
$query->where(function ($query) use ($term) {
$query->where('name', 'like', $term)
->orWhere('email', 'like', $term);
});
}
return $query->paginate($count);
}
/**
* Creates a new user and attaches a role to them.
*/
public function registerNew(array $data, bool $emailConfirmed = false): User
{
$user = $this->create($data, $emailConfirmed);
$user->attachDefaultRole();
$this->downloadAndAssignUserAvatar($user);
return $user;
}
/**
* Assign a user to a system-level role.
*
* @throws NotFoundException
*/
public function attachSystemRole(User $user, string $systemRoleName)
{
$role = Role::getSystemRole($systemRoleName);
if (is_null($role)) {
throw new NotFoundException("Role '{$systemRoleName}' not found");
}
$user->attachRole($role);
}
/**
* Checks if the give user is the only admin.
*/
public function isOnlyAdmin(User $user): bool
{
if (!$user->hasSystemRole('admin')) {
return false;
}
$adminRole = Role::getSystemRole('admin');
if ($adminRole->users()->count() > 1) {
return false;
}
return true;
}
/**
* Set the assigned user roles via an array of role IDs.
*
* @throws UserUpdateException
*/
public function setUserRoles(User $user, array $roles)
{
if ($this->demotingLastAdmin($user, $roles)) {
throw new UserUpdateException(trans('errors.role_cannot_remove_only_admin'), $user->getEditUrl());
}
$user->roles()->sync($roles);
}
/**
* Check if the given user is the last admin and their new roles no longer
* contains the admin role.
*/
protected function demotingLastAdmin(User $user, array $newRoles): bool
{
if ($this->isOnlyAdmin($user)) {
$adminRole = Role::getSystemRole('admin');
if (!in_array(strval($adminRole->id), $newRoles)) {
return true;
}
}
return false;
}
/**
* Create a new basic instance of user.
*/
public function create(array $data, bool $emailConfirmed = false): User
{
$details = [
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
'email_confirmed' => $emailConfirmed,
'external_auth_id' => $data['external_auth_id'] ?? '',
];
$user = new User();
$user->forceFill($details);
$user->refreshSlug();
$user->save();
return $user;
}
/**
* Remove the given user from storage, Delete all related content.
*
* @throws Exception
*/
public function destroy(User $user, ?int $newOwnerId = null)
{
$user->socialAccounts()->delete();
$user->apiTokens()->delete();
$user->favourites()->delete();
$user->mfaValues()->delete();
$user->delete();
// Delete user profile images
$this->userAvatar->destroyAllForUser($user);
if (!empty($newOwnerId)) {
$newOwner = User::query()->find($newOwnerId);
if (!is_null($newOwner)) {
$this->migrateOwnership($user, $newOwner);
}
}
}
/**
* Migrate ownership of items in the system from one user to another.
*/
protected function migrateOwnership(User $fromUser, User $toUser)
{
$entities = (new EntityProvider())->all();
foreach ($entities as $instance) {
$instance->newQuery()->where('owned_by', '=', $fromUser->id)
->update(['owned_by' => $toUser->id]);
}
}
/**
* Get the latest activity for a user.
*/
public function getActivity(User $user, int $count = 20, int $page = 0): array
{
return Activity::userActivity($user, $count, $page);
}
/**
* Get the recently created content for this given user.
*/
public function getRecentlyCreated(User $user, int $count = 20): array
{
$query = function (Builder $query) use ($user, $count) {
return $query->orderBy('created_at', 'desc')
->where('created_by', '=', $user->id)
->take($count)
->get();
};
return [
'pages' => $query(Page::visible()->where('draft', '=', false)),
'chapters' => $query(Chapter::visible()),
'books' => $query(Book::visible()),
'shelves' => $query(Bookshelf::visible()),
];
}
/**
* Get asset created counts for the give user.
*/
public function getAssetCounts(User $user): array
{
$createdBy = ['created_by' => $user->id];
return [
'pages' => Page::visible()->where($createdBy)->count(),
'chapters' => Chapter::visible()->where($createdBy)->count(),
'books' => Book::visible()->where($createdBy)->count(),
'shelves' => Bookshelf::visible()->where($createdBy)->count(),
];
}
/**
* Get the roles in the system that are assignable to a user.
*/
public function getAllRoles(): Collection
{
return Role::query()->orderBy('display_name', 'asc')->get();
}
/**
* Get an avatar image for a user and set it as their avatar.
* Returns early if avatars disabled or not set in config.
*/
public function downloadAndAssignUserAvatar(User $user): void
{
try {
$this->userAvatar->fetchAndAssignToUser($user);
} catch (Exception $e) {
Log::error('Failed to save user avatar image');
}
}
}

View File

@@ -1,97 +0,0 @@
<?php namespace BookStack;
class Book extends Entity
{
public $searchFactor = 2;
protected $fillable = ['name', 'description', 'image_id'];
/**
* Get the url for this book.
* @param string|bool $path
* @return string
*/
public function getUrl($path = false)
{
if ($path !== false) {
return baseUrl('/books/' . urlencode($this->slug) . '/' . trim($path, '/'));
}
return baseUrl('/books/' . urlencode($this->slug));
}
/**
* Returns book cover image, if book cover not exists return default cover image.
* @param int $width - Width of the image
* @param int $height - Height of the image
* @return string
*/
public function getBookCover($width = 440, $height = 250)
{
$default = baseUrl('/book_default_cover.png');
if (!$this->image_id) {
return $default;
}
try {
$cover = $this->cover ? baseUrl($this->cover->getThumb($width, $height, false)) : $default;
} catch (\Exception $err) {
$cover = $default;
}
return $cover;
}
/**
* Get the cover image of the book
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function cover()
{
return $this->belongsTo(Image::class, 'image_id');
}
/*
* Get the edit url for this book.
* @return string
*/
public function getEditUrl()
{
return $this->getUrl() . '/edit';
}
/**
* Get all pages within this book.
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function pages()
{
return $this->hasMany(Page::class);
}
/**
* Get all chapters within this book.
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function chapters()
{
return $this->hasMany(Chapter::class);
}
/**
* Get an excerpt of this book's description to the specified length or less.
* @param int $length
* @return string
*/
public function getExcerpt($length = 100)
{
$description = $this->description;
return strlen($description) > $length ? substr($description, 0, $length-3) . '...' : $description;
}
/**
* Return a generalised, common raw query that can be 'unioned' across entities.
* @return string
*/
public function entityRawQuery()
{
return "'BookStack\\\\Book' 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";
}
}

View File

@@ -1,61 +0,0 @@
<?php namespace BookStack;
class Chapter extends Entity
{
public $searchFactor = 1.3;
protected $fillable = ['name', 'description', 'priority', 'book_id'];
/**
* Get the book this chapter is within.
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function book()
{
return $this->belongsTo(Book::class);
}
/**
* Get the pages that this chapter contains.
* @param string $dir
* @return mixed
*/
public function pages($dir = 'ASC')
{
return $this->hasMany(Page::class)->orderBy('priority', $dir);
}
/**
* Get the url of this chapter.
* @param string|bool $path
* @return string
*/
public function getUrl($path = false)
{
$bookSlug = $this->getAttribute('bookSlug') ? $this->getAttribute('bookSlug') : $this->book->slug;
if ($path !== false) {
return baseUrl('/books/' . urlencode($bookSlug) . '/chapter/' . urlencode($this->slug) . '/' . trim($path, '/'));
}
return baseUrl('/books/' . urlencode($bookSlug) . '/chapter/' . urlencode($this->slug));
}
/**
* Get an excerpt of this chapter's description to the specified length or less.
* @param int $length
* @return string
*/
public function getExcerpt($length = 100)
{
$description = $this->description;
return strlen($description) > $length ? substr($description, 0, $length-3) . '...' : $description;
}
/**
* Return a generalised, common raw query that can be 'unioned' across entities.
* @return string
*/
public function entityRawQuery()
{
return "'BookStack\\\\Chapter' as entity_type, id, id as entity_id, slug, name, {$this->textField} as text, '' as html, book_id, priority, '0' as chapter_id, '0' as draft, created_by, updated_by, updated_at, created_at";
}
}

23
app/Config/api.php Normal file
View File

@@ -0,0 +1,23 @@
<?php
/**
* API configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
return [
// The default number of items that are returned in listing API requests.
// This count can often be overridden, up the the max option, per-request via request options.
'default_item_count' => env('API_DEFAULT_ITEM_COUNT', 100),
// The maximum number of items that can be returned in a listing API request.
'max_item_count' => env('API_MAX_ITEM_COUNT', 500),
// The number of API requests that can be made per minute by a single user.
'requests_per_minute' => env('API_REQUESTS_PER_MIN', 180),
];

199
app/Config/app.php Executable file
View File

@@ -0,0 +1,199 @@
<?php
/**
* Global app configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
return [
// The environment to run BookStack in.
// Options: production, development, demo, testing
'env' => env('APP_ENV', 'production'),
// Enter the application in debug mode.
// Shows much more verbose error messages. Has potential to show
// private configuration variables so should remain disabled in public.
'debug' => env('APP_DEBUG', false),
// The number of revisions to keep in the database.
// Once this limit is reached older revisions will be deleted.
// If set to false then a limit will not be enforced.
'revision_limit' => env('REVISION_LIMIT', 50),
// The number of days that content will remain in the recycle bin before
// being considered for auto-removal. It is not a guarantee that content will
// be removed after this time.
// Set to 0 for no recycle bin functionality.
// Set to -1 for unlimited recycle bin lifetime.
'recycle_bin_lifetime' => env('RECYCLE_BIN_LIFETIME', 30),
// Allow <script> tags to entered within page content.
// <script> tags are escaped by default.
// Even when overridden the WYSIWYG editor may still escape script content.
'allow_content_scripts' => env('ALLOW_CONTENT_SCRIPTS', false),
// Allow server-side fetches to be performed to potentially unknown
// and user-provided locations. Primarily used in exports when loading
// in externally referenced assets.
'allow_untrusted_server_fetching' => env('ALLOW_UNTRUSTED_SERVER_FETCHING', false),
// Override the default behaviour for allowing crawlers to crawl the instance.
// May be ignored if view has be overridden or modified.
// Defaults to null since, if not set, 'app-public' status used instead.
'allow_robots' => env('ALLOW_ROBOTS', null),
// Application Base URL, Used by laravel in development commands
// and used by BookStack in URL generation.
'url' => env('APP_URL', '') === 'http://bookstack.dev' ? '' : env('APP_URL', ''),
// A list of hosts that BookStack can be iframed within.
// Space separated if multiple. BookStack host domain is auto-inferred.
'iframe_hosts' => env('ALLOWED_IFRAME_HOSTS', null),
// Application timezone for back-end date functions.
'timezone' => env('APP_TIMEZONE', 'UTC'),
// Default locale to use
'locale' => env('APP_LANG', 'en'),
// Locales available
'locales' => ['en', 'ar', 'bg', 'bs', 'ca', 'cs', 'da', 'de', 'de_informal', 'es', 'es_AR', 'fa', 'fr', 'he', 'hr', 'hu', 'id', 'it', 'ja', 'ko', 'lt', 'lv', 'nl', 'nb', 'pt', 'pt_BR', 'sk', 'sl', 'sv', 'pl', 'ru', 'th', 'tr', 'uk', 'vi', 'zh_CN', 'zh_TW'],
// Application Fallback Locale
'fallback_locale' => 'en',
// Faker Locale
'faker_locale' => 'en_GB',
// Enable right-to-left text control.
'rtl' => false,
// Auto-detect the locale for public users
// For public users their locale can be guessed by headers sent by their
// browser. This is usually set by users in their browser settings.
// If not found the default app locale will be used.
'auto_detect_locale' => env('APP_AUTO_LANG_PUBLIC', true),
// Encryption key
'key' => env('APP_KEY', 'AbAZchsay4uBTU33RubBzLKw203yqSqr'),
// Encryption cipher
'cipher' => 'AES-256-CBC',
// Application Services Provides
'providers' => [
// Laravel Framework Service Providers...
Illuminate\Auth\AuthServiceProvider::class,
Illuminate\Broadcasting\BroadcastServiceProvider::class,
Illuminate\Bus\BusServiceProvider::class,
Illuminate\Cache\CacheServiceProvider::class,
Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
Illuminate\Cookie\CookieServiceProvider::class,
Illuminate\Database\DatabaseServiceProvider::class,
Illuminate\Encryption\EncryptionServiceProvider::class,
Illuminate\Filesystem\FilesystemServiceProvider::class,
Illuminate\Foundation\Providers\FoundationServiceProvider::class,
Illuminate\Hashing\HashServiceProvider::class,
Illuminate\Mail\MailServiceProvider::class,
Illuminate\Pipeline\PipelineServiceProvider::class,
Illuminate\Queue\QueueServiceProvider::class,
Illuminate\Redis\RedisServiceProvider::class,
Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
Illuminate\Session\SessionServiceProvider::class,
Illuminate\Validation\ValidationServiceProvider::class,
Illuminate\View\ViewServiceProvider::class,
Illuminate\Notifications\NotificationServiceProvider::class,
SocialiteProviders\Manager\ServiceProvider::class,
// Third party service providers
Intervention\Image\ImageServiceProvider::class,
Barryvdh\DomPDF\ServiceProvider::class,
Barryvdh\Snappy\ServiceProvider::class,
// BookStack replacement service providers (Extends Laravel)
BookStack\Providers\PaginationServiceProvider::class,
BookStack\Providers\TranslationServiceProvider::class,
// BookStack custom service providers
BookStack\Providers\ThemeServiceProvider::class,
BookStack\Providers\AuthServiceProvider::class,
BookStack\Providers\AppServiceProvider::class,
BookStack\Providers\BroadcastServiceProvider::class,
BookStack\Providers\EventServiceProvider::class,
BookStack\Providers\RouteServiceProvider::class,
BookStack\Providers\CustomFacadeProvider::class,
BookStack\Providers\CustomValidationServiceProvider::class,
],
/*
|--------------------------------------------------------------------------
| Class Aliases
|--------------------------------------------------------------------------
|
| This array of class aliases will be registered when this application
| is started. However, feel free to register as many as you wish as
| the aliases are "lazy" loaded so they don't hinder performance.
|
*/
// Class aliases, Registered on application start
'aliases' => [
// Laravel
'App' => Illuminate\Support\Facades\App::class,
'Arr' => Illuminate\Support\Arr::class,
'Artisan' => Illuminate\Support\Facades\Artisan::class,
'Auth' => Illuminate\Support\Facades\Auth::class,
'Blade' => Illuminate\Support\Facades\Blade::class,
'Bus' => Illuminate\Support\Facades\Bus::class,
'Cache' => Illuminate\Support\Facades\Cache::class,
'Config' => Illuminate\Support\Facades\Config::class,
'Cookie' => Illuminate\Support\Facades\Cookie::class,
'Crypt' => Illuminate\Support\Facades\Crypt::class,
'DB' => Illuminate\Support\Facades\DB::class,
'Eloquent' => Illuminate\Database\Eloquent\Model::class,
'Event' => Illuminate\Support\Facades\Event::class,
'File' => Illuminate\Support\Facades\File::class,
'Hash' => Illuminate\Support\Facades\Hash::class,
'Input' => Illuminate\Support\Facades\Input::class,
'Inspiring' => Illuminate\Foundation\Inspiring::class,
'Lang' => Illuminate\Support\Facades\Lang::class,
'Log' => Illuminate\Support\Facades\Log::class,
'Mail' => Illuminate\Support\Facades\Mail::class,
'Notification' => Illuminate\Support\Facades\Notification::class,
'Password' => Illuminate\Support\Facades\Password::class,
'Queue' => Illuminate\Support\Facades\Queue::class,
'Redirect' => Illuminate\Support\Facades\Redirect::class,
'Redis' => Illuminate\Support\Facades\Redis::class,
'Request' => Illuminate\Support\Facades\Request::class,
'Response' => Illuminate\Support\Facades\Response::class,
'Route' => Illuminate\Support\Facades\Route::class,
'Schema' => Illuminate\Support\Facades\Schema::class,
'Session' => Illuminate\Support\Facades\Session::class,
'Storage' => Illuminate\Support\Facades\Storage::class,
'Str' => Illuminate\Support\Str::class,
'URL' => Illuminate\Support\Facades\URL::class,
'Validator' => Illuminate\Support\Facades\Validator::class,
'View' => Illuminate\Support\Facades\View::class,
'Socialite' => Laravel\Socialite\Facades\Socialite::class,
// Third Party
'ImageTool' => Intervention\Image\Facades\Image::class,
'DomPDF' => Barryvdh\DomPDF\Facade::class,
'SnappyPDF' => Barryvdh\Snappy\Facades\SnappyPdf::class,
// Custom BookStack
'Activity' => BookStack\Facades\Activity::class,
'Permissions' => BookStack\Facades\Permissions::class,
'Theme' => BookStack\Facades\Theme::class,
],
// Proxy configuration
'proxies' => env('APP_PROXIES', ''),
];

76
app/Config/auth.php Normal file
View File

@@ -0,0 +1,76 @@
<?php
/**
* Authentication configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
return [
// Method of authentication to use
// Options: standard, ldap, saml2
'method' => env('AUTH_METHOD', 'standard'),
// Authentication Defaults
// This option controls the default authentication "guard" and password
// reset options for your application.
'defaults' => [
'guard' => env('AUTH_METHOD', 'standard'),
'passwords' => 'users',
],
// Authentication Guards
// All authentication drivers have a user provider. This defines how the
// users are actually retrieved out of your database or other storage
// mechanisms used by this application to persist your user's data.
// Supported drivers: "session", "api-token", "ldap-session"
'guards' => [
'standard' => [
'driver' => 'session',
'provider' => 'users',
],
'ldap' => [
'driver' => 'ldap-session',
'provider' => 'external',
],
'saml2' => [
'driver' => 'saml2-session',
'provider' => 'external',
],
'api' => [
'driver' => 'api-token',
],
],
// User Providers
// All authentication drivers have a user provider. This defines how the
// users are actually retrieved out of your database or other storage
// mechanisms used by this application to persist your user's data.
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => \BookStack\Auth\User::class,
],
'external' => [
'driver' => 'external-users',
'model' => \BookStack\Auth\User::class,
],
],
// Resetting Passwords
// The expire time is the number of minutes that the reset token should be
// considered valid. This security feature keeps tokens short-lived so
// they have less time to be guessed. You may change this as needed.
'passwords' => [
'users' => [
'provider' => 'users',
'email' => 'emails.password',
'table' => 'password_resets',
'expire' => 60,
],
],
];

View File

@@ -0,0 +1,51 @@
<?php
/**
* Broadcasting configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
return [
// Default Broadcaster
// This option controls the default broadcaster that will be used by the
// framework when an event needs to be broadcast. This can be set to
// any of the connections defined in the "connections" array below.
'default' => env('BROADCAST_DRIVER', 'pusher'),
// Broadcast Connections
// Here you may define all of the broadcast connections that will be used
// to broadcast events to other systems or over websockets. Samples of
// each available type of connection are provided inside this array.
'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => true,
],
],
'redis' => [
'driver' => 'redis',
'connection' => 'default',
],
'log' => [
'driver' => 'log',
],
'null' => [
'driver' => 'null',
],
],
];

71
app/Config/cache.php Normal file
View File

@@ -0,0 +1,71 @@
<?php
/**
* Caching configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
// MEMCACHED - Split out configuration into an array
if (env('CACHE_DRIVER') === 'memcached') {
$memcachedServerKeys = ['host', 'port', 'weight'];
$memcachedServers = explode(',', trim(env('MEMCACHED_SERVERS', '127.0.0.1:11211:100'), ','));
foreach ($memcachedServers as $index => $memcachedServer) {
$memcachedServerDetails = explode(':', $memcachedServer);
if (count($memcachedServerDetails) < 2) {
$memcachedServerDetails[] = '11211';
}
if (count($memcachedServerDetails) < 3) {
$memcachedServerDetails[] = '100';
}
$memcachedServers[$index] = array_combine($memcachedServerKeys, $memcachedServerDetails);
}
}
return [
// Default cache store to use
// Can be overridden at cache call-time
'default' => env('CACHE_DRIVER', 'file'),
// Available caches stores
'stores' => [
'apc' => [
'driver' => 'apc',
],
'array' => [
'driver' => 'array',
],
'database' => [
'driver' => 'database',
'table' => 'cache',
'connection' => null,
],
'file' => [
'driver' => 'file',
'path' => storage_path('framework/cache'),
],
'memcached' => [
'driver' => 'memcached',
'servers' => env('CACHE_DRIVER') === 'memcached' ? $memcachedServers : [],
],
'redis' => [
'driver' => 'redis',
'connection' => 'default',
],
],
// Cache key prefix
// Used to prevent collisions in shared cache systems.
'prefix' => env('CACHE_PREFIX', 'bookstack_cache'),
];

107
app/Config/database.php Normal file
View File

@@ -0,0 +1,107 @@
<?php
/**
* Database configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
// REDIS
// Split out configuration into an array
if (env('REDIS_SERVERS', false)) {
$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 = ['client' => 'predis'];
$cluster = count($redisServers) > 1;
if ($cluster) {
$redisConfig['clusters'] = ['default' => []];
}
foreach ($redisServers as $index => $redisServer) {
$redisServerDetails = explode(':', $redisServer);
$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_host = env('DB_HOST', 'localhost');
$mysql_host_exploded = explode(':', $mysql_host);
$mysql_port = env('DB_PORT', 3306);
if (count($mysql_host_exploded) > 1) {
$mysql_host = $mysql_host_exploded[0];
$mysql_port = intval($mysql_host_exploded[1]);
}
return [
// Default database connection name.
// Options: mysql, mysql_testing
'default' => env('DB_CONNECTION', 'mysql'),
// Available database connections
// Many of those shown here are unsupported by BookStack.
'connections' => [
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => $mysql_host,
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'port' => $mysql_port,
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => false,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
'mysql_testing' => [
'driver' => 'mysql',
'url' => env('TEST_DATABASE_URL'),
'host' => '127.0.0.1',
'database' => 'bookstack-test',
'username' => env('MYSQL_USER', 'bookstack-test'),
'password' => env('MYSQL_PASSWORD', 'bookstack-test'),
'port' => $mysql_port,
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => false,
],
],
// Migration Repository Table
// This table keeps track of all the migrations that have already run for
// your application. Using this information, we can determine which of
// the migrations on disk haven't actually been run in the database.
'migrations' => 'migrations',
// Redis configuration to use if set
'redis' => env('REDIS_SERVERS', false) ? $redisConfig : [],
];

132
app/Config/debugbar.php Normal file
View File

@@ -0,0 +1,132 @@
<?php
/**
* Debugbar Configuration Options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
return [
// Debugbar is enabled by default, when debug is set to true in app.php.
// You can override the value by setting enable to true or false instead of null.
//
// You can provide an array of URI's that must be ignored (eg. 'api/*')
'enabled' => env('DEBUGBAR_ENABLED', false),
'except' => [
'telescope*',
],
// DebugBar stores data for session/ajax requests.
// You can disable this, so the debugbar stores data in headers/session,
// but this can cause problems with large data collectors.
// By default, file storage (in the storage folder) is used. Redis and PDO
// can also be used. For PDO, run the package migrations first.
'storage' => [
'enabled' => true,
'driver' => 'file', // redis, file, pdo, custom
'path' => storage_path('debugbar'), // For file driver
'connection' => null, // Leave null for default connection (Redis/PDO)
'provider' => '', // Instance of StorageInterface for custom driver
],
// Vendor files are included by default, but can be set to false.
// This can also be set to 'js' or 'css', to only include javascript or css vendor files.
// Vendor files are for css: font-awesome (including fonts) and highlight.js (css files)
// and for js: jquery and and highlight.js
// So if you want syntax highlighting, set it to true.
// jQuery is set to not conflict with existing jQuery scripts.
'include_vendors' => true,
// The Debugbar can capture Ajax requests and display them. If you don't want this (ie. because of errors),
// you can use this option to disable sending the data through the headers.
// Optionally, you can also send ServerTiming headers on ajax requests for the Chrome DevTools.
'capture_ajax' => true,
'add_ajax_timing' => false,
// When enabled, the Debugbar shows deprecated warnings for Symfony components
// in the Messages tab.
'error_handler' => false,
// The Debugbar can emulate the Clockwork headers, so you can use the Chrome
// Extension, without the server-side code. It uses Debugbar collectors instead.
'clockwork' => false,
// Enable/disable DataCollectors
'collectors' => [
'phpinfo' => true, // Php version
'messages' => true, // Messages
'time' => true, // Time Datalogger
'memory' => true, // Memory usage
'exceptions' => true, // Exception displayer
'log' => true, // Logs from Monolog (merged in messages if enabled)
'db' => true, // Show database (PDO) queries and bindings
'views' => true, // Views with their data
'route' => true, // Current route information
'auth' => true, // Display Laravel authentication status
'gate' => true, // Display Laravel Gate checks
'session' => true, // Display session data
'symfony_request' => true, // Only one can be enabled..
'mail' => true, // Catch mail messages
'laravel' => false, // Laravel version and environment
'events' => false, // All events fired
'default_request' => false, // Regular or special Symfony request logger
'logs' => false, // Add the latest log messages
'files' => false, // Show the included files
'config' => false, // Display config settings
'cache' => false, // Display cache events
'models' => true, // Display models
],
// Configure some DataCollectors
'options' => [
'auth' => [
'show_name' => true, // Also show the users name/email in the debugbar
],
'db' => [
'with_params' => true, // Render SQL with the parameters substituted
'backtrace' => true, // Use a backtrace to find the origin of the query in your files.
'timeline' => false, // Add the queries to the timeline
'explain' => [ // Show EXPLAIN output on queries
'enabled' => false,
'types' => ['SELECT'], // ['SELECT', 'INSERT', 'UPDATE', 'DELETE']; for MySQL 5.6.3+
],
'hints' => true, // Show hints for common mistakes
],
'mail' => [
'full_log' => false,
],
'views' => [
'data' => false, //Note: Can slow down the application, because the data can be quite large..
],
'route' => [
'label' => true, // show complete route on bar
],
'logs' => [
'file' => null,
],
'cache' => [
'values' => true, // collect cache values
],
],
// Inject Debugbar into the response
// Usually, the debugbar is added just before </body>, by listening to the
// Response after the App is done. If you disable this, you have to add them
// in your template yourself. See http://phpdebugbar.com/docs/rendering.html
'inject' => true,
// DebugBar route prefix
// Sometimes you want to set route prefix to be used by DebugBar to load
// its resources from. Usually the need comes from misconfigured web server or
// from trying to overcome bugs like this: http://trac.nginx.org/nginx/ticket/97
'route_prefix' => '_debugbar',
// DebugBar route domain
// By default DebugBar route served from the same domain that request served.
// To override default domain, specify it as a non-empty value.
'route_domain' => env('APP_URL', '') === 'http://bookstack.dev' ? '' : env('APP_URL', ''),
];

View File

@@ -1,21 +1,20 @@
<?php
/**
* DOMPDF configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
return [
/*
|--------------------------------------------------------------------------
| Settings
|--------------------------------------------------------------------------
|
| Set some default values. It is possible to add all defines that can be set
| in dompdf_config.inc.php. You can also override the entire config file.
|
*/
'show_warnings' => false, // Throw an Exception on warnings from dompdf
'orientation' => 'portrait',
'defines' => [
'orientation' => 'portrait',
'defines' => [
/**
* The location of the DOMPDF font directory
* The location of the DOMPDF font directory.
*
* The location of the directory where DOMPDF will store fonts and font metrics
* Note: This directory must exist and be writable by the webserver process.
@@ -38,17 +37,17 @@ return [
* Times-Roman, Times-Bold, Times-BoldItalic, Times-Italic,
* Symbol, ZapfDingbats.
*/
"DOMPDF_FONT_DIR" => app_path('vendor/dompdf/dompdf/lib/fonts/'), //storage_path('fonts/'), // advised by dompdf (https://github.com/dompdf/dompdf/pull/782)
'font_dir' => storage_path('fonts/'), // advised by dompdf (https://github.com/dompdf/dompdf/pull/782)
/**
* The location of the DOMPDF font cache directory
* The location of the DOMPDF font cache directory.
*
* This directory contains the cached font metrics for the fonts used by DOMPDF.
* This directory can be the same as DOMPDF_FONT_DIR
*
* Note: This directory must exist and be writable by the webserver process.
*/
"DOMPDF_FONT_CACHE" => storage_path('fonts/'),
'font_cache' => storage_path('fonts/'),
/**
* The location of a temporary directory.
@@ -57,10 +56,10 @@ return [
* The temporary directory is required to download remote images and when
* using the PFDLib back end.
*/
"DOMPDF_TEMP_DIR" => sys_get_temp_dir(),
'temp_dir' => sys_get_temp_dir(),
/**
* ==== IMPORTANT ====
* ==== IMPORTANT ====.
*
* dompdf's "chroot": Prevents dompdf from accessing system files or other
* files on the webserver. All local files opened by dompdf must be in a
@@ -69,9 +68,9 @@ return [
* should be an absolute path.
* This is only checked on command line call by dompdf.php, but not by
* direct class use like:
* $dompdf = new DOMPDF(); $dompdf->load_html($htmldata); $dompdf->render(); $pdfdata = $dompdf->output();
* $dompdf = new DOMPDF(); $dompdf->load_html($htmldata); $dompdf->render(); $pdfdata = $dompdf->output();
*/
"DOMPDF_CHROOT" => realpath(base_path()),
'chroot' => realpath(base_path()),
/**
* Whether to use Unicode fonts or not.
@@ -82,20 +81,19 @@ return [
* When enabled, dompdf can support all Unicode glyphs. Any glyphs used in a
* document must be present in your fonts, however.
*/
"DOMPDF_UNICODE_ENABLED" => true,
'unicode_enabled' => true,
/**
* Whether to enable font subsetting or not.
*/
"DOMPDF_ENABLE_FONTSUBSETTING" => false,
'enable_fontsubsetting' => false,
/**
* The PDF rendering backend to use
* The PDF rendering backend to use.
*
* Valid settings are 'PDFLib', 'CPDF' (the bundled R&OS PDF class), 'GD' and
* 'auto'. 'auto' will look for PDFLib and use it if found, or if not it will
* fall back on CPDF. 'GD' renders PDFs to graphic files. {@link
* Canvas_Factory} ultimately determines which rendering class to instantiate
* fall back on CPDF. 'GD' renders PDFs to graphic files. {@link * Canvas_Factory} ultimately determines which rendering class to instantiate
* based on this setting.
*
* Both PDFLib & CPDF rendering backends provide sufficient rendering
@@ -117,10 +115,10 @@ return [
* @link http://www.ros.co.nz/pdf
* @link http://www.php.net/image
*/
"DOMPDF_PDF_BACKEND" => "CPDF",
'pdf_backend' => 'CPDF',
/**
* PDFlib license key
* PDFlib license key.
*
* If you are using a licensed, commercial version of PDFlib, specify
* your license key here. If you are using PDFlib-Lite or are evaluating
@@ -143,7 +141,7 @@ return [
* the desired content might be different (e.g. screen or projection view of html file).
* Therefore allow specification of content here.
*/
"DOMPDF_DEFAULT_MEDIA_TYPE" => "print",
'default_media_type' => 'print',
/**
* The default paper size.
@@ -152,18 +150,19 @@ return [
*
* @see CPDF_Adapter::PAPER_SIZES for valid sizes ('letter', 'legal', 'A4', etc.)
*/
"DOMPDF_DEFAULT_PAPER_SIZE" => "a4",
'default_paper_size' => 'a4',
/**
* The default font family
* The default font family.
*
* Used if no suitable fonts can be found. This must exist in the font folder.
*
* @var string
*/
"DOMPDF_DEFAULT_FONT" => "dejavu sans",
'default_font' => 'dejavu sans',
/**
* Image DPI setting
* Image DPI setting.
*
* This setting determines the default DPI setting for images and fonts. The
* DPI may be overridden for inline images by explictly setting the
@@ -195,10 +194,10 @@ return [
*
* @var int
*/
"DOMPDF_DPI" => 96,
'dpi' => 96,
/**
* Enable inline PHP
* Enable inline PHP.
*
* If this setting is set to true then DOMPDF will automatically evaluate
* inline PHP contained within <script type="text/php"> ... </script> tags.
@@ -209,20 +208,20 @@ return [
*
* @var bool
*/
"DOMPDF_ENABLE_PHP" => false,
'enable_php' => false,
/**
* Enable inline Javascript
* Enable inline Javascript.
*
* If this setting is set to true then DOMPDF will automatically insert
* JavaScript code contained within <script type="text/javascript"> ... </script> tags.
*
* @var bool
*/
"DOMPDF_ENABLE_JAVASCRIPT" => true,
'enable_javascript' => false,
/**
* Enable remote file access
* Enable remote file access.
*
* If this setting is set to true, DOMPDF will access remote sites for
* images and CSS files as required.
@@ -238,29 +237,27 @@ return [
*
* @var bool
*/
"DOMPDF_ENABLE_REMOTE" => true,
'enable_remote' => env('ALLOW_UNTRUSTED_SERVER_FETCHING', false),
/**
* A ratio applied to the fonts height to be more like browsers' line height
* A ratio applied to the fonts height to be more like browsers' line height.
*/
"DOMPDF_FONT_HEIGHT_RATIO" => 1.1,
'font_height_ratio' => 1.1,
/**
* Enable CSS float
* Enable CSS float.
*
* Allows people to disabled CSS float support
*
* @var bool
*/
"DOMPDF_ENABLE_CSS_FLOAT" => true,
'enable_css_float' => true,
/**
* Use the more-than-experimental HTML5 Lib parser
* Use the more-than-experimental HTML5 Lib parser.
*/
"DOMPDF_ENABLE_HTML5PARSER" => true,
'enable_html5parser' => true,
],
];

View File

@@ -0,0 +1,57 @@
<?php
/**
* Filesystem configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
return [
// Default Filesystem Disk
// Options: local, local_secure, s3
'default' => env('STORAGE_TYPE', 'local'),
// Filesystem to use specifically for image uploads.
'images' => env('STORAGE_IMAGE_TYPE', env('STORAGE_TYPE', 'local')),
// Filesystem to use specifically for file attachments.
'attachments' => env('STORAGE_ATTACHMENT_TYPE', env('STORAGE_TYPE', 'local')),
// Storage URL
// This is the url to where the storage is located for when using an external
// file storage service, such as s3, to store publicly accessible assets.
'url' => env('STORAGE_URL', false),
// Default Cloud Filesystem Disk
'cloud' => 's3',
// Available filesystem disks
// Only local, local_secure & s3 are supported by BookStack
'disks' => [
'local' => [
'driver' => 'local',
'root' => public_path(),
],
'local_secure' => [
'driver' => 'local',
'root' => storage_path(),
],
's3' => [
'driver' => 's3',
'key' => env('STORAGE_S3_KEY', 'your-key'),
'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,
],
],
];

37
app/Config/hashing.php Normal file
View File

@@ -0,0 +1,37 @@
<?php
/**
* Hashing configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
return [
// Default Hash Driver
// This option controls the default hash driver that will be used to hash
// passwords for your application. By default, the bcrypt algorithm is used.
// Supported: "bcrypt", "argon", "argon2id"
'driver' => 'bcrypt',
// Bcrypt Options
// Here you may specify the configuration options that should be used when
// passwords are hashed using the Bcrypt algorithm. This will allow you
// to control the amount of time it takes to hash the given password.
'bcrypt' => [
'rounds' => env('BCRYPT_ROUNDS', 10),
],
// Argon Options
// Here you may specify the configuration options that should be used when
// passwords are hashed using the Argon algorithm. These will allow you
// to control the amount of time it takes to hash the given password.
'argon' => [
'memory' => 1024,
'threads' => 2,
'time' => 2,
],
];

111
app/Config/logging.php Normal file
View File

@@ -0,0 +1,111 @@
<?php
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\ErrorLogHandler;
use Monolog\Handler\NullHandler;
use Monolog\Handler\StreamHandler;
/**
* Logging configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
return [
// Default Log Channel
// This option defines the default log channel that gets used when writing
// messages to the logs. The name specified in this option should match
// one of the channels defined in the "channels" configuration array.
'default' => env('LOG_CHANNEL', 'single'),
// Log Channels
// Here you may configure the log channels for your application. Out of
// the box, Laravel uses the Monolog PHP logging library. This gives
// you a variety of powerful log handlers / formatters to utilize.
// Available Drivers: "single", "daily", "slack", "syslog",
// "errorlog", "monolog",
// "custom", "stack"
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['daily'],
'ignore_exceptions' => false,
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
'days' => 14,
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
'days' => 7,
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => 'Laravel Log',
'emoji' => ':boom:',
'level' => 'critical',
],
'stderr' => [
'driver' => 'monolog',
'handler' => StreamHandler::class,
'with' => [
'stream' => 'php://stderr',
],
],
'syslog' => [
'driver' => 'syslog',
'level' => 'debug',
],
'errorlog' => [
'driver' => 'errorlog',
'level' => 'debug',
],
// Custom errorlog implementation that logs out a plain,
// non-formatted message intended for the webserver log.
'errorlog_plain_webserver' => [
'driver' => 'monolog',
'level' => 'debug',
'handler' => ErrorLogHandler::class,
'handler_with' => [4],
'formatter' => LineFormatter::class,
'formatter_with' => [
'format' => '%message%',
],
],
'null' => [
'driver' => 'monolog',
'handler' => NullHandler::class,
],
// Testing channel
// Uses a shared testing instance during tests
// so that logs can be checked against.
'testing' => [
'driver' => 'testing',
],
],
// Failed Login Message
// Allows a configurable message to be logged when a login request fails.
'failed_login' => [
'message' => env('LOG_FAILED_LOGIN_MESSAGE', null),
'channel' => env('LOG_FAILED_LOGIN_CHANNEL', 'errorlog_plain_webserver'),
],
];

55
app/Config/mail.php Normal file
View File

@@ -0,0 +1,55 @@
<?php
/**
* Mail configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
return [
// Mail driver to use.
// Options: smtp, sendmail, log, array
'driver' => env('MAIL_DRIVER', 'smtp'),
// SMTP host address
'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
// SMTP host port
'port' => env('MAIL_PORT', 587),
// Global "From" address & name
'from' => [
'address' => env('MAIL_FROM', 'mail@bookstackapp.com'),
'name' => env('MAIL_FROM_NAME', 'BookStack'),
],
// Email encryption protocol
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
// SMTP server username
'username' => env('MAIL_USERNAME'),
// SMTP server password
'password' => env('MAIL_PASSWORD'),
// Sendmail application path
'sendmail' => '/usr/sbin/sendmail -bs',
// Email markdown configuration
'markdown' => [
'theme' => 'default',
'paths' => [
resource_path('views/vendor/mail'),
],
],
// Log Channel
// If you are using the "log" driver, you may specify the logging channel
// if you prefer to keep mail messages separate from other log entries
// for simpler reading. Otherwise, the default channel will be used.
'log_channel' => env('MAIL_LOG_CHANNEL'),
];

46
app/Config/queue.php Normal file
View File

@@ -0,0 +1,46 @@
<?php
/**
* Queue configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
return [
// Default driver to use for the queue
// Options: null, sync, redis
'default' => env('QUEUE_CONNECTION', 'sync'),
// Queue connection configuration
'connections' => [
'sync' => [
'driver' => 'sync',
],
'database' => [
'driver' => 'database',
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 90,
],
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 90,
'block_for' => null,
],
],
// Failed queue job logging
'failed' => [
'database' => 'mysql', 'table' => 'failed_jobs',
],
];

153
app/Config/saml2.php Normal file
View File

@@ -0,0 +1,153 @@
<?php
$SAML2_IDP_AUTHNCONTEXT = env('SAML2_IDP_AUTHNCONTEXT', true);
return [
// Display name, shown to users, for SAML2 option
'name' => env('SAML2_NAME', 'SSO'),
// Dump user details after a login request for debugging purposes
'dump_user_details' => env('SAML2_DUMP_USER_DETAILS', false),
// Attribute, within a SAML response, to find the user's email address
'email_attribute' => env('SAML2_EMAIL_ATTRIBUTE', 'email'),
// Attribute, within a SAML response, to find the user's display name
'display_name_attributes' => explode('|', env('SAML2_DISPLAY_NAME_ATTRIBUTES', 'username')),
// Attribute, within a SAML response, to use to connect a BookStack user to the SAML user.
'external_id_attribute' => env('SAML2_EXTERNAL_ID_ATTRIBUTE', null),
// Group sync options
// Enable syncing, upon login, of SAML2 groups to BookStack groups
'user_to_groups' => env('SAML2_USER_TO_GROUPS', false),
// Attribute, within a SAML response, to find group names on
'group_attribute' => env('SAML2_GROUP_ATTRIBUTE', 'group'),
// When syncing groups, remove any groups that no longer match. Otherwise sync only adds new groups.
'remove_from_groups' => env('SAML2_REMOVE_FROM_GROUPS', false),
// Autoload IDP details from the metadata endpoint
'autoload_from_metadata' => env('SAML2_AUTOLOAD_METADATA', false),
// Overrides, in JSON format, to the configuration passed to underlying onelogin library.
'onelogin_overrides' => env('SAML2_ONELOGIN_OVERRIDES', null),
'onelogin' => [
// If 'strict' is True, then the PHP Toolkit will reject unsigned
// or unencrypted messages if it expects them signed or encrypted
// Also will reject the messages if not strictly follow the SAML
// standard: Destination, NameId, Conditions ... are validated too.
'strict' => true,
// Enable debug mode (to print errors)
'debug' => env('APP_DEBUG', false),
// Set a BaseURL to be used instead of try to guess
// the BaseURL of the view that process the SAML Message.
// Ex. http://sp.example.com/
// http://example.com/sp/
'baseurl' => null,
// Service Provider Data that we are deploying
'sp' => [
// Identifier of the SP entity (must be a URI)
'entityId' => '',
// Specifies info about where and how the <AuthnResponse> message MUST be
// returned to the requester, in this case our SP.
'assertionConsumerService' => [
// URL Location where the <Response> from the IdP will be returned
'url' => '',
// SAML protocol binding to be used when returning the <Response>
// message. Onelogin Toolkit supports for this endpoint the
// HTTP-POST binding only
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
],
// Specifies info about where and how the <Logout Response> message MUST be
// returned to the requester, in this case our SP.
'singleLogoutService' => [
// URL Location where the <Response> from the IdP will be returned
'url' => '',
// SAML protocol binding to be used when returning the <Response>
// message. Onelogin Toolkit supports for this endpoint the
// HTTP-Redirect binding only
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
],
// Specifies constraints on the name identifier to be used to
// represent the requested subject.
// Take a look on lib/Saml2/Constants.php to see the NameIdFormat supported
'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
// Usually x509cert and privateKey of the SP are provided by files placed at
// the certs folder. But we can also provide them with the following parameters
'x509cert' => '',
'privateKey' => '',
],
// Identity Provider Data that we want connect with our SP
'idp' => [
// Identifier of the IdP entity (must be a URI)
'entityId' => env('SAML2_IDP_ENTITYID', null),
// SSO endpoint info of the IdP. (Authentication Request protocol)
'singleSignOnService' => [
// URL Target of the IdP where the SP will send the Authentication Request Message
'url' => env('SAML2_IDP_SSO', null),
// SAML protocol binding to be used when returning the <Response>
// message. Onelogin Toolkit supports for this endpoint the
// HTTP-Redirect binding only
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
],
// SLO endpoint info of the IdP.
'singleLogoutService' => [
// URL Location of the IdP where the SP will send the SLO Request
'url' => env('SAML2_IDP_SLO', null),
// URL location of the IdP where the SP will send the SLO Response (ResponseLocation)
// if not set, url for the SLO Request will be used
'responseUrl' => null,
// SAML protocol binding to be used when returning the <Response>
// message. Onelogin Toolkit supports for this endpoint the
// HTTP-Redirect binding only
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
],
// Public x509 certificate of the IdP
'x509cert' => env('SAML2_IDP_x509', null),
/*
* Instead of use the whole x509cert you can use a fingerprint in
* order to validate the SAMLResponse, but we don't recommend to use
* that method on production since is exploitable by a collision
* attack.
* (openssl x509 -noout -fingerprint -in "idp.crt" to generate it,
* or add for example the -sha256 , -sha384 or -sha512 parameter)
*
* If a fingerprint is provided, then the certFingerprintAlgorithm is required in order to
* let the toolkit know which Algorithm was used. Possible values: sha1, sha256, sha384 or sha512
* 'sha1' is the default value.
*/
// 'certFingerprint' => '',
// 'certFingerprintAlgorithm' => 'sha1',
/* In some scenarios the IdP uses different certificates for
* signing/encryption, or is under key rollover phase and more
* than one certificate is published on IdP metadata.
* In order to handle that the toolkit offers that parameter.
* (when used, 'x509cert' and 'certFingerprint' values are
* ignored).
*/
// 'x509certMulti' => array(
// 'signing' => array(
// 0 => '<cert1-string>',
// ),
// 'encryption' => array(
// 0 => '<cert2-string>',
// )
// ),
],
'security' => [
// SAML2 Authn context
// When set to false no AuthContext will be sent in the AuthNRequest,
// When set to true (Default) you will get an AuthContext 'exact' 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'.
// Multiple forced values can be passed via a space separated array, For example:
// SAML2_IDP_AUTHNCONTEXT="urn:federation:authentication:windows urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
'requestedAuthnContext' => is_string($SAML2_IDP_AUTHNCONTEXT) ? explode(' ', $SAML2_IDP_AUTHNCONTEXT) : $SAML2_IDP_AUTHNCONTEXT,
],
],
];

139
app/Config/services.php Normal file
View File

@@ -0,0 +1,139 @@
<?php
/**
* Third party service configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
return [
// Single option to disable non-auth external services such as Gravatar and Draw.io
'disable_services' => env('DISABLE_EXTERNAL_SERVICES', false),
// Draw.io integration active
'drawio' => env('DRAWIO', !env('DISABLE_EXTERNAL_SERVICES', false)),
// URL for fetching avatars
'avatar_url' => env('AVATAR_URL', ''),
// Callback URL for social authentication methods
'callback_url' => env('APP_URL', false),
'github' => [
'client_id' => env('GITHUB_APP_ID', false),
'client_secret' => env('GITHUB_APP_SECRET', false),
'redirect' => env('APP_URL') . '/login/service/github/callback',
'name' => 'GitHub',
'auto_register' => env('GITHUB_AUTO_REGISTER', false),
'auto_confirm' => env('GITHUB_AUTO_CONFIRM_EMAIL', false),
],
'google' => [
'client_id' => env('GOOGLE_APP_ID', false),
'client_secret' => env('GOOGLE_APP_SECRET', false),
'redirect' => env('APP_URL') . '/login/service/google/callback',
'name' => 'Google',
'auto_register' => env('GOOGLE_AUTO_REGISTER', false),
'auto_confirm' => env('GOOGLE_AUTO_CONFIRM_EMAIL', false),
'select_account' => env('GOOGLE_SELECT_ACCOUNT', false),
],
'slack' => [
'client_id' => env('SLACK_APP_ID', false),
'client_secret' => env('SLACK_APP_SECRET', false),
'redirect' => env('APP_URL') . '/login/service/slack/callback',
'name' => 'Slack',
'auto_register' => env('SLACK_AUTO_REGISTER', false),
'auto_confirm' => env('SLACK_AUTO_CONFIRM_EMAIL', false),
],
'facebook' => [
'client_id' => env('FACEBOOK_APP_ID', false),
'client_secret' => env('FACEBOOK_APP_SECRET', false),
'redirect' => env('APP_URL') . '/login/service/facebook/callback',
'name' => 'Facebook',
'auto_register' => env('FACEBOOK_AUTO_REGISTER', false),
'auto_confirm' => env('FACEBOOK_AUTO_CONFIRM_EMAIL', false),
],
'twitter' => [
'client_id' => env('TWITTER_APP_ID', false),
'client_secret' => env('TWITTER_APP_SECRET', false),
'redirect' => env('APP_URL') . '/login/service/twitter/callback',
'name' => 'Twitter',
'auto_register' => env('TWITTER_AUTO_REGISTER', false),
'auto_confirm' => env('TWITTER_AUTO_CONFIRM_EMAIL', false),
],
'azure' => [
'client_id' => env('AZURE_APP_ID', false),
'client_secret' => env('AZURE_APP_SECRET', false),
'tenant' => env('AZURE_TENANT', false),
'redirect' => env('APP_URL') . '/login/service/azure/callback',
'name' => 'Microsoft Azure',
'auto_register' => env('AZURE_AUTO_REGISTER', false),
'auto_confirm' => env('AZURE_AUTO_CONFIRM_EMAIL', false),
],
'okta' => [
'client_id' => env('OKTA_APP_ID'),
'client_secret' => env('OKTA_APP_SECRET'),
'redirect' => env('APP_URL') . '/login/service/okta/callback',
'base_url' => env('OKTA_BASE_URL'),
'name' => 'Okta',
'auto_register' => env('OKTA_AUTO_REGISTER', false),
'auto_confirm' => env('OKTA_AUTO_CONFIRM_EMAIL', false),
],
'gitlab' => [
'client_id' => env('GITLAB_APP_ID'),
'client_secret' => env('GITLAB_APP_SECRET'),
'redirect' => env('APP_URL') . '/login/service/gitlab/callback',
'instance_uri' => env('GITLAB_BASE_URI'), // Needed only for self hosted instances
'name' => 'GitLab',
'auto_register' => env('GITLAB_AUTO_REGISTER', false),
'auto_confirm' => env('GITLAB_AUTO_CONFIRM_EMAIL', false),
],
'twitch' => [
'client_id' => env('TWITCH_APP_ID'),
'client_secret' => env('TWITCH_APP_SECRET'),
'redirect' => env('APP_URL') . '/login/service/twitch/callback',
'name' => 'Twitch',
'auto_register' => env('TWITCH_AUTO_REGISTER', false),
'auto_confirm' => env('TWITCH_AUTO_CONFIRM_EMAIL', false),
],
'discord' => [
'client_id' => env('DISCORD_APP_ID'),
'client_secret' => env('DISCORD_APP_SECRET'),
'redirect' => env('APP_URL') . '/login/service/discord/callback',
'name' => 'Discord',
'auto_register' => env('DISCORD_AUTO_REGISTER', false),
'auto_confirm' => env('DISCORD_AUTO_CONFIRM_EMAIL', false),
],
'ldap' => [
'server' => env('LDAP_SERVER', false),
'dump_user_details' => env('LDAP_DUMP_USER_DETAILS', false),
'dn' => env('LDAP_DN', false),
'pass' => env('LDAP_PASS', false),
'base_dn' => env('LDAP_BASE_DN', false),
'user_filter' => env('LDAP_USER_FILTER', '(&(uid=${user}))'),
'version' => env('LDAP_VERSION', false),
'id_attribute' => env('LDAP_ID_ATTRIBUTE', 'uid'),
'email_attribute' => env('LDAP_EMAIL_ATTRIBUTE', 'mail'),
'display_name_attribute' => env('LDAP_DISPLAY_NAME_ATTRIBUTE', 'cn'),
'follow_referrals' => env('LDAP_FOLLOW_REFERRALS', false),
'user_to_groups' => env('LDAP_USER_TO_GROUPS', false),
'group_attribute' => env('LDAP_GROUP_ATTRIBUTE', 'memberOf'),
'remove_from_groups' => env('LDAP_REMOVE_FROM_GROUPS', false),
'tls_insecure' => env('LDAP_TLS_INSECURE', false),
'start_tls' => env('LDAP_START_TLS', false),
'thumbnail_attribute' => env('LDAP_THUMBNAIL_ATTRIBUTE', null),
],
];

88
app/Config/session.php Normal file
View File

@@ -0,0 +1,88 @@
<?php
use Illuminate\Support\Str;
/**
* Session configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
return [
// Default session driver
// Options: file, cookie, database, redis, memcached, array
'driver' => env('SESSION_DRIVER', 'file'),
// Session lifetime, in minutes
'lifetime' => env('SESSION_LIFETIME', 120),
// Expire session on browser close
'expire_on_close' => false,
// Encrypt session data
'encrypt' => false,
// Location to store session files
'files' => storage_path('framework/sessions'),
// Session Database Connection
// When using the "database" or "redis" session drivers, you can specify a
// connection that should be used to manage these sessions. This should
// correspond to a connection in your database configuration options.
'connection' => null,
// Session database table, if database driver is in use
'table' => 'sessions',
// Session Cache Store
// When using the "apc" or "memcached" session drivers, you may specify a
// cache store that should be used for these sessions. This value must
// correspond with one of the application's configured cache stores.
'store' => null,
// Session Sweeping Lottery
// Some session drivers must manually sweep their storage location to get
// rid of old sessions from storage. Here are the chances that it will
// happen on a given request. By default, the odds are 2 out of 100.
'lottery' => [2, 100],
// Session Cookie Name
// Here you may change the name of the cookie used to identify a session
// instance by ID. The name specified here will get used every time a
// new session cookie is created by the framework for every driver.
'cookie' => env('SESSION_COOKIE_NAME', 'bookstack_session'),
// Session Cookie Path
// The session cookie path determines the path for which the cookie will
// be regarded as available. Typically, this will be the root path of
// your application but you are free to change this when necessary.
'path' => '/' . (explode('/', env('APP_URL', ''), 4)[3] ?? ''),
// Session Cookie Domain
// Here you may change the domain of the cookie used to identify a session
// in your application. This will determine which domains the cookie is
// available to in your application. A sensible default has been set.
'domain' => env('SESSION_DOMAIN', null),
// HTTPS Only Cookies
// By setting this option to true, session cookies will only be sent back
// to the server if the browser has a HTTPS connection. This will keep
// the cookie from being sent to you if it can not be done securely.
'secure' => env('SESSION_SECURE_COOKIE', null)
?? Str::startsWith(env('APP_URL'), 'https:'),
// HTTP Access Only
// Setting this value to true will prevent JavaScript from accessing the
// value of the cookie and the cookie will only be accessible through the HTTP protocol.
'http_only' => true,
// Same-Site Cookies
// This option determines how your cookies behave when cross-site requests
// take place, and can be used to mitigate CSRF attacks. By default, we
// do not enable this as other CSRF protection services are in place.
// Options: lax, strict, none
'same_site' => 'lax',
];

View File

@@ -0,0 +1,35 @@
<?php
/**
* Default system settings.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
return [
'app-name' => 'BookStack',
'app-logo' => '',
'app-name-header' => true,
'app-editor' => 'wysiwyg',
'app-color' => '#206ea7',
'app-color-light' => 'rgba(32,110,167,0.15)',
'bookshelf-color' => '#a94747',
'book-color' => '#077b70',
'chapter-color' => '#af4d0d',
'page-color' => '#206ea7',
'page-draft-color' => '#7e50b1',
'app-custom-head' => false,
'registration-enabled' => false,
// User-level default settings
'user' => [
'dark-mode-enabled' => env('APP_DEFAULT_DARK_MODE', false),
'bookshelves_view_type' => env('APP_VIEWS_BOOKSHELVES', 'grid'),
'bookshelf_view_type' => env('APP_VIEWS_BOOKSHELF', 'grid'),
'books_view_type' => env('APP_VIEWS_BOOKS', 'grid'),
],
];

View File

@@ -1,11 +1,21 @@
<?php
/**
* SnappyPDF configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
return [
'pdf' => [
'enabled' => true,
'binary' => file_exists(base_path('wkhtmltopdf')) ? base_path('wkhtmltopdf') : env('WKHTMLTOPDF', false),
'timeout' => false,
'options' => [],
'options' => [
'outline' => true,
],
'env' => [],
],
'image' => [

37
app/Config/view.php Normal file
View File

@@ -0,0 +1,37 @@
<?php
/**
* View configuration options.
*
* Changes to these config files are not supported by BookStack and may break upon updates.
* Configuration should be altered via the `.env` file or environment variables.
* Do not edit this file unless you're happy to maintain any changes yourself.
*/
// Join up possible view locations
$viewPaths = [realpath(base_path('resources/views'))];
if ($theme = env('APP_THEME', false)) {
array_unshift($viewPaths, base_path('themes/' . $theme));
}
return [
// App theme
// This option defines the theme to use for the application. When a theme
// is set there must be a `themes/<theme_name>` folder to hold the
// custom theme overrides.
'theme' => env('APP_THEME', false),
// View Storage Paths
// Most templating systems load templates from disk. Here you may specify
// an array of paths that should be checked for your views. Of course
// the usual Laravel view path has already been registered for you.
'paths' => $viewPaths,
// Compiled View Path
// This option determines where all the compiled Blade templates will be
// stored for your application. Typically, this is within the storage
// directory. However, as usual, you are free to change this value.
'compiled' => realpath(storage_path('framework/views')),
];

View File

@@ -2,7 +2,7 @@
namespace BookStack\Console\Commands;
use BookStack\Services\ImageService;
use BookStack\Uploads\ImageService;
use Illuminate\Console\Command;
use Symfony\Component\Console\Output\OutputInterface;
@@ -14,8 +14,8 @@ class CleanupImages extends Command
* @var string
*/
protected $signature = 'bookstack:cleanup-images
{--a|all : Include images that are used in page revisions}
{--f|force : Actually run the deletions}
{--a|all : Also delete images that are only used in old revisions}
{--f|force : Actually run the deletions, Defaults to a dry-run}
';
/**
@@ -25,12 +25,12 @@ class CleanupImages extends Command
*/
protected $description = 'Cleanup images and drawings';
protected $imageService;
/**
* Create a new command instance.
* @param ImageService $imageService
*
* @param \BookStack\Uploads\ImageService $imageService
*/
public function __construct(ImageService $imageService)
{
@@ -63,6 +63,7 @@ class CleanupImages extends Command
$this->comment($deleteCount . ' images found that would have been deleted');
$this->showDeletedImages($deleted);
$this->comment('Run with -f or --force to perform deletions');
return;
}
@@ -72,7 +73,9 @@ class CleanupImages extends Command
protected function showDeletedImages($paths)
{
if ($this->getOutput()->getVerbosity() <= OutputInterface::VERBOSITY_NORMAL) return;
if ($this->getOutput()->getVerbosity() <= OutputInterface::VERBOSITY_NORMAL) {
return;
}
if (count($paths) > 0) {
$this->line('Images to delete:');
}

View File

@@ -2,7 +2,7 @@
namespace BookStack\Console\Commands;
use BookStack\Activity;
use BookStack\Actions\Activity;
use Illuminate\Console\Command;
class ClearActivity extends Command

View File

@@ -2,7 +2,7 @@
namespace BookStack\Console\Commands;
use BookStack\PageRevision;
use BookStack\Entities\Models\PageRevision;
use Illuminate\Console\Command;
class ClearRevisions extends Command

View File

@@ -2,6 +2,7 @@
namespace BookStack\Console\Commands;
use BookStack\Actions\View;
use Illuminate\Console\Command;
class ClearViews extends Command
@@ -18,11 +19,10 @@ class ClearViews extends Command
*
* @var string
*/
protected $description = 'Clear all view-counts for all entities.';
protected $description = 'Clear all view-counts for all entities';
/**
* Create a new command instance.
*
*/
public function __construct()
{
@@ -36,7 +36,7 @@ class ClearViews extends Command
*/
public function handle()
{
\Views::resetAll();
View::clearAll();
$this->comment('Views cleared');
}
}

View File

@@ -0,0 +1,89 @@
<?php
namespace BookStack\Console\Commands;
use BookStack\Entities\Models\Bookshelf;
use BookStack\Entities\Repos\BookshelfRepo;
use Illuminate\Console\Command;
class CopyShelfPermissions extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'bookstack:copy-shelf-permissions
{--a|all : Perform for all shelves in the system}
{--s|slug= : The slug for a shelf to target}
';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Copy shelf permissions to all child books';
/**
* @var BookshelfRepo
*/
protected $bookshelfRepo;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(BookshelfRepo $repo)
{
$this->bookshelfRepo = $repo;
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$shelfSlug = $this->option('slug');
$cascadeAll = $this->option('all');
$shelves = null;
if (!$cascadeAll && !$shelfSlug) {
$this->error('Either a --slug or --all option must be provided.');
return;
}
if ($cascadeAll) {
$continue = $this->confirm(
'Permission settings for all shelves will be cascaded. ' .
'Books assigned to multiple shelves will receive only the permissions of it\'s last processed shelf. ' .
'Are you sure you want to proceed?'
);
if (!$continue && !$this->hasOption('no-interaction')) {
return;
}
$shelves = Bookshelf::query()->get(['id', 'restricted']);
}
if ($shelfSlug) {
$shelves = Bookshelf::query()->where('slug', '=', $shelfSlug)->get(['id', 'restricted']);
if ($shelves->count() === 0) {
$this->info('No shelves found with the given slug.');
}
}
foreach ($shelves as $shelf) {
$this->bookshelfRepo->copyDownPermissions($shelf, false);
$this->info('Copied permissions for shelf [' . $shelf->id . ']');
}
$this->info('Permissions copied for ' . $shelves->count() . ' shelves.');
}
}

View File

@@ -2,7 +2,7 @@
namespace BookStack\Console\Commands;
use BookStack\Repos\UserRepo;
use BookStack\Auth\UserRepo;
use Illuminate\Console\Command;
class CreateAdmin extends Command
@@ -28,8 +28,6 @@ class CreateAdmin extends Command
/**
* Create a new command instance.
*
* @param UserRepo $userRepo
*/
public function __construct(UserRepo $userRepo)
{
@@ -40,8 +38,9 @@ class CreateAdmin extends Command
/**
* Execute the console command.
*
* @return mixed
* @throws \BookStack\Exceptions\NotFoundException
*
* @return mixed
*/
public function handle()
{
@@ -49,7 +48,7 @@ class CreateAdmin extends Command
if (empty($email)) {
$email = $this->ask('Please specify an email address for the new admin user');
}
if (strlen($email) < 5 || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
if (mb_strlen($email) < 5 || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
return $this->error('Invalid email address provided');
}
@@ -61,7 +60,7 @@ class CreateAdmin extends Command
if (empty($name)) {
$name = $this->ask('Please specify an name for the new admin user');
}
if (strlen($name) < 2) {
if (mb_strlen($name) < 2) {
return $this->error('Invalid name provided');
}
@@ -69,14 +68,13 @@ class CreateAdmin extends Command
if (empty($password)) {
$password = $this->secret('Please specify a password for the new admin user');
}
if (strlen($password) < 5) {
if (mb_strlen($password) < 5) {
return $this->error('Invalid password provided, Must be at least 5 characters');
}
$user = $this->userRepo->create(['email' => $email, 'name' => $name, 'password' => $password]);
$this->userRepo->attachSystemRole($user, 'admin');
$this->userRepo->downloadGravatarToUserAvatar($user);
$this->userRepo->downloadAndAssignUserAvatar($user);
$user->email_confirmed = true;
$user->save();

View File

@@ -2,13 +2,12 @@
namespace BookStack\Console\Commands;
use BookStack\User;
use BookStack\Repos\UserRepo;
use BookStack\Auth\User;
use BookStack\Auth\UserRepo;
use Illuminate\Console\Command;
class DeleteUsers extends Command
{
/**
* The name and signature of the console command.
*
@@ -25,7 +24,7 @@ class DeleteUsers extends Command
*
* @var string
*/
protected $description = 'Delete users that are not "admin" or system users.';
protected $description = 'Delete users that are not "admin" or system users';
public function __construct(User $user, UserRepo $userRepo)
{
@@ -47,7 +46,7 @@ class DeleteUsers extends Command
continue;
}
$this->userRepo->destroy($user);
++$numDeleted;
$numDeleted++;
}
$this->info("Deleted $numDeleted of $totalUsers total users.");
} else {

View File

@@ -0,0 +1,61 @@
<?php
namespace BookStack\Console\Commands;
use BookStack\Actions\Comment;
use BookStack\Actions\CommentRepo;
use Illuminate\Console\Command;
class RegenerateCommentContent extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'bookstack:regenerate-comment-content {--database= : The database connection to use.}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Regenerate the stored HTML of all comments';
/**
* @var CommentRepo
*/
protected $commentRepo;
/**
* Create a new command instance.
*/
public function __construct(CommentRepo $commentRepo)
{
$this->commentRepo = $commentRepo;
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$connection = \DB::getDefaultConnection();
if ($this->option('database') !== null) {
\DB::setDefaultConnection($this->option('database'));
}
Comment::query()->chunk(100, function ($comments) {
foreach ($comments as $comment) {
$comment->html = $this->commentRepo->commentToHtml($comment->text);
$comment->save();
}
});
\DB::setDefaultConnection($connection);
$this->comment('Comment HTML content has been regenerated');
}
}

View File

@@ -2,7 +2,7 @@
namespace BookStack\Console\Commands;
use BookStack\Services\PermissionService;
use BookStack\Auth\Permissions\PermissionService;
use Illuminate\Console\Command;
class RegeneratePermissions extends Command
@@ -30,8 +30,6 @@ class RegeneratePermissions extends Command
/**
* Create a new command instance.
*
* @param PermissionService $permissionService
*/
public function __construct(PermissionService $permissionService)
{

View File

@@ -2,7 +2,8 @@
namespace BookStack\Console\Commands;
use BookStack\Services\SearchService;
use BookStack\Entities\Tools\SearchIndex;
use DB;
use Illuminate\Console\Command;
class RegenerateSearch extends Command
@@ -21,17 +22,15 @@ class RegenerateSearch extends Command
*/
protected $description = 'Re-index all content for searching';
protected $searchService;
protected $searchIndex;
/**
* Create a new command instance.
*
* @param SearchService $searchService
*/
public function __construct(SearchService $searchService)
public function __construct(SearchIndex $searchIndex)
{
parent::__construct();
$this->searchService = $searchService;
$this->searchIndex = $searchIndex;
}
/**
@@ -41,14 +40,13 @@ class RegenerateSearch extends Command
*/
public function handle()
{
$connection = \DB::getDefaultConnection();
$connection = DB::getDefaultConnection();
if ($this->option('database') !== null) {
\DB::setDefaultConnection($this->option('database'));
$this->searchService->setConnection(\DB::connection($this->option('database')));
DB::setDefaultConnection($this->option('database'));
}
$this->searchService->indexAllEntities();
\DB::setDefaultConnection($connection);
$this->searchIndex->indexAllEntities();
DB::setDefaultConnection($connection);
$this->comment('Search index regenerated');
}
}

View File

@@ -0,0 +1,77 @@
<?php
namespace BookStack\Console\Commands;
use BookStack\Auth\User;
use Illuminate\Console\Command;
class ResetMfa extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'bookstack:reset-mfa
{--id= : Numeric ID of the user to reset MFA for}
{--email= : Email address of the user to reset MFA for}
';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Reset & Clear any configured MFA methods for the given user';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$id = $this->option('id');
$email = $this->option('email');
if (!$id && !$email) {
$this->error('Either a --id=<number> or --email=<email> option must be provided.');
return 1;
}
/** @var User $user */
$field = $id ? 'id' : 'email';
$value = $id ?: $email;
$user = User::query()
->where($field, '=', $value)
->first();
if (!$user) {
$this->error("A user where {$field}={$value} could not be found.");
return 1;
}
$this->info("This will delete any configure multi-factor authentication methods for user: \n- ID: {$user->id}\n- Name: {$user->name}\n- Email: {$user->email}\n");
$this->info('If multi-factor authentication is required for this user they will be asked to reconfigure their methods on next login.');
$confirm = $this->confirm('Are you sure you want to proceed?');
if ($confirm) {
$user->mfaValues()->delete();
$this->info('User MFA methods have been reset.');
return 0;
}
return 1;
}
}

View File

@@ -0,0 +1,122 @@
<?php
namespace BookStack\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Database\Connection;
class UpdateUrl extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'bookstack:update-url
{oldUrl : URL to replace}
{newUrl : URL to use as the replacement}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Find and replace the given URLs in your BookStack database';
protected $db;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(Connection $db)
{
$this->db = $db;
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$oldUrl = str_replace("'", '', $this->argument('oldUrl'));
$newUrl = str_replace("'", '', $this->argument('newUrl'));
$urlPattern = '/https?:\/\/(.+)/';
if (!preg_match($urlPattern, $oldUrl) || !preg_match($urlPattern, $newUrl)) {
$this->error('The given urls are expected to be full urls starting with http:// or https://');
return 1;
}
if (!$this->checkUserOkayToProceed($oldUrl, $newUrl)) {
return 1;
}
$columnsToUpdateByTable = [
'attachments' => ['path'],
'pages' => ['html', 'text', 'markdown'],
'images' => ['url'],
'settings' => ['value'],
'comments' => ['html', 'text'],
];
foreach ($columnsToUpdateByTable as $table => $columns) {
foreach ($columns as $column) {
$changeCount = $this->replaceValueInTable($table, $column, $oldUrl, $newUrl);
$this->info("Updated {$changeCount} rows in {$table}->{$column}");
}
}
$jsonColumnsToUpdateByTable = [
'settings' => ['value'],
];
foreach ($jsonColumnsToUpdateByTable as $table => $columns) {
foreach ($columns as $column) {
$oldJson = trim(json_encode($oldUrl), '"');
$newJson = trim(json_encode($newUrl), '"');
$changeCount = $this->replaceValueInTable($table, $column, $oldJson, $newJson);
$this->info("Updated {$changeCount} JSON encoded rows in {$table}->{$column}");
}
}
$this->info('URL update procedure complete.');
$this->info('============================================================================');
$this->info('Be sure to run "php artisan cache:clear" to clear any old URLs in the cache.');
$this->info('============================================================================');
return 0;
}
/**
* Perform a find+replace operations in the provided table and column.
* Returns the count of rows changed.
*/
protected function replaceValueInTable(string $table, string $column, string $oldUrl, string $newUrl): int
{
$oldQuoted = $this->db->getPdo()->quote($oldUrl);
$newQuoted = $this->db->getPdo()->quote($newUrl);
return $this->db->table($table)->update([
$column => $this->db->raw("REPLACE({$column}, {$oldQuoted}, {$newQuoted})"),
]);
}
/**
* Warn the user of the dangers of this operation.
* Returns a boolean indicating if they've accepted the warnings.
*/
protected function checkUserOkayToProceed(string $oldUrl, string $newUrl): bool
{
$dangerWarning = "This will search for \"{$oldUrl}\" in your database and replace it with \"{$newUrl}\".\n";
$dangerWarning .= 'Are you sure you want to proceed?';
$backupConfirmation = 'This operation could cause issues if used incorrectly. Have you made a backup of your existing database?';
return $this->confirm($dangerWarning) && $this->confirm($backupConfirmation);
}
}

View File

@@ -23,7 +23,6 @@ class UpgradeDatabaseEncoding extends Command
/**
* Create a new command instance.
*
*/
public function __construct()
{
@@ -44,12 +43,12 @@ class UpgradeDatabaseEncoding extends Command
$database = DB::getDatabaseName();
$tables = DB::select('SHOW TABLES');
$this->line('ALTER DATABASE `'.$database.'` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
$this->line('USE `'.$database.'`;');
$this->line('ALTER DATABASE `' . $database . '` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
$this->line('USE `' . $database . '`;');
$key = 'Tables_in_' . $database;
foreach ($tables as $table) {
$tableName = $table->$key;
$this->line('ALTER TABLE `'.$tableName.'` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
$this->line('ALTER TABLE `' . $tableName . '` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
}
DB::setDefaultConnection($connection);

View File

@@ -1,4 +1,6 @@
<?php namespace BookStack\Console;
<?php
namespace BookStack\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
@@ -17,7 +19,8 @@ class Kernel extends ConsoleKernel
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @param \Illuminate\Console\Scheduling\Schedule $schedule
*
* @return void
*/
protected function schedule(Schedule $schedule)
@@ -32,6 +35,6 @@ class Kernel extends ConsoleKernel
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
$this->load(__DIR__ . '/Commands');
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace BookStack\Entities;
use BookStack\Entities\Models\Book;
use BookStack\Entities\Tools\ShelfContext;
use Illuminate\View\View;
class BreadcrumbsViewComposer
{
protected $entityContextManager;
/**
* BreadcrumbsViewComposer constructor.
*
* @param ShelfContext $entityContextManager
*/
public function __construct(ShelfContext $entityContextManager)
{
$this->entityContextManager = $entityContextManager;
}
/**
* Modify data when the view is composed.
*
* @param View $view
*/
public function compose(View $view)
{
$crumbs = $view->getData()['crumbs'];
$firstCrumb = $crumbs[0] ?? null;
if ($firstCrumb instanceof Book) {
$shelf = $this->entityContextManager->getContextualShelfForBook($firstCrumb);
if ($shelf) {
array_unshift($crumbs, $shelf);
$view->with('crumbs', $crumbs);
}
}
}
}

View File

@@ -0,0 +1,94 @@
<?php
namespace BookStack\Entities;
use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Bookshelf;
use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Models\Entity;
use BookStack\Entities\Models\Page;
use BookStack\Entities\Models\PageRevision;
/**
* Class EntityProvider.
*
* Provides access to the core entity models.
* Wrapped up in this provider since they are often used together
* so this is a neater alternative to injecting all in individually.
*/
class EntityProvider
{
/**
* @var Bookshelf
*/
public $bookshelf;
/**
* @var Book
*/
public $book;
/**
* @var Chapter
*/
public $chapter;
/**
* @var Page
*/
public $page;
/**
* @var PageRevision
*/
public $pageRevision;
public function __construct()
{
$this->bookshelf = new Bookshelf();
$this->book = new Book();
$this->chapter = new Chapter();
$this->page = new Page();
$this->pageRevision = new PageRevision();
}
/**
* Fetch all core entity types as an associated array
* with their basic names as the keys.
*
* @return array<Entity>
*/
public function all(): array
{
return [
'bookshelf' => $this->bookshelf,
'book' => $this->book,
'chapter' => $this->chapter,
'page' => $this->page,
];
}
/**
* Get an entity instance by it's basic name.
*/
public function get(string $type): Entity
{
$type = strtolower($type);
return $this->all()[$type];
}
/**
* Get the morph classes, as an array, for a single or multiple types.
*/
public function getMorphClasses(array $types): array
{
$morphClasses = [];
foreach ($types as $type) {
$model = $this->get($type);
$morphClasses[] = $model->getMorphClass();
}
return $morphClasses;
}
}

View File

@@ -0,0 +1,126 @@
<?php
namespace BookStack\Entities\Models;
use BookStack\Uploads\Image;
use Exception;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Collection;
/**
* Class Book.
*
* @property string $description
* @property int $image_id
* @property Image|null $cover
*/
class Book extends Entity implements HasCoverImage
{
public $searchFactor = 2;
protected $fillable = ['name', 'description'];
protected $hidden = ['restricted', 'pivot', 'image_id', 'deleted_at'];
/**
* Get the url for this book.
*/
public function getUrl(string $path = ''): string
{
return url('/books/' . implode('/', [urlencode($this->slug), trim($path, '/')]));
}
/**
* Returns book cover image, if book cover not exists return default cover image.
*
* @param int $width - Width of the image
* @param int $height - Height of the image
*
* @return string
*/
public function getBookCover($width = 440, $height = 250)
{
$default = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
if (!$this->image_id) {
return $default;
}
try {
$cover = $this->cover ? url($this->cover->getThumb($width, $height, false)) : $default;
} catch (Exception $err) {
$cover = $default;
}
return $cover;
}
/**
* Get the cover image of the book.
*/
public function cover(): BelongsTo
{
return $this->belongsTo(Image::class, 'image_id');
}
/**
* Get the type of the image model that is used when storing a cover image.
*/
public function coverImageTypeKey(): string
{
return 'cover_book';
}
/**
* Get all pages within this book.
*
* @return HasMany
*/
public function pages()
{
return $this->hasMany(Page::class);
}
/**
* Get the direct child pages of this book.
*
* @return HasMany
*/
public function directPages()
{
return $this->pages()->where('chapter_id', '=', '0');
}
/**
* Get all chapters within this book.
*
* @return HasMany
*/
public function chapters()
{
return $this->hasMany(Chapter::class);
}
/**
* Get the shelves this book is contained within.
*
* @return BelongsToMany
*/
public function shelves()
{
return $this->belongsToMany(Bookshelf::class, 'bookshelves_books', 'book_id', 'bookshelf_id');
}
/**
* Get the direct child items within this book.
*
* @return Collection
*/
public function getDirectChildren(): Collection
{
$pages = $this->directPages()->visible()->get();
$chapters = $this->chapters()->visible()->get();
return $pages->concat($chapters)->sortBy('priority')->sortByDesc('draft');
}
}

View File

@@ -0,0 +1,74 @@
<?php
namespace BookStack\Entities\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* Class BookChild.
*
* @property int $book_id
* @property int $priority
* @property string $book_slug
* @property Book $book
*
* @method Builder whereSlugs(string $bookSlug, string $childSlug)
*/
abstract class BookChild extends Entity
{
protected static function boot()
{
parent::boot();
// Load book slugs onto these models by default during query-time
static::addGlobalScope('book_slug', function (Builder $builder) {
$builder->addSelect(['book_slug' => function ($builder) {
$builder->select('slug')
->from('books')
->whereColumn('books.id', '=', 'book_id');
}]);
});
}
/**
* Scope a query to find items where the child has the given childSlug
* where its parent has the bookSlug.
*/
public function scopeWhereSlugs(Builder $query, string $bookSlug, string $childSlug)
{
return $query->with('book')
->whereHas('book', function (Builder $query) use ($bookSlug) {
$query->where('slug', '=', $bookSlug);
})
->where('slug', '=', $childSlug);
}
/**
* Get the book this page sits in.
*/
public function book(): BelongsTo
{
return $this->belongsTo(Book::class)->withTrashed();
}
/**
* Change the book that this entity belongs to.
*/
public function changeBook(int $newBookId): Entity
{
$this->book_id = $newBookId;
$this->refreshSlug();
$this->save();
$this->refresh();
// Update all child pages if a chapter
if ($this instanceof Chapter) {
foreach ($this->pages()->withTrashed()->get() as $page) {
$page->changeBook($newBookId);
}
}
return $this;
}
}

View File

@@ -0,0 +1,115 @@
<?php
namespace BookStack\Entities\Models;
use BookStack\Uploads\Image;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Bookshelf extends Entity implements HasCoverImage
{
protected $table = 'bookshelves';
public $searchFactor = 3;
protected $fillable = ['name', 'description', 'image_id'];
protected $hidden = ['restricted', 'image_id', 'deleted_at'];
/**
* Get the books in this shelf.
* Should not be used directly since does not take into account permissions.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function books()
{
return $this->belongsToMany(Book::class, 'bookshelves_books', 'bookshelf_id', 'book_id')
->withPivot('order')
->orderBy('order', 'asc');
}
/**
* Related books that are visible to the current user.
*/
public function visibleBooks(): BelongsToMany
{
return $this->books()->visible();
}
/**
* Get the url for this bookshelf.
*/
public function getUrl(string $path = ''): string
{
return url('/shelves/' . implode('/', [urlencode($this->slug), trim($path, '/')]));
}
/**
* Returns BookShelf cover image, if cover does not exists return default cover image.
*
* @param int $width - Width of the image
* @param int $height - Height of the image
*
* @return string
*/
public function getBookCover($width = 440, $height = 250)
{
// 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;
}
try {
$cover = $this->cover ? url($this->cover->getThumb($width, $height, false)) : $default;
} catch (\Exception $err) {
$cover = $default;
}
return $cover;
}
/**
* Get the cover image of the shelf.
*/
public function cover(): BelongsTo
{
return $this->belongsTo(Image::class, 'image_id');
}
/**
* Get the type of the image model that is used when storing a cover image.
*/
public function coverImageTypeKey(): string
{
return 'cover_shelf';
}
/**
* Check if this shelf contains the given book.
*
* @param Book $book
*
* @return bool
*/
public function contains(Book $book): bool
{
return $this->books()->where('id', '=', $book->id)->count() > 0;
}
/**
* Add a book to the end of this shelf.
*
* @param Book $book
*/
public function appendBook(Book $book)
{
if ($this->contains($book)) {
return;
}
$maxOrder = $this->books()->max('order');
$this->books()->attach($book->id, ['order' => $maxOrder + 1]);
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace BookStack\Entities\Models;
use Illuminate\Support\Collection;
/**
* Class Chapter.
*
* @property Collection<Page> $pages
* @property mixed description
*/
class Chapter extends BookChild
{
public $searchFactor = 1.3;
protected $fillable = ['name', 'description', 'priority', 'book_id'];
protected $hidden = ['restricted', 'pivot', 'deleted_at'];
/**
* Get the pages that this chapter contains.
*
* @param string $dir
*
* @return mixed
*/
public function pages($dir = 'ASC')
{
return $this->hasMany(Page::class)->orderBy('priority', $dir);
}
/**
* Get the url of this chapter.
*/
public function getUrl($path = ''): string
{
$parts = [
'books',
urlencode($this->book_slug ?? $this->book->slug),
'chapter',
urlencode($this->slug),
trim($path, '/'),
];
return url('/' . implode('/', $parts));
}
/**
* Get the visible pages in this chapter.
*/
public function getVisiblePages(): Collection
{
return $this->pages()->visible()
->orderBy('draft', 'desc')
->orderBy('priority', 'asc')
->get();
}
}

Some files were not shown because too many files have changed in this diff Show More