Compare commits

..

1294 Commits

Author SHA1 Message Date
Dan Brown
27bf4299cf Updated version and assets for release v23.08 2023-08-30 12:38:48 +01:00
Dan Brown
164f01bb25 Merge branch 'development' into release 2023-08-30 12:38:22 +01:00
Dan Brown
c6d0e690f9 Updated translations with latest Crowdin changes (#4462) 2023-08-30 12:35:10 +01:00
Dan Brown
77d65d1ca1 Updated translator attribution before v23.08 2023-08-30 11:49:45 +01:00
Dan Brown
dc77233ec3 MD Editor: Fixed scroll on mobile widths
Added min-height to flex elements to ensure they properly flex within
the container rathen than adjust to content.

For #4466
2023-08-30 02:41:51 +01:00
Dan Brown
3622c440d7 SSR: Added new option to complete env example file 2023-08-30 02:31:36 +01:00
Dan Brown
642210ab4c Merge branch 'srr_host_allowlist' into development 2023-08-27 12:45:00 +01:00
Dan Brown
e176aae940 Updated translations with latest Crowdin changes (#4380) 2023-08-27 12:43:59 +01:00
Dan Brown
903895814a SSR: Updated allow list handling & covered webhook usage
- Covered webhook SSR allow list useage via test.
- Updated allow list handling to use trailing slash, or hash, or end of
  line as late anchor for better handling for hosts (prevent .co.uk
passing for .co domain host)
2023-08-26 20:13:37 +01:00
Dan Brown
c324ad928d Security: Added new SSR allow list and validator
Included unit tests to cover validator functionality.
Added to webhooks.
Still need to do testing specifically for webhooks.
2023-08-26 15:28:29 +01:00
Dan Brown
9100a82b47 Guests: Prevented access to profile routes
Prevention of action on certain routes for guest user when public access
is enabled. Could not see a way this could be a security issue, beyond a
mild nuisance that'd only be visible if public users can edit, which
would present larger potential nuisance anyway.
2023-08-26 14:07:48 +01:00
Dan Brown
32516f7b68 Merge pull request #4457 from BookStackApp/drawing_backup_store
Browser-based drawing backup storage system
2023-08-23 19:12:29 +01:00
Dan Brown
69ac425903 Updated readme attribution and fixed eslint issues 2023-08-23 19:02:23 +01:00
Dan Brown
3917e50c90 Drawio: Tweaked fail backup handling during testing
- Tweaked wording of popup title.
- Updated WYSIWYG create handling to properly remove drawing container
  on failure.

Tested across FF and chrome, in both editors for create & editing.
2023-08-23 18:50:37 +01:00
Dan Brown
dd71658d70 Drawio: Added unsaved restore prompt and logic 2023-08-23 14:16:20 +01:00
Dan Brown
a4fbde9185 Drawio: Started browser drawing backup store system
Adds just the part to store image data, and remove on successfull save.
Alters save events to properly throw upon error.
Adds IDB-Keyval library for local large-size store.
For #4421
2023-08-22 19:30:39 +01:00
Dan Brown
cbcec189fd RTL: Fixed screen-reader-only elements pushout out view
For #4429
2023-08-22 18:25:14 +01:00
Dan Brown
0628c28f66 Cache: Increases database cache value size
Upped from text to medium text.
Aligns with modern Laravel default.
Fixes #4453 where were reaching the limit of TEXT.
2023-08-21 23:01:42 +01:00
Dan Brown
391478465a Merge branch 'add-priority' into development 2023-08-21 15:43:16 +01:00
Dan Brown
9ca1139ab0 API: Reviewed changes for API priority control
Review of #4313
- Made constructor changes while reviewing some classes.
- Updated API examples for consistency.
- Tweaked formatting for some array changes.
- Simplified added tests.
- Tweaked chapter/page repo priority handling to be simpler.

Performed manual API endpoint testing of page/chapter create/update.
2023-08-21 15:42:47 +01:00
Dan Brown
7bf5425c6b Updated PHP and npm deps, Upped node version 2023-08-19 20:22:19 +01:00
Dan Brown
e44ef57219 Status: Updated cache check to use unique key
Updated status endpoint cache check to include a random component in the
key to avoid conflict during simultaneous checks.
For #4396
2023-08-17 21:24:35 +01:00
Dan Brown
fef433a9cb Merge pull request #4390 from BookStackApp/content_notifications
Content user notifications
2023-08-17 21:09:52 +01:00
Dan Brown
e709caa005 Notifications: Switched testing from string to reference levels 2023-08-17 18:10:34 +01:00
Dan Brown
38829f8a38 Notifications: Fixed send content permission checking
Added test and changed logic to properly check the view permissions for
the notification receiver before sending.
Required change to permissions applicator to allow the user to be
manually determined, and a service provider update to provide the class
as a singleton without a specific user, so it checks the current logged
in user on demand.
2023-08-17 17:57:31 +01:00
Dan Brown
ee9e342b58 Notifications: Fixed issues causing failing tests
- Ensured watch options passed in all meta template usage to fix failing
  scenarios where watch options did not exist.
- Fixed testing issue caused by guest user permission caching.
2023-08-17 14:59:28 +01:00
Dan Brown
79470ea4b7 Notifications: Made improvements from manual testing
- Added titles for preference pages.
- Added extra check for non-guest for notifications on preferences page.
2023-08-16 20:15:49 +01:00
Dan Brown
565908ef52 Notifications: Add phpunit test for notification sending
Covers core case scenarios, and check of notification content.
2023-08-16 16:02:00 +01:00
Dan Brown
bc6e19b2a1 Notifications: Added testing to cover controls 2023-08-15 20:08:27 +01:00
Dan Brown
615741af9d Notifications: Cleaned up mails, added debounce for updates
- Updated mail notification design to be a bit prettier, and extracted
  text to new lang file for translation.
- Added debounce logic for page update notifications.
- Fixed watch options not being filtered to current user.
2023-08-15 14:39:39 +01:00
Dan Brown
371779205a Notifications: Added new preferences view and access control
- Added general user preferences view and updated link in profile menu
  to suit.
- Made notification permission required for notification preferences
  view, added test to cover.
2023-08-14 17:29:12 +01:00
Dan Brown
d9fdecd902 Notifications: User watch list and differnt page watch options
- Adds option filtering and alternative text for page watch options.
- Adds "Watched & Ignored Items" list to user notification preferences
  page to show existing watched items.
2023-08-14 13:11:18 +01:00
Dan Brown
c47b3f805a Notifications: Updated watch control to show parent status 2023-08-09 14:53:31 +01:00
Dan Brown
ecab2c8e42 Notifications: Added logic and classes for remaining notification types 2023-08-05 14:19:23 +01:00
Dan Brown
18ae67a138 Notifications: Got core notification logic working for new pages
Also rolled out watch UI to chapter and page views
2023-08-04 16:51:29 +01:00
Dan Brown
9779c1a357 Notifications: Started core user notification logic
Put together an initial notification.
Started logic to query and identify watchers.
2023-08-04 12:27:29 +01:00
Dan Brown
9d149e4d36 Notifications: Linked watch functionality to UI
Got watch system working to an initial base state.
Moved some existing logic where it makes sense.
2023-08-02 13:14:00 +01:00
Dan Brown
8cdf3203ef Notifications: Started back-end for watch system
Added DB and started controller method.
2023-07-31 16:08:29 +01:00
Dan Brown
6100b99828 Notifications: Extracted watch options, updated UI further 2023-07-31 15:23:28 +01:00
Dan Brown
730f539029 Notifications: Started entity watch UI 2023-07-27 14:27:45 +01:00
Dan Brown
ff2674c464 Notifications: Added role receive-notifications permission 2023-07-25 17:59:04 +01:00
Dan Brown
100b28707c Notifications: added user preference UI & logic
Includes testing to cover.
Also added file missing from previous commit.
2023-07-25 17:08:40 +01:00
Dan Brown
45e75edf05 Notifications: Started activity->notification core framework 2023-07-19 11:03:05 +01:00
Dan Brown
1c922be4c7 Comments: Added text for new activity types 2023-07-19 10:11:53 +01:00
Dan Brown
0359e2490a Comments: Updated testing to check for new activities 2023-07-19 10:09:08 +01:00
Dan Brown
422e50302a Comments: Added extra comment-specific activities
Kept existing "COMMENTED_ON" activity for upgrade compatibility,
specifically for existing webhook usage and for showing comment
activities in activity lists.

Precursor to content notifications.
Currently untested.
Also applied some type updates.
2023-07-18 15:07:31 +01:00
Dan Brown
f563a005f5 Updated version and assets for release v23.06.2 2023-07-12 22:34:25 +01:00
Dan Brown
a14d8e30cc Merge branch 'development' into release 2023-07-12 22:34:15 +01:00
Dan Brown
7504ad32a7 Updated translator attribution before release v23.06.2 2023-07-12 22:34:04 +01:00
Dan Brown
fca18862d2 Updated translations with latest Crowdin changes (#4367) 2023-07-12 22:22:43 +01:00
Dan Brown
ae834050f5 Shelf permissions: reverted create removal
Reverted work in 847a57a49a.
Left test in but updated to new expectation.
Left migration in but removed content to prevent new pre-v23.06
upgraders loosing shelf create permission status.
Added note to permission to describe use-case.

For #4375
2023-07-12 22:04:05 +01:00
Dan Brown
a83150131a Webhooks: Fixed failing delete-based events
Due to queue serialization.
Added a test to check a couple of delete events.
Added ApiTokenFactory to support.
Also made a couple of typing/doc updates while there.

Related to #4373
2023-07-12 16:16:12 +01:00
Jean-René ROUET
3a36d3c847 add tests for priority 2023-07-11 14:11:13 +02:00
Jean-René ROUET
4d399f6ba7 add priority on page and chapter create 2023-07-11 13:28:20 +02:00
Jean-René Rouet
b1b8067cbe Merge branch 'BookStackApp:development' into add-priority 2023-07-11 08:57:14 +02:00
Dan Brown
a9194ffb63 Updated version and assets for release v23.06.1 2023-07-05 13:04:51 +01:00
Dan Brown
2f9c1b7127 Merge branch 'development' into release 2023-07-05 13:04:30 +01:00
Dan Brown
18979e84d6 Updated tranlsator attribution and sponsors 2023-07-05 12:40:49 +01:00
Dan Brown
bf5e886d76 Updated translations with latest Crowdin changes (#4352) 2023-07-05 12:28:19 +01:00
Dan Brown
e04a1af444 Merge pull request #4344 from devdot/update-api-docs
Update API Docs
2023-07-05 12:08:51 +01:00
Dan Brown
eb2c5d00cb Audit log: Added IP address wrapping
Primarily to support long ipv6 addresses which would overflow over the
activity date.
For #4349
2023-07-05 11:37:49 +01:00
Dan Brown
96819b7bd9 Images: Updated image timestamp upon file change
For #4354
2023-07-05 11:28:03 +01:00
Dan Brown
18ee80a743 Roles: fixed error upon created_at sorting
Added test to cover core role sorting functionality.
For #4350
2023-07-04 21:52:46 +01:00
Dan Brown
1a56de6cb4 Testing: Split out role tests to management and permissions 2023-07-04 21:40:05 +01:00
Dan Brown
465989efa9 Mail: Updated to forked symfony/mailer to allow assurance of tls
Related to #4358
2023-07-04 15:21:31 +01:00
Dan Brown
bbea76668b Updated version and assets for release v23.06 2023-06-30 11:06:19 +01:00
Dan Brown
becc630acf Merge branch 'development' into release 2023-06-30 11:05:57 +01:00
Dan Brown
80635144b1 Meta: Updated dev version and translation attribution 2023-06-30 10:55:54 +01:00
Thomas Kuschan
d293171da2 API Docs: Add Missing Fields in Example Responses 2023-06-30 09:36:46 +02:00
Thomas Kuschan
174cd5a893 API Docs: Add Missing editor fields in Example Responses 2023-06-30 09:35:47 +02:00
Thomas Kuschan
ccfe38e963 API Docs: Add book_slug to Example Responses
Remove the book attribute in responses because it is never returned by the API. Currently, Chapters Create does not return book_slug! (The example response is consistent with the inconsistent API behavior)
2023-06-30 09:33:53 +02:00
Thomas Kuschan
23ae332c1b API Docs: Sort a few example responses 2023-06-30 09:27:18 +02:00
Thomas Kuschan
3a39f13420 API Docs: Remove Dates from Tags in Example Responses 2023-06-30 09:24:46 +02:00
Thomas Kuschan
ca2d2c97d4 API Docs: Add User Slugs to Example Responses 2023-06-30 09:23:02 +02:00
Dan Brown
d23cfc3d32 Updated test to match German translation 2023-06-28 23:46:59 +01:00
Dan Brown
5ea2d0c57b WYSIWYG: Fixed growing rows on Firefox
Occured when the cell contained any block content with a differnt line
height to the table cell itself.
In firefox, cells with a height would end up with an actual greater
real cell height, which messed up TinyMCE resize calculations, causing
tables to grow.
Adding default vertical-align: top, changes this behaviour to get proper
cell heights.
Related to Firefox issue: https://bugzilla.mozilla.org/show_bug.cgi?id=569645
Have tested that editor cell text align options can still be used with
this.

For #4337
2023-06-28 23:28:31 +01:00
Dan Brown
b425d0f65c Updated tinymce to v6.5.1 2023-06-28 22:45:21 +01:00
Dan Brown
63f03046b3 Updated translations with latest Crowdin changes (#4256) 2023-06-28 17:54:32 +01:00
Dan Brown
7f98906b0f Comments: Tweaked design to be more consistent and compact 2023-06-28 13:41:14 +01:00
Dan Brown
b24246085f CSS: Tweaked css heading font to fall back to body font 2023-06-28 09:35:30 +01:00
Thomas Kuschan
e47870794d API Docs: Add Missing Type in Response
Type is always returned when pages/chapters are in a contents array.
2023-06-26 10:14:10 +02:00
Thomas Kuschan
e43d85b801 API Docs: Remove id from Tag in Response 2023-06-26 10:13:02 +02:00
Dan Brown
bae0e80cee Merge pull request #4320 from devdot/improve-api-auth-exception
Improve ApiAuthException control flow
2023-06-25 23:35:19 +01:00
Dan Brown
847a57a49a Shelf permissions: Removed unused 'create' permission from view
Was causing confusion.
Added test to cover.
Also added migration to remove existing create entries to pre-emptively
avoid issues in future if 'create' is used again.
2023-06-25 23:22:49 +01:00
Dan Brown
c74a2608c4 Updated php dependencies 2023-06-24 11:32:54 +01:00
Dan Brown
dbb6c87580 Mail Config: Updated how TLS is configured
After full review of current MAIL_ENCRYPTION usage in laravel and
smyfony mailer, this updates the options in BookStack to be simplified
and specific in usage:

- Removed mail.mailers.smtp.encryption option since it did not actually
  affect anything in the current state of dependancies.
- Updated MAIL_ENCRYPTION so values of tls OR ssl will force-enable tls
  via 'scheme' option with laravel passes to the SMTP transfport, which
  Smyfony uses as an indicator to force TLS.

When MAIL_ENCRYPTION is not used, STARTTLS will still be attempted by
symfony mailer.
Updated .env files to refer to BookStack docs (which was updated for
this) and to reflect correct default port.
Related to #4342
2023-06-24 11:32:07 +01:00
Dan Brown
9ae17efce9 Shelf view: Updated books to be database sorted
Fixes issue where sorting would not match other database-sorted parts of
app due to case sensitivity differences.
Added test to cover.

For #4341
2023-06-23 16:42:40 +01:00
Dan Brown
0a485baf8b Merge pull request #4332 from BookStackApp/api_docs_tweaks
API Docs: Allowed multi-paragraph descriptions
2023-06-20 23:47:58 +01:00
Dan Brown
38883e8d46 API Docs: Allowed multi-paragraph descriptions
Added support for mulit-line endpoint descriptions via blank
intermediate lines in php controller method docblocks.

Also tweaks endpoint header design for better flexing and alignment.
2023-06-20 23:44:39 +01:00
Dan Brown
4bb2cf5c5f Pages API: Added extra helper text to read endpoint 2023-06-20 17:15:32 +01:00
Dan Brown
8b935e71d1 Pages API: Made raw_html available on page responses
To provide a way to see the original un-pre-processed database HTML
content.

For #4310
2023-06-20 17:07:46 +01:00
Dan Brown
41c3ed154b Content Permissions API: Fixed param combination bug
Fixes issue where providing owner_id alongside certain
fallback_permissions would cause the owner change not to take affect,
due to bad variable shadowing.

For #4323
2023-06-20 14:13:26 +01:00
Dan Brown
f5396ecaf0 Merge pull request #4317 from devdot/http-fetch-improve-exception-logging
Modify HttpFetchException flow to log the exception
2023-06-20 13:49:23 +01:00
Thomas Kuschan
97d46f43a7 Revert some changes to HttpFetchException 2023-06-19 08:47:47 +02:00
Dan Brown
22fc720c22 Merge pull request #4318 from devdot/improve-json-debug-exception
Change JsonDebugException to Responsable interface
2023-06-18 17:52:57 +01:00
Dan Brown
eb44748084 Merge branch 'development' of github.com:BookStackApp/BookStack into development 2023-06-17 18:22:01 +01:00
Dan Brown
00b5dd7852 Users API: Fixed incorrect created_at date on index endpoint
For #4325
2023-06-17 18:18:17 +01:00
Dan Brown
9f4450fea9 Merge pull request #4322 from BookStackApp/comments_in_editor
Added read-only comments listing into page editor
2023-06-16 13:23:40 +01:00
Dan Brown
88aae5b004 Comments: Fixed failing tests due to unset template variable 2023-06-16 13:17:11 +01:00
Dan Brown
9a2ef7ef44 Comments: Added read-only listing into page editor 2023-06-16 13:08:04 +01:00
Thomas Kuschan
74097bd47c Simplify ApiAuthException control flow
Remove unnecessary UnauthorizedException
and make ApiAuthException compatible with HttpExceptionInterface.

Move the creation of a rsponse for the exception
from ApiAuthenticate middleware into the application exception handler.
2023-06-16 10:00:02 +02:00
Thomas Kuschan
7249d947ec Change JsonDebugException to Responsable interface
In all other exceptions, when a Response is supposed to be returned,
the Responsable interface is used instead of render.
2023-06-16 09:53:12 +02:00
Thomas Kuschan
c35080d6ce Modify HttpFetchException handle to log exception
Within the flow of HttpFetchException, the actual exception from curl is preserved and logged. Make HttpFetchException a pretty exception for when it is shown to users.
2023-06-16 09:21:25 +02:00
Dan Brown
ec775aec02 Merge branch 'fix-api-404' into development 2023-06-15 17:08:51 +01:00
Dan Brown
e72cf61f7e Exceptions: Added some types, simplified some classes
During review of #4291
2023-06-15 17:07:40 +01:00
Jean-René Rouet
bb3ce845b4 Merge branch 'BookStackApp:development' into add-priority 2023-06-15 16:55:14 +02:00
Dan Brown
70be2e8c9e CSS: Reduced styles used in export formats
Extracted many main page content styles to own scss partial.
Styles could do with a more general clean-up.

Closes #4303
2023-06-14 13:19:29 +01:00
Dan Brown
610ad0d613 Updated fonts to be defined via CSS variables
Exports system remains separate due to lacking css variable support.
2023-06-14 12:53:48 +01:00
Thomas Kuschan
34d8268b2b Refactor notify exception to clean up api exception handling 2023-06-14 11:08:20 +02:00
Thomas Kuschan
321a459421 Refactor exception handling by using interface 2023-06-13 18:52:02 +02:00
Dan Brown
56a40f1b23 Merge pull request #4301 from BookStackApp/css_color_variables
CSS: Updated status colors to be CSS variables, Added dark variants
2023-06-13 15:54:27 +01:00
Dan Brown
f7ad387a10 CSS: Updated status colors to be CSS variables, Added dark variants
Needed some level of harcoding though due to callouts using colors,
which can't be css colors as DOMPDF won't understand these.
Use css variables elsewhere and added new dark variants to fit a bit
better.
2023-06-13 15:52:33 +01:00
Dan Brown
b01bbf9c89 Page Drafts: Added new "Delete Draft" action to draft menu
Provides a way for users to actually delte their user drafts where
required.
For #3927

Added test to cover new endpoint.

Makes update to MD editor #setText so that new selection is within new
range, otherwise it errors and fails operation.
2023-06-13 15:13:07 +01:00
Dan Brown
f39938c4e3 Added activity text for each activity type
Ensures some sensible text is always in webhook text data.
Also aligned some notification reporting to use centralised activity
system instead of custom success events.

For #4216
2023-06-12 16:47:36 +01:00
Jean-René ROUET
458cea3644 [API] add priority in book read
[API] add priority in chapter create and update
[API] add priority in page create and update
2023-06-12 15:12:46 +02:00
Dan Brown
af0b4fa851 Search: Updated popular items query, load parent book for chapters/pages
Primarily intended to show parent book for chapters when moving/copying
pages, since the default parent selector interfaces, which used the
entity-selector search endpoint, would run this popular query when no
term was present as a default backup.

For #4264
2023-06-10 15:08:07 +01:00
Dan Brown
777027bc48 Permissions: Updated guest user handling so additional roles apply
Previously additional roles would only partially apply (system or "all"
permissions). This aligns the query-handling of permissions so that
additional roles will be used for permission queries.

Adds migration to detach existing roles as a safety precaution since
this is likely to widen permissions in scenarios that the public user
has other roles assigned already.

For #1229
2023-06-10 11:37:01 +01:00
Dan Brown
1e220c473f API: Fixed misaligned image datetime format
For #4294
2023-06-10 10:54:56 +01:00
Dan Brown
59c7077fd9 Fixed error on pages without comments 2023-06-09 19:21:49 +01:00
Dan Brown
07de6ecdc5 Merge pull request #4286 from BookStackApp/comment_threads
Comment threads
2023-06-09 17:39:02 +01:00
Dan Brown
19e39ddd1f Comments: Updated reply-to and general styling
Updated reply inidicator to fit with new nesting system, only showing on
view when nest within nesting structure.

Updated the general design to be a bit cleaner and better adapt on
mobile.

Tested on FF+Chrome, inc. dark mode.
2023-06-09 17:36:30 +01:00
Dan Brown
3bede42121 Comments: Added visual nesting limit, added nesting test 2023-06-09 11:12:39 +01:00
Dan Brown
3b46b92bb9 Comments: Updated to show form in expected location
Includes a change of create response to use a branch as a template.
2023-06-08 15:09:54 +01:00
Thomas Kuschan
9ba7d1e6c5 Fix "HTTP 500 on not found" bug #4290 2023-06-08 10:50:12 +02:00
Thomas Kuschan
ecf99fa0ed Add test showing the "HTTP 500 on not found" bug 2023-06-08 09:53:53 +02:00
Dan Brown
154924cc0c Comments: updated component and split out code
Split out comment component code so single-comment actions (delete, edit) are handled within their own compontent.
Modernised existing component code.
2023-06-07 17:47:37 +01:00
Dan Brown
4b9f6beb37 Comments: Updated to show as nested threads
Initial functional implementation, a lot of tweaking and adapting to be
done.
2023-06-07 13:24:49 +01:00
Dan Brown
88785aa71b Page display pointer: Considerably improved accessibility
- Updated pointer to move within content DOM so that you can back-focus
  into the pointer if desired.
- Added new "Section select mode" which toggles focusabiltiy for main
  content sections, with ability to show pointer via enter press on
  these.
- Updated pointer with proper input/button labelling.

Tested via orca screen reader on Firefox/Fedora/Gnome.
For #3975
2023-05-31 16:44:20 +01:00
Dan Brown
0323ebccd3 Chapters API: Allowed move via book_id property
Aligns it with pages and with the book_id property already being part of
the API.
For #4272.
2023-05-30 20:55:24 +01:00
Dan Brown
3f5dc10cd4 Altered ldap_connect usage, cleaned up LDAP classes
Primarily updated ldap_connect to avoid usage of deprecated syntax.
Updated tests and service to handle as expected.
Cleaned up syntax and types in classes while there.

Closes #4274
2023-05-30 13:12:00 +01:00
Dan Brown
242d23788d Merge pull request #4265 from BookStackApp/image_manager_responsive
Enhanced Responsive Image Manager
2023-05-29 16:52:55 +01:00
Dan Brown
08c73f02c9 Removed forced initial image manager display 2023-05-29 16:23:37 +01:00
Dan Brown
a139c2a8a2 Image manager: Improved screen reader usage
Added extra labels, or removed duplicate info, to improve screen reader
ux after testing via gnome/fedora/firefox screen reader usage testing.
2023-05-29 16:21:44 +01:00
Dan Brown
f5ef52ca59 Image manager: cleaned up style changes, dark mode support
- Updated tab handling to be smarter on initial tab selection, to first
  target non-hidden tab panels where they may be handled server-side.
- Extracted contained search box handling styles to _forms.scss, after
  merging with image-manager-specific styles since this is only usage of
  contained variant.
- Aligned focus handling on image manager UI elements.
2023-05-29 15:50:36 +01:00
Dan Brown
948e95e1ad Updated test to align with image manager HTML changes 2023-05-29 15:16:16 +01:00
Dan Brown
cd4b612019 Image update API: added update image file ability 2023-05-29 15:06:17 +01:00
Dan Brown
f78c0635ee Fixed bad /api docs redirection on sub path
Direct route redirect does not seem to go via standard URL generator so
misses off generation via base URL.
2023-05-29 14:41:59 +01:00
Dan Brown
e3c4a9d167 Added the ability to replace existing image files
- Updated UI with image form dropdown containing delete and replace
  image actions.
- Adds new endpoint and service/repo handling for replacing existing
  image.
- Includes tests to cover.
2023-05-28 17:32:22 +01:00
Dan Brown
9ff7c97911 Image manager: Added extra detail below image edit form 2023-05-28 12:07:19 +01:00
Dan Brown
89d6d862fa Image manager: extracted lang text, updated anims and search cancel
- Updated search cancel to only show when a search is active.
- Updated gallery image load animation to be much faster.
2023-05-28 11:37:49 +01:00
Dan Brown
946c9ae804 Image manager: supported a tabbed interface on mobile
Makes interface relatively usable now on mobile sizes.
Required updating of tab handling to support tabs being active at only
mobile screen sizes, include change on resize, upon support for
potentially nested tab usage.
Tab component will now search within sensible depths for finding its own
tabs and panels to control.
2023-05-27 16:58:10 +01:00
Dan Brown
dc6133c4c4 Image manager: added ability to trigger load more via scroll 2023-05-26 18:05:29 +01:00
Dan Brown
6c91e09c73 Image manager: Redesigned header bar(s) 2023-05-26 14:30:59 +01:00
Dan Brown
e467324658 Updated image manager to use grid-based css 2023-05-24 17:07:32 +01:00
Dan Brown
4c726201f9 Merge pull request #4262 from BookStackApp/command_cleanup
Command cleanup & alignment
2023-05-24 13:22:25 +01:00
Dan Brown
431aeefdda Updated command classes to include "Command" in name 2023-05-24 13:21:46 +01:00
Dan Brown
c0620da9f8 Aligned command class code
- Aligned usage of injecting through handler.
- Aligned handler return type.
- Aligned argument and arg desc format.
- Aligned lack of constructor.
2023-05-24 12:59:50 +01:00
Dan Brown
0704f1bd0d Covered untested commands with testing 2023-05-24 10:34:43 +01:00
Dan Brown
3b31ac75ec Merge pull request #4247 from BookStackApp/controller_cleanup
Revised `app/` folder layout/structure
2023-05-24 09:12:49 +01:00
Dan Brown
df6326e5ab Fixed failing references after controller/file reshuffle 2023-05-24 09:06:15 +01:00
Dan Brown
4ac8ecad6b Updated version and assets for release v23.05.2 2023-05-23 12:36:46 +01:00
Dan Brown
903e88c700 Merge branch 'development' into release 2023-05-23 12:36:29 +01:00
Dan Brown
c0d5e158d7 Updated translation attribution before v23.05.2 2023-05-23 12:32:39 +01:00
Dan Brown
99377d43c1 Updated php deps 2023-05-22 20:52:50 +01:00
Dan Brown
ebb1942fb8 Updated translations with latest Crowdin changes (#4239) 2023-05-22 20:51:22 +01:00
Dan Brown
152f7f3ad0 Merge pull request #4252 from BookStackApp/cli_update_2
Updated System CLI
2023-05-22 20:45:32 +01:00
Dan Brown
8a03442b5b Merge pull request #4254 from BookStackApp/code_active_line
Updated code view block line highlighting to only show on focus
2023-05-22 20:44:05 +01:00
Dan Brown
e591f4896e Allowed attachment drag via main text link
Enables easier sorting and dragging of box into content.
Related to #591
2023-05-22 20:23:19 +01:00
Dan Brown
6a7bc68b61 Allowed button-based multi-file uploads
Likely something that worked via dropzone before.
This adds support for our custom dropzone file handling.
Related to #4241
2023-05-22 14:20:20 +01:00
Dan Brown
924f517217 Updated code view block line highlighting to only show on focus
The default 1st line highlighting confused users when existing on
read-only blocks as it was not clear this represented the active line.
This changes the highlight to only show when the block is focused upon.
2023-05-22 14:05:07 +01:00
Dan Brown
150b40edc1 Updated System CLI
- Fixed a range of additional issues involving symlinks.
- Fixed incorrect app locating relative to system cli.
2023-05-22 10:28:12 +01:00
Dan Brown
141eecb858 Cleaned up namespacing in routes
Also moved home controller and moved controllers up a level in http.
2023-05-18 20:57:05 +01:00
Dan Brown
295cd01605 Played around with a new app structure 2023-05-17 17:56:55 +01:00
Dan Brown
ed96aa820e Updated version and assets for release v23.05.1 2023-05-08 16:05:50 +01:00
Dan Brown
63ec079b7b Merge branch 'development' into release 2023-05-08 16:04:51 +01:00
Dan Brown
c17906c758 Updated translator attribution before release v23.05.1 2023-05-08 16:04:02 +01:00
Dan Brown
62d5701578 Merge pull request #4229 from BookStackApp/cli-update
Updated system CLI
2023-05-08 15:21:04 +01:00
Dan Brown
9f1a6947ab Updated system CLI
- Fixed wrong env details being used on restore.
- Updated update-url on restore actually work.
- Added better support for symlinked locations.
- Added warning against updating in docker-like (non git controlled)
  environments.
2023-05-08 15:16:30 +01:00
Dan Brown
ae90776927 Updated translations with latest Crowdin changes (#4211) 2023-05-08 14:49:01 +01:00
Dan Brown
4489f65371 Fixed code block line-number bar showing in exports
Also fixed in print view.
Likely crept in during CM6 changes.

For #4215
2023-05-08 14:45:45 +01:00
Dan Brown
ee1e047964 Updated php deps, formatted command changes 2023-05-08 14:37:01 +01:00
Dan Brown
8846f7d255 Prevented shorcuts activating when in codemirror areas
For #4227
2023-05-08 14:28:03 +01:00
Dan Brown
2523cee0e2 WYSWIYG code blocks: copied head styles into shadow root
Currently only link-based styles are made available in the shadow root
code editor environment, this adds normal styles to apply any user-added
via custom head content.

Fixes #4228
2023-05-08 12:21:53 +01:00
Dan Brown
b5cc0a8e38 Fixed added padding around hr tags in details blocks
Due to manual handling & wrapping of non-block content in details block
not taking hr elements into account.
For #3963
2023-05-08 12:01:52 +01:00
Dan Brown
3bcbf6b9c5 Added WYSWIYG editor code editor cancel focus return
Focus now returns to the editor properly when you quit out the code
editor without saving.
This also sets the return location to be correct on normal saving (Would
sometimes jump to the end of the document).

For #4109.
2023-05-07 19:36:10 +01:00
Dan Brown
573bc3ec45 Added force option for update-url command
Includes test to cover.
Closes #4223
2023-05-06 23:05:25 +01:00
Dan Brown
d485fcb3db Updated version and assets for release v23.05 2023-05-03 11:05:33 +01:00
Dan Brown
0f895668a4 Merge branch 'development' into release 2023-05-03 11:03:29 +01:00
Dan Brown
57bdd83d8c Added mostodon badge in readme, updated CLI 2023-05-03 10:57:09 +01:00
Dan Brown
ce0b75294f Set page include limit to be 3 as expected instead of 4 2023-05-02 12:44:55 +01:00
Dan Brown
4bb2b31bc9 Updated translator attribution pre v23.05 release 2023-05-01 19:39:20 +01:00
Dan Brown
9d74508ae3 Updated translations with latest Crowdin changes (#4163) 2023-05-01 19:37:49 +01:00
Dan Brown
c41baa1b76 Updated CLI & PHP deps, added gitignore for local composer 2023-05-01 18:44:46 +01:00
Dan Brown
cd32597d4d Fixed broken favourites in code editor 2023-05-01 18:43:03 +01:00
Dan Brown
8594656f6e Merge pull request #4206 from BookStackApp/system_cli
Added System CLI
2023-04-28 19:17:38 +01:00
Dan Brown
0aca1c2332 Added system cli, and created backups directory 2023-04-28 19:08:45 +01:00
Dan Brown
8c738aedee Added sessionindex to SAML2 single logout request to idp
related to  #3936
2023-04-28 13:55:25 +01:00
Dan Brown
f64ce71afc Added oidc_id_token_pre_validate logical theme event
For #4200
2023-04-27 23:40:14 +01:00
Dan Brown
277d5392fb Merge branch 'esakkiraja100116/development' into development 2023-04-27 16:34:14 +01:00
Dan Brown
23c35af9ef Review of #4202, Rolled out to other searches, added testing 2023-04-27 16:33:24 +01:00
esakkiraja100116
78fecdfcb0 suggesstion issue fix (#4175) 2023-04-27 16:32:39 +01:00
SnowCode
a9d952560d Adding a video { width: 100%; } (#4204)
* Adding a video { width: 100%; }

This is to prevent that videos included in pages don't exceed the page border

* Reverting precedent commit

* Adding a video { max-width: 100% } instead
2023-04-27 15:58:35 +01:00
Dan Brown
56f234d1ee Review of #4192, Fixed formatting and added test 2023-04-27 15:52:16 +01:00
jasonF1000
011800d425 changed PageContent.php to accept nested includes (#4192)
* changed app/Entities/Tools/PageContent.php to accept nested include levels. Tested it and it works.

* changed recommendations

This loop is now only around parsePageIncludes and bugfixes the space indentation.

* Update PageContent.php

fix spaces
2023-04-27 15:51:46 +01:00
Dan Brown
647ce6c237 Fixed sort urls with no params not building full path
The provided partial path would be return which may not resolve to the
full URL when used on systems like those hosting BookStack on a
sub-path.
Fixes #4201
2023-04-27 13:49:22 +01:00
Dan Brown
607da73109 Merge pull request #4193 from BookStackApp/custom_dropzone
Custom dropzone implementation
2023-04-27 13:43:38 +01:00
Dan Brown
1135d477ba Fixed linting and failing test issues from dropzone work 2023-04-27 13:31:03 +01:00
Dan Brown
a4a96a3df7 Dropzone: Adjusted styles for dark mode 2023-04-27 12:55:05 +01:00
Dan Brown
38e8a96dcd Removed dropzone from package and attribution list 2023-04-26 23:35:25 +01:00
Dan Brown
9a17656f88 dropzone: Addressed existing todos, cleaned attachment ux
Updated dom layout of attahcments to prevent nested dropzones (No issue
but potential to be one) and updated edit form dropzone handling so the
dropzone item card was not as distracting.
2023-04-26 23:31:38 +01:00
Dan Brown
e36cdaad0d Updated attachments to work with new dropzone
- Fixes existing broken attachment edit tabs.
- Redesigns area to move away from old tabbed interface.
- Integrates new dropzone system, for both addition and edit.
2023-04-26 16:41:34 +01:00
Dan Brown
722c38d576 Image manager: fix upload control for drawing, updated styles
- Tightened image manager styles to address things that looked akward.
- Prevented visiblity/use of upload controls for drawings.
- Updated dropzone to use error handling from validation messages.
2023-04-26 14:25:56 +01:00
Dan Brown
8cd6c797e8 Merge branch 'development' of github.com:BookStackApp/BookStack into development 2023-04-26 01:43:16 +01:00
Dan Brown
dff45e2c5d Fixed broken shortcut hint overlay
Also updated event handler usage to use abort controller while there.
2023-04-26 01:42:12 +01:00
Dan Brown
61d2ea6ac7 Dropzone: Polished image manager elements
- Added file placeholder for non-image uploads.
- Added use of upload limits.
- Removed upload timeout variable.
- Added pass-through and usage of filetypes.
- Extracted some view text to language files and made use of existing
  text.
2023-04-25 16:41:39 +01:00
Esakkiraja
752562d23d .vscode folder is added in .gitignore file (#4197)
Squash of 7 commits.

---------

Co-authored-by: esakkiraja100116 <esakkiraja100116@gmai.com>
2023-04-25 15:25:31 +01:00
Dan Brown
b21a9007c5 Dropzone: Developed ux further
- Added image manager button for uploads.
- Added image manager placeholder sidebar text for guidance.
- Improved dropzone layer styling.
- Removed old dropzone styles.
- Got success events and auto-hide working.
- Updated upload items to animate out.
2023-04-25 13:10:25 +01:00
Dan Brown
a8fc29a31e Dropzone: started on design/ui of uploading
- Added new wider target handling.
- Updated upload item dom with design and seperate "landing" zone.
- Added new helper for simple dom element creation.
2023-04-24 23:24:58 +01:00
Dan Brown
36116a45d4 Dropzone: Swapped fetch for XHR for progress tracking 2023-04-24 18:18:08 +01:00
Dan Brown
23915c3b1a Started custom dropzone implementation 2023-04-24 16:19:20 +01:00
Dan Brown
55af22b487 Merge pull request #4191 from tigsikram/fix-api-docs-timestamp
Fix timestamp in API docs example response
2023-04-24 14:46:40 +01:00
Mark Weiler
01f3f4d315 Fix timestamp in API docs example response 2023-04-24 11:19:00 +02:00
Dan Brown
58cadce052 Merge branch 'feature/mail-verify-peer' into development 2023-04-23 15:05:13 +01:00
Dan Brown
1de72d09ca Mail: updated peer verify option name and added test 2023-04-23 15:04:35 +01:00
Dan Brown
fa6fcc1c1c Added clojure code language option
For #4112
2023-04-23 14:16:31 +01:00
Dan Brown
a46b438a4c Merge branch 'wkhtmltopdf-env-example' into development 2023-04-21 11:56:31 +01:00
Dan Brown
7505443a0c Updated complete env wkhtml text and added advisory
Added advisory to start to refer to docs for full details.
Updated added WKHTMLTOPDF option text.
2023-04-21 11:54:23 +01:00
Dan Brown
f837083c12 Updated php deps 2023-04-21 11:37:41 +01:00
Dan Brown
e1bd13f481 Edits from reviewing public events page 2023-04-20 16:54:11 +01:00
Dan Brown
c74f7cc628 Documented public JS events used
Related to #4179
2023-04-20 16:25:48 +01:00
Dan Brown
9f467f4052 Merge pull request #4181 from BookStackApp/js_formatting
Added standard JS formatting via ESLint
2023-04-19 23:01:10 +01:00
Dan Brown
974390688d ESLINT: Added GH action and details to dev docs 2023-04-19 22:56:55 +01:00
Dan Brown
da3ae3ba8b ESLINT: Addressed remaining detected issues 2023-04-19 15:20:04 +01:00
Dan Brown
0519e58fbf ESLINT: Started inital pass at addressing issues 2023-04-19 10:46:13 +01:00
Dan Brown
e711290d8b Ran eslint fix on existing codebase
Had to do some manual fixing of the app.js file due to misplaced
comments
2023-04-18 22:20:02 +01:00
Dan Brown
752ee664c2 Added code formatting standard via eslint 2023-04-18 22:19:27 +01:00
Dan Brown
69d03042c6 Merge pull request #3617 from BookStackApp/codemirror6
Upgrade to codemirror 6
2023-04-18 15:35:39 +01:00
Dan Brown
baf5edd73a CM6: Further fixes/improvements after testing
- Updated event naming to be "cm6" when codemirror-specific.
- Removed cm block border in md editor to prevent double bordering.
- Updated copy handling to fallback to execCommand.
2023-04-18 15:08:17 +01:00
Dan Brown
3e738b1471 CM6: Fixed a range of issues during browser testing
- Fixed some keybindings not running as expected, due to some editor
  defaults overriding or further actions taking place since the action
  would not indicate it's been dealt with (by returning boolean).
- Fixed spacing/border-radius being used on codeblocks on non-intended
  areas like the MD editor.
- Fixed lack of BG on default light theme, visible on full screen md
  editor.
- Fixed error thrown when the user does not have access to change the
  current editor (Likely non-cm related existing issue)
2023-04-18 14:21:22 +01:00
Dan Brown
94f464cd14 CM6: Added tabbing, fixed dark mode border in WYSIWYG 2023-04-18 13:43:59 +01:00
Dan Brown
900571ac9c CM6: Updated for popup editor, added new interface
New simple interface added for abstraction of CM editor in simple
use-cases, just to provide common actions like get/set content, focus
and set mode.
2023-04-17 13:24:29 +01:00
Dan Brown
09fd0bc5b7 CM6: Got WYSIWYG code blocks working
Required monkey-patch to work around potential codemirror issue with
shadowdom+iframe usage.
Also updated JS packages to latest versions.
2023-04-16 23:50:11 +01:00
Dan Brown
74b4751a1c CM6: Aligned styling with existing, improved theme handling 2023-04-16 16:05:16 +01:00
Dan Brown
74b76ecdb9 Updated cm6 theme handling to allow extension via API
Uses our custom event system, uses methods that take callables so that
internal dependancies can be passed.
2023-04-15 15:35:41 +01:00
Dan Brown
9874a53206 Added cm6 strategy for splitting and dyn. loading langs
Split out legacy modes to their own dynamically imported bundle to
reduce main code bundle size.
2023-04-14 18:08:57 +01:00
Dan Brown
257a703878 Addressed existing cm6 todos
- Updated clipboard handling
  - Removed old clipboard package for browser-native API.
- Updated codemirror editor events to use new props for new data types.
2023-04-14 14:08:40 +01:00
Dan Brown
fdda813d5f Cleaned up change handling in cm6 editor action handling 2023-04-13 17:38:11 +01:00
Dan Brown
6f45d34bf8 Finished update pass of all md editor actions to cm6 2023-04-13 17:18:32 +01:00
Dan Brown
32c765d0c3 Updated another range of actions for cm6 2023-04-13 12:51:52 +01:00
Dan Brown
9813c94720 Made a start on updating editor actions 2023-04-11 13:16:04 +01:00
Dan Brown
da3e4f5f75 Got md shortcuts working, marked actions for update 2023-04-11 11:48:58 +01:00
Dan Brown
572037ef1f Got markdown editor barely functional
Updated content sync and preview scoll sync to work.
Many features commented out until they can be updated.
2023-04-10 15:01:44 +01:00
Dan Brown
50f3c10f19 Merge branch 'v23.02-branch' into development 2023-04-07 18:12:00 +01:00
Dan Brown
6c577ac3bf Updated version and assets for release v23.02.3 2023-04-07 18:07:32 +01:00
Dan Brown
31cc2423d2 Merge branch 'v23.02-branch' into release 2023-04-07 18:07:09 +01:00
Dan Brown
3f3f221e0d Updated translator attribution before release v23.02.3 2023-04-07 18:06:44 +01:00
Dan Brown
d0f970fe4f Updated translations with latest Crowdin changes (#4131) 2023-04-07 18:00:03 +01:00
Dan Brown
95b75c067f Updated translations with latest Crowdin changes (#4131) 2023-04-07 17:59:34 +01:00
Dan Brown
81134e7071 Fixed tag numbering in last commit 2023-04-07 17:54:17 +01:00
Dan Brown
e722ee4268 Fixed click issue with tag suggestions in safari
Updated selectable elements to be divs instead of buttons since Safari
akwardly does not focus on buttons on click.
Also standardised keyboard handling to our standard nav class.
Also addressed empty tag values showing in results.
For #4139
2023-04-07 17:50:57 +01:00
Dan Brown
fd674d10e3 Fixed error upon user delete with no migration id
Fixes #4162
2023-04-07 15:57:21 +01:00
Dan Brown
4835a0dcb1 Cleaned up old token services 2023-04-04 10:44:38 +01:00
Daiki Urata
d353e87ca1 Add WKHTMLTOPDF to .env.example.complete 2023-03-30 17:58:17 +09:00
Dan Brown
8e64324d62 Merge branch 'v23.02-branch' into development 2023-03-25 12:33:59 +00:00
Dan Brown
c9ed32e518 Updated version and assets for release v23.02.2 2023-03-25 12:27:32 +00:00
Dan Brown
6b4c3a0969 Merge branch 'v23.02-branch' into release 2023-03-25 12:27:05 +00:00
Dan Brown
0a0fdd7f3e Fixed delete role failing with no migrate role provided
For #4128
2023-03-25 12:21:22 +00:00
Dan Brown
3410cf21cb Updated php deps 2023-03-25 12:21:04 +00:00
Dan Brown
6e284d7a6c Fixed issue with user delete ownership not migrating
Caused by input not being part of the submitted form.
Updated test to ensure the input is within a form.
For #4124
2023-03-25 12:20:49 +00:00
Dan Brown
ea7914422c Updated php deps 2023-03-25 12:20:13 +00:00
Dan Brown
509cab3e28 Merged latest crowdin changes 2023-03-25 12:18:45 +00:00
Dan Brown
dde38e91b5 Fixed delete role failing with no migrate role provided
For #4128
2023-03-25 12:08:45 +00:00
Dan Brown
970088a8a1 Updated php deps 2023-03-24 14:46:30 +00:00
Dan Brown
0e43618dda Fixed issue with user delete ownership not migrating
Caused by input not being part of the submitted form.
Updated test to ensure the input is within a form.
For #4124
2023-03-24 14:43:48 +00:00
Vincent Bernat
f2293a70f8 Allow a user to disable peer check when using TLS/STARTTLS
This is useful when developing and on Docker setups. Despite setting
encryption to null, if a server supports STARTTLS with a self-signed
certificate, the mailer try to upgrade the connection with STARTTLS.
2023-03-24 09:34:37 +01:00
Dan Brown
dce5123452 Added own twig/smarty packages for cm6 lang support 2023-03-21 20:53:35 +00:00
Dan Brown
c81cb6f2af Merge branch 'development' into codemirror6 2023-03-19 10:22:44 +00:00
Dan Brown
9b66e93b15 Merge pull request #4103 from BookStackApp/image_api
Image API Endpoints
2023-03-15 11:45:36 +00:00
Dan Brown
402eb845ab Added examples, updated docs for image gallery api endpoints 2023-03-15 11:37:03 +00:00
Dan Brown
3a808fd768 Added phpunit tests to cover image API endpoints 2023-03-14 19:29:08 +00:00
Dan Brown
d9eec6d82c Started Image API build 2023-03-14 12:19:19 +00:00
Dan Brown
6357056d7b Updated php deps 2023-03-13 21:03:00 +00:00
Dan Brown
a369971e04 Merge pull request #4099 from BookStackApp/permissions_api
Content-Permissions API Endpoints
2023-03-13 20:55:44 +00:00
Dan Brown
1903924829 Added content-perms API examples and docs tweaks 2023-03-13 20:41:32 +00:00
Dan Brown
0de7530059 Tweaked content permission endpoints, covered with tests 2023-03-13 20:06:52 +00:00
Dan Brown
c42956bcaf Started build of content-permissions API endpoints 2023-03-13 13:18:33 +00:00
Dan Brown
7b5111571c Removed bookstack wording instances in color setting options 2023-02-28 01:01:25 +00:00
Dan Brown
2dad92d1bd Updated version and assets for release v23.02.1 2023-02-27 19:26:13 +00:00
Dan Brown
c1fb7ab7dc Merge branch 'development' into release 2023-02-27 19:23:33 +00:00
Dan Brown
3464f5e961 Updated translations with latest Crowdin changes (#4066) 2023-02-27 19:19:03 +00:00
Dan Brown
7c27d26161 Fixed language locale setting issue
Attempted to access an array that had been filtered and therefore could
have holes within, including as position 0 which would then be
accessed.
Also added cs language to internal map

Related to #4068
2023-02-27 19:14:45 +00:00
Dan Brown
98315f3899 Updated version and assets for release v23.02 2023-02-26 11:03:49 +00:00
Dan Brown
8c82aaabd6 Merge branch 'development' into release 2023-02-26 11:02:56 +00:00
Dan Brown
c7e33d1981 Fixed caching issue when running tests 2023-02-26 10:50:14 +00:00
Dan Brown
ba21b54195 Updated translations with latest Crowdin changes (#4025) 2023-02-26 10:36:15 +00:00
Dan Brown
f35c42b0b8 Updated php deps and translaters in prep for v23.02 2023-02-25 17:35:21 +00:00
Dan Brown
b88b1bef2c Added updated_at index to pages table
This has a large impact on some areas where latest updated pages are
shown, such as the homepage for example.
2023-02-23 23:06:12 +00:00
Dan Brown
8abb41abbd Added caching to the loading of system roles
Admin system role was being loaded for each permission check performed.
This caches the fetching for the request lifetime.
2023-02-23 23:01:03 +00:00
Dan Brown
a031edec16 Fixed old deprecated encoding convert on HTML doc load 2023-02-23 22:59:26 +00:00
Dan Brown
2724b2867b Merge pull request #4062 from BookStackApp/settings_perf
Changed the way settings are loaded
2023-02-23 22:22:32 +00:00
Dan Brown
8bebea4cca Changed the way settings are loaded
This new method batch-loads them from the database, and removes the
cache-layer with the intention that a couple of batch fetches from the
DB is more efficient than hitting the cache each time.
2023-02-23 22:14:47 +00:00
Dan Brown
6545afacd6 Changed autosave handling for better editor performance
This changes how the editors interact with the parent page-editor
compontent, which handles auto-saving.
Instead of blasting the full editor content upon any change to that
parent compontent, the editors just alert of a change, without the
content. The parent compontent then requests the editor content from the
editor component when it needs that data for an autosave.

For #3981
2023-02-23 12:30:27 +00:00
Dan Brown
31495758a9 Made page-save HTML formatting much more efficient
Replaced the existing xpath-heavy system with a more manual traversal
approach. Fixes following slow areas of old system:
- Old system would repeat ID-setting action for elements (Headers could
  be processed up to three times).
- Old system had a few very open xpath queries for headers.
- Old system would update links on every ID change, which triggers it's
  own xpath query for links, leading to exponential scaling issues.

New system only does one xpath query for links when changes are needed.
Added test to cover.

For #3932
2023-02-22 14:32:40 +00:00
Dan Brown
c80396136f Increased attachment link limit from 192 to 2k
Added test to cover.
Did attempt a 64k limit, but values over 2k significantly increase
chance of other issues since this URL may be used in redirect headers.
Would rather catch issues in-app.

For #4044
2023-02-20 13:05:23 +00:00
Dan Brown
8da3e64039 Updated language files to remove literal "1" values
This is to encourge the ":count" values to be used instead of 1s in the
translated variants so that non-pluralised languages are hardcoded with
"1"s in their content, even when not used in a singular context.

For #4040
2023-02-20 12:05:52 +00:00
Dan Brown
c1167f8821 Merge pull request #4051 from BookStackApp/roles_api
User Roles API Endpoint
2023-02-19 16:11:30 +00:00
Dan Brown
4176b598ce Fixed unselectable checkbox role form options 2023-02-19 16:03:50 +00:00
Dan Brown
950c02e996 Added role API responses & requests
Also applied other slight tweaks and comment updates based upon manual
endpoint testing.
2023-02-19 15:58:29 +00:00
Dan Brown
9502f349a2 Updated test to have reliable check ordering 2023-02-18 19:01:38 +00:00
Dan Brown
3c3c2ae9b5 Set order to role permissions API response 2023-02-18 18:50:01 +00:00
Dan Brown
723f108bd9 Aded roles API controller methods
Altered & updated permissions repo, and existing connected
RoleController to suit.
Also extracts in-app success notifications to auto activity system.
Tweaked tests where required.
2023-02-18 18:36:34 +00:00
Dan Brown
55456a57d6 Added tests for not-yet-built role API endpoints 2023-02-18 13:51:18 +00:00
Dan Brown
c148e2f3d9 Added esbuild bundle inspection metafile 2023-02-17 22:37:13 +00:00
Dan Brown
f51036b203 Added newer languages where possible
Cannot find existing option for twig/smarty, need to look other methods.
2023-02-17 22:14:34 +00:00
Dan Brown
9135a85de4 Merge branch 'codemirror6' into codemirror6_take2 2023-02-17 21:28:23 +00:00
Dan Brown
fd45d280b4 Updated tinymce from 6.1.0 to 6.3.1 2023-02-17 21:16:42 +00:00
Dan Brown
524adce654 Merge pull request #4049 from BookStackApp/shelf_book_sort_updates
Shelf book sort improvements
2023-02-17 16:20:59 +00:00
Dan Brown
f799c9b260 Applied shelf book sort changes from testing
Added better labelling of sort lists for screen readers.
Fadded out sort-item action buttons until hovering for a cleaner look.
2023-02-17 16:18:24 +00:00
Dan Brown
9c26ccf43d Added shelf book item sort action functionality
Adds JS logic, and dropdown action list, for quick-sorting the book
shelf list in addition to handling the book item action buttons.
2023-02-17 15:53:24 +00:00
Dan Brown
71a09bcf6e Started accessible controls for shelf book sort
Added buttons and fit to design.
Added new icon variations to support.
Extracted book item to own view and setup for future auto sorts.
2023-02-17 15:05:28 +00:00
Dan Brown
af31a6fc1b Made sendmail command configurable
For #4001
Added simple test to cover config option.
2023-02-17 14:25:38 +00:00
Dan Brown
08b39500b3 Fixed gallery images not visible until draft publish
For #4028
2023-02-16 17:57:34 +00:00
Dan Brown
f9fcc9f3c7 Updated php deps 2023-02-16 17:27:09 +00:00
Dan Brown
0812184995 Added torutec as sponsor, updated license and version 2023-02-14 16:16:08 +00:00
Dan Brown
646f8f60c0 Merge pull request #4032 from BookStackApp/favicon
Generate favicon.ico file
2023-02-09 21:37:38 +00:00
Dan Brown
f333db8e4f Added control-upon-access of the default favicon.ico file 2023-02-09 21:16:27 +00:00
Dan Brown
da42fc7457 Added default favicon creation upon access. 2023-02-09 20:57:35 +00:00
Dan Brown
48f1934387 Updated favicon gen to use png-based ICO
From testing, worked on Firefox, Chrome, Gnome Web
2023-02-09 17:47:33 +00:00
Dan Brown
2845e0003e Got favicons better supported, can't get transparency right
Digging deeper, I don't think PHPGD supports 32bit bmp output which
complicates matters.
2023-02-09 15:14:41 +00:00
Dan Brown
1a189640f1 Integrated favicon handler with correct files & actions
Format does not look 100% correct though, won't show in Firefox/gimp.
2023-02-09 13:24:43 +00:00
Dan Brown
420f89af99 Built custom favicon.ico file creator
Followed wikipedia-defined ICO file format info, and used with
Intervention's good bmp support, to create a working proof-of-concept.
2023-02-08 23:06:42 +00:00
Dan Brown
da1a66abd3 Extracted test file handling to its own class
Closes #3995
2023-02-08 14:39:13 +00:00
Dan Brown
5d18e7df79 Removed deprecated syntax in old migration file 2023-02-08 13:20:00 +00:00
Dan Brown
ba25a3e1b7 Merge pull request #4021 from BookStackApp/laravel9
Upgrade framework to Laravel 9
2023-02-07 12:11:04 +00:00
Dan Brown
bc18dc7da6 Removed parallel testing, updated predis
Parallel testing paratest library caused issues due to a single version
not being compatibile across our php range. Removed for now as not
really worth the faff to get compatible.
2023-02-07 11:50:59 +00:00
Dan Brown
5e8ec56196 Fixed issues found from tests 2023-02-06 20:41:33 +00:00
Dan Brown
9ca088a4e2 Fixed static analysis issues 2023-02-06 20:00:44 +00:00
Dan Brown
008e7a4d25 Followed Laravel 9 update steps and file changes 2023-02-06 16:58:29 +00:00
Dan Brown
ce9b536b78 Updated version and assets for release v23.01.1 2023-02-02 12:29:26 +00:00
Dan Brown
d9c50e5bc1 Merge branch 'development' into release 2023-02-02 12:29:07 +00:00
Dan Brown
6e6f113336 Merge branch 'development' of github.com:BookStackApp/BookStack into development 2023-02-02 12:17:06 +00:00
Dan Brown
f7441e2abc Updated translations with latest Crowdin changes (#4008) 2023-02-02 12:16:56 +00:00
Dan Brown
28c168145f Added missing app icon image
Fixes #4006
2023-02-02 11:49:06 +00:00
Dan Brown
c2115cab59 Updated php depenencies 2023-02-02 11:44:25 +00:00
Dan Brown
bf075f7dd8 Updated version and assets for release v23.01 2023-01-31 11:59:51 +00:00
Dan Brown
a4fd673285 Merge branch 'development' into release 2023-01-31 11:59:28 +00:00
Dan Brown
813d140213 Merge branch 'development' of github.com:BookStackApp/BookStack into development 2023-01-31 11:39:21 +00:00
Dan Brown
3dc5942a85 Updated translation attribution before v23.01 release 2023-01-31 11:38:56 +00:00
Dan Brown
03e2a9b200 Updated translations with latest Crowdin changes (#3925) 2023-01-31 11:29:36 +00:00
Dan Brown
8367a94e90 Merge pull request #4002 from BookStackApp/color_upgrades
Better application color scheme control
2023-01-28 17:59:54 +00:00
Dan Brown
631546a68a Adjusted/improved some color setting wording 2023-01-28 17:57:43 +00:00
Dan Brown
7751022c66 Updated migration to carry across more colors, updated export
Updated export to use link color for link.
Export will now copy primary color to link color options for stable
upgrades.
2023-01-28 17:49:48 +00:00
Dan Brown
f42ff59b43 Added migration of color settings to dark mode 2023-01-28 17:31:43 +00:00
Dan Brown
104621841b Update JS to show live changes and set light color values 2023-01-28 17:11:15 +00:00
Dan Brown
c337439370 Rolled out use of seperate link color style 2023-01-28 16:06:11 +00:00
Dan Brown
65ebdb7234 Added usage and defaults for dark colors 2023-01-28 15:20:08 +00:00
Dan Brown
e708ce93ba Updated generic tab styles and js to force accessible usage
Added use of more accessible tags to create tabbed-interfaces then
updated css and JS to require use of those attributes rather than custom
techniques.

Updated relevant parts of app.
Some custom parts using their own tabs though, something to improve in
future.
2023-01-28 12:50:51 +00:00
Dan Brown
1f69965c1e Updated settings view to have dark-mode color options
Also added link color option, not yet used.
Cleaned up tabbed interface control design as part of this.
2023-01-28 11:50:46 +00:00
Dan Brown
d7723b33f3 Merge pull request #3999 from BookStackApp/sort_ui_improvements
Improve Book Sorting User Experience
2023-01-27 18:02:14 +00:00
Dan Brown
87e371ffde Added prevention of nested chapters on sort 2023-01-27 17:39:51 +00:00
Dan Brown
b649738718 Made book-sort changes based on screen reader testing
- Removed having sort items in tabbing order since they have no action.
- Updated "show other books" list to add upon single selection since it
  was not clear how these were added (double press) without then seeing
the add button, and even then the add button would be after the scroll
list.
2023-01-27 17:06:39 +00:00
Dan Brown
022cbb9c00 Finished off design and fixing of sort buttons 2023-01-27 16:25:06 +00:00
Dan Brown
40e112fc5b Extracted text & added dropdown for book sort move actions
Primarily styling and testing left to do.
2023-01-27 13:26:58 +00:00
Dan Brown
7cacbaadf0 Added functionality/logic for button-based sorting 2023-01-27 13:08:35 +00:00
Dan Brown
a3e7e754b9 Improves sortable ux
- Fixes multi-select functionality.
- Updated other books to be sticky.
- Added some general intro/desc text.
- Updated sort boxes to be collapsible.
- Cleaned up other books styling.
2023-01-27 11:16:17 +00:00
Dan Brown
03ad288aaa Updated user avatar reset to clear relation id in database
Added test to cover.
For #3977
2023-01-26 17:15:09 +00:00
Dan Brown
811be3a36a Added option to change the OIDC claim regarded as the ID
Defined via a OIDC_EXTERNAL_ID_CLAIM env option.
For #3914
2023-01-26 16:43:15 +00:00
Dan Brown
3202f96181 Tweak tag list to add new row on input instead of change
Prevented interferance with the user's action if they interacted with
something below the tags, since a new row would be added on blur and
hence shift down positions.

For #3931
2023-01-26 16:10:47 +00:00
Dan Brown
f6a6b11ec5 Added and addressed multi-role/own-role-perm/inheretance scenario
Found during manual testing.
Have checked against relation queries manually too.
2023-01-26 12:53:25 +00:00
Dan Brown
48df8725d8 Added better drawing load failure handling
Failure of loading drawings will now close the drawing view and show an
error message, hinting at file or permission issues, instead of leaving
the user facing a continuosly loading interface.

Adds test to cover.

This also updates errors from our HTTP service to be wrapped in a custom
error type for better identification and so the error is an actual
javascript error. Should be object compatible.

Related to #3955.
2023-01-26 12:18:33 +00:00
Dan Brown
25bdd71477 Add scheme and sql-variant code language options
For #3954 and #3942
2023-01-26 11:26:20 +00:00
Dan Brown
deda331745 Fixed global search preview click on safari
Safari needs an element to be focusable to be able to use :focus-within.
For #3926
2023-01-25 21:46:26 +00:00
Dan Brown
f6d3944b20 Merge pull request #3994 from BookStackApp/app_icon_setting
Added ability to control app icon (favicon) via settings
2023-01-25 16:50:48 +00:00
Dan Brown
a50b0ea1e5 Covered app icon setting with testing 2023-01-25 16:41:41 +00:00
Dan Brown
3c658e39ab Extracted app icon text, fixed issues
Tweaked sizes and meta tags based unpon ipad testing.
Fixed reduced sizes not being cleaned up.
2023-01-25 16:11:34 +00:00
Dan Brown
d8354255e7 Added practicali to sponsor list 2023-01-25 12:06:11 +00:00
Dan Brown
55b6a7842e Added ability to control app icon (favicon) via settings 2023-01-25 11:03:19 +00:00
Dan Brown
0f113ec41f Merge pull request #3986 from BookStackApp/permission_testing
Permission Testing & Alignment
2023-01-24 21:37:28 +00:00
Dan Brown
1fa5a31960 Fixed role entity permissions ignoring inheritance
Added additional scnenario tests to cover
2023-01-24 21:26:41 +00:00
Dan Brown
8be36455ab Addressed fallback override cases found during testing
Had misalignment between query and usercan, The nuance between fallback
and entity-role permissions was not taken into account by the query
system. Now added with new test cases to cover.
2023-01-24 20:42:20 +00:00
Dan Brown
d1bd6d0e39 Fixed incorrect field in down migration 2023-01-24 19:21:23 +00:00
Dan Brown
1660e72cc5 Migrated remaining relation permission usages
Now all tests are passing.
Some level of manual checks to do.
2023-01-24 19:04:32 +00:00
Dan Brown
2d1f1abce4 Implemented alternate approach to current joint_permissions
Is a tweak upon the existing approach, mainly to store and query role
permission access in a way that allows muli-level states that may
override eachother. These states are represented in the new PermissionStatus
class.

This also simplifies how own permissions are stored and queried, to be
part of a single column.
2023-01-24 14:55:34 +00:00
Dan Brown
7d74575eb8 Found a sql having-style approach to permissions
As a way to check aggregate queries for required changes to need to
analyse across combined permission values.
2023-01-24 13:44:38 +00:00
Dan Brown
91e613fe60 Shared entity permission logic across both query methods
The runtime userCan() and the JointPermissionBuilder now share much of
the same logic for handling entity permission resolution.
2023-01-23 15:09:03 +00:00
Dan Brown
f3f2a0c1d5 Updated userCan logic to meet expectations in tests
Updated with similar logic to that used in the user_permissions branch,
but all extracted to a seperate class for doing all fetch and collapse
work.
2023-01-23 12:40:11 +00:00
Dan Brown
1c2ae7bff6 Added gmp extension to test workflow
If was not already enabled by default, should enable faster testing
handling as it helps the phpseclib usage for OIDC tokens in test rocket
through.
2023-01-21 21:34:39 +00:00
Dan Brown
78ebcb6f38 Addressed a range of deprecation warnings
Closes #3969
2023-01-21 20:50:04 +00:00
Dan Brown
28dda39260 Updated PHP and JS depenencies 2023-01-21 19:09:19 +00:00
Dan Brown
e2a72d16aa Made adjustments to fit copied work into dev branch
Ported non-compatible elements, Now all tests passing apart from some
specific permission scenario tests which are probably correctly failing.
Updates some tests to better avoid messing environment state.
2023-01-21 13:03:47 +00:00
Dan Brown
c724bfe4d3 Copied over work from user_permissions branch
Only that relevant to the additional testing work.
2023-01-21 11:08:34 +00:00
Dan Brown
6070d804f8 Fixed incorrect pluralisation for de_informal
Updated language system to only use initial part of locale for
translation pluralisation to better match the hard-coded logic of the
built-in MessageSelector. Extends and overrides Laravel's default for
this system.

Added test to cover.
Related to #3976.
2023-01-16 16:56:41 +00:00
Dan Brown
e794c977bc Updated version and assets for release v22.11.1 2022-12-16 23:49:14 +00:00
Dan Brown
0b088ef1d3 Merge branch 'development' into release 2022-12-16 23:48:35 +00:00
Dan Brown
5393465ea7 Updated translator attribution before release v22.11.1 2022-12-16 23:48:04 +00:00
Dan Brown
f5df811b15 Removed old unused style definition 2022-12-16 23:21:24 +00:00
Dan Brown
a521f41838 Fixed lack of scroll in editor toolbox contents
For #2887
2022-12-16 23:16:51 +00:00
Dan Brown
0123d83fb2 Fixed not being able to remove all user roles
User roles would only be actioned if they existed in the form request,
hence removal of all roles would have no data to action upon.
This adds a placeholder 0-id role to ensure there is always role data to
send, even when no roles are selected. This field value is latter
filtered out.

Added test to cover.

Likely related to #3922.
2022-12-16 17:44:13 +00:00
Dan Brown
559e392f1b Merge branch 'development' of https://github.com/jhit/BookStack into jhit-development 2022-12-16 17:12:57 +00:00
Dan Brown
8468b632a1 Updated crowdin config with PR title and labels
Aligns to the title and labelling I already do manually.
2022-12-16 17:11:01 +00:00
Dan Brown
7053a8669f New Crowdin updates (#3881) 2022-12-16 17:06:52 +00:00
Dan Brown
2c0a7346b1 Prevent search focus change on left/right arrow press
For #3920
2022-12-16 17:03:48 +00:00
Dan Brown
bf6a6af683 Updated version and assets for release v22.11 2022-11-30 12:30:21 +00:00
Dan Brown
914790fd99 Merge branch 'development' into release 2022-11-30 12:29:52 +00:00
Dan Brown
69d702c783 Updated locale list to align with lang folders 2022-11-30 12:13:50 +00:00
Dan Brown
dd92cf9e96 Updated translator attribution before v22.11 release 2022-11-30 12:02:10 +00:00
Dan Brown
0cd0b44cdb New Crowdin updates (#3828) 2022-11-30 12:01:19 +00:00
Jürgen Hörmann
d505642336 Add popular PHP templating languages to code editor
Smarty and Twig are two very popular PHP templating engines and might be
useful to some Bookstack users too.
2022-11-29 14:53:41 +01:00
Dan Brown
31c28be57a Converted md settings to localstorage, added preview resize 2022-11-28 14:08:20 +00:00
Dan Brown
38db3a28ea Merge pull request #3878 from BookStackApp/dark_style_cleanup
Cleaned up dark mode styles inc. setting browser color scheme
2022-11-28 12:42:16 +00:00
Dan Brown
09fa2d2c9c Cleaned up dark mode styles inc. setting browser color scheme
Forces browser colorscheme based on BookStack color scheme, via
'color-scheme' css property.
Sets proper dark mode colors for some previously missed areas like
templates and attachment control buttons.
Also fixed search bar icon position for some search inputs.
2022-11-28 12:38:30 +00:00
Dan Brown
b786ed07be Merge pull request #3875 from BookStackApp/md_editor_updates
Markdown Editor Updates
2022-11-28 12:21:33 +00:00
Dan Brown
0527c4a1ea Added test to preference boolean endpoint 2022-11-28 12:17:22 +00:00
Dan Brown
ec3713bc74 Connected md editor settings to logic for functionality 2022-11-28 12:12:36 +00:00
Dan Brown
9fd5190c70 Added md editor ui dropdown options & their back-end storage
Still need to perform actual in-editor functionality for those controls.
2022-11-27 20:30:14 +00:00
Dan Brown
3995b01399 Tightened existing markdown editor styles 2022-11-27 19:52:10 +00:00
Dan Brown
3fdb88c7aa Added callout cycling in markdown editor via shortcut 2022-11-26 23:18:51 +00:00
Dan Brown
8e4bb32b77 Fixed md editor refactoring issues after manual test
Testing was a full manual feature test of each piece of supported logic
defined in the code.
2022-11-26 21:33:39 +00:00
Dan Brown
63d6272282 Refactored markdown editor logic
Split out the markdown editor logic into seperate components to provide
a more orgranised heirachy with feature-specific files.
2022-11-26 16:43:28 +00:00
Dan Brown
40a1377c0b Fixed tests to align with recent changes, Updated php deps 2022-11-23 12:08:55 +00:00
Dan Brown
e20c944350 Fixed OIDC handling when no JWKS 'use' prop exists
Now assume, based on OIDC discovery spec, that keys without 'use' are
'sig' keys. Should not affect existing use-cases since existance of such
keys would have throw exceptions in prev. versions of bookstack.

For #3869
2022-11-23 11:50:59 +00:00
Dan Brown
85b7b10c01 Merge branch 'development' of github.com:BookStackApp/BookStack into development 2022-11-23 00:13:02 +00:00
Dan Brown
35f73bb474 Updated global search component to new format 2022-11-23 00:12:41 +00:00
Dan Brown
ffc9c28ad5 Merge branch 'search_preview' into development 2022-11-23 00:10:21 +00:00
Dan Brown
fcff206853 Adjusted global search preview for dark mode 2022-11-23 00:05:24 +00:00
Dan Brown
0e528986ab Extracted keyboard nav. from dropdowns to share w/ search 2022-11-21 17:35:19 +00:00
Dan Brown
e7e83a4109 Added new endpoint for search suggestions 2022-11-21 10:35:53 +00:00
Dan Brown
891543ff0a Merge pull request #3852 from BookStackApp/php82
PHP8.2 Support
2022-11-20 22:21:52 +00:00
Dan Brown
c617190905 Added global search input debounce and loading indicator 2022-11-20 22:20:31 +00:00
Dan Brown
2c1f20969a Replaced JS logic with CSS focus-within logic 2022-11-20 21:53:53 +00:00
Dan Brown
851ab47f8a Fixed input styles in search preview mode, added animation
Also added JS handlers for hiding the suggestions
2022-11-20 21:50:59 +00:00
Dan Brown
bbf13e9242 Merge pull request #3853 from BookStackApp/component_refactor
Started refactor and alignment of JS component system
2022-11-16 16:05:57 +00:00
Dan Brown
05a24ea355 Updated js dev docs with latest component changes 2022-11-16 16:02:31 +00:00
Dan Brown
be736b3939 Replaced el.components mapping with component service weakmap
Old system was hard to track in terms of usage and it's application of
'components' properties directly to elements was shoddy.
This routes usage via the components service, with element-specific
component usage tracked via a local weakmap.
Updated existing found usages to use the new system.
2022-11-16 15:46:41 +00:00
Dan Brown
25c23a2e5f Removed use of image-manager/entity-selector window globals 2022-11-16 15:21:22 +00:00
Dan Brown
3b8ee3954e Finished updating remainder of JS components to new system 2022-11-16 13:06:08 +00:00
Dan Brown
db79167469 Updated a whole load more js components 2022-11-15 16:04:46 +00:00
Dan Brown
b37e84dc10 Updated another set of components 2022-11-15 12:44:57 +00:00
Dan Brown
4310d34135 Updated a batch of JS components 2022-11-15 11:24:31 +00:00
Dan Brown
09c6a3c240 Started refactor and alignment of component system
- Updates old components to newer format, removes legacy component
support.
- Makes component registration easier and less duplicated.
- Adds base component class to extend for better editor support.
- Aligns global window exposure usage and aligns with other service
  names.
2022-11-14 23:19:02 +00:00
Dan Brown
796f4090b5 Added php8.2 to GH action checks 2022-11-14 18:26:01 +00:00
Dan Brown
19a792bc12 Started on a live-preview on global search input 2022-11-14 10:24:14 +00:00
Dan Brown
a1b1f8138a Updated email confirmation flow so confirmation is done via POST
To avoid non-user GET requests (Such as those from email scanners)
auto-triggering the confirm submission. Made auto-submit the form via
JavaScript in this extra added step with user-link backup to keep
existing user flow experience.

Closes #3797
2022-11-12 15:11:59 +00:00
Dan Brown
0e627a6e05 Merge pull request #3848 from BookStackApp/auth_message_partials
Added login/register message partials for easier use via theme system
2022-11-12 09:03:59 +00:00
Dan Brown
d2cd33e226 Added login/register message partials for easier use via theme system
Related to #608
2022-11-12 09:02:33 +00:00
Dan Brown
2fa5c2581c Added swift support to code blocks and editor
Closes #3847
2022-11-12 08:44:25 +00:00
Dan Brown
d2260b234c Fixed app logo visibility with secure_restricted images
Includes test to cover.
For #3827
2022-11-10 14:15:59 +00:00
Dan Brown
832356d56e Added test to cover books perms. gen with deleted chapter
Closes #3796
2022-11-10 13:48:17 +00:00
Dan Brown
5fd1c07c9d Added dart support to code blocks/editing
For #3808
2022-11-10 13:38:56 +00:00
Dan Brown
4c75358abd Extracted hardcoded english text to language files
Closes #3822
2022-11-10 13:30:48 +00:00
Dan Brown
d520d6cab8 Merge pull request #3830 from BookStackApp/shortcuts
User interface shortcuts system
2022-11-10 10:32:56 +00:00
Dan Brown
737904fa63 Extracted shortcut text to language files 2022-11-10 10:25:28 +00:00
Dan Brown
a3fcc98d6e Aligned user preference endpoints in style and behaviour
Changes their endpoints and remove the user id from the URLs.
Simplifies list changes to share a single endpoint, which aligns it to
the behaviour of the existing sort preference endpoint.
Also added test to ensure user preferences are deleted on user delete.
2022-11-09 19:30:08 +00:00
Dan Brown
24a7e8500d Added tests to cover shortcut endpoints 2022-11-09 18:42:54 +00:00
Dan Brown
9067902267 Added shortcut input controls to make custom shortcuts work 2022-11-09 14:40:44 +00:00
Dan Brown
66c8809799 Started interface user shortcut form interface
Built controller actions and initual UI.
Still needs JS logic for shortcut input handling.
2022-11-08 21:17:45 +00:00
Dan Brown
1fc994177f Improved shortcut overlay with related action highlighting 2022-11-05 13:57:22 +00:00
Dan Brown
78b6450031 Distributed shortcut actions to common ui elements 2022-11-05 13:39:17 +00:00
Dan Brown
b4cb375a02 Started implementation of UI shortcuts system 2022-11-04 15:20:19 +00:00
Dan Brown
33e5c85503 Merge pull request #3821 from BookStackApp/list_reworks
Revision of item list views
2022-11-03 14:52:40 +00:00
Dan Brown
9e8240a736 Addressed additional unsupported array spread operation 2022-11-03 14:40:01 +00:00
Dan Brown
37afd35b6f Fixed use of array unpacking syntax
Since it was using keyed arrays, unpacking is only supported in php8.1+
2022-11-03 14:33:23 +00:00
Dan Brown
6364c541ea Fixed phpstan static usage warning, updated ci flows
CI flow updates to follow deprecation warnings
2022-11-03 14:14:22 +00:00
Dan Brown
8ec6b07690 Updated role permission table to responsive format 2022-11-03 13:28:07 +00:00
Dan Brown
7101ec09ed Updated search term lists to flex layouts 2022-11-03 12:49:05 +00:00
Dan Brown
2c5efddf6c Merge branch 'v22-10' into development 2022-11-02 15:22:53 +00:00
Dan Brown
edb0c6a9e8 Updated version and assets for release v22.10.2 2022-11-02 15:22:13 +00:00
Dan Brown
84049de696 Merge branch 'v22-10' into release 2022-11-02 15:19:33 +00:00
Dan Brown
a37bdffcd9 Updated translator attribution before release v22.10.2 2022-11-02 15:19:13 +00:00
Dan Brown
e95ab36f76 Merged and squashed l10n_development into v22-10 2022-11-02 15:17:54 +00:00
Dan Brown
f809bd3a62 Updated tests to align with recent list changes 2022-11-01 14:53:36 +00:00
Dan Brown
d4e71e431b Revised revision list to responsive layout 2022-10-31 21:26:31 +00:00
Dan Brown
de807f8538 Updated recycle bin list to new responsive layout 2022-10-31 16:45:32 +00:00
Dan Brown
80d2889217 Updated tags list to new responsive format 2022-10-31 11:40:28 +00:00
Dan Brown
9e8516c2df Tweaked list spacings a little to align paddings 2022-10-30 21:06:42 +00:00
Dan Brown
09f2bc28d2 Removed addition detail spacing in audit list 2022-10-30 20:29:21 +00:00
Dan Brown
be320c5501 Adjusted audit log row spacing a tad 2022-10-30 20:27:41 +00:00
Dan Brown
2bbf7b2194 Revised audit log list to new responsive format 2022-10-30 20:24:08 +00:00
Dan Brown
ab184c01d8 Updated API tokens list to new responsive format 2022-10-30 15:37:52 +00:00
Dan Brown
2c114e1a4a Split out user controller preference methods to new controller 2022-10-30 15:25:02 +00:00
Dan Brown
ec4cbbd004 Refactored common list handling operations to new class 2022-10-30 15:16:06 +00:00
Dan Brown
f75091a1c5 Revised webhooks list to new format
Also aligned query naming to start with model in use.
Also added created/updated sort options to roles.
2022-10-30 12:02:06 +00:00
Dan Brown
98b59a1024 Revised role index list to align with user list 2022-10-29 20:52:17 +01:00
Dan Brown
0ef06fd298 Extracted user list item to its own template 2022-10-29 15:25:28 +01:00
Dan Brown
986346a0e9 Redesigned users list to be responsive and aligned 2022-10-29 15:23:21 +01:00
Dan Brown
2a65331573 Worked towards phpstan level 2, 13 errors remain 2022-10-24 12:12:48 +01:00
Dan Brown
45d0860448 Updated npm package versions 2022-10-24 11:40:05 +01:00
Dan Brown
da0531e63b Updated version and assets for release v22.10.1 2022-10-21 21:52:32 +01:00
Dan Brown
421dc75f4e Merge branch 'development' into release 2022-10-21 21:52:16 +01:00
Dan Brown
ea6eacb400 Fixed chapter fetching during joint permission building
Somehow I accidentally deleted previous line 143 in this commit:
3839bf6bf1
which would then break permission generation for content related to, or
containing, chapters in the recycle bin.
Found via user report (subz) & debugging in discord.
2022-10-21 21:49:29 +01:00
Dan Brown
8ae91df038 Updated version and assets for release v22.10 2022-10-21 11:16:45 +01:00
Dan Brown
64b41dd626 Merge branch 'development' into release 2022-10-21 11:16:25 +01:00
Dan Brown
103649887f Updated translator attribution before release v22.10 2022-10-21 11:15:35 +01:00
Dan Brown
7b2fd515da Updated test to align with latest translation 2022-10-21 10:41:55 +01:00
Dan Brown
3f61bfc43c Fixed toggle controls on added content permission role rows 2022-10-21 10:13:11 +01:00
Dan Brown
905d339572 Added greek language option 2022-10-20 12:25:02 +01:00
Dan Brown
5d37a814fd New Crowdin updates (#3737) 2022-10-20 12:18:58 +01:00
Dan Brown
f9c0edbd0c Set fixed cell widths for users list table
To prevent certain cells squashing others.
Related to #3787.
2022-10-19 11:15:17 +01:00
Dan Brown
d084f225a0 Updated page pointer to use a fixed positioning system
Avoids interferance with elements that have their own overflow behaviour
such as table cells.
Related to #3774
2022-10-18 22:40:13 +01:00
Dan Brown
ff3fb2ebb9 Extracted page pointer to its own compontent 2022-10-18 22:02:34 +01:00
Dan Brown
725ff5a328 Updated php deps 2022-10-16 09:54:07 +01:00
Dan Brown
f0ac454be1 Prevented saml2 autodiscovery on metadata load
Fixes issue where metadata cannot be viewed if autload is active and
entityid url is not active.
For #2480
2022-10-16 09:50:08 +01:00
Dan Brown
0269f5122e Added wysiwyg code block edit tooltip
For easier editing access on mobile devices where previous doubleclick
does not work so well.
For #2815
2022-10-15 15:47:34 +01:00
Dan Brown
6adc642d2f Merge branch 'development' into bugfix/fix-being-unable-to-clear-filters 2022-10-15 15:12:55 +01:00
Dan Brown
22a91c955d Merge pull request #3760 from BookStackApp/item_permission_revamp
Refactor of item-level permission to be more intuitive
2022-10-14 17:34:51 +01:00
Dan Brown
6951aa3d39 Fixed permission row permission check 2022-10-14 16:03:06 +01:00
Dan Brown
bd412ddbf9 Updated test for perms. changes and fixed static issues 2022-10-12 12:12:36 +01:00
Dan Brown
7792da99ce Updated entity perms. changes for dark mode support 2022-10-12 11:27:24 +01:00
Dan Brown
98c6422fa6 Extracted entity perms. text to translation files 2022-10-11 15:52:56 +01:00
Dan Brown
25708542ff Refined design and text for entity permission changes 2022-10-11 15:41:21 +01:00
Dan Brown
0fae807713 Fixed and updated "Everyone Else" permissions handling
- Fixed inheriting control for new system.
- Tested copying shelf permissions to books.
- Added additional handling for inheriting scenario identification.
2022-10-10 17:22:38 +01:00
Dan Brown
0f68be608d Removed most usages of restricted entitiy property 2022-10-10 16:58:26 +01:00
Dan Brown
63056dbef4 Updated restricted usage on search and entity meta details
Also removed now unused view.
2022-10-10 16:22:51 +01:00
Dan Brown
803934d020 Added interface for adding/removing roles in entity perms. 2022-10-10 12:24:23 +01:00
Dan Brown
ffd6a1002e Centralised handling of permission form data to own class
Also updates show roles on permission view to just those with
permissions applied.
Fixes rounded borders for lone permission rows.
Moves "Everyone Else" handling from role to new class.
2022-10-09 17:14:11 +01:00
Dan Brown
bf591765c1 Reorgranised permission routes into their own controller
Also introduced helpers for getting entities by slugs since we do it in
so many places.
2022-10-09 16:36:03 +01:00
Dan Brown
06a7f1b54a Added migration to drop entity restricted field 2022-10-08 15:30:03 +01:00
Dan Brown
3839bf6bf1 Updated joint perms. gen. to use new entity permission format 2022-10-08 14:28:44 +01:00
Dan Brown
aee0e16194 Started code update for new entity permission format 2022-10-08 13:52:59 +01:00
Dan Brown
1d3dbd6f6e Migrated entity_permissions table to new flat format
Simplifies structure and limits content count, while allowing direct
mapping of new UI intent, where we may have entries with no permissions.
Not yet updated app logic to suit.

Tested via migrating and rolling-back, then comparing export data,
across a set of custom permission entries.
2022-10-07 15:07:09 +01:00
Dan Brown
1df9ec9647 Added proper entity permission removal on role deletion
Added test to cover.
2022-10-07 13:12:33 +01:00
Allan
d4143c3101 Only output hidden user filters when not set to 'me' 2022-10-06 19:25:47 +02:00
Dan Brown
a03245e427 Added user-interface for "Everyone Else" entity permission item
Nothing on back-end logic done to hook this new option up.
Addition of permissions for role_id=0 works out of the box, but active
"everyone else" permissions, with no priviliges, is currently not
working. Needs change of permission gen logic also.
2022-10-02 18:09:48 +01:00
Dan Brown
a090720241 Developed dev JS docs a bit further 2022-10-02 14:27:12 +01:00
Dan Brown
b8b0afa0df Cleaned up old permission JS code
Removed now unused JS entity-permissions compontent.
Updated existing permissions-table compontent to newer format.
Removed now unused translation string.
2022-10-02 13:57:32 +01:00
Dan Brown
f19bad8903 Started item permission design revamp 2022-10-02 13:17:28 +01:00
Dan Brown
953402f2eb Started playing with table icons
To make a little more accessible, Related to #3397
2022-09-30 18:37:37 +01:00
Dan Brown
8c945034b9 Merge pull request #3757 from BookStackApp/tests_entity_cleanup
Testing cleanup
2022-09-29 22:18:34 +01:00
Dan Brown
900e853b15 Quick run through of applying new test entity helper class 2022-09-29 22:11:16 +01:00
Dan Brown
b56f7355aa Migrated much test entity usage via find/replace 2022-09-29 17:31:38 +01:00
Dan Brown
068a8a068c Extracted entity testcase methods to own class
Also added some new fetch helper methods for future use.
2022-09-29 16:49:25 +01:00
Dan Brown
0e94fd44a8 Added contents to book-show endpoint
Created a generic list formatting helper class for this, to align with
logic used on the search results endpoint and for easier future re-use
in a standardised way.
Also updated some class property types.
Added test to cover new books-contents results.
Related to #3734
2022-09-29 15:08:18 +01:00
Dan Brown
ccbc68b560 Updated shelf book management to allow scroll on mobile
Updates book drag handling to be limited to the handle so scrolling can
be done on the items themselves.
Increased handling area and improved styling to support
2022-09-28 20:48:29 +01:00
Dan Brown
f79b7bc799 Added api format advisory regarding PUT/DELETE form data 2022-09-28 20:15:48 +01:00
Dan Brown
60171b3522 Updated book copy to copy shelf relations
Where permission to edit the shelf is allowed.
For #3699
2022-09-28 14:14:51 +01:00
Dan Brown
8f3430d386 Improved tag suggestion handling
- Aligned prefix-type filtering with back-end.
- Increased suggestion search cut-off from 3 to 4.
- Increased amount of suggestions shown.
- Ordered suggestions to be name asc, as you'd expect on search.
- Updated front-end filtering to use full search query, instead of
  truncated version, for further front-end filtering capability.

Related to #3720
2022-09-28 13:50:40 +01:00
Dan Brown
1ac1cf0c78 Applied permissions to revision action visibility
Related to #3723
2022-09-28 11:10:06 +01:00
Dan Brown
6dd89ba956 Split out some development-specific readme parts to own pages 2022-09-27 20:11:58 +01:00
Dan Brown
bf56254077 Merge branch 'auth_review' into development 2022-09-27 19:34:48 +01:00
Dan Brown
d933fe5dce Updated WYSIWYG config to allow styles on list elements 2022-09-27 19:05:03 +01:00
Dan Brown
391fb2cc62 Added MATLAB/Octave code highlighting support 2022-09-27 18:52:21 +01:00
Dan Brown
af11e7dd54 Merge branch 'development' of github.com:BookStackApp/BookStack into development 2022-09-27 18:45:08 +01:00
Dan Brown
af434d0216 Fixed custom code theme not showing in WYSIWYG
Fixes #3753
Was caused by not including added styles to the code block shadow root.
2022-09-27 18:44:06 +01:00
Dan Brown
931641ed2c Tweaked license and readme text
Updated license copyright line to better help it be detected as MIT by
automatic license systems (Such as GitHub license detection) while
removing contributors link which would not actually list all
contributors.
Also added year range back in to be more specific about active lifetime.
2022-09-27 12:23:16 +01:00
Dan Brown
b716fd2b8b Updated composer deps, incremented dev version 2022-09-27 02:56:49 +01:00
Dan Brown
a6a78d2ab5 Refactored app service providers
Removed old pagination provider as url handling now achieved in a better
way.
Removed unused broadcast service provider.
Moved view-based tweaks into specific provider.
Reorganised provider config list.
2022-09-27 02:48:05 +01:00
Dan Brown
67d7534d4f Merge pull request #3751 from BookStackApp/parallel_testing
Parallel Testing Support
2022-09-27 01:31:37 +01:00
Dan Brown
f21669c0c9 Cleaned testing service provider usage
Moved testing content out of AppServiceProvider, to a testing-specific
service provider. Updated docs and added composer commands to support
parallel testing.
Also reverted unintentional change to wysiwyg/config.js.
2022-09-27 01:27:51 +01:00
Dan Brown
e18033ec1a Added initial support for parallel testing 2022-09-26 21:25:32 +01:00
Dan Brown
5c5ea64228 Added login throttling test, updated reset-pw test method names 2022-09-22 17:29:38 +01:00
Dan Brown
90b4257889 Split out registration and pw-reset tests methods 2022-09-22 17:15:15 +01:00
Dan Brown
f4388d5e4a Removed usage of laravel/ui dependency
Brings app auth controller handling aligned within the app, rather than
having many overrides of the framwork packages causing confusion and
messiness over time.
2022-09-22 16:54:27 +01:00
Dan Brown
7165481075 Updated auth controllers with property types 2022-09-22 15:12:05 +01:00
Dan Brown
ebd6e4d3a2 Updated version and assets for release v22.09.1 2022-09-20 13:19:34 +01:00
Dan Brown
80374aea5c Merge branch 'development' into release 2022-09-20 13:19:03 +01:00
Dan Brown
aec772c5eb Updated translator attribution before release v22.09.1 2022-09-20 13:18:41 +01:00
Dan Brown
2e4d29e062 New Crowdin updates (#3710) 2022-09-20 13:16:15 +01:00
Dan Brown
dce6a82954 Added reason, if existing, into SAML acs error
Closes #3731
2022-09-20 12:52:44 +01:00
Dan Brown
050d69ea27 Added extra setlocale format to help windows support
Related to #3650
2022-09-20 12:00:14 +01:00
Dan Brown
0cc68b7665 Fixed language request link in readme 2022-09-19 17:24:21 +01:00
Dan Brown
75d6b56072 Merge pull request #3728 from BookStackApp/php_formatting
Addition of PHPCS for formatting
2022-09-18 15:04:07 +01:00
Dan Brown
ac27b5aebb Updated readme for phpcs usage, aligned gh action workflows 2022-09-18 14:50:25 +01:00
Dan Brown
ecbc7344fc Added php lint gh action, updated composer scripts 2022-09-18 01:56:45 +01:00
Dan Brown
8a749c6acf Added and ran PHPCS 2022-09-18 01:25:20 +01:00
Dan Brown
2ac9efae7d Updated version and assets for release v22.09 2022-09-08 12:41:09 +01:00
Dan Brown
a11d565ba4 Merge branch 'development' into release 2022-09-08 12:40:57 +01:00
Dan Brown
d0dc5e5c5d Added a little protection to migration query
Just to be sure the query is filtered as expected to only affect
shelf-based images.
2022-09-08 12:26:14 +01:00
Dan Brown
e4642257a6 New Crowdin updates (#3701) 2022-09-08 11:59:57 +01:00
Dan Brown
f7418d0600 Updated translator attribution 2022-09-08 11:58:55 +01:00
Dan Brown
98aed794cc Made a range of rtl fixes
Mostly around dropdowns and other items that had right/left specific
styling.
For #3702
2022-09-06 21:31:18 +01:00
Dan Brown
623ccd4cfa Removed old thai files, added romanian as lang option
Also applied styleci changes
2022-09-06 17:41:32 +01:00
Dan Brown
d8672944a5 Added image view access notice to role form
Added to clarify the role permission in scenarios where users may have
not read the docs site to understand image access control.

Related to #3688
2022-09-06 17:20:35 +01:00
Dan Brown
6955b2fd5a Widened svg content attribute xss filtering
Takes care of additional cases that can occur.
Closes #3705
2022-09-06 17:01:56 +01:00
Dan Brown
24f82749ff Updated OIDC group attr option name
To match the existing option name for display names.
Closes #3704
2022-09-06 16:33:17 +01:00
Dan Brown
b9941e8e61 Merge pull request #3698 from BookStackApp/include_theme_event
Added "page_include_parse" theme event
2022-09-05 16:51:01 +01:00
Dan Brown
7101ce3050 Added "page_include_parse" theme event
For custom control of include tag parsing.
2022-09-05 16:40:42 +01:00
Dan Brown
fbef0d06f2 Added permission visiblity control to image-delete button
Includes test to cover.
For #3697
2022-09-05 15:52:12 +01:00
Dan Brown
b698bb0e07 Wrapped wysiwyg drawing change in editor transaction
To make the content changes made a undoable transaction that is picked
up as a change.
From my testing, should address #3682
2022-09-05 15:06:47 +01:00
Dan Brown
2d7552aa09 Addressed setlocale issue caught by phpstan
setlocale could be called with no second param if the language given to
the modified function was empty.
2022-09-05 13:33:05 +01:00
Dan Brown
ee1e936660 Applied styleci changes, updated composer deps 2022-09-05 13:18:37 +01:00
Dan Brown
50214d5fe6 New Crowdin updates (#3643) 2022-09-05 13:17:10 +01:00
Dan Brown
2fe261e207 Updated page revisions link visibility
To match the actual visibilities of the revisions listing page and
options.
Related to #2946
2022-09-03 12:32:21 +01:00
Dan Brown
9158a66bff Updated & improved language locale handling
Extracted much of the language and locale work to a seperate, focused class.
Updated php set_locale usage to prioritise UTF8 usage.
Added locale options for windows.
Clarified what's a locale and a bookstack language string.

For #3590 and maybe #3650
2022-09-02 19:19:01 +01:00
Dan Brown
7f8b3eff5a Fixed failing tests due to shelf text changes, applied styleci changes 2022-09-02 14:47:44 +01:00
Dan Brown
5736919836 Merge pull request #3693 from BookStackApp/local_secure_restricted
Addition of a `local_secure_restricted` image storage option
2022-09-02 14:41:25 +01:00
Dan Brown
c76b5e2ec4 Fixed local_secure_restricted preventing attachment uploads
Due to option name change and therefore lack of handling.
Added test case to cover.
2022-09-02 14:40:17 +01:00
Dan Brown
092b6d6378 Added test and handling for local_secure_restricted in exports 2022-09-02 14:21:43 +01:00
Dan Brown
f88330202b Added test to cover secure restricted functionality 2022-09-02 14:03:23 +01:00
Dan Brown
f28ed0ef0b Fixed shelf covers being stored as 'cover_book'
Are now stored as 'cover_bookshelf' as expected.
Added a migrate to alter existing shelf cover image types.
2022-09-02 12:54:54 +01:00
Dan Brown
27ac122502 Started work on local_secure_restricted image option 2022-09-01 16:17:14 +01:00
Dan Brown
9da3130a12 Aligned bookshelf terminology to consistently be 'Shelf'
For #3553
EN only, other languages should be handled via CrowdIn
2022-09-01 14:55:35 +01:00
Dan Brown
1afc915aed Fixed missing nested list indent next to floated content
Fixes #3672
2022-09-01 13:11:59 +01:00
Dan Brown
34c63e1c30 Added test & update to prevent page creation w/ empty slug
Caused by changes to page repo in reference work,
This adds back in the slug generate although at a more central place.
Adds a test case to cover the problematic scenario.
2022-09-01 12:53:34 +01:00
Dan Brown
f092c97748 Fixed lack of url reference updating on book child move 2022-08-30 22:12:52 +01:00
Dan Brown
9153be963d Added book child reference handling on book url change
Closes #3683
2022-08-30 22:00:32 +01:00
Dan Brown
1cc7c649dc Applied StyleCi changes, updated php deps 2022-08-29 17:46:41 +01:00
Dan Brown
e537d0c4e8 Merge pull request #3656 from BookStackApp/x_linking
Link reference tracking & updating
2022-08-29 17:45:05 +01:00
Dan Brown
961e418cb7 Fixed phpstan wanring about usage of static 2022-08-29 17:39:50 +01:00
Dan Brown
6edf2c155d Added maintenance action to regenerate references 2022-08-29 17:30:26 +01:00
Dan Brown
401c156687 Merge pull request #3616 from BookStackApp/oidc_group_sync
Added OIDC group sync functionality
2022-08-25 11:17:18 +01:00
Dan Brown
760eff397f Updated API docs with better request format explanation
Explained the content-types accepted by BookStack.
Made it clear that 'Content-Type' is expected on requests.
Added example to shown how to achieve more complex formats using
non-json requests.
Also added link to api-scripts repo.

Related to #3666 and #3652
2022-08-23 17:05:42 +01:00
Dan Brown
d134639eca Doubled default revision limit
Due to potential increase of revision entries due to auto-changes.
2022-08-23 16:32:07 +01:00
Dan Brown
b86ee6d252 Rolled out reference link updating logic usage
Added test to cover updating of content on reference url change
2022-08-21 18:05:19 +01:00
Dan Brown
0dbf08453f Built out cross link replacer, not yet tested 2022-08-21 11:29:34 +01:00
Dan Brown
26ccb7b644 Started work on reference on-change-updates
Refactored out revision-specific actions within PageRepo for
organisition and re-use for cross-linking work.
2022-08-20 21:09:07 +01:00
Dan Brown
f634b4ea57 Added entity meta link to reference page
Not totally happy with implementation as is requires extra service to be
injected to core controllers, but does the job.
Included test to cover.
Updated some controller properties to be typed while there.
2022-08-20 12:07:38 +01:00
Dan Brown
d198332d3c Rolled out reference pages to all entities, added testing
Including testing to check permissions applied to listed references.
2022-08-19 22:40:44 +01:00
Dan Brown
d5465726e2 Added inbound references listing for pages 2022-08-19 13:14:43 +01:00
Dan Brown
bbe504c559 Added reference handling on page actions
Page update/create/restore/clone/delete.
Added a couple of tests to cover a couple of those.
2022-08-17 17:37:27 +01:00
Dan Brown
3290ab3ac9 Added regenerate-references command test
Also updated model resolvers to only fetch model ID, to prevent bringing
back way more data from database than desired.
2022-08-17 16:59:23 +01:00
Dan Brown
5d29d0cc7b Added reference storage system, and command to re-index
Also re-named/orgranized some files for this, to make them "References"
specific instead of a subset of "Util".
2022-08-17 14:40:14 +01:00
Dan Brown
344b3a3615 Added system to extract model references from HTML content
For the start of a managed cross-linking system.
2022-08-16 13:23:53 +01:00
Dan Brown
837fd74bf6 Refactored search-based code to its own folder
Also applied StyleCI changes
2022-08-16 11:28:05 +01:00
Dan Brown
2b06e86d53 Merge pull request #3653 from krsriq/patch-1
Fix typos
2022-08-15 22:31:49 +01:00
Daniel Schmelz
9041e25476 Fix typos 2022-08-15 22:41:44 +02:00
Dan Brown
1fdf854ea7 Updated version and assets for release v22.07.3 2022-08-11 15:17:06 +01:00
Dan Brown
e9c9792cb9 Merge branch 'development' into release 2022-08-11 15:16:34 +01:00
Dan Brown
d6235bcf92 Merge branch '3636-security-patch' into development 2022-08-11 15:15:19 +01:00
Dan Brown
6a3f4f5e79 Updated translator attribution pre v22.07.3 release 2022-08-11 13:17:18 +01:00
Dan Brown
7b100ef361 Merge branch 'persian_translate_22_08_10' into development 2022-08-11 13:15:15 +01:00
Dan Brown
443415ea0d New Crowdin updates (#3635) 2022-08-11 13:12:55 +01:00
Dan Brown
e02bd5e57e Added content security section to the api docs
Related to #3636
2022-08-11 10:49:45 +01:00
Dan Brown
5f7cd735ea Added content filtering of tags with javascript or data in values attr
Case would be blocked by CSP but adding for cases where CSP may not be
active when content taken externally.

For #3636
2022-08-11 10:28:32 +01:00
samad hassan allafi
89ff0d43bb Completion of Persian translation 2022-08-10 2022-08-10 22:55:31 +04:30
Dan Brown
375abca1ee Merge pull request #3632 from BookStackApp/ownable_permission_fix
Fixed failed permission checks due to non-loaded fields
2022-08-10 17:59:46 +01:00
Dan Brown
031c67ba58 Reduced the memory usage, db queries and cache hits loading revisions
Updated revision listing to only fetch required fields, massively
reducing memory usage by not loading content.
This also updates user avatar handling to effectively cache the avatar
url within request to avoid re-searching from cache, which may improve
performance of others areas of the application.
This also upates handling of the revisions list view to extract table
row to its own view to break things down a bit.

For #3633
2022-08-10 17:50:35 +01:00
Dan Brown
764489e30b Improved WYSWYG editor code block layout update
To help prevent against empty areas during inital empty-cache loads.
This delays the original layout update a little to give time for the
layout to render as expected.

For #3637
2022-08-10 13:51:54 +01:00
Dan Brown
16eedc8264 Fixed failed permission checks due to non-loaded fields
Added additional exceptions to prevent such cases in the future, so
that they are caught in dev ideally.
Added test case specifically for reported favourite scenario.
2022-08-10 08:06:48 +01:00
Dan Brown
5ae524c25a Updated version and assets for release v22.07.2 2022-08-09 13:55:52 +01:00
Dan Brown
0d7287fc8b Merge branch 'development' into release 2022-08-09 13:55:40 +01:00
Dan Brown
219da9da9b Updated translator attribution before release v22.07.2 2022-08-09 13:55:26 +01:00
Dan Brown
38ce54ea0c Merge pull request #3630 from BookStackApp/export_template_parts
Export template partials
2022-08-09 13:51:24 +01:00
Dan Brown
97ec560282 Added test to cover export body start/end partial usage 2022-08-09 13:49:42 +01:00
Dan Brown
06b5a83d8f Added convenience theme system partials for export layouts
To allow easier additions to start/end of body tag in export formats.
2022-08-09 13:46:52 +01:00
Dan Brown
45dc28ba2a Applied latest styleci changes 2022-08-09 13:26:45 +01:00
Dan Brown
6e0a7344fa Added revision activity types to system and audit log
Closes #3628
2022-08-09 13:25:18 +01:00
Dan Brown
7fa934e7f2 New Crowdin updates (#3625) 2022-08-09 13:00:39 +01:00
Dan Brown
a90446796a Fixed issue preventing selection of activity type in audit log
For #3623
2022-08-09 12:58:10 +01:00
Dan Brown
4209f27f1a Set a fairly sensible limit on user name validation
Also updated controller properties with types within modified files.
Related to #3614
2022-08-09 12:40:59 +01:00
Dan Brown
89ec9a5081 Sprinkled in some user language validation
For #3615
2022-08-04 17:24:04 +01:00
Dan Brown
9fd7a6abed Added dark theme handling 2022-08-04 14:19:04 +01:00
Dan Brown
4757ed9453 Converted codemirror languges to new packages where available
Does increase bundle size massively though, Will need to think about
solutions for this.
2022-08-04 13:33:51 +01:00
Dan Brown
97146a6359 Added handling of codemirror 6 code languages 2022-08-03 19:40:16 +01:00
Dan Brown
d4f2fcdf79 Started codemirror update, In broken state 2022-08-02 20:11:02 +01:00
Dan Brown
b987bea37a Added OIDC group sync functionality
Is generally aligned with out SAML2 group sync functionality, but for
OIDC based upon feedback in #3004.
Neeeded the tangental addition of being able to define custom scopes on
the initial auth request as some systems use this to provide additional
id token claims such as groups.

Includes tests to cover.
Tested live using Okta.
2022-08-02 16:56:56 +01:00
Dan Brown
e77c96f6b7 Updated version and assets for release v22.07.1 2022-08-02 11:47:25 +01:00
Dan Brown
9b8a10dd3a Merge branch 'development' into release 2022-08-02 11:47:08 +01:00
Dan Brown
42f4c9afae New Crowdin updates (#3605) 2022-08-02 11:31:24 +01:00
Dan Brown
8d6071cb84 Updated cache busting for tinymce library import
Changes from a manual cache buster string to a app-version-based cache
buster, as per our other scripts and styles.

To address #3611
2022-08-02 11:17:02 +01:00
Dan Brown
49200ca5ce Updated version and assets for release v22.07 2022-07-28 14:53:15 +01:00
Dan Brown
34aa4dbf10 Merge branch 'development' into release 2022-07-28 14:53:01 +01:00
Dan Brown
a21d09fed7 New Crowdin updates (#3600) 2022-07-28 14:12:13 +01:00
Dan Brown
50bc2e49c1 Update translators.txt 2022-07-28 14:10:14 +01:00
Dan Brown
8776113210 Updated translator attribution pre 22.07 release 2022-07-28 14:01:27 +01:00
Dan Brown
397a36cfd0 Merge branch 'lang_de' into development 2022-07-27 11:20:08 +01:00
Dan Brown
ee24635e06 Merge pull request #3556 from GongMingCai/development
Fixed comment count update error
2022-07-27 11:18:05 +01:00
Dan Brown
7c8368cc63 Merge pull request #3545 from BookStackApp/l10n_development
New Crowdin updates
2022-07-27 11:15:45 +01:00
Dan Brown
f93e380d19 Merge branch 'development' of github.com:BookStackApp/BookStack into development 2022-07-27 11:08:03 +01:00
Dan Brown
0bb5654f80 Updated composer deps, applied StyleCI changes 2022-07-27 11:07:41 +01:00
Dan Brown
89324bf9cc Merge pull request #3599 from BookStackApp/editor_list_shortcuts
Add editor shortcuts for two main list types
2022-07-27 11:03:08 +01:00
Dan Brown
9abb207e4d Added list shortcuts to markdown editor
Added some logic for ordered lists to continue the numbering logic,
while keeping the number list format style the same [1. vs 1)]
2022-07-27 11:01:37 +01:00
Dan Brown
8aad8e4a24 New translations entities.php (Spanish) 2022-07-26 20:14:59 +01:00
Dan Brown
8681c5f613 Added ordered/unordered WYSIWYG list shortcuts
Related to #1269
2022-07-26 16:43:15 +01:00
Dan Brown
944ac2e6eb New translations entities.php (German Informal) 2022-07-26 13:13:26 +01:00
Dan Brown
75759fb735 New translations entities.php (Dutch) 2022-07-26 13:13:25 +01:00
Dan Brown
f47c9a53aa New translations entities.php (Lithuanian) 2022-07-26 13:13:24 +01:00
Dan Brown
480d591acf New translations entities.php (Korean) 2022-07-26 13:13:23 +01:00
Dan Brown
ae40ec10a4 New translations entities.php (Japanese) 2022-07-26 13:13:22 +01:00
Dan Brown
180927cdb9 New translations entities.php (Italian) 2022-07-26 13:13:21 +01:00
Dan Brown
f37e7186d9 New translations entities.php (Hungarian) 2022-07-26 13:13:20 +01:00
Dan Brown
bb7bd903ef New translations entities.php (Hebrew) 2022-07-26 13:13:19 +01:00
Dan Brown
6c767cd205 New translations entities.php (Polish) 2022-07-26 13:13:18 +01:00
Dan Brown
99aa093e2b New translations entities.php (Basque) 2022-07-26 13:13:17 +01:00
Dan Brown
42b576df55 New translations entities.php (Czech) 2022-07-26 13:13:16 +01:00
Dan Brown
3fbe304cfc New translations entities.php (Catalan) 2022-07-26 13:13:15 +01:00
Dan Brown
e0d4a43e1e New translations entities.php (Bulgarian) 2022-07-26 13:13:14 +01:00
Dan Brown
ab6a3144ec New translations entities.php (Arabic) 2022-07-26 13:13:13 +01:00
Dan Brown
7a2f54b890 New translations entities.php (Spanish) 2022-07-26 13:13:12 +01:00
Dan Brown
8f28bb9e3c New translations entities.php (French) 2022-07-26 13:13:11 +01:00
Dan Brown
cb12f76f46 New translations entities.php (German) 2022-07-26 13:13:10 +01:00
Dan Brown
3f1b376b2b New translations entities.php (Danish) 2022-07-26 13:13:09 +01:00
Dan Brown
147f038806 New translations entities.php (Ukrainian) 2022-07-26 13:13:08 +01:00
Dan Brown
812675dfc2 New translations entities.php (Russian) 2022-07-26 13:13:06 +01:00
Dan Brown
3b2fb67d78 New translations entities.php (Slovenian) 2022-07-26 13:13:05 +01:00
Dan Brown
ae91831ba6 New translations entities.php (Norwegian Bokmal) 2022-07-26 13:13:04 +01:00
Dan Brown
fcfafbdac5 New translations entities.php (Uzbek) 2022-07-26 13:13:02 +01:00
Dan Brown
705f81561a New translations entities.php (Bosnian) 2022-07-26 13:13:01 +01:00
Dan Brown
1c70684a99 New translations entities.php (Welsh) 2022-07-26 13:13:00 +01:00
Dan Brown
32e305ef4f New translations entities.php (Latvian) 2022-07-26 13:12:59 +01:00
Dan Brown
8c70a69fff New translations entities.php (Estonian) 2022-07-26 13:12:58 +01:00
Dan Brown
f0eb4df1e9 New translations entities.php (Croatian) 2022-07-26 13:12:57 +01:00
Dan Brown
852f4e61a5 New translations entities.php (Slovak) 2022-07-26 13:12:56 +01:00
Dan Brown
d68ee461e0 New translations entities.php (Spanish, Argentina) 2022-07-26 13:12:55 +01:00
Dan Brown
98ce7a0675 New translations entities.php (Indonesian) 2022-07-26 13:12:54 +01:00
Dan Brown
e6e1b9423d New translations entities.php (Portuguese, Brazilian) 2022-07-26 13:12:52 +01:00
Dan Brown
b3c93a2188 New translations entities.php (Vietnamese) 2022-07-26 13:12:51 +01:00
Dan Brown
59dbc0b9f1 New translations entities.php (Chinese Traditional) 2022-07-26 13:12:50 +01:00
Dan Brown
7a43b6d5b7 New translations entities.php (Chinese Simplified) 2022-07-26 13:12:49 +01:00
Dan Brown
fb8f92e835 New translations entities.php (Turkish) 2022-07-26 13:12:48 +01:00
Dan Brown
0d36e3fecf New translations entities.php (Swedish) 2022-07-26 13:12:47 +01:00
Dan Brown
b878ccc361 New translations entities.php (Persian) 2022-07-26 13:12:46 +01:00
Dan Brown
2bab892dce New translations entities.php (Portuguese) 2022-07-26 13:12:45 +01:00
Dan Brown
4fa73be80e Merge pull request #3598 from BookStackApp/chapter_sort_book_option
Added 'Sort Book' action to chapters
2022-07-26 12:37:18 +01:00
Dan Brown
bd14dc067b Added 'Sort Book' action to chapters
Related to #2335
2022-07-26 12:36:17 +01:00
Dan Brown
d4a119b2aa Fixed disabling of avatar urls, Removed id from gravatar image name
Included test to cover avatar url disabling.
Related to #1835
2022-07-26 12:10:19 +01:00
Dan Brown
2ec8a33927 Removed labels from WYSIWYG colors
To ease burden of translation.

Related to #3530
2022-07-26 11:07:40 +01:00
Dan Brown
fee3022ad8 Added tinymce de-focus toolbar hack for drawing editor load
The tinymce event system would not pick up the focus within the loaded
draw.io instance, after the drawing toolbar button was clicked, hence
the toolbar would hang around.

This adds a hack to dispatch a mousedown event on the body to get the
toolbar to hide.

For #3597
2022-07-25 19:56:01 +01:00
Dan Brown
050ae01f94 Merge pull request #3593 from BookStackApp/code-editor-favorites
Code-editor lang favorites system
2022-07-25 19:16:11 +01:00
Dan Brown
8e5f7c6425 Added language list favourites sorting, updated styles
- Also made code box be greedier with vertical space.
2022-07-25 19:13:25 +01:00
Dan Brown
7fdc7c68b9 Added test to cover code favourite pref. endpoint 2022-07-25 18:48:40 +01:00
Dan Brown
017c7659e5 New translations editor.php (Estonian) 2022-07-25 16:03:40 +01:00
Dan Brown
a08ea54615 New translations entities.php (Estonian) 2022-07-25 16:03:39 +01:00
Dan Brown
0df5ae0658 Added core code-lang-favourites JS, PHP & CSS logic
- Got the functionality now working to favourite items and store that
  status within the system for the user.
- Improved CSS display for usability.
2022-07-25 13:10:27 +01:00
Dan Brown
3fa43c804b New translations activities.php (Indonesian) 2022-07-25 00:23:51 +01:00
Dan Brown
ebc5a53410 Started code-editor lang favorites system
- Split bash from shell in language list
- Updated code-lang highlighting to be exact match only to prevent
  confusion scenarios (Java matching JavaScript, etc..)
- Added design for favorites
- Changed blade language list to be generated from array.
2022-07-24 21:15:43 +01:00
Dan Brown
62500a9bfa New translations editor.php (Dutch) 2022-07-24 19:51:07 +01:00
Dan Brown
a5153ff5af New translations entities.php (Dutch) 2022-07-24 19:51:06 +01:00
Dan Brown
3734b0a37e New translations editor.php (Spanish) 2022-07-24 15:39:46 +01:00
Dan Brown
4d72ac16a3 New translations entities.php (Spanish) 2022-07-24 15:39:46 +01:00
Dan Brown
29404f7e38 New translations entities.php (German Informal) 2022-07-24 12:39:49 +01:00
Dan Brown
a7252301c1 New translations entities.php (Dutch) 2022-07-24 12:39:48 +01:00
Dan Brown
0825dd17cf New translations entities.php (Lithuanian) 2022-07-24 12:39:47 +01:00
Dan Brown
9dd51c7cff New translations entities.php (Korean) 2022-07-24 12:39:46 +01:00
Dan Brown
854d2fe2dc New translations entities.php (Japanese) 2022-07-24 12:39:45 +01:00
Dan Brown
27848cea75 New translations entities.php (Italian) 2022-07-24 12:39:44 +01:00
Dan Brown
d1d999a98a New translations entities.php (Hungarian) 2022-07-24 12:39:43 +01:00
Dan Brown
5a6e171a7e New translations entities.php (Hebrew) 2022-07-24 12:39:42 +01:00
Dan Brown
90ffa46331 New translations entities.php (Polish) 2022-07-24 12:39:42 +01:00
Dan Brown
957214b84b New translations entities.php (Basque) 2022-07-24 12:39:41 +01:00
Dan Brown
a2bda11787 New translations entities.php (Czech) 2022-07-24 12:39:40 +01:00
Dan Brown
56204963e7 New translations entities.php (Catalan) 2022-07-24 12:39:39 +01:00
Dan Brown
ee579115b6 New translations entities.php (Bulgarian) 2022-07-24 12:39:38 +01:00
Dan Brown
d431141918 New translations entities.php (Arabic) 2022-07-24 12:39:37 +01:00
Dan Brown
4ff6b7fc51 New translations entities.php (Spanish) 2022-07-24 12:39:36 +01:00
Dan Brown
5d42f36a2b New translations entities.php (French) 2022-07-24 12:39:35 +01:00
Dan Brown
fb3491092e New translations entities.php (German) 2022-07-24 12:39:34 +01:00
Dan Brown
812c65fa3c New translations entities.php (Danish) 2022-07-24 12:39:33 +01:00
Dan Brown
9b48ee90f0 New translations entities.php (Ukrainian) 2022-07-24 12:39:32 +01:00
Dan Brown
6ad6bcaf82 New translations entities.php (Russian) 2022-07-24 12:39:31 +01:00
Dan Brown
f4ef85d587 New translations entities.php (Slovenian) 2022-07-24 12:39:30 +01:00
Dan Brown
1c57223a2d New translations entities.php (Norwegian Bokmal) 2022-07-24 12:39:29 +01:00
Dan Brown
a1a900035b New translations entities.php (Uzbek) 2022-07-24 12:39:28 +01:00
Dan Brown
bc8d4c40da New translations entities.php (Bosnian) 2022-07-24 12:39:28 +01:00
Dan Brown
cb91bd4933 New translations entities.php (Welsh) 2022-07-24 12:39:27 +01:00
Dan Brown
f336ce9119 New translations entities.php (Latvian) 2022-07-24 12:39:26 +01:00
Dan Brown
f9e040658d New translations entities.php (Estonian) 2022-07-24 12:39:25 +01:00
Dan Brown
d1b9d62e40 New translations entities.php (Croatian) 2022-07-24 12:39:24 +01:00
Dan Brown
7e70c14a16 New translations entities.php (Slovak) 2022-07-24 12:39:23 +01:00
Dan Brown
1b7a1e847e New translations entities.php (Spanish, Argentina) 2022-07-24 12:39:22 +01:00
Dan Brown
011178c302 New translations entities.php (Indonesian) 2022-07-24 12:39:21 +01:00
Dan Brown
e27b53fc6c New translations entities.php (Portuguese, Brazilian) 2022-07-24 12:39:20 +01:00
Dan Brown
260c9d528f New translations entities.php (Vietnamese) 2022-07-24 12:39:19 +01:00
Dan Brown
14b5c39e71 New translations entities.php (Chinese Traditional) 2022-07-24 12:39:18 +01:00
Dan Brown
4c1256f02a New translations entities.php (Chinese Simplified) 2022-07-24 12:39:16 +01:00
Dan Brown
a7f7200478 New translations entities.php (Turkish) 2022-07-24 12:39:15 +01:00
Dan Brown
f2088d3a56 New translations entities.php (Swedish) 2022-07-24 12:39:14 +01:00
Dan Brown
affd8df594 New translations entities.php (Persian) 2022-07-24 12:39:13 +01:00
Dan Brown
bc40601d7d New translations entities.php (Portuguese) 2022-07-24 12:39:12 +01:00
Dan Brown
da6169159d Merge pull request #3591 from BookStackApp/shelf_books_enhancements
Improved shelf book management interface
2022-07-24 12:28:01 +01:00
Dan Brown
b0adb74d62 Improved shelf book management interface
- Added ability to search books list (Local simple text match).
- Added handles, hover-states and cursor states for better user
  interaction and clearer use of drag & drop.
- Improved styles for dark mode.
- Converted shelf sort component to newer component format.
- Modernized shelf controller code a little.

Related to #3266
2022-07-24 12:23:25 +01:00
Dan Brown
f004cb69d7 New translations editor.php (French) 2022-07-23 19:12:14 +01:00
Dan Brown
975ba4f8d8 Added content-view body classes generated from tags
Included tests to cover.

Closes #3583
2022-07-23 18:29:04 +01:00
Dan Brown
468040edc4 New translations activities.php (Slovak) 2022-07-23 17:51:24 +01:00
Dan Brown
840a1ea011 Applied latest styleci changes 2022-07-23 15:11:06 +01:00
Dan Brown
72c8b138e1 Updated tests to use ssddanbrown/asserthtml package
Closes #3519
2022-07-23 15:10:18 +01:00
Dan Brown
cf73e5f2c6 Tweaked wording aroung the IP address precision option 2022-07-23 13:46:13 +01:00
Dan Brown
4e8995c3d0 Added ability to adjust stored IP address precision
Included tests to cover.

For #3560
2022-07-23 13:41:29 +01:00
Dan Brown
67d12cc1df Fixed failing license test 2022-07-23 12:08:55 +01:00
Dan Brown
7931ab1b91 New translations editor.php (German Informal) 2022-07-23 11:43:10 +01:00
Dan Brown
137beb4002 New translations editor.php (Polish) 2022-07-23 11:43:09 +01:00
Dan Brown
2354ce49ba New translations editor.php (Dutch) 2022-07-23 11:43:08 +01:00
Dan Brown
d0925e0e91 New translations editor.php (Lithuanian) 2022-07-23 11:43:07 +01:00
Dan Brown
69473d28f3 New translations editor.php (Korean) 2022-07-23 11:43:06 +01:00
Dan Brown
11cf9fd832 New translations editor.php (Japanese) 2022-07-23 11:43:06 +01:00
Dan Brown
c89865b574 New translations editor.php (Italian) 2022-07-23 11:43:05 +01:00
Dan Brown
8a1fb300fe New translations editor.php (Hungarian) 2022-07-23 11:43:04 +01:00
Dan Brown
8c4ed9e0b7 New translations editor.php (Portuguese) 2022-07-23 11:43:03 +01:00
Dan Brown
c4f3a71652 New translations editor.php (Hebrew) 2022-07-23 11:43:02 +01:00
Dan Brown
c5259d0195 New translations editor.php (German) 2022-07-23 11:43:01 +01:00
Dan Brown
3899b44622 New translations editor.php (Danish) 2022-07-23 11:43:00 +01:00
Dan Brown
58057855f8 New translations editor.php (Czech) 2022-07-23 11:42:59 +01:00
Dan Brown
4cdaa1ad99 New translations editor.php (Catalan) 2022-07-23 11:42:58 +01:00
Dan Brown
c737fa8a6b New translations editor.php (Bulgarian) 2022-07-23 11:42:58 +01:00
Dan Brown
c5a0b99d20 New translations editor.php (Arabic) 2022-07-23 11:42:57 +01:00
Dan Brown
554d706468 New translations editor.php (Spanish) 2022-07-23 11:42:56 +01:00
Dan Brown
4591583deb New translations editor.php (Basque) 2022-07-23 11:42:55 +01:00
Dan Brown
05f9f8f969 New translations editor.php (French) 2022-07-23 11:42:54 +01:00
Dan Brown
1f7f26bd29 New translations editor.php (Russian) 2022-07-23 11:42:53 +01:00
Dan Brown
1e028f51eb New translations editor.php (Slovenian) 2022-07-23 11:42:52 +01:00
Dan Brown
7389b33980 New translations editor.php (Norwegian Bokmal) 2022-07-23 11:42:52 +01:00
Dan Brown
70fccfd8d3 New translations editor.php (Uzbek) 2022-07-23 11:42:51 +01:00
Dan Brown
9ccee6707d New translations editor.php (Bosnian) 2022-07-23 11:42:50 +01:00
Dan Brown
2de804950b New translations editor.php (Welsh) 2022-07-23 11:42:49 +01:00
Dan Brown
e4e130a5da New translations editor.php (Latvian) 2022-07-23 11:42:48 +01:00
Dan Brown
3101d76726 New translations editor.php (Estonian) 2022-07-23 11:42:47 +01:00
Dan Brown
694da007b6 New translations editor.php (Croatian) 2022-07-23 11:42:46 +01:00
Dan Brown
ea2aa626a9 New translations editor.php (Slovak) 2022-07-23 11:42:45 +01:00
Dan Brown
9ab485093e New translations editor.php (Spanish, Argentina) 2022-07-23 11:42:44 +01:00
Dan Brown
93d9c77595 New translations editor.php (Indonesian) 2022-07-23 11:42:43 +01:00
Dan Brown
71e760e345 New translations editor.php (Portuguese, Brazilian) 2022-07-23 11:42:43 +01:00
Dan Brown
34d15230dc New translations editor.php (Vietnamese) 2022-07-23 11:42:42 +01:00
Dan Brown
af5517ad59 New translations editor.php (Chinese Traditional) 2022-07-23 11:42:41 +01:00
Dan Brown
002b093e82 New translations editor.php (Ukrainian) 2022-07-23 11:42:40 +01:00
Dan Brown
2e9000b18c New translations editor.php (Turkish) 2022-07-23 11:42:39 +01:00
Dan Brown
b24f5b7392 New translations editor.php (Swedish) 2022-07-23 11:42:38 +01:00
Dan Brown
3caf308f6b New translations editor.php (Persian) 2022-07-23 11:42:37 +01:00
Dan Brown
e01baac15d New translations editor.php (Chinese Simplified) 2022-07-23 11:42:36 +01:00
Dan Brown
f573e09004 Applied styleci changes, updated dev version & readme roadmap 2022-07-23 11:36:37 +01:00
Dan Brown
f4dd38ea94 Merge pull request #3580 from BookStackApp/tinymce6
TinyMCE6 update
2022-07-23 11:33:51 +01:00
Dan Brown
aad22384cb Enabled modern tinymce table features 2022-07-23 11:32:26 +01:00
Dan Brown
8176ca153a Fixed blue wyswiyg toolbar in dark mode 2022-07-23 11:22:34 +01:00
Dan Brown
f86bb27a83 Ensured wysiwyg details contents are wrapped in block elements
Fixes issue where inline-only content would disappear when unwrapping a
details block element.
2022-07-23 11:18:03 +01:00
Dan Brown
a9ee2e6889 Removed toolbar dialog background line 2022-07-23 10:43:47 +01:00
Dan Brown
d9f0c9eee8 New translations entities.php (French) 2022-07-20 08:32:06 +01:00
Dan Brown
7b508dac3d New translations editor.php (Chinese Simplified) 2022-07-18 18:51:48 +01:00
Dan Brown
3ca64da4a5 New translations entities.php (Italian) 2022-07-18 15:55:46 +01:00
Dan Brown
6a6f00058f Added back in image options context toolbar item 2022-07-18 13:37:50 +01:00
Dan Brown
cd929b2555 Made a bunch of tinymce 6 upgrade fixes
- Added workaround for new 'srcdoc' usage that's breaking content in
  Firefox, added new 'custom-changes.md' file to document for future.
- Updated old usages of 'new' when creating nodes.
- Tested and changed logic, where required, where 'editor.dom.select'
  has been used to replace the old '$' usages.
- Fixed bad boolean value being passed to 'setActive' in task list
  logic.
2022-07-18 13:18:46 +01:00
Dan Brown
400e584911 New translations activities.php (Norwegian Bokmal) 2022-07-18 10:54:22 +01:00
Dan Brown
9c90e798df New translations entities.php (Spanish) 2022-07-17 23:19:49 +01:00
Dan Brown
c519f707e8 Started upgrade to TinyMCE6, Untested
- Merged in latest TinyMCE code.
- Gone through tinymce upgrade guide, made required config changes.
- Altered license references.
2022-07-17 18:33:03 +01:00
Dan Brown
e024b03a61 New translations entities.php (Chinese Simplified) 2022-07-17 17:19:51 +01:00
Dan Brown
d9e9c1735a Merge pull request #3579 from BookStackApp/dompdf_and_php_deps
Updated DOMPDF, and other PHP dependancies
2022-07-17 14:40:19 +01:00
Dan Brown
56da25b07a Fixed failing tests from dompdf chanages 2022-07-17 14:32:09 +01:00
Dan Brown
24f4febcd5 Updated DOMPDF, and other PHP dependancies 2022-07-17 14:01:59 +01:00
Dan Brown
5f5b6ff0be Added "ACTIVITY_LOGGED" theme event
Closes #3572
2022-07-17 13:28:56 +01:00
Dan Brown
8f9923c7c1 Re-ordered theme events to be alphabetical 2022-07-17 13:08:44 +01:00
Dan Brown
7be7caacd5 New translations entities.php (German Informal) 2022-07-17 10:50:26 +01:00
Dan Brown
bcd06c1d56 New translations entities.php (Chinese Simplified) 2022-07-17 10:50:26 +01:00
Dan Brown
e01a0e61d9 New translations entities.php (Chinese Traditional) 2022-07-17 10:50:24 +01:00
Dan Brown
f0049e346b New translations entities.php (Portuguese, Brazilian) 2022-07-17 10:50:24 +01:00
Dan Brown
b7f84171c6 New translations entities.php (Indonesian) 2022-07-17 10:50:23 +01:00
Dan Brown
cb5b4392f4 New translations entities.php (Persian) 2022-07-17 10:50:22 +01:00
Dan Brown
4eb76699a9 New translations entities.php (Spanish, Argentina) 2022-07-17 10:50:21 +01:00
Dan Brown
a48a1d80ae New translations entities.php (Croatian) 2022-07-17 10:50:20 +01:00
Dan Brown
b3b8da0fe7 New translations entities.php (Vietnamese) 2022-07-17 10:50:19 +01:00
Dan Brown
a2440e20bc New translations entities.php (Latvian) 2022-07-17 10:50:18 +01:00
Dan Brown
f3f72fde6b New translations entities.php (Welsh) 2022-07-17 10:50:17 +01:00
Dan Brown
9023487d99 New translations entities.php (Bosnian) 2022-07-17 10:50:16 +01:00
Dan Brown
d77c0d3ddd New translations entities.php (Uzbek) 2022-07-17 10:50:15 +01:00
Dan Brown
cffa0a0cf3 New translations entities.php (Norwegian Bokmal) 2022-07-17 10:50:14 +01:00
Dan Brown
7b4e36eb38 New translations entities.php (Estonian) 2022-07-17 10:50:13 +01:00
Dan Brown
f3eb7c4208 New translations entities.php (Basque) 2022-07-17 10:50:12 +01:00
Dan Brown
2fcb0b6db2 New translations entities.php (Danish) 2022-07-17 10:50:11 +01:00
Dan Brown
ea0ac2a853 New translations entities.php (Czech) 2022-07-17 10:50:10 +01:00
Dan Brown
76049f0cdb New translations entities.php (Catalan) 2022-07-17 10:50:09 +01:00
Dan Brown
0143fe88d3 New translations entities.php (Bulgarian) 2022-07-17 10:50:08 +01:00
Dan Brown
0b89642610 New translations entities.php (Spanish) 2022-07-17 10:50:07 +01:00
Dan Brown
bc8d2d8209 New translations entities.php (French) 2022-07-17 10:50:06 +01:00
Dan Brown
f832a9545e New translations entities.php (German) 2022-07-17 10:50:05 +01:00
Dan Brown
aad2f54c15 New translations entities.php (Hebrew) 2022-07-17 10:50:04 +01:00
Dan Brown
0cd44a6e7d New translations entities.php (Arabic) 2022-07-17 10:50:03 +01:00
Dan Brown
79e386f457 New translations entities.php (Hungarian) 2022-07-17 10:50:02 +01:00
Dan Brown
387b6620e4 New translations entities.php (Russian) 2022-07-17 10:50:01 +01:00
Dan Brown
d76bdbc976 New translations entities.php (Japanese) 2022-07-17 10:50:00 +01:00
Dan Brown
89de7a60c6 New translations entities.php (Korean) 2022-07-17 10:49:59 +01:00
Dan Brown
42c6179350 New translations entities.php (Lithuanian) 2022-07-17 10:49:58 +01:00
Dan Brown
01c2c92710 New translations entities.php (Dutch) 2022-07-17 10:49:57 +01:00
Dan Brown
4b770ee2dc New translations entities.php (Polish) 2022-07-17 10:49:56 +01:00
Dan Brown
c47997bbb7 New translations entities.php (Ukrainian) 2022-07-17 10:49:55 +01:00
Dan Brown
9d78af2c1d New translations entities.php (Slovak) 2022-07-17 10:49:54 +01:00
Dan Brown
a8d933753e New translations entities.php (Slovenian) 2022-07-17 10:49:53 +01:00
Dan Brown
2853feb9c4 New translations entities.php (Swedish) 2022-07-17 10:49:52 +01:00
Dan Brown
86e7386db9 New translations entities.php (Turkish) 2022-07-17 10:49:52 +01:00
Dan Brown
ce9a788fb9 New translations entities.php (Italian) 2022-07-17 10:49:51 +01:00
Dan Brown
6b8083244d New translations entities.php (Portuguese) 2022-07-17 10:49:50 +01:00
Dan Brown
94bf7e2e0c Merge pull request #3569 from BookStackApp/permissions_v2
Permissions System Refactor
2022-07-17 10:36:33 +01:00
Dan Brown
9cf05944f6 Applied StyleCI changes 2022-07-17 10:32:16 +01:00
Dan Brown
e6e6d25974 Removed test web route, extracted text, added test 2022-07-17 10:18:24 +01:00
Dan Brown
8f90996cef Dropped use of non-view joint permissions 2022-07-16 21:50:42 +01:00
Dan Brown
2332401854 Fixed a couple of non-intended logical permission issues
Both caught in tests:
Fixed loss of permissions for admin users when entity restrictions were
active, since there are no entity-restrictions for the admin role but
we'd force generate them in joint permissions, which would be queried.
Fixed new role permission checks when permissions given with only the
action (eg. 'view'), since the type prefix would be required for role
permission checks. Was previously not needed as only the simpler form
was used in the jointpermissions after merge & calculation.
2022-07-16 20:55:32 +01:00
Dan Brown
afe1a04239 Aligned permission applicator method names
Also removed lesser used function, that was mostly a duplicate of an
existing function, and only used for search.
2022-07-16 19:54:25 +01:00
Dan Brown
f459a68535 Removed remaining dynamic action usages in joint permission queries 2022-07-16 19:28:04 +01:00
Dan Brown
1d875ccfb7 Continued removal of joint permission non-view queries
Cleaned up PermissionApplicator to remove old cache system which was
hardly ever actuall caching anything since it was reset after each
public method run.

Changed the scope of 'userCanOnAny' to just check entity permissions,
and added protections of action scope creep, in case a role permission
action was passed by mistake.
2022-07-16 13:17:08 +01:00
Dan Brown
2b4b7c68cc New translations entities.php (German) 2022-07-15 08:45:23 +01:00
Dan Brown
ad8d8dde2d New translations entities.php (German) 2022-07-15 07:39:07 +01:00
Dan Brown
23f9b4d217 New translations auth.php (German) 2022-07-15 07:39:06 +01:00
Dan Brown
bfbd0fc168 New translations activities.php (German) 2022-07-14 23:50:40 +01:00
Dan Brown
77b57c068f New translations activities.php (German) 2022-07-14 22:50:28 +01:00
Dan Brown
40d939394b Merge pull request #3573 from BookStackApp/m1_docker_support
M1/Apple Silicon dev docker compatibility
2022-07-14 11:03:25 +01:00
Dan Brown
7e04f70bf3 Tweaked docker dev container to work with m1 apple silicon
Tested on m1 macbook, needs testing on amd64
2022-07-14 01:34:57 +01:00
Dan Brown
4fb85a9a5c Started removal of non-view permission queries
Updated ajax search and entity selector usage to display and handle
items that the user does not have permission to interact with.
Started logic changes to not allow permission type to be passed around,
with views instead being the fixed sole permission.
2022-07-13 15:23:03 +01:00
Jan Koid
55dc86037f Fixed some typos and corrected grammar. 2022-07-12 23:05:44 +02:00
Dan Brown
2989852520 Added simple data model for faster permission generation 2022-07-12 21:13:02 +01:00
Dan Brown
4daac5a114 New translations auth.php (Croatian) 2022-07-12 21:07:49 +01:00
Dan Brown
82baab66cc New translations activities.php (Croatian) 2022-07-12 21:07:48 +01:00
Dan Brown
b0a4d3d059 Renamed and cleaned up existing permission service classes use 2022-07-12 20:15:41 +01:00
Dan Brown
943cb7810b New translations activities.php (Croatian) 2022-07-12 20:02:15 +01:00
Dan Brown
2d4f708c79 Extracted permission building out of permission service 2022-07-12 19:38:11 +01:00
Dan Brown
376640db25 New translations settings.php (Portuguese) 2022-07-12 13:03:52 +01:00
Dan Brown
9cfded1311 New translations common.php (Portuguese) 2022-07-12 13:03:51 +01:00
Dan Brown
dde2ea743f New translations auth.php (Portuguese) 2022-07-12 13:03:50 +01:00
Dan Brown
ddd45dde6b New translations entities.php (Portuguese) 2022-07-12 13:03:49 +01:00
Dan Brown
a99cbcfe12 New translations activities.php (Portuguese) 2022-07-12 13:03:47 +01:00
Dan Brown
c5e9dfa168 Optimized pre-joint-permission logic efficiency 2022-07-10 13:45:04 +01:00
mcgong
83d2a3c763 Fixed comment count update error 2022-07-06 17:30:46 +08:00
Dan Brown
f3d7d06536 New translations activities.php (Polish) 2022-07-05 19:10:04 +01:00
Dan Brown
bd1971c827 New translations editor.php (Ukrainian) 2022-07-05 14:30:15 +01:00
Dan Brown
61b3bc10a3 New translations common.php (Ukrainian) 2022-07-05 14:30:14 +01:00
Dan Brown
1a224e1719 New translations auth.php (Ukrainian) 2022-07-05 14:30:13 +01:00
Dan Brown
e89348b02a New translations entities.php (Ukrainian) 2022-07-05 14:30:12 +01:00
Dan Brown
451300606f New translations activities.php (Ukrainian) 2022-07-05 14:30:10 +01:00
Dan Brown
459659a680 New translations entities.php (Dutch) 2022-07-02 22:09:56 +01:00
Dan Brown
4487ea576f New translations common.php (Dutch) 2022-07-02 22:09:55 +01:00
Dan Brown
0c8bd581ae New translations auth.php (Dutch) 2022-07-02 21:05:42 +01:00
Dan Brown
f9f4a87e1b New translations entities.php (Dutch) 2022-07-02 21:05:41 +01:00
Dan Brown
f4fda8d80c New translations activities.php (Dutch) 2022-07-02 21:05:40 +01:00
Dan Brown
6d66682620 New translations entities.php (German) 2022-06-30 09:36:18 +01:00
Dan Brown
ab52f3367a New translations editor.php (Russian) 2022-06-29 15:26:03 +01:00
Dan Brown
5ee79d16c9 Updated version and assets for release v22.06.2 2022-06-28 11:57:37 +01:00
Dan Brown
a1ea4006e0 Merge branch 'development' into release 2022-06-28 11:57:24 +01:00
Dan Brown
a721405202 New Crowdin updates (#3540) 2022-06-28 11:56:07 +01:00
Dan Brown
d20aacb732 Merge branch '3535-group-sync-fix' into development 2022-06-28 11:47:22 +01:00
Dan Brown
65fa96e405 New Crowdin updates (#3531) 2022-06-27 14:29:10 +01:00
Dan Brown
736d6afb7d Aligned entity-selector-popup button and dblclick behaviour
Fixes #3534
2022-06-27 14:27:29 +01:00
Dan Brown
0bcd1795cb Auth group sync: Fixed unintential mapping behaviour change
Due to change in how casing was handled when used in the "External Auth
ID" role field.
Likely related to #3535.
Added test to cover.
2022-06-27 14:18:46 +01:00
Dan Brown
47887ec595 Added path example to visual theme system 2022-06-27 13:38:51 +01:00
Dan Brown
9078188939 Updated version and assets for release v22.06.1 2022-06-25 14:33:07 +01:00
Dan Brown
ed0aad1a7a Merge branch 'development' into release 2022-06-25 14:32:49 +01:00
Dan Brown
43749cd94e Merge branch 'development' of github.com:BookStackApp/BookStack into development 2022-06-25 14:27:46 +01:00
Dan Brown
107df6c28f Applied StyleCI changes 2022-06-25 14:27:32 +01:00
Dan Brown
c1d1ec5b89 New Crowdin updates (#3526) 2022-06-25 14:26:40 +01:00
Dan Brown
12c282597d Fixed non-translated category strings
For #3529
2022-06-25 14:24:38 +01:00
Dan Brown
c9d0e22132 Updated entity-selector-popup to reset on selection
Better links the core selector component to the popup version, with new
public methods for direct controlling.

For #3528
2022-06-25 14:13:17 +01:00
Dan Brown
0801955a26 Fixed grid layouts being pushed out by child content
Ran a quick app run-thorugh in FireFox & Chrome, No secondary affects
immediately noticed but possible this could cause changes elsewhere due
to wide-spread grid item child targeting.

For #3523
2022-06-25 13:55:57 +01:00
Dan Brown
3ed1ffdbeb Fixed issue blocking tags on book update
For #3527
2022-06-25 13:46:55 +01:00
Dan Brown
5c59cfb020 Updated version and assets for release v22.06 2022-06-24 11:50:56 +01:00
Dan Brown
3ca15ad68a Merge branch 'development' into release 2022-06-24 11:45:29 +01:00
Dan Brown
36f0a68f1b Added missing welsh locale to config 2022-06-24 11:42:38 +01:00
Dan Brown
ed981cbab1 New Crowdin updates (#3428) 2022-06-24 11:35:59 +01:00
Dan Brown
f69af8933c Updated translator list before v22.06 release 2022-06-24 11:30:15 +01:00
Dan Brown
46d71a181e Updated php deps and applied styleci changes 2022-06-22 12:49:58 +01:00
Dan Brown
8d8da31fdd Added base template convenience partials for theme system users
Included test to cover usage and paths.
Closes #894
2022-06-22 12:47:31 +01:00
Dan Brown
0d9b5a9d90 Merge branch 'login-auto-redirect' into development 2022-06-21 15:38:01 +01:00
Dan Brown
8b211ed461 Review and update of login auto initiation PR
For PR #3406

- Updated naming from 'redirect' to 'initate/initation'.
- Updated phpunit.xml and .env.example.complete files with the new
  option.
- Cleaned up controller logic a bit.
- Added content and design to the new initation view to not leave user
  on a blank view for a while.
- Added non-JS button to initiation view as fallback option for
  progression.
- Moved new test to it's own Test class and expanded with additional
  scenario tests for better functionality coverage.
2022-06-21 15:32:18 +01:00
Dan Brown
9dd69b04b8 Fixed code snippets being added as single line
TinyMCE was adding attributes to <br> elements within code blocks which
would then not be converted to newlines by our code regex match.
This changes the conversion to use dom querying instead.

Fixes #3507
2022-06-21 12:01:06 +01:00
Dan Brown
0c6f598d91 Fixed issue where text after line breaks not indexed
Linebreaks would previously essentially be removed during index and
hence joined to adjacent words, breaking prefix matching.
Added test to cover.
For #3508
2022-06-20 23:47:42 +01:00
Dan Brown
df94b73e29 Merge pull request #3512 from BookStackApp/code_manager_updates
WYSIWYG Code Editor Updates
2022-06-20 23:13:28 +01:00
Dan Brown
7d4b941abf Added code editor changes mobile design handling 2022-06-20 23:12:07 +01:00
Dan Brown
d181106df3 Adjusted code manager changes for dark mode 2022-06-20 23:06:54 +01:00
Dan Brown
75110813e6 Aligned other popup windows
Primary change was altering image-manager to use same footer bar style
as other windows.
2022-06-20 23:02:06 +01:00
Dan Brown
1e41546e51 Updated code editor language lists
To align and update supported languages.

Related to #3511 and #3494
2022-06-20 17:49:56 +01:00
Dan Brown
f39b565a1c Tweaked code editor sidebar side to be smaller 2022-06-20 17:16:28 +01:00
Dan Brown
77cd550fae Polished up code editor design 2022-06-20 17:11:34 +01:00
Dan Brown
96d9077479 Started design changes to the code-editor 2022-06-20 13:42:12 +01:00
Dan Brown
be1d691529 Merge pull request #3499 from BookStackApp/convert_hierachy
Chapter and Book Conversion Actions
2022-06-20 12:51:13 +01:00
Dan Brown
8cde362f6f Removed bad trailing comma in method 2022-06-19 18:45:48 +01:00
Dan Brown
388343aeb0 Fixed failing tests after conversion changes 2022-06-19 18:44:34 +01:00
Dan Brown
ba25dda031 Applied styleci changes for conversion work 2022-06-19 18:14:53 +01:00
Dan Brown
85f59b5275 Added tests for content conversion action permissions
- Updated 'removePermissionFromUser' test helper to work for
  entity-permissions that become part of the joint permissions system.
2022-06-19 18:12:36 +01:00
Dan Brown
65d4505079 Added tests and doc updates for shelf/book cover image API abilities 2022-06-19 17:26:23 +01:00
Dan Brown
663f81a2b1 Added tests to cover convert functionality
Also updated cloner class with typed properties.
2022-06-19 16:57:33 +01:00
Dan Brown
f145ffc930 Extracted conversion text to translation file 2022-06-19 16:23:18 +01:00
Dan Brown
19d7e26dda Merge pull request #3503 from andrii-bodnar/fix/crowdin-name
Fix Crowdin name in the language_request issue template
2022-06-16 12:07:40 +01:00
Andrii Bodnar
a13b9d8d14 Fix Crowdin name in the language_request issue template 2022-06-16 11:34:27 +03:00
Dan Brown
8c67011a1d Got book to shelf conversions working
- Also extracted shelf to book view elements to own partial.
- Fixed some existing logic including image param handling in update
  request and activity logging against correct element.
2022-06-15 15:05:08 +01:00
Dan Brown
8da856bac3 Got chapter conversion to books working
- Added required UI within edit view.
- Added required routes and controller actions.
2022-06-14 16:42:29 +01:00
Dan Brown
90ec40691a Added clone of entity permissions on chapter/book promotion 2022-06-14 15:55:44 +01:00
Dan Brown
d676e1e824 Started work on hierachy conversion actions
- Updates book/shelf cover image handling for easier cloning/handling.
- Adds core logic for promoting books/chapters up a level.
- Enables usage of book/shelf cover image via API.

Related to #1087
2022-06-13 17:20:21 +01:00
Dan Brown
0a05119aa5 Applied styleci changes, updated composer deps 2022-06-10 12:37:14 +01:00
Dan Brown
abc283fc64 Extracted download response logic to its own class
Cleans up base controller and groups up download & streaming logic for
potential future easier addition of range request support.
2022-06-08 23:50:42 +01:00
Dan Brown
e72ade727d Added audio mimes to our safe list for inline serving
Closes #3485
2022-06-08 22:30:55 +01:00
Dan Brown
c8b123bfac Updated composer deps, applied styleci changes 2022-06-08 18:00:30 +01:00
Dan Brown
88012449f3 Reorganised and split out export templates & styles
Moved export templates elements into their own folder for better
grouping of logical usage.
Within the base export template, added some body classes to allow easier
targeted customisation via custom head css.
Split content of export templates into smaller partials for easier
future customization.

Closes #3443
2022-06-08 17:56:59 +01:00
Dan Brown
e00d88f45d Updated markdown preview to update on diff-basis
Uses vdom system to diff and update the current markdown preview view
instead of requiring a full HTML replace change.
This should provide better performance, expecially where dynamically
loaded content such as iframes were in use.

Closes #3454
2022-06-07 16:07:28 +01:00
Dan Brown
3fe666f36a Updated image drop handling to respect original file name
Now uses the previously timestamp gen name as a backup to the original
name. Aligns with the image manager upload which uses the original name
where given.

Closes #3470
2022-06-07 14:59:00 +01:00
Dan Brown
3f271ebecb Removed image_id property from books & shelves api docs
This was either not provided or not provided for the last 18 months.
Likely not providing much value as-is so removing.

Closes #3474
2022-06-07 14:30:43 +01:00
Dan Brown
7c597a05f6 Added codeblock latex/stext support
For #3458
2022-05-30 18:41:40 +01:00
Dan Brown
16e023985d Prevented inadvertant logging during MFA flow
- Added StoppedAuthenticationException to dontReport list.
- Added test to cover.

Closes #3468
2022-05-30 18:31:08 +01:00
Dan Brown
43cbab2822 Merge branch 'development' of github.com:BookStackApp/BookStack into development 2022-05-30 17:01:46 +01:00
Dan Brown
1a3505c899 Updated JS deps 2022-05-30 17:01:32 +01:00
Dan Brown
2930025f51 Update dev version to track current release target 2022-05-30 16:58:01 +01:00
Dan Brown
39fcf3a68f Merge pull request #3416 from BookStackApp/group_sync_comma_escaping
Added ability to escape role "External Auth ID" commas
2022-05-30 16:55:32 +01:00
Dan Brown
6ce34fe6cc Merge pull request #3433 from BookStackApp/tiny_improvements
Bunch of tiny improvements
2022-05-30 16:51:59 +01:00
Dan Brown
3c3aed58aa Updated funding with kofi link 2022-05-30 16:49:24 +01:00
Dan Brown
73f36b279e Updated PHP deps 2022-05-30 16:46:48 +01:00
Dan Brown
2b817e7d24 Updated attachment links to have dropdown for open type
- Allows easier accessibility of inline attachments.
- Introduces a new split-icon-list-item thingy to support such cases
  where only part of the button is actually linked.
2022-05-19 17:38:04 +01:00
Dan Brown
cb10ad804f Made chapter toggle in book sidebar nav more consistent
- Now has a hover state to match other items.
- Now spans the full sidebar with like other items.
- Also updated chapter-toggle to a chapter-contents component, following
  the newer component system.
2022-05-18 14:06:40 +01:00
Dan Brown
eeccc2ef10 Readjusted book child item styles after other changes
Was extra space showing due to structure changes and flex gap.
2022-05-18 13:28:34 +01:00
Dan Brown
b030c1398b Tweaked chapter list item styles
- Improves animation smoothness
- Changed animation slideup/down animations to use max-height instead of height
  to better avoid jutter at the end.
- Cleaned spacing to match page items in books listing.
2022-05-18 13:18:21 +01:00
Dan Brown
4759fa1e1f Made the "Custom HTML Head Content" setting a highlighted code editor 2022-05-17 17:39:31 +01:00
Dan Brown
cb1c2db282 Aligned collapsed header dropdown item styles
Previously the desktop-visible items would style different when collapsed
into the expanded dropdown menu, compared to existing items.
2022-05-17 14:27:58 +01:00
Dan Brown
4866a3a198 Refined header bar styles
- Updated many items to be flexbox-based.
- Updated & aligned hover states across header bar items.
2022-05-17 14:16:43 +01:00
Dan Brown
340c9ec7a1 Fixed some inputs affected by height changes 2022-05-17 13:37:43 +01:00
Dan Brown
49498cfaf9 Fixed entity-specific tag counts listing
Was reporting wrong due to use of old polymorphic namespace references.
Test was not picking up as assertElementContains had wider scope than
expected, looking within the HTML of the element instead of the text
which you might expect. Updated test helper to look at text instead.
2022-05-16 14:05:21 +01:00
Dan Brown
3a4aa81115 Removed dialog debug script from default home
Accidentally left in from before.
Closes #3430
2022-05-16 13:36:42 +01:00
Dan Brown
d20c74babf Improved input size consistency
Specifically updates dropdown search and user-search implementation,
although does affect all inputs.
Decouples breadcrum and select-style dropdown search toggles.

Addresses #2678
2022-05-14 16:05:29 +01:00
Dan Brown
9fda0df798 Updated dropdown search boxe positions to align with other dropdowns 2022-05-14 14:19:54 +01:00
Dan Brown
6fa699a835 Fixed skip-to-content link shadow being slightly visible
Would cause a slight dark area in top left of view while hidden.
2022-05-14 13:59:10 +01:00
Dan Brown
78920d7d65 Updated tri-layout sidebars to not be cut-off by padding
Would cause effect where scroll area would be cut of by spacing which
looked a bit strange. This retains the same padding sizes but cuts the
content at the header or top of viewport.
2022-05-14 13:55:03 +01:00
Dan Brown
35a47a273b Added animation transition for breadcrumb dropdown load
Animates the height on breadcrumb dropdown menus to transition to the
loaded animations quicker. Includes a new animation helper for doing
similar tasks in future.
2022-05-14 13:32:25 +01:00
Dan Brown
89dfa43e73 Fixed loading animation delay
Loading animation would show in an unready state due to animation-delay
on components. Updated to a negative delay to ensure elements were in
correct positions right away upon show.
2022-05-14 13:31:24 +01:00
Dan Brown
2c74dfd1d4 Updated breadcrumb dropdown styles, improved keyboard nav
- Removed harsh theme color border between search and content.
- Prevented intermediate focus on list container to align arrow & tab
  behaviour, and to get to content quicker.
2022-05-14 13:11:48 +01:00
Dan Brown
e6864a9cff Improved card list design
- Removed border and rounded list item styles to make hover states have
  less edge detail and to align with other UI elements.
- In expanded-detail view, removed space used for entity description if
  there is not description content existing.
2022-05-14 12:54:23 +01:00
Dan Brown
60e319c4b4 Tidied up book navigation styles
- Removed background track line since it would darken entity item bars.
- Updated item spacing to be a bit tighter.
- Updated action hover styles to be a bit lighter, and visible on dark
  mode, to fit rest of system.
2022-05-13 18:34:47 +01:00
Dan Brown
24b31b624c Cleaned up entity details listing 2022-05-13 18:03:43 +01:00
Dan Brown
a0fe6147d8 Improved the display of dropdown menus
- Tweaked styling to add a little extra shadow and be more rounded to
  match other UI areas.
- Added slight horizontal inset when in right sidebar to prevent shadow
  being cut-off in most cases.
- Added logic to "drop upwards" if dropping down would take the menu
  offscreen.
2022-05-13 17:12:45 +01:00
Dan Brown
221d910ff2 Reduced excess margin in chapter contents lists 2022-05-12 17:27:57 +01:00
Dan Brown
bef2045df1 Embedded css sources for easier firefox dev work 2022-05-12 17:27:29 +01:00
Dan Brown
f021823287 Updated default value for secure session detection
Updated default value for APP_URL so that the startsWith call is not
passed null, since that causes deprecation notice in PHP8.1.
Would show when APP_URL was not set, adding extra confusiion.
2022-05-11 16:47:09 +01:00
Dan Brown
60014989f5 Updated version and assets for release v22.04.2 2022-05-09 16:10:16 +01:00
Dan Brown
57b10f195e Merge branch 'development' into release 2022-05-09 16:09:54 +01:00
Dan Brown
3a8a476906 Updated translators, applied styleCI change 2022-05-09 16:09:31 +01:00
Dan Brown
328bc88f02 Fixed LDAP_DUMP_* options when data contains binary
Dumping details that were binary, such as the jpegphoto data, would
cause the dump to fail on the encoding to JSON.
This change forces content to be UTF8 before dumping.
Updated existing test to cover.

Closes #3396
2022-05-09 15:57:50 +01:00
Dan Brown
2a99e23e6d Updated attachment download to check OB before cleaning it
Call to `ob_end_clean` would error if the environment did not use the
PHP `output_buffering` option. This adds an additional check and updates
the comment to be more specific to the exact scenario of the condition.
Tested with output_buffering=Off and output_buffering=4096

Closes #3415
2022-05-09 15:25:06 +01:00
Dan Brown
b855bbaaea New Crowdin updates (#3418) 2022-05-09 15:15:35 +01:00
Dan Brown
96436839f1 Added rate limit section to the API docs
Closes #3423
2022-05-09 15:12:29 +01:00
Dan Brown
b4f29a85ab Added Farsi language available
Closes #3426
2022-05-09 14:58:04 +01:00
Dan Brown
4a2a044f3d Updated PHP deps 2022-05-09 14:57:34 +01:00
Dan Brown
ca09ed916f Added support plans link to issue links 2022-05-05 15:48:27 +01:00
Dan Brown
dbefda055f Updated method of string interpolation
In prep for future PHP changes as per RFC
https://wiki.php.net/rfc/deprecate_dollar_brace_string_interpolation
2022-05-05 09:33:25 +01:00
Dan Brown
b1e95eb39f Updated version and assets for release v22.04.1 2022-05-04 21:26:58 +01:00
Dan Brown
b3da77b8f9 Merge branch 'development' into release 2022-05-04 21:26:31 +01:00
Dan Brown
93ef8c97b6 Applied styleci changes 2022-05-04 21:19:46 +01:00
Dan Brown
420b29f32f New Crowdin updates (#3402) 2022-05-04 21:18:47 +01:00
Dan Brown
d795af04df Added ability to escape role "External Auth ID" commas
- Using a backslash in this field before a comma.
- Could potentially (Although unlikely) be a breaking change.

For #3405
2022-05-04 21:03:13 +01:00
Dan Brown
d2ed98d20d Merge branch 'development' of github.com:BookStackApp/BookStack into development 2022-05-04 21:01:20 +01:00
Dan Brown
ebc69a8f2c Fixed double path slash URL issue in some cases
- Occurred on system request path usage (Primarily on guest login
  redirection) when a custom path was not in use.
- Added test to cover.

For #3404
2022-05-04 20:08:22 +01:00
Robert Meredith
d5ce6b680c Skip intermediate login page with single provider 2022-05-02 20:35:11 +10:00
Dan Brown
1a345b74bb Updated version and assets for release v22.04 2022-04-29 15:55:32 +01:00
Dan Brown
8ffc3a4abf Merge branch 'development' into release 2022-04-29 15:55:05 +01:00
Dan Brown
44013721f0 New Crowdin updates (#3401) 2022-04-29 15:53:06 +01:00
Dan Brown
16222de5fa Added uzbeck into local list
Not yet an actual added language yet due to low translation rate.
2022-04-29 15:52:11 +01:00
Dan Brown
ebfe946160 Updated translation attribution before v22.04 2022-04-29 15:43:30 +01:00
Dan Brown
5d2aad6a9e Merge pull request #3373 from evandroamaro/patch-1
Tiny header
2022-04-29 15:41:04 +01:00
Dan Brown
8fb016d1bf New Crowdin updates (#3384) 2022-04-29 15:40:38 +01:00
Dan Brown
c216a6a210 Applied stylci changes, updated composer deps 2022-04-29 15:38:06 +01:00
Dan Brown
26af9acc6c Improved iframe & summary handling in HTML to MD conversion 2022-04-29 14:58:28 +01:00
Dan Brown
c8a7acb6c7 Fixed drawing handling on HTML to Markdown conversion 2022-04-29 12:17:14 +01:00
Dan Brown
d3b39fbe50 Move html to markdown formatting tests to their own class 2022-04-29 11:50:34 +01:00
Dan Brown
ac7b2dd1bf Tweaked DRAW.IO params in complete .env file to show configure param 2022-04-27 17:52:35 +01:00
Dan Brown
f1a8ad4980 Applied latest StyleCI changes 2022-04-25 18:42:31 +01:00
Dan Brown
d5b7fff102 Merge branch 'recycle_bin_api_endpoints' into development 2022-04-25 18:32:55 +01:00
Dan Brown
0930e8519c Updated polymorphic database relation types to simpler version
- Means we can use these simpler types in API response, As desired in #3377.

Closes #3395
2022-04-25 18:31:37 +01:00
Dan Brown
ff8dadefee Reviewed recycle bin API PR and made changes
Made the following changes, many of these are just to align with
existing conventions.

- Updated urls to be hypenated, instead of underscored, to match other system endpoints.
- Updated URL parameter to be `deletionId` instead of `id`, and removed the ID-based comment on controller methods, so the required ID model is clear from the URL alone, since its not clear from the URL endpoint alone like existing endpoints. This follows the pattern used in the "web" routes.
- Added extra detail on some controller method comments, and copied permission comment to each method.
- Removed existing field visibility mechanisms to use simpler model-based visibility since we didn't need anything too special here (After some of my other changes).
- Allowed the "deletable" model to be shown in response to provide a little more detail on the main deleted item.
- Updated parent/child-count loading to be on the "deletable" model instead of additional properties which results in simpler controller logic and enforces the idea these are relations on the deletable, not the deletion itself. It also removes additional exposure of model namespacing.
- Updated (int) casts to intval, just since that's our most common conversion method in the codebase.
- Testing: Removed `actingAsAuthorizedUser` and used the admin user instead to prevent extra auth steps on each test.
- Testing: Cut logic/data-checks from tests if already covered by other tests.
- Testing: Added simple assertions for delete/restore response data.
- Examples: Updated list example to reflect changes.

Review of PR #3377
To be followed up with changes to polymorphic relations to hide
namespacing.
2022-04-25 17:54:59 +01:00
Dan Brown
2b0ae23da0 Updated composer deps, applied latest StyleCI changes 2022-04-24 18:22:40 +01:00
Dan Brown
63cb6015a8 Merge pull request #3364 from BookStackApp/app_url_requests
Updated custom request overrides to better match original intent
2022-04-24 14:52:38 +01:00
Dan Brown
5a7fb20116 Merge pull request #3387 from BookStackApp/editor_switching
Page editor switching
2022-04-24 14:03:03 +01:00
Dan Brown
829f808800 Merge pull request #3365 from BookStackApp/data_streaming
Add data streaming where beneficial to reduce memory usage
2022-04-24 13:59:47 +01:00
Dan Brown
0dfe5cb66b Merge pull request #3391 from BookStackApp/drawio_config_event
Made it possible to configure draw.io/diagrams.net integration
2022-04-24 13:58:59 +01:00
julesdevops
14bccae6bd do some cleanup and add doc 2022-04-24 10:49:29 +02:00
Dan Brown
b97c150ac8 Added additional testing for editor switching permissions 2022-04-23 23:34:15 +01:00
Dan Brown
0c5723d76e Switched to database-based tracking for page editor
- Works better to avoid bad assumptions when showing the editor based
  upon content type.
- Also updated some previous tests to cleaner format.
2022-04-23 23:20:46 +01:00
Dan Brown
bec61a56c0 Added listing of editor type to revisions
- Also tweaked some editor revision table styles and merged some
  sections to reduce space usage.
2022-04-23 15:03:58 +01:00
Dan Brown
1b46aa8756 Aded tests for core editor switching functionality 2022-04-23 14:22:04 +01:00
julesdevops
f14e6e8f2d Complete list endpoint and add some tests 2022-04-21 22:23:24 +02:00
Dan Brown
0003ce61cd Fixed failing test after drawio default url change 2022-04-20 23:42:47 +01:00
Dan Brown
d76bbb2954 Made it possible to configure draw.io/diagrams.net integration
Added new editor public event to hook into draw.io configuration step.
Required change of embed url to trigger the configure step.
2022-04-20 23:32:02 +01:00
Dan Brown
478067483f Linked up confirmation prompt to editor switching 2022-04-20 18:21:21 +01:00
Dan Brown
eff539f89b Added new confirm-dialog component, both view and logic 2022-04-20 14:58:37 +01:00
Dan Brown
214992650d Standardised dropdown list item styles, Extracted page editor toolbar
- Updated all dropdown list item actions into three specific styles:
  icon-item, text-item & label-item. Allows a stronger structure while
  prevents mixing of styles as we were getting for header dropdown in
  dark mode.
- Extracted out page editor top toolbar to its own view file & split
  editor switch options to different markdown options.
2022-04-20 14:03:47 +01:00
Dan Brown
492ffff0a4 Added core editor switching functionality 2022-04-18 17:39:28 +01:00
Dan Brown
956eb1308f Aligned page edit controller method data usage
Extracted page editor view data gathering to its own class for
alignment. Updated the data used in views as part of the process to use
view-specific variables instead of custom attributes added to models.
Also moved tinymce library loading so it's not loaded when not using the
wysiwyg editor.
2022-04-17 23:01:14 +01:00
Dan Brown
0cc215f8c3 Added editor type change button 2022-04-17 15:01:29 +01:00
Dan Brown
e8e38f1f7b Added an 'editor-change' role permission 2022-04-17 14:33:06 +01:00
Dan Brown
7dc80a9e14 Updated editor setting to reflect "Default editor" 2022-04-17 14:13:14 +01:00
Dan Brown
e49afdbd72 New Crowdin updates (#3358) 2022-04-14 16:14:05 +01:00
Dan Brown
56254bdb66 Added testing for our request method overrides 2022-04-13 13:02:42 +01:00
Dan Brown
25654b2322 Fixed base URL starting slash usage 2022-04-13 12:46:19 +01:00
Dan Brown
27339079f7 Extracted esbuild config to a build script
Allows us to use NodeJS code for file/directory locating to not be
shell/os specific, while also also reducing duplicated complexity within
packages.json file.

Related to #3323
2022-04-13 12:08:56 +01:00
julesdevops
55e52e45fb Start recycle bin API endpoints: list, restore, delete 2022-04-07 22:34:00 +02:00
evandroamaro
c979e6465e Tiny header
Had the same translation as the small header. Corrected the translation.
2022-04-05 10:53:52 +01:00
Dan Brown
c30a9d3564 Touched entity timestamps on entity tag update
Decided it's relevant to entity updated_at since tags are now indexed
alongside content.

- Also fixed tags not applied on shelf.
- Also enforced proper page API update validation.
- Adds tests to cover.

For #3319
Fixes #3370
2022-04-04 17:24:05 +01:00
Dan Brown
59d1fb2d10 Fixed tests from streaming changes
- Added testing check to buffer stop/clear on streaming output due to
  interference during tests.
- Made content-disposition header a little safer in download responses.
- Also aligned how we check for testing environment.
2022-04-03 16:22:31 +01:00
Dan Brown
08a8c0070e Added streaming support to API attachment read responses
Required some special handling due to the content being base64-encoded
within a JSON response.
2022-04-02 19:21:19 +01:00
Dan Brown
cb770c534d Added streamed uploads for attachments 2022-04-02 18:46:48 +01:00
Dan Brown
6749faa89a Fixed streamed outputs in more extreme scenarios
Fixes hitting memory limits where downloaded file sizes are much greater
than memory limit. Stopping and flushing output buffer seemed to stop
limits causing issues when fpassthru is used.
Tested with 24M memory limit and 734M file
2022-04-02 18:42:15 +01:00
Dan Brown
82e8b1577e Updated attachment download responses to stream from filesystem
This allows download of attachments that are larger than current memory
limits, since we're not loading the entire file into memory any more.

For inline file responses, we take a 1kb portion of the file to sniff
before to check mime before we proceed.
2022-04-02 18:07:43 +01:00
Dan Brown
4dce03c0d3 Updated custom request overrides to better match original intent
This updates the custom Request handler to provide only the scheme and
host on the `getSchemeAndHttpHost` call, instead of providing the whole
APP_URL value, while adding an override to the 'getBaseUrl' to use the
APP_URL content instead of the guessed/detected Symfony value.

Untested apart from simple local setup.

Related to #2765
2022-04-02 17:14:37 +01:00
Dan Brown
7233c1c7b2 Updated version and assets for release v22.03.1 2022-03-30 19:37:07 +01:00
Dan Brown
1309a01131 Merge branch 'development' into release 2022-03-30 19:36:45 +01:00
Dan Brown
affae2e3c4 New Crowdin updates (#3354) 2022-03-30 19:29:13 +01:00
Dan Brown
1a90b98b8f Updated composer dependancies 2022-03-30 19:22:47 +01:00
Dan Brown
da4308bb0f Fixed settings redirect issue and custom head display
- Fixed issue where redirect for `/settings` view would not be ran
  through base url generator so would not create a correct path in some
  cases. Now routed through controller with normal redirect.
- Fixed custom head content being active on settings pages due to route
  name changes, for when viewing settings, in last release.

Fixes #3356 and #3355
2022-03-30 19:15:24 +01:00
Dan Brown
0333185b6d Updated version and assets for release v22.03 2022-03-30 13:49:17 +01:00
Dan Brown
83f89f64e8 Merge branch 'development' into release 2022-03-30 13:49:05 +01:00
Dan Brown
135022136a New Crowdin updates (#3353) 2022-03-30 13:31:59 +01:00
Dan Brown
12f96bb1a4 Updated translation contributors, added Basque to language options 2022-03-30 13:12:17 +01:00
Dan Brown
678314a0c5 New Crowdin updates (#3320) 2022-03-30 13:00:27 +01:00
Dan Brown
0887c39694 Updated example env with LDAP group dump option 2022-03-29 11:49:02 +01:00
Dan Brown
078e8e7dc3 PHPStan and StyleCI fixes
- Updated PhpStan PHP version option to match project.
- Applied StyleCI changes.
- Updated static to self in WebhookFormatter, following static analysis
  guidance.
- Fixed mis-matched header tags.
2022-03-28 11:31:06 +01:00
Dan Brown
038015f852 Merge pull request #3349 from BookStackApp/settings_reorg
Reorganization of settings view
2022-03-28 11:22:21 +01:00
Dan Brown
7c12920dc8 Added 404 response for non-existing setting categories
- Added test to cover.
2022-03-28 11:16:20 +01:00
Dan Brown
895f656897 Split out settings view and made functional
- Split settings out to new views using a core shared layout.
- Extracted added language text to translation files.
- Updated settings routes to be dynamic to category.
- Added redirect for old primary settings route.
- Updated existing tests to cover settings route changes.
- Added tests to cover settings view.
- Improved contrast of settings links for dark mode.
2022-03-28 11:09:55 +01:00
Dan Brown
31dbf132b9 Started playing with new settings view layout 2022-03-26 21:36:05 +00:00
Dan Brown
b5281bc9ca Fixed tests, applied StyleCI changes 2022-03-26 20:38:03 +00:00
Dan Brown
3625f12abe Added extendable/scalable formatter for webhook data
Creates a new organsied formatting system for webhook data, with
interfaces for extending with custom model formatting rules.
Allows easy usage & extension of the default bookstack formatting
behaviour when customizing webhook events via theme system, and keeps
default data customizations organised.

This also makes the following webhook data changes:
- owned_by/created_by/updated_by user details are loaded for events with
  Entity details. (POTENTIALLY BREAKING CHANGE).
- current_revision details are loaded for page update/create events.

Added testing to cover added model formatting rules.

For #3279 and #3218
2022-03-26 16:53:02 +00:00
Dan Brown
55d61fceb2 Added manual image thumbnail exif orientation handling
Uses original image data to extract orientation exif to apply image
transformations before scaling and save. Manually done due to issues
with exif data loss during the existing Invervention image path.

For #1854
2022-03-26 12:32:08 +00:00
Dan Brown
2325a307a5 Applied latest styleCI changes 2022-03-25 11:14:27 +00:00
Dan Brown
d2b49084b0 Added pre-render sizes to wysiwyg code blocks
Sets sizes on WYSIWYG code block sections based on content lines
as an early pre-codemirror height prediction to avoid excessive
jumping in the editor.

For #3326
2022-03-25 11:13:04 +00:00
Dan Brown
8594f42584 Added LDAP group debugging env option
Closes #3345
2022-03-23 16:34:23 +00:00
Dan Brown
dd7463259a Added wysiwyg filter to handle <br> tags within code blocks
This filters out <br> elements within code blocks and replaces them with
newlines. The editor started using <br>'s more harshley after some
configuration changes upon upgrading tinymce, in which we standardised
on forced br tags to avoid empty elements.

For #3327
2022-03-23 15:11:14 +00:00
Dan Brown
d23b24b8db Added additional missing editor translations
- Also merged StyleCI fixes

As per #3342
2022-03-23 14:41:54 +00:00
Dan Brown
1c859e94e0 Fixed conctenation of direct book pages within markdown export
- Updated to ensure seperation with newlines.
- Added test to cover.

For #3341
2022-03-23 14:31:42 +00:00
Dan Brown
981807220c Applied StyleCI changes and updated dependancies 2022-03-23 12:02:01 +00:00
Dan Brown
a2231c3604 Merge pull request #3333 from BookStackApp/wysiwyg_tasklist
WYSIWYG tasklist support
2022-03-23 11:58:16 +00:00
Dan Brown
622adc5450 Updated justify translation for editor
Fixes #3342
2022-03-23 11:57:20 +00:00
Dan Brown
95e496d16f Added translation string for tasklist WYSIWYG action 2022-03-23 11:54:27 +00:00
Dan Brown
883e18f7c4 Updated tasklist style and functionality for cross-browser use
- Updated styles to better align checkboxes within page content.
- Updated functionality to use a cross-compatible property on checkbox
  click within the editor.
2022-03-23 11:51:19 +00:00
Dan Brown
c5aad29c72 Added tasklist support to markdown exporter 2022-03-22 14:56:51 +00:00
Dan Brown
ea62fe6004 Improved tasklist wysiwyg behaviour
- Updated buttons/actions to better handle nesting.
- Added hack for better usage with normal bullets
2022-03-22 14:03:20 +00:00
Dan Brown
5ae9ed1e22 Added functioning wysiwyg tasklist toolbar button
- Includes new icon.
- Includes menu button overrides of existing list styles to prevent
  incompatible mixing.
2022-03-20 13:30:48 +00:00
Dan Brown
b6be8a2bb9 Added WYSIWYG tasklist clicking ability 2022-03-20 11:59:46 +00:00
Dan Brown
65dd7ad1e9 Changed to a psuedo-style approach for tasklist in wysiwyg 2022-03-19 17:13:26 +00:00
Dan Brown
f991948c49 Started initial tasklist attempt, failed implementation 2022-03-19 16:04:33 +00:00
Dan Brown
ee6a2339b6 Applied latest styleCI changes 2022-03-09 14:30:36 +00:00
Dan Brown
fd26f54b99 Merge pull request #3298 from BookStackApp/wysiwyg_links
WYSIWYG editor link updates
2022-03-09 14:29:03 +00:00
Dan Brown
11a1a6fb16 Updated version and assets for release v22.02.3 2022-03-07 15:12:22 +00:00
Dan Brown
882c609296 Merge branch 'development' into release 2022-03-07 15:12:09 +00:00
Dan Brown
77ad819970 Updated translation attribution before v22.02.3 release 2022-03-07 15:06:44 +00:00
Dan Brown
2835e5be93 New Crowdin updates (#3312) 2022-03-07 15:06:21 +00:00
Dan Brown
856fca8289 Updated CSP with frame-src rules
- Configurable via 'ALLOWED_IFRAME_SOURCES' .env option.
- Also updated how CSP rules are set, with a single header being used
  instead of many.
- Also applied CSP rules to HTML export outputs.
- Updated tests to cover.

For #3314
2022-03-07 14:27:41 +00:00
Dan Brown
48d0095aa2 Added mysql-ssl-ca option to complete .env 2022-03-02 21:51:18 +00:00
Dan Brown
176a0dcd59 Updated version and assets for release v22.02.2 2022-03-01 22:45:41 +00:00
Dan Brown
94b0f70bfa Merge branch 'development' into release 2022-03-01 22:45:12 +00:00
Dan Brown
36d7ff77a9 New translations editor.php (Italian) (#3301) 2022-03-01 22:32:43 +00:00
Dan Brown
fb16ac326f Reduced dynamic fade in dark mode
For #3203
2022-03-01 22:29:31 +00:00
Dan Brown
5947f59a04 Updated strategy for empty newline sections
- For some reason, TinyMCE would handle empty paragraphs with a '&nbsp'
  by default but this would be removed when the paragraph had an
  attribute. This was fine in the old editor.
- This changes the approach to use '<br>' tags within elements
  for "spaced emptiness".
- For compatbility with any existing empty paragraphs, I updated the
  styles to show default height for empty paragraph sections.
- This also makes changes to help preserve encoded &nbsp; html tags
  since they were getting converted along the journey.

Related to #3302
2022-03-01 17:26:06 +00:00
Dan Brown
1843d80fb7 Added cache breaker to tinymce loading systems
Takes the version from BookStack app.js paths instead of tinyMCE version
since things external from TinyMCE could be loaded using this.
2022-03-01 13:41:53 +00:00
Dan Brown
6252b46395 Added a custom link context toolbar
- Allows for easy unlinking, link preview or link editing.
- Created custom one to limit actions available.
- Performed refactoring of non-plugin toolbar editor code to extact into
  its own file.

Related to #3276
2022-02-28 13:56:23 +00:00
Dan Brown
20ecaa5c5a Added ctrl+shift+k shortcut to WYSIWYG
Shows entity select dialog for more direct entity link insertion.
Aligns with shortcut from markdown editor.

For #3244
2022-02-28 13:34:32 +00:00
Dan Brown
08b2a77d41 Updated version and assets for release v22.02.1 2022-02-27 17:46:06 +00:00
Dan Brown
3e8e9a23cf Merge branch 'development' into release 2022-02-27 17:45:49 +00:00
Dan Brown
1253711c7d New translations editor.php (Chinese Simplified) (#3291) 2022-02-27 17:44:58 +00:00
Dan Brown
963d8f4693 Updated issue templates, readme and dev version
- Updated bug report template to capture browser.
- Updated readme roadmap.
- Bumped dev version.
2022-02-27 17:26:27 +00:00
Dan Brown
0de4d6d223 Improved WYSIWYG code block behaviour via range of fixes
- Fixed issues with new code blocks breaking or acting odd due to
  misnamed contenteditable attribute.
- Helped fix issue where code blocks may show in a strage blank state
  due to timing within shadow dom loading.
- Fixed some function timing issues where some functions required their
  async predecessor to have finished.

Tested rather heavily in firefox and brave.
Fixes #3292
2022-02-27 17:21:24 +00:00
Dan Brown
06f694bad2 Updated tinymce link query to break caches
Fixes #3293
2022-02-27 16:03:18 +00:00
Dan Brown
58b83b64c8 Updated version and assets for release v22.02 2022-02-26 12:01:44 +00:00
Dan Brown
dfe4cde6ee Merge branch 'development' into release 2022-02-26 12:00:46 +00:00
Dan Brown
41689a1e65 New Crowdin updates (#3259) 2022-02-26 11:46:33 +00:00
Dan Brown
2ae8026903 Updated translators for v22.02 release 2022-02-26 11:40:09 +00:00
Dan Brown
dcb36b27a0 Updated github issue templates
- Removed titles since they don't provide added benefit upon the labels
  and would often lead to being submitted with just the placeholder
  title.
- Feature request form
  - Added further context to benefits field for hopefully better
    responses that target the core goal.
  - Added a field to ask if feature can already be achieved, to
    gain an idea if the submitter has explored other options (if
    existing).
  - Added a field to ensure the submitter has search the issue list
    before submitting.
  - Added a field to ask existing BookStack usage time to understand
    potential evolution of usage and/or influence of other platforms.
2022-02-24 18:26:34 +00:00
Dan Brown
83082c32ef Applied latest StyleCI changes 2022-02-24 15:04:09 +00:00
Dan Brown
1e112f78d8 On WYSIWYG details unwrap, provided better restore of cursor
Also prevents the toolbar from sticking around after the details block
was removed.
2022-02-24 15:02:23 +00:00
Dan Brown
9283f28e31 Updated JS deps 2022-02-24 15:02:06 +00:00
Dan Brown
7f5fc9fbe3 Updated composer dependancies
Includes update to dompdf v1.2 which helps address image sizing in
tables and hence fix #3190
2022-02-24 14:30:55 +00:00
Dan Brown
ce566bea2a Updated OIDC error handling for better error reporting
Fixes issue where certain errors would not show to the user
due to extra navigation jumps which lost the error message
in the process.
This simplifies and aligns exceptions with more directly
handled exception usage at the controller level.

Fixes #3264
2022-02-24 14:16:09 +00:00
Dan Brown
63ce3c9add Updated incorrect feature request template description 2022-02-13 13:18:42 +00:00
Dan Brown
f0470afb4c Applied StyleCI changes, updated readme badges & roadmap 2022-02-13 13:16:43 +00:00
Dan Brown
f8e6172582 Updated github actions to ignore language branch
Old branch filters did not seem to work since they are supposed to
reference the target branch, not source branch.
Instead used if statement to prevent run on crowdin branch.
2022-02-13 13:03:41 +00:00
Dan Brown
7a8505f812 Made a pass to clean up UserRepo 2022-02-13 12:56:26 +00:00
Dan Brown
9806907d53 Merge pull request #3260 from BookStackApp/wysiwyg_details
WYSIWYG details/summary blocks
2022-02-09 19:33:53 +00:00
Dan Brown
2b3726702d Revamped workings of WYSIWYG code blocks
Code blocks in tinymce could sometimes end up exploded into the sub
elements of the codemirror display.
This changes the strategy to render codemirror within the shadow dom of
a custom element while preserving the normal pre/code DOM structure.

Still a little instability when moving/adding code blocks within details
blocks but much harder to break things now.
2022-02-09 19:24:27 +00:00
Dan Brown
2b46b00f29 Updated PDF export to open detail blocks 2022-02-09 11:33:23 +00:00
Dan Brown
536ad14276 WYSIWYG details: Improved usage reliability and dark mdoe styles 2022-02-09 11:25:22 +00:00
Dan Brown
a318775cfc Improved wysiwyg details/summary edit controls
- Added specific non-editable/editable filtering to make editing within
  box more reliable.
- Updated toolbar icons and controls.
2022-02-09 10:40:46 +00:00
Dan Brown
9e0b8a9fb6 Started support for WYSIWYG details/summary blocks 2022-02-08 23:08:00 +00:00
Dan Brown
7c692ec588 Changed editor bottom padding technique
- Ensures padding works across FF & Chrome, was only working on FF
  before.
- Fixes sketchy editor positioning focus on FF, since tinyMCE would
  add a hidden element to the bottom of the body which would remove/add
  our body padding causing unstable positioning.
2022-02-08 17:05:38 +00:00
Dan Brown
da0dc7292c Merged in editor translation strings 2022-02-08 15:57:19 +00:00
Dan Brown
045710ea08 Updated with latest styleci changes 2022-02-08 15:29:58 +00:00
Dan Brown
c6ad16dba6 Merge branch 'tinymce' into development 2022-02-08 15:28:56 +00:00
Dan Brown
4ea1f0c633 Merge crowdin changes from users API changes 2022-02-08 15:14:18 +00:00
Dan Brown
f5077c17f4 Merge pull request #3238 from BookStackApp/users_api
User Management API
2022-02-08 13:32:45 +00:00
Dan Brown
c73773930e Merge pull request #3245 from BookStackApp/php7.4
Updated minimum php version from 7.3 to 7.4
2022-02-08 13:31:15 +00:00
Dan Brown
1782618c64 New Crowdin updates (#3251)
* New translations activities.php (Hebrew)

* New translations auth.php (Hebrew)

* New translations common.php (Hebrew)

* New translations activities.php (Hebrew)

* New translations common.php (Hebrew)

* New translations entities.php (Hebrew)

* New translations errors.php (Hebrew)

* New translations validation.php (Spanish)
2022-02-08 13:29:16 +00:00
ististyle
a01bb92989 Update Korean translation (#3256)
* Update validation.php

* Update activities.php

* Update passwords.php

* Update common.php

* Update common.php

* Update auth.php

* Update components.php

* Add files via upload

* Update errors.php

* Update entities.php

* Update entities.php

* Update entities.php

* Update auth.php

* Update activities.php

* Update components.php

* Update components.php

* Update entities.php

* Update components.php

* Update entities.php

* Update errors.php

* Update settings.php

* Update settings.php

* Add files via upload

* Update errors.php
2022-02-08 13:29:01 +00:00
Dan Brown
a2bcf765a8 Split out codemirror JS to its own module
Added a cache-compatible module loading system/pattern to the codebase.
2022-02-08 11:10:01 +00:00
Dan Brown
130dc05517 Updated wysiwyg with dark mode patches
- To better fit in with default BookStack dark theme.
2022-02-08 10:09:17 +00:00
Dan Brown
572d8b3700 Removed unused scroll patch after testing
- Tested on android and ios
- Also checked on translations and removed todo.
2022-02-08 09:42:18 +00:00
Dan Brown
e0d9380055 Aligned some editor events, Changed wysiwyg custom styles loading
- Removed old 'editor-*-update' commands to instead use the aligned
  'editor::replace' command that we already have.
- Changed the way custom styles are loaded for the WYSIWYG editor so we
  don't need an API call but instead scape content from the parent page
  header using comments as identifiers. Added tests to ensure comments
  exist and align.
2022-02-08 01:01:37 +00:00
Dan Brown
15647a0409 Merged color and formats wysiwyg groups 2022-02-08 00:20:36 +00:00
Dan Brown
e88dbe4db3 Added license references to readme attribution 2022-02-08 00:18:29 +00:00
Dan Brown
84c501bcf4 Simplified wysiwyg toolbar with a overflow groups 2022-02-07 23:56:39 +00:00
Dan Brown
c8b6f622f4 Added help/about box to wysiwyg editor
- To display license info along with shortcuts.
- Extracted out plain layout from 503 error page.
- Added tests to ensure license references are as expected.
2022-02-07 23:19:04 +00:00
Dan Brown
ef211a76ae Made WYSIWYG editor translatable
- Created new translation file for editor view.
- Added simple logic to format for tinymce.
- Aligned some of the custom labels we were using.
2022-02-06 21:17:08 +00:00
Dan Brown
d11144d9e2 Updated version and assets for release v21.12.5 2022-02-06 15:49:23 +00:00
Dan Brown
f96b0ea5f3 Merge branch 'development' into release 2022-02-06 15:48:55 +00:00
Dan Brown
b4e29d2b7d New Crowdin updates (#3225) 2022-02-06 15:46:28 +00:00
Dan Brown
2732d8961f Merge branch 'fix-code-block-linefeed' into development 2022-02-06 15:19:52 +00:00
Dan Brown
b2f863e1f1 WYSIWG: Improved handling of cross-block code block creation
- Updated code content to get specific text selection instead of using
  node-based handling which could return the whole document when
  multiple top-level nodes were in selection.
- Simplified how code gets applied into the page to not be node based
  but use native editor methods to replace the selection. Allows
  creation from half-way through a block.

Tested on chrome+Firefox on Fedora 35.
Builds upon changes in #3246.
For #3200.
2022-02-06 15:19:18 +00:00
Dan Brown
1df7497c09 Added missing validation.file message
- Included test to cover
- Also applied StyleCI fixes

Closes #3248
2022-02-06 14:48:33 +00:00
Dan Brown
d29a2a647a Prevented PCRE limit issues in markdown base64 extraction
For #3249
2022-02-06 07:51:38 +00:00
Dan Brown
43f32f6d5a Added attachment API file size limit test
Created while testing for #3248, Was not something that's currently
failing within BookStack but will still add for coverage.
2022-02-06 05:05:17 +00:00
Dan Brown
921131f999 Modularised our tinymce config and plugins
- Split everything into specific plugin/concern files to make things
  more managable. Means original component file is now simple and much
  of the core config is focused in one place.
2022-02-05 23:15:58 +00:00
Dan Brown
0cde2704d0 Made further tweaks to align with current editor
- Ensured each of the core actions worked at a high level.
- Handled some TinyMCE API changes.
- Moved code block insert to its own button.
2022-02-05 21:20:20 +00:00
Dan Brown
db4093d523 Got TinyMCE 5 added in barely working state
- Some extensions & custom actions not working.
- Updated anything visual to not be breaking (Icons) and anything
  functional that prevented loading.
2022-02-05 16:57:42 +00:00
julesdevops
049d6ba5b2 fix(wysiwyg): preserves line feeds in code block mode 2022-02-05 10:28:44 +01:00
Dan Brown
e33b587b87 Updated minimum php version from 7.3 to 7.4
Closes #3152
2022-02-04 13:27:11 +00:00
Dan Brown
c8be6ee8a6 Addressed test failures from users API changes 2022-02-04 01:02:13 +00:00
Dan Brown
46e6e239dc Added user API examples 2022-02-04 00:44:56 +00:00
Dan Brown
eb653bda16 Added user-create API endpoint
- Required extracting logic into repo.
- Changed some existing creation paths to standardise behaviour.
- Added test to cover new endpoint.
- Added extra test for user delete to test migration.
- Changed how permission errors are thrown to ensure the right status
  code can be reported when handled in API.
2022-02-04 00:26:19 +00:00
Dan Brown
9e1c8ec82a Added user-update API endpoint
- Required changing the docs generator to handle more complex
  object-style rules. Bit of a hack for some types (password).
- Extracted core update logic to repo for sharing with API.
- Moved user update language string to align with activity/logging
  system.
- Added tests to cover.
2022-02-03 16:52:28 +00:00
Dan Brown
2cd7a48044 Added users-delete API endpoint
- Refactored some delete checks into repo.
- Added tests to cover.
- Moved some translations to align with activity/logging system.
2022-02-03 15:12:50 +00:00
Dan Brown
d089623aac Refactored existing user API work
- Updated routes to use new format.
- Changed how hidden fields are exposed to be more flexible to different
  use-cases.
- Updated properties available on read/list results.
- Started adding testing coverage.
- Removed old unused UserRepo 'getAllUsers' function.

Related to #2701, Progression of #2734
2022-02-03 12:33:26 +00:00
Dan Brown
8d7febe482 Merge branch 'api-endpoint-users' into users_api 2022-02-03 11:38:55 +00:00
Dan Brown
815f8d79ed Updated version and assets for release v21.12.4 2022-02-01 11:52:24 +00:00
Dan Brown
b62dab32e0 Merge branch 'development' into release 2022-02-01 11:51:48 +00:00
Dan Brown
9d15688a43 Applied latest styleci changes 2022-02-01 11:49:30 +00:00
Dan Brown
033b163675 New Crowdin updates (#3214)
* New translations auth.php (Spanish)

* New translations auth.php (Estonian)

* New translations entities.php (Estonian)

* New translations common.php (French)

* New translations common.php (Indonesian)

* New translations common.php (Turkish)

* New translations common.php (Ukrainian)

* New translations common.php (Chinese Simplified)

* 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 (Slovenian)

* New translations common.php (Spanish, Argentina)

* New translations common.php (Croatian)

* New translations common.php (Estonian)

* New translations common.php (Latvian)

* New translations common.php (Bosnian)

* New translations common.php (Norwegian Bokmal)

* New translations common.php (Swedish)

* New translations common.php (Slovak)

* New translations common.php (Spanish)

* New translations common.php (Hebrew)

* New translations common.php (Arabic)

* New translations common.php (Bulgarian)

* New translations common.php (Catalan)

* New translations common.php (Czech)

* New translations common.php (Danish)

* New translations common.php (German)

* New translations common.php (Hungarian)

* New translations common.php (Russian)

* New translations common.php (Italian)

* New translations common.php (Japanese)

* New translations common.php (Korean)

* New translations common.php (Lithuanian)

* New translations common.php (Dutch)

* New translations common.php (Polish)

* New translations common.php (Portuguese)

* New translations common.php (German Informal)

* New translations common.php (Spanish)

* New translations common.php (Italian)

* New translations settings.php (Italian)

* New translations common.php (Spanish, Argentina)
2022-02-01 11:48:29 +00:00
Dan Brown
6eadf3efb3 Added language select to the user create form
- Updated user invite to take language from user.
- Added tests to cover.
- Added page/tab title to user create view.

For #2576 and #2408
2022-01-31 22:15:21 +00:00
Dan Brown
f83cc83877 Added external-auth-id option to create-admin command
- Added tests to cover.
- Refactored some existing testing.
- Requires password or external_auth_id to be provided. Defaults to
  password.
- Randomly sets password to 32 digit random chars if external_auth_id
  provided instead.

For #3222
2022-01-31 20:43:41 +00:00
Dan Brown
17215431ca Fixed default registration role display options
- This also allows an admin to choose not to have a default role.
- Also applied latest styleCI fixes.

For #3220
2022-01-31 14:16:56 +00:00
Dan Brown
90c543064b Merge branch 'development' of github.com:BookStackApp/BookStack into development 2022-01-30 17:41:16 +00:00
Dan Brown
a709fd04b5 Added option to configure PDF export paper size
For #995
2022-01-30 17:40:42 +00:00
StyleCI Bot
4a1d060eb9 Apply fixes from StyleCI 2022-01-30 16:44:51 +00:00
Dan Brown
e17cdab420 Updated default branch name references 2022-01-30 16:33:03 +00:00
Dan Brown
2d074caf72 Merge pull request #3210 from Julesdevops/simple-503-error-file
Massively simplify the 503 error view
2022-01-30 16:24:24 +00:00
julesdevops
99202b3bb8 fix(503): massively simplify the 503 error view
This view was relying on too much app logic, which could lead to errors
when rendering it.
2022-01-29 10:56:13 +01:00
Dan Brown
73eac83afe Fixed OIDC JWT key parsing in microsoft environments
Made existence of 'alg' optional when JWK array set so we instead infer
it as RSA256 if not existing.

Fixes #3206
2022-01-28 14:00:55 +00:00
Dan Brown
c11f795c1d Added cloudabove sponsor logo 2022-01-26 20:45:14 +00:00
Dan Brown
262f863981 Updated version and assets for release v21.12.3 2022-01-24 22:49:42 +00:00
Dan Brown
a4c94390a1 Merge branch 'master' into release 2022-01-24 22:49:31 +00:00
Dan Brown
7e6e1fca76 Fixed test broken by PdfGenerator changes 2022-01-24 22:24:41 +00:00
Dan Brown
aaa2205df1 Refreshed markdown cm instance layout on size change
Intended to fix positioning quirks caused by changing codemirror
instance size when you have lines that wrap and cause line height
changes. Often caused by editor toolbox expand/collapse.

This adds a debounced resize observer to refresh editor layout on size
change.
Also tweaks toolbox expand/collapse to more consistently set aria
attribute.

For #3186
2022-01-24 22:08:36 +00:00
Dan Brown
4aed3f8558 Patched gallery duplication on multi-image upload
Quick patch to clear the gallery display when getting the first page.
Duplication of the galler was occuring due to the mulitple upload events
loading the gallery mulitple times while only clearing the existing
gallery at the start of all refreshes.

A bit flashy in terms of user experience, as there will still be
mulitple load/clear events but fixes the duplication. Could be done more
elegently in future by communicating up image upload counts.

For #3160
2022-01-24 21:38:11 +00:00
Dan Brown
7b4086107c Added parent context to recently updated items
- Includes tests to cover
For #3183
2022-01-24 21:21:30 +00:00
Dan Brown
585bd0cc45 Updated translator attribution and StyleCI changes 2022-01-24 20:55:03 +00:00
Dan Brown
f18e2784be New Crowdin updates (#3158)
* New translations activities.php (Slovak)

* New translations activities.php (Slovak)

* New translations common.php (Russian)

* New translations settings.php (Russian)

* New translations common.php (Japanese)

* New translations settings.php (Japanese)

* New translations activities.php (Persian)

* New translations auth.php (Persian)

* New translations auth.php (Persian)

* New translations entities.php (Persian)

* New translations common.php (Persian)

* New translations auth.php (Persian)

* New translations entities.php (Persian)

* New translations settings.php (Persian)

* New translations entities.php (Persian)

* New translations validation.php (Persian)

* New translations settings.php (Persian)

* New translations settings.php (Spanish, Argentina)

* New translations common.php (Spanish, Argentina)

* New translations settings.php (Spanish, Argentina)

* New translations activities.php (Spanish, Argentina)

* New translations entities.php (Spanish, Argentina)

* New translations entities.php (Persian)

* New translations settings.php (Persian)

* New translations entities.php (Persian)

* New translations errors.php (Persian)

* New translations settings.php (French)

* New translations common.php (French)

* New translations settings.php (French)

* New translations entities.php (Persian)

* New translations settings.php (Persian)

* New translations entities.php (Persian)

* New translations errors.php (Persian)
2022-01-24 20:53:36 +00:00
Dan Brown
f88e6d1520 Updated HTMLDiff package to address multibtye issue
Addresses potential issue when using multibyte characters.
Couple of other packages seemed to have updates also since earlier.

For #3170
2022-01-24 20:27:14 +00:00
Dan Brown
872961ef7c Updated npm and php dependancies 2022-01-24 18:53:28 +00:00
Dan Brown
bbd8d63652 Merge pull request #3179 from Julesdevops/atomic-user-creation
When creating a user, do not persist the user on invitation sending failure
2022-01-24 18:48:00 +00:00
Dan Brown
af39ff15ac Merge branch 'show_more_informations_on_recently_updated_pages' 2022-01-24 18:23:47 +00:00
Dan Brown
aae3cd69d7 Added test to cover PR #3177 2022-01-24 18:23:16 +00:00
Dan Brown
2d3df955ae Merge branch 'master' of github.com:BookStackApp/BookStack 2022-01-24 17:26:17 +00:00
Dan Brown
8b5747eae2 Further adjusted linked image sizes on PDF export
Further fixes for #3120, Adds DOMPDF specific adjustments to prevent
full width linked images being cut-off as per last tweak.
This does not fix usage in smaller cases (tables) but tested on
master DOMPDF branch shows that will likely be fixed in next DOMPDF
upstream release.
DOMPDF fixes would break WKHTMLTOPDF presentation so system updated
to conditionally apply styles.
2022-01-24 17:24:00 +00:00
Dan Brown
6c699f7fab Merge pull request #3193 from Julesdevops/xdebug-docker-compose-setup
chore(dev): add xdebug support for docker setup
2022-01-24 16:11:29 +00:00
julesdevops
ac6eceb0e5 doc(dev): add xdebug informations 2022-01-23 14:26:01 +01:00
julesdevops
a2a2f3a4dd chore(dev): add xdebug support for docker setup 2022-01-22 17:43:29 +01:00
julesdevops
6db64763fe enh(recently updated): show updatedBy and updated_at 2022-01-19 21:49:45 +01:00
julesdevops
c9beacbfbf fix(User Creation): do not persist the user if invitation fails
- Wrap the user creation process in a transaction
- Add test
2022-01-19 20:46:38 +01:00
Dan Brown
53f3cca85d Updated version and assets for release v21.12.2 2022-01-10 18:23:44 +00:00
Dan Brown
ed08bbcecc Merge branch 'master' into release 2022-01-10 18:23:19 +00:00
Dan Brown
2aace16704 Updated translator attribution before release v21.12.2 2022-01-10 18:22:43 +00:00
Dan Brown
ade66dcf2f Applied latest styleci changes 2022-01-10 18:18:15 +00:00
Dan Brown
d3eaaf6457 New Crowdin updates (#3148)
* New translations common.php (Czech)

* New translations common.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations errors.php (Japanese)

* New translations entities.php (Japanese)

* New translations common.php (Japanese)

* New translations settings.php (Japanese)

* New translations entities.php (Japanese)

* New translations settings.php (Japanese)

* New translations auth.php (Japanese)

* New translations common.php (Portuguese, Brazilian)

* New translations activities.php (Portuguese, Brazilian)

* New translations activities.php (Portuguese, Brazilian)
2022-01-10 18:17:28 +00:00
Dan Brown
941217d9fb Improved loading for images with failed thumbnails
- A placeholder is now shown in the gallery.
- The page editors will use the original image url if the display
  thumbnail is missing.

For #3142
2022-01-10 18:13:48 +00:00
Dan Brown
4239d4c54d Fixed error on webhooks for recycle bin operations
Updated the getUrl method on deletions to not require any passed
params to align with usage in webhooks.
Probably better to have a proper interface but would require a wider
change.

Fixes #3154
2022-01-10 17:47:49 +00:00
Dan Brown
8d91f4369b Improved custom homepage check on item deletion
Custom homepage usage will now be checked before any actioning
of deletion rather than potentially causing an exception acting
during the deletion.

Previously a deletion could still be created, within the recycle bin,
for the parent which may lead to the page being deleted anyway.

For #3150
2022-01-10 17:04:01 +00:00
Dan Brown
722aa04577 Merge pull request #3153 from AitorMatxi/patch-1
Update auth.php
2022-01-10 16:10:39 +00:00
Aitor Matxinea
2d0abc4164 Update auth.php
Fix misspelled word "As" to "Has".
2022-01-10 11:45:48 +01:00
Dan Brown
c3f7b39a0f Addressed phpstan cases 2022-01-07 13:04:49 +00:00
Dan Brown
de97ebf9b7 Updated version and assets for release v21.12.1 2022-01-06 12:20:37 +00:00
Dan Brown
f492a660a8 Merge branch 'master' into release 2022-01-06 12:20:26 +00:00
Dan Brown
ef11100863 Updated translator attribution before release v21.12.1 2022-01-06 12:20:13 +00:00
Dan Brown
1a26b47782 Applied latest styleCI changes 2022-01-06 12:18:11 +00:00
Dan Brown
cb0d674a71 Merge branch 'sort_changes'
Related to #3134
2022-01-06 12:03:15 +00:00
Dan Brown
4d094331cf New Crowdin updates (#3117)
* New translations auth.php (Bulgarian)

* New translations auth.php (Catalan)

* New translations auth.php (Czech)

* New translations auth.php (Danish)

* New translations auth.php (Hebrew)

* New translations auth.php (Swedish)

* New translations auth.php (Hungarian)

* New translations auth.php (Italian)

* New translations auth.php (Japanese)

* New translations auth.php (Korean)

* New translations auth.php (Lithuanian)

* New translations auth.php (Dutch)

* New translations auth.php (Polish)

* New translations auth.php (Russian)

* New translations auth.php (Slovak)

* New translations auth.php (Slovenian)

* New translations settings.php (Korean)

* New translations settings.php (Lithuanian)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Norwegian Bokmal)

* New translations settings.php (Bosnian)

* New translations settings.php (Latvian)

* New translations settings.php (Estonian)

* New translations settings.php (Croatian)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Persian)

* New translations settings.php (Indonesian)

* New translations settings.php (Vietnamese)

* New translations settings.php (Dutch)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Chinese Simplified)

* 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 (Polish)

* New translations settings.php (German Informal)

* New translations settings.php (Spanish)

* New translations activities.php (Spanish)

* New translations auth.php (Spanish)

* New translations common.php (Spanish)

* New translations settings.php (Spanish)

* New translations auth.php (German)

* New translations passwords.php (German)

* New translations settings.php (German)

* New translations activities.php (German)

* New translations auth.php (German)

* New translations auth.php (German Informal)

* New translations common.php (German)

* New translations entities.php (German)

* New translations errors.php (German)

* New translations errors.php (German Informal)

* New translations settings.php (German)

* New translations settings.php (German Informal)

* New translations entities.php (Japanese)

* New translations entities.php (Vietnamese)

* New translations entities.php (Slovak)

* New translations entities.php (Slovenian)

* New translations entities.php (Swedish)

* New translations entities.php (Turkish)

* New translations entities.php (Chinese Simplified)

* New translations entities.php (Chinese Traditional)

* New translations entities.php (Portuguese, Brazilian)

* New translations entities.php (Polish)

* New translations entities.php (Indonesian)

* New translations entities.php (Persian)

* New translations entities.php (Croatian)

* New translations entities.php (Estonian)

* New translations entities.php (Latvian)

* New translations entities.php (Bosnian)

* New translations entities.php (Russian)

* New translations entities.php (Dutch)

* New translations entities.php (Portuguese)

* New translations entities.php (Bulgarian)

* New translations entities.php (Ukrainian)

* New translations entities.php (Spanish, Argentina)

* New translations entities.php (Norwegian Bokmal)

* New translations entities.php (French)

* New translations entities.php (Spanish)

* New translations entities.php (Arabic)

* New translations entities.php (Catalan)

* New translations entities.php (Lithuanian)

* New translations entities.php (Czech)

* New translations entities.php (Danish)

* New translations entities.php (German)

* New translations entities.php (Hebrew)

* New translations entities.php (Hungarian)

* New translations entities.php (Italian)

* New translations entities.php (Korean)

* New translations entities.php (German Informal)

* New translations entities.php (Spanish)

* New translations auth.php (Portuguese)

* New translations common.php (Portuguese)

* New translations errors.php (Portuguese)

* New translations settings.php (Portuguese)

* New translations activities.php (French)

* New translations activities.php (French)

* New translations auth.php (French)

* New translations common.php (French)

* New translations entities.php (French)

* New translations settings.php (French)

* New translations activities.php (Spanish, Argentina)

* New translations entities.php (Spanish, Argentina)

* New translations auth.php (Spanish, Argentina)

* New translations common.php (Spanish, Argentina)

* New translations activities.php (German Informal)

* New translations common.php (German Informal)

* New translations settings.php (Spanish, Argentina)

* New translations activities.php (Chinese Simplified)

* New translations activities.php (Chinese Simplified)

* New translations auth.php (Chinese Simplified)

* New translations common.php (Chinese Simplified)

* New translations entities.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations activities.php (Estonian)

* New translations auth.php (Estonian)

* New translations common.php (Estonian)

* New translations entities.php (Chinese Simplified)

* New translations entities.php (Estonian)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Estonian)

* New translations settings.php (Estonian)

* New translations validation.php (Estonian)

* New translations auth.php (Italian)

* New translations common.php (Italian)

* New translations entities.php (Italian)

* New translations settings.php (Italian)

* New translations activities.php (Russian)

* New translations auth.php (Russian)

* New translations common.php (Russian)

* New translations activities.php (Russian)

* New translations entities.php (Russian)

* New translations settings.php (Russian)

* New translations activities.php (Japanese)

* New translations auth.php (Portuguese, Brazilian)

* New translations auth.php (Portuguese, Brazilian)

* New translations auth.php (Arabic)

* New translations activities.php (Czech)

* New translations auth.php (Czech)

* New translations activities.php (Czech)

* New translations auth.php (Czech)

* New translations common.php (Czech)

* New translations entities.php (Czech)

* New translations settings.php (Czech)

* New translations activities.php (Czech)

* New translations auth.php (Czech)

* New translations common.php (Czech)

* New translations entities.php (Czech)

* New translations settings.php (Czech)

* New translations auth.php (Czech)

* New translations entities.php (Czech)

* New translations settings.php (Czech)

* New translations auth.php (Czech)

* New translations auth.php (Czech)

* New translations activities.php (Latvian)

* New translations auth.php (Latvian)

* New translations common.php (Latvian)

* New translations entities.php (Latvian)

* New translations settings.php (Latvian)

* New translations activities.php (Latvian)

* New translations settings.php (Latvian)

* New translations activities.php (Italian)

* New translations entities.php (Italian)

* New translations activities.php (Italian)

* New translations settings.php (Italian)

* New translations common.php (Japanese)

* New translations settings.php (French)

* New translations common.php (Vietnamese)

* New translations common.php (Portuguese, Brazilian)

* New translations common.php (Indonesian)

* New translations common.php (Persian)

* New translations common.php (Croatian)

* New translations common.php (Estonian)

* New translations common.php (Latvian)

* New translations common.php (Bosnian)

* New translations common.php (German Informal)

* New translations settings.php (Spanish)

* New translations common.php (Chinese Simplified)

* 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 (German)

* New translations settings.php (Hebrew)

* New translations settings.php (Hungarian)

* New translations settings.php (Italian)

* New translations settings.php (Japanese)

* New translations common.php (Chinese Traditional)

* New translations common.php (Turkish)

* New translations common.php (Portuguese)

* New translations common.php (Danish)

* New translations common.php (Ukrainian)

* New translations common.php (Spanish, Argentina)

* New translations common.php (Norwegian Bokmal)

* New translations settings.php (Ukrainian)

* New translations common.php (French)

* New translations common.php (Spanish)

* New translations common.php (Arabic)

* New translations common.php (Bulgarian)

* New translations common.php (Catalan)

* New translations common.php (Czech)

* New translations common.php (German)

* New translations common.php (Swedish)

* New translations common.php (Hebrew)

* New translations common.php (Hungarian)

* New translations common.php (Italian)

* New translations common.php (Korean)

* New translations common.php (Lithuanian)

* New translations common.php (Dutch)

* New translations common.php (Polish)

* New translations common.php (Russian)

* New translations common.php (Slovak)

* New translations common.php (Slovenian)

* New translations settings.php (Korean)

* New translations settings.php (Lithuanian)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Norwegian Bokmal)

* New translations settings.php (Bosnian)

* New translations settings.php (Latvian)

* New translations settings.php (Estonian)

* New translations settings.php (Croatian)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Persian)

* New translations settings.php (Indonesian)

* New translations settings.php (Vietnamese)

* New translations settings.php (Dutch)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Chinese Simplified)

* 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 (Polish)

* New translations settings.php (German Informal)

* New translations common.php (Estonian)

* New translations entities.php (Estonian)

* New translations settings.php (Estonian)

* New translations common.php (Spanish)

* New translations settings.php (Spanish)

* New translations entities.php (French)

* New translations settings.php (French)

* New translations common.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations common.php (Spanish, Argentina)

* New translations settings.php (Spanish, Argentina)
2022-01-06 12:02:49 +00:00
Dan Brown
2312d07bb5 Removed old book sort permission test
Permission handling now done via other means with more extensive
permissions testing in SortTest class.
2022-01-05 16:46:03 +00:00
Dan Brown
fbd388ba4c Aligned chapter move permissions with page move permissions 2022-01-05 16:18:19 +00:00
Dan Brown
d3ca23b195 Added additional permission checks and tests for book sorts
- Aligned permissions control with move operations to check
  delete/create permissions against old/new locations.
- Added tests to cover additional permissions scenarios.
2022-01-05 15:42:59 +00:00
Dan Brown
553954ad18 Altered sort permission checking and started tests
Previous implemenations were hard to read so changing to be more
logically simplistic. Still needs further coverage in tests and
review/alignment of permissions to use.
2022-01-05 14:39:21 +00:00
Dan Brown
d8c45f5746 Changed model loading and permission checking on book sort
Models are now loaded into their own map to then be used for sorting and
reporting back of changed books. Prevents akward logic ordering issues
of before where some bits of code assumed/hoped for loaded models on
abstract data structures.

New levels of permissions are now checked for items within the
sort operation. Needs testing to cover.
2022-01-04 21:09:34 +00:00
Dan Brown
edc7c12edf Refactored sort system a little
To standardise the handled data format a little better.
2022-01-04 17:31:57 +00:00
Dan Brown
a72bd75e3a Added page titles to many missing app areas
Many pages were missing their unique tab/page titles
so this change is just to distribute them back over
many common areas where they were missing.
2022-01-04 13:33:24 +00:00
Dan Brown
31f1dca8a8 Added detection and thumbnail bypass for apng images
Adds apng sniffing when generating thumbnails with retained ratios to
serve the original image files, as we do for GIF images, to prevent
the image being resized to a static version.

Is more tricky than GIF since apng file mimes and extensions
are the same as png, we have to detect part of the file header
to sniff the type. Means we have to sniff at a later stage
than GIF since we have to load the image file data.

Made some changes to the image thubmnail caching while doing
this work to fit in with this handling.

Added test to cover.
For #3136.
2022-01-04 13:10:35 +00:00
Dan Brown
819ec55b1b Fixed code block language parsing issue
Language parsing of code blocks could falter on pasted code blocks due
to the lanuage being parsed with a space which would throw an error when
used as a css class.
This adds more extensive language parsing to be safer.

Fixes #3133
2022-01-04 11:54:24 +00:00
Dan Brown
dba506a20e Added search autofocus on entity-selector-popup
Closes #3127
2022-01-04 11:30:44 +00:00
Dan Brown
d0de4fd8f9 Fixed failing webhook test cases 2022-01-03 19:51:13 +00:00
Dan Brown
00eedafbfd Added timeout and debugging statuses to webhooks
- Added a user-configurable timeout option to webhooks.
- Added webhook fields for last-call/error datetime, in addition to last
  error string, which are shown on  webhook edit view.

Related to #3122
2022-01-03 19:42:48 +00:00
Dan Brown
6e18620a0a Added webhook call http exception handling
Will now catch and log errors on events such as http timeouts.
For #3122
2022-01-03 18:37:56 +00:00
Dan Brown
fe54c7f27a Added webhook_call_before theme event hook 2022-01-03 18:22:03 +00:00
Dan Brown
65830b428c Fixed linked images being micro on pdf export
Was caused by max-width: 100% causing confusion when images were
inside an anchor. This change resets that property on PDF
exports allowing full width images to be shown as so
without affecting smaller sizes.

Fixes #3120
2022-01-01 18:18:37 +00:00
Dan Brown
b438e0187c Updated webhooks list to not squash events/status
Closes #3135
2022-01-01 17:43:33 +00:00
Dan Brown
8614775c14 Updated sponsors in readme 2021-12-30 16:43:28 +00:00
Dan Brown
09436836a5 Updated version and assets for release v21.12 2021-12-22 17:04:18 +00:00
Dan Brown
bb455d7788 Merge branch 'master' into release 2021-12-22 17:03:50 +00:00
Dan Brown
b0666e5d70 Updated translator contribution before v21.12 release 2021-12-22 16:30:48 +00:00
Dan Brown
fc109f7e1c Applied latest StyleCI changes 2021-12-20 17:40:27 +00:00
Dan Brown
21f2a7087c Merge pull request #3118 from BookStackApp/copy_stuff
Additional copy/clone abilities
2021-12-20 17:39:44 +00:00
Dan Brown
ff70509fca Added copy considerations
Show to the user when copying stuff to highlight important things such
as what's not copied or change in permissions.
2021-12-20 17:33:19 +00:00
Dan Brown
0288320700 Added ability to clone books 2021-12-19 19:20:31 +00:00
Dan Brown
20e093a7a1 Added ability to copy/clone chapters
Builds upon page clone work. Takes permissions into account to decide
if child pages should be copied.
2021-12-19 15:40:52 +00:00
Dan Brown
3f9527f166 Extracted page copy to new cloner class
Fundemental refactor for planned additional clone operations.
No behaviour change intended in this commit.
2021-12-19 12:56:27 +00:00
Dan Brown
da01913616 Added ability to copy a role
- Copies via loading in model on create view.
- Updated role views while editing to bring up to similar format as
  that used for more modern app areas.
- Added tests to cover.

Related to #1123
2021-12-19 12:27:14 +00:00
Dan Brown
67b6c07548 Updated failing tests, Applied StyleCI changes 2021-12-18 16:41:42 +00:00
Dan Brown
bb9cd9d610 Aligned password length requirements
Updated all password validation to use central password defaults
system while updating length requirements to now all match
at 8 characters minimum.

Some language text was technically correct (More than 7 characters)
but this has been updated for clarity and to prompt other translations
to be updated.

Closes #2237
2021-12-18 16:33:40 +00:00
Dan Brown
04f37e21e2 Applied latest StyleCI changes 2021-12-18 11:43:05 +00:00
Dan Brown
a3ead5062a Merge branch 'webhooks' 2021-12-18 11:40:08 +00:00
Dan Brown
24e29c523b Aligned notification capitalisation 2021-12-18 11:24:58 +00:00
Dan Brown
04d59763c3 Updated auditlog IP search test
To ensure the test covers filtering logic.
Related to #3081.
2021-12-18 11:05:41 +00:00
Dan Brown
5c04f25c86 Merge branch 'search-by-ip' of https://github.com/johnroyer/BookStack into johnroyer-search-by-ip 2021-12-18 10:58:07 +00:00
Dan Brown
767a82fb41 Reverted unrequired use of mb_ function 2021-12-18 10:43:43 +00:00
Dan Brown
5c5a3de7cb Merge branch 'fix/multibyte-safe-search' 2021-12-18 10:40:38 +00:00
Dan Brown
c6e3e85e82 Added test case for multibyte search highlighting
Related to #3113
2021-12-18 10:38:33 +00:00
Kristian Krastev
d0fd1b7f5c Make building of search results work for multi-byte encoded characters 2021-12-15 16:29:43 +02:00
Dan Brown
d00ac3101d Allowed database queue usage where desired 2021-12-13 18:34:18 +00:00
Dan Brown
f27d0d5aeb Added testing to cover webhook calling
Migrated call logic to Laravel's HTTP client for easier testing
capabilities.
2021-12-12 19:01:50 +00:00
Dan Brown
8d8b45860a Updated REST API docs with links to webhooks & theme-systems 2021-12-12 18:14:22 +00:00
Dan Brown
3bf34b6a0d Added webhook format example to webhook management views 2021-12-12 18:02:08 +00:00
Dan Brown
dbd4281ae8 Added active toggle to webhooks
To allow easy temporary de-activation without deletion or other
workarounds. Updated tests to cover.
2021-12-12 17:39:06 +00:00
Dan Brown
917598f7c8 Added webhook call functionality 2021-12-11 22:29:33 +00:00
Dan Brown
9079700170 Refactored the activity service
- Renamed to "ActivityLogger" to be more focused in usage.
- Extracted out query elements to seperate "ActivityQueries" class.
- Removed old 'addForEntity' activity method to limit activity record
  points.
2021-12-11 17:29:33 +00:00
Dan Brown
f2cb3b94f9 Added missing migration down table drop 2021-12-10 14:58:14 +00:00
Dan Brown
6381041252 Added testing for webhook management interface 2021-12-10 14:54:58 +00:00
Zero
7d13666039 Add unit test for ip addess searching 2021-12-10 15:11:30 +08:00
Zero
e6e92618b1 Fix PHP CS 2021-12-10 14:58:05 +08:00
Zero
2342f0c1c7 Fix UI error of IP searching input box 2021-12-10 14:50:04 +08:00
Zero
ee1106630e Update translation setting in blade 2021-12-10 14:50:04 +08:00
Zero
93e80e5d4e Delete duplicated translation 2021-12-10 14:50:04 +08:00
Zero
72d19968dd Search IP by partial-equal 2021-12-10 14:50:04 +08:00
Zero
2fd7b1f0d5 Update index name to 'activities_ip_index' 2021-12-10 14:50:04 +08:00
Zero
a93254430c Add index for user IP address 2021-12-10 14:50:04 +08:00
Zero
e686b2cf3c Show current search IP 2021-12-10 14:50:04 +08:00
Zero
4e63554cc6 Add an hidden submit
This hidden submit makes auto submit while user press Enter on IP
input field.
2021-12-10 14:50:04 +08:00
Zero
882f195927 Add margin right for IP input box 2021-12-10 14:50:04 +08:00
Zero
a12e346439 Add filter of user IP 2021-12-10 14:50:04 +08:00
Zero
8dee3d3a83 Add label translation 2021-12-10 14:50:04 +08:00
Zero
0e25298db9 Fix label and input box error 2021-12-10 14:50:04 +08:00
Zero
9cac6fad73 Add IP address search field mock 2021-12-10 14:50:04 +08:00
Dan Brown
8716b1922b Completed webhook management interface
Got webhook CRUD actions in place within the interface.
Quick manual test pass done, Needs automated tests.
2021-12-08 17:35:58 +00:00
Dan Brown
4621d8bcc5 Initial controller/views for webhooks management 2021-12-08 14:29:42 +00:00
Dan Brown
a3a3055695 Started webhook implementation 2021-12-07 14:55:11 +00:00
Jascha Sticher
4cbd1a9eb5 Extend /users API endpoint
* add /users/{id} to get a single user
* add variable to print fields that are otherwise hidden (e.g. email)
2021-05-06 11:20:08 +02:00
Jascha Sticher
07626669da Test API Endpoint for users 2021-05-05 14:16:15 +02:00
1725 changed files with 80138 additions and 34937 deletions

View File

@@ -37,8 +37,10 @@ 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.
# For more detailed documentation on mail options, refer to:
# https://www.bookstackapp.com/docs/admin/email-webhooks/#email-configuration
MAIL_HOST=localhost
MAIL_PORT=1025
MAIL_PORT=587
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

View File

@@ -3,6 +3,10 @@
# Each option is shown with it's default value.
# Do not copy this whole file to use as your '.env' file.
# The details here only serve as a quick reference.
# Please refer to the BookStack documentation for full details:
# https://www.bookstackapp.com/docs/
# Application environment
# Can be 'production', 'development', 'testing' or 'demo'
APP_ENV=production
@@ -42,7 +46,7 @@ APP_TIMEZONE=UTC
# overrides can be made. Defaults to disabled.
APP_THEME=false
# Trusted Proxies
# Trusted proxies
# Used to indicate trust of systems that proxy to the application so
# certain header values (Such as "X-Forwarded-For") can be used from the
# incoming proxy request to provide origin detail.
@@ -58,20 +62,27 @@ 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
# MySQL specific connection options
# Path to Certificate Authority (CA) certificate file for your MySQL instance.
# When this option is used host name identity verification will be performed
# which checks the hostname, used by the client, against names within the
# certificate itself (Common Name or Subject Alternative Name).
MYSQL_ATTR_SSL_CA="/path/to/ca.pem"
# Mail sending options
# Mail configuration
# Refer to https://www.bookstackapp.com/docs/admin/email-webhooks/#email-configuration
MAIL_DRIVER=smtp
MAIL_FROM=mail@bookstackapp.com
MAIL_FROM_NAME=BookStack
# SMTP mail options
MAIL_HOST=localhost
MAIL_PORT=1025
MAIL_PORT=587
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_VERIFY_SSL=true
MAIL_SENDMAIL_COMMAND="/usr/sbin/sendmail -bs"
# Cache & Session driver to use
# Can be 'file', 'database', 'memcached' or 'redis'
@@ -100,8 +111,7 @@ MEMCACHED_SERVERS=127.0.0.1:11211:100
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.
# Can be 'sync', 'database' or 'redis'
QUEUE_CONNECTION=sync
# Storage system to use
@@ -137,6 +147,10 @@ STORAGE_URL=false
# Can be 'standard', 'ldap', 'saml2' or 'oidc'
AUTH_METHOD=standard
# Automatically initiate login via external auth system if it's the only auth method.
# Works with saml2 or oidc auth methods.
AUTH_AUTO_INITIATE=false
# Social authentication configuration
# All disabled by default.
# Refer to https://www.bookstackapp.com/docs/admin/third-party-auth/
@@ -217,6 +231,7 @@ LDAP_DUMP_USER_DETAILS=false
LDAP_USER_TO_GROUPS=false
LDAP_GROUP_ATTRIBUTE="memberOf"
LDAP_REMOVE_FROM_GROUPS=false
LDAP_DUMP_USER_GROUPS=false
# SAML authentication configuration
# Refer to https://www.bookstackapp.com/docs/admin/saml2-auth/
@@ -252,7 +267,12 @@ OIDC_ISSUER_DISCOVER=false
OIDC_PUBLIC_KEY=null
OIDC_AUTH_ENDPOINT=null
OIDC_TOKEN_ENDPOINT=null
OIDC_ADDITIONAL_SCOPES=null
OIDC_DUMP_USER_DETAILS=false
OIDC_USER_TO_GROUPS=false
OIDC_GROUPS_CLAIM=groups
OIDC_REMOVE_FROM_GROUPS=false
OIDC_EXTERNAL_ID_CLAIM=sub
# Disable default third-party services such as Gravatar and Draw.IO
# Service-specific options will override this option
@@ -267,7 +287,7 @@ 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
# For URLs, The following URL parameters should be included: embed=1&proto=json&spin=1&configure=1
DRAWIO=true
# Default item listing view
@@ -284,7 +304,7 @@ 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
REVISION_LIMIT=100
# Recycle Bin Lifetime
# The number of days that content will remain in the recycle bin before
@@ -298,6 +318,18 @@ RECYCLE_BIN_LIFETIME=30
# Maximum file size, in megabytes, that can be uploaded to the system.
FILE_UPLOAD_SIZE_LIMIT=50
# Export Page Size
# Primarily used to determine page size of PDF exports.
# Can be 'a4' or 'letter'.
EXPORT_PAGE_SIZE=a4
# Set path to wkhtmltopdf binary for PDF generation.
# Can be 'false' or a path path like: '/home/bins/wkhtmltopdf'
# When false, BookStack will attempt to find a wkhtmltopdf in the application
# root folder then fall back to the default dompdf renderer if no binary exists.
# Only used if 'ALLOW_UNTRUSTED_SERVER_FETCHING=true' which disables security protections.
WKHTMLTOPDF=false
# Allow <script> tags in page content
# Note, if set to 'true' the page editor may still escape scripts.
ALLOW_CONTENT_SCRIPTS=false
@@ -320,6 +352,22 @@ ALLOW_UNTRUSTED_SERVER_FETCHING=false
# Setting this option will also auto-adjust cookies to be SameSite=None.
ALLOWED_IFRAME_HOSTS=null
# A list of sources/hostnames that can be loaded within iframes within BookStack.
# Space separated if multiple. BookStack host domain is auto-inferred.
# Can be set to a lone "*" to allow all sources for iframe content (Not advised).
# Defaults to a set of common services.
# Current host and source for the "DRAWIO" setting will be auto-appended to the sources configured.
ALLOWED_IFRAME_SOURCES="https://*.draw.io https://*.youtube.com https://*.youtube-nocookie.com https://*.vimeo.com"
# A list of the sources/hostnames that can be reached by application SSR calls.
# This is used wherever users can provide URLs/hosts in-platform, like for webhooks.
# Host-specific functionality (usually controlled via other options) like auth
# or user avatars for example, won't use this list.
# Space seperated if multiple. Can use '*' as a wildcard.
# Values will be compared prefix-matched, case-insensitive, against called SSR urls.
# Defaults to allow all hosts.
ALLOWED_SSR_HOSTS="*"
# The default and maximum item-counts for listing API requests.
API_DEFAULT_ITEM_COUNT=100
API_MAX_ITEM_COUNT=500
@@ -334,3 +382,11 @@ API_REQUESTS_PER_MIN=180
# user identifier (Username or email).
LOG_FAILED_LOGIN_MESSAGE=false
LOG_FAILED_LOGIN_CHANNEL=errorlog_plain_webserver
# Alter the precision of IP addresses stored by BookStack.
# Should be a number between 0 and 4, where 4 retains the full IP address
# and 0 completely hides the IP address. As an example, a value of 2 for the
# IP address '146.191.42.4' would result in '146.191.x.x' being logged.
# For the IPv6 address '2001:db8:85a3:8d3:1319:8a2e:370:7348' this would result as:
# '2001:db8:85a3:8d3:x:x:x:x'
IP_ADDRESS_PRECISION=4

1
.github/FUNDING.yml vendored
View File

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

View File

@@ -1,6 +1,5 @@
name: New API Endpoint or API Ability
description: Request a new endpoint or API feature be added
title: "[API Request]: "
labels: [":nut_and_bolt: API Request"]
body:
- type: textarea

View File

@@ -1,6 +1,5 @@
name: Bug Report
description: Create a report to help us improve or fix things
title: "[Bug Report]: "
labels: [":bug: Bug"]
body:
- type: textarea
@@ -36,6 +35,15 @@ body:
description: Provide any additional context and screenshots here to help us solve this issue
validations:
required: false
- type: input
id: browserdetails
attributes:
label: Browser Details
description: |
If this is an issue that occurs when using the BookStack interface, please provide details of the browser used which presents the reported issue.
placeholder: (eg. Firefox 97 (64-bit) on Windows 11)
validations:
required: false
- type: input
id: bsversion
attributes:

View File

@@ -1,9 +1,13 @@
blank_issues_enabled: false
contact_links:
- name: Discord chat support
- name: Discord Chat Support
url: https://discord.gg/ztkBqR2
about: Realtime support / chat with the community and the team.
about: Realtime support & chat with the BookStack 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.
about: Find details on how to debug issues and view common issues with their resolutions.
- name: Official Support Plans
url: https://www.bookstackapp.com/support/
about: View our official support plans that offer assured support for business.

View File

@@ -1,6 +1,5 @@
name: Feature Request
description: Request a new language to be added to CrowdIn for you to translate
title: "[Feature Request]: "
description: Request a new feature or idea to be added to BookStack
labels: [":hammer: Feature Request"]
body:
- type: textarea
@@ -13,8 +12,41 @@ body:
- type: textarea
id: benefits
attributes:
label: Describe the benefits this feature would bring to BookStack users
description: Explain the measurable benefits this feature would achieve for existing BookStack users
label: Describe the benefits this would bring to existing BookStack users
description: |
Explain the measurable benefits this feature would achieve for existing BookStack users.
These benefits should details outcomes in terms of what this request solves/achieves, and should not be specific to implementation.
This helps us understand the core desired goal so that a variety of potential implementations could be explored.
This field is important. Lack if input here may lead to early issue closure.
validations:
required: true
- type: textarea
id: already_achieved
attributes:
label: Can the goal of this request already be achieved via other means?
description: |
Yes/No. If yes, please describe how the requested approach fits in with the existing method.
validations:
required: true
- type: checkboxes
id: confirm-search
attributes:
label: Have you searched for an existing open/closed issue?
description: |
To help us keep these issues under control, please ensure you have first [searched our issue list](https://github.com/BookStackApp/BookStack/issues?q=is%3Aissue) for any existing issues that cover the fundemental benefit/goal of your request.
options:
- label: I have searched for existing issues and none cover my fundemental request
required: true
- type: dropdown
id: existing_usage
attributes:
label: How long have you been using BookStack?
options:
- Not using yet, just scoping
- 0 to 6 months
- 6 months to 1 year
- 1 to 5 years
- Over 5 years
validations:
required: true
- type: textarea

View File

@@ -1,6 +1,5 @@
name: Language Request
description: Request a new language to be added to CrowdIn for you to translate
title: "[Language Request]: "
description: Request a new language to be added to Crowdin for you to translate
labels: [":earth_africa: Translations"]
assignees:
- ssddanbrown
@@ -24,7 +23,7 @@ body:
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.
options:
- label: I confirm I'm offering to help translate for this new language via CrowdIn.
- label: I confirm I'm offering to help translate for this new language via Crowdin.
required: true
- type: markdown
attributes:

View File

@@ -1,6 +1,5 @@
name: Support Request
description: Request support for a specific problem you have not been able to solve yourself
title: "[Support Request]: "
labels: [":dog2: Support"]
body:
- type: checkboxes

View File

@@ -55,6 +55,8 @@ Name :: Languages
@Baptistou :: French
@arcoai :: Spanish
@Jokuna :: Korean
@smartshogu :: German; German Informal
@samadha56 :: Persian
cipi1965 :: Italian
Mykola Ronik (Mantikor) :: Ukrainian
furkanoyk :: Turkish
@@ -126,7 +128,7 @@ Zenahr Barzani (Zenahr) :: German; Japanese; Dutch; German Informal
tatsuya.info :: Japanese
fadiapp :: Arabic
Jakub Bouček (jakubboucek) :: Czech
Marco (cdrfun) :: German
Marco (cdrfun) :: German; German Informal
10935336 :: Chinese Simplified
孟繁阳 (FanyangMeng) :: Chinese Simplified
Andrej Močan (andrejm) :: Slovenian
@@ -136,7 +138,7 @@ Xiphoseer :: German
MerlinSVK (merlinsvk) :: Slovak
Kauê Sena (kaue.sena.ks) :: Portuguese, Brazilian
MatthieuParis :: French
Douradinho :: Portuguese, Brazilian
Douradinho :: Portuguese, Brazilian; Portuguese
Gaku Yaguchi (tama11) :: Japanese
johnroyer :: Chinese Traditional
jackaaa :: Chinese Traditional
@@ -158,14 +160,14 @@ HenrijsS :: Latvian
Pascal R-B (pborgner) :: German
Boris (Ginfred) :: Russian
Jonas Anker Rasmussen (jonasanker) :: Danish
Gerwin de Keijzer (gdekeijzer) :: Dutch; German; German Informal
Gerwin de Keijzer (gdekeijzer) :: Dutch; German Informal; German
kometchtech :: Japanese
Auri (Atalonica) :: Catalan
Francesco Franchina (ffranchina) :: Italian
Aimrane Kds (aimrane.kds) :: Arabic
whenwesober :: Indonesian
Rem (remkovdhoef) :: Dutch
syn7ax69 :: Bulgarian; Turkish
syn7ax69 :: Bulgarian; Turkish; German
Blaade :: French
Behzad HosseinPoor (behzad.hp) :: Persian
Ole Aldric (Swoy) :: Norwegian Bokmal
@@ -174,7 +176,7 @@ Alexander Predl (Harveyhase68) :: German
Rem (Rem9000) :: Dutch
Michał Stelmach (stelmach-web) :: Polish
arniom :: French
REMOVED_USER :: Turkish
REMOVED_USER :: ; French; Dutch; Turkish
林祖年 (contagion) :: Chinese Traditional
Siamak Guodarzi (siamakgoudarzi88) :: Persian
Lis Maestrelo (lismtrl) :: Portuguese, Brazilian
@@ -206,3 +208,150 @@ Thiago Rafael Pereira de Carvalho (thiago.rafael) :: Portuguese, Brazilian
Ken Roger Bolgnes (kenbo124) :: Norwegian Bokmal
Nguyen Hung Phuong (hnwolf) :: Vietnamese
Umut ERGENE (umutergene67) :: Turkish
Tomáš Batelka (Vofy) :: Czech
Mundo Racional (ismael.mesquita) :: Portuguese, Brazilian
Zarik (3apuk) :: Russian
Ali Shaatani (a.shaatani) :: Arabic
ChacMaster :: Portuguese, Brazilian
Saeed (saeed205) :: Persian
Julesdevops :: French
peter cerny (posli.to.semka) :: Slovak
Pavel Karlin (pavelkarlin) :: Russian
SmokingCrop :: Dutch
Maciej Lebiest (Szwendacz) :: Polish
DiscordDigital :: German; German Informal
Gábor Marton (dodver) :: Hungarian
Jasell :: Swedish
Ghost_chu (ghostchu) :: Chinese Simplified
Ravid Shachar (ravidshachar) :: Hebrew
Helga Guchshenskaya (guchshenskaya) :: Russian
daniel chou (chou0214) :: Chinese Traditional
Manolis PATRIARCHE (m.patriarche) :: French
Mohammed Haboubi (haboubi92) :: Arabic
roncallyt :: Portuguese, Brazilian
goegol :: Dutch
msevgen :: Turkish
Khroners :: French
MASOUD HOSSEINY (masoudme) :: Persian
Thomerson Roncally (roncallyt) :: Portuguese, Brazilian
metaarch :: Bulgarian
Xabi (xabikip) :: Basque
pedromcsousa :: Portuguese
Nir Louk (looknear) :: Hebrew
Alex (qianmengnet) :: Chinese Simplified
stothew :: German
sgenc :: Turkish
Shukrullo (vodiylik) :: Uzbek
William W. (Nevnt) :: Chinese Traditional
eamaro :: Portuguese
Ypsilon-dev :: Arabic
Hieu Vuong Trung (vuongtrunghieu) :: Vietnamese
David Clubb (davidoclubb) :: Welsh
welles freire (wellesximenes) :: Portuguese, Brazilian
Magnus Jensen (MagnusHJensen) :: Danish
Hesley Magno (hesleymagno) :: Portuguese, Brazilian
Éric Gaspar (erga) :: French
Fr3shlama :: German
DSR :: Spanish, Argentina
Andrii Bodnar (andrii-bodnar) :: Ukrainian
Younes el Anjri (younesea28) :: Dutch
Guclu Ozturk (gucluoz) :: Turkish
Atmis :: French
redjack666 :: Chinese Traditional
Ashita007 :: Russian
lihaorr :: Chinese Simplified
Marcus Silber (marcus.silber82) :: German
PellNet :: Croatian
Winetradr :: German
Sebastian Klaus (sebklaus) :: German
Filip Antala (AntalaFilip) :: Slovak
mcgong (GongMingCai) :: Chinese Simplified; Chinese Traditional
Nanang Setia Budi (sefidananang) :: Indonesian
Андрей Павлов (andrei.pavlov) :: Russian
Alex Navarro (alex.n.navarro) :: Portuguese, Brazilian
Ji-Hyeon Gim (PotatoGim) :: Korean
Mihai Ochian (soulstorm19) :: Romanian
HeartCore :: German Informal; German
simon.pct :: French
okaeiz :: Persian
Naoto Ishikawa (na3shkw) :: Japanese
sdhadi :: Persian
DerLinkman (derlinkman) :: German; German Informal
TurnArabic :: Arabic
Martin Sebek (sebekmartin) :: Czech
Kuchinashi Hoshikawa (kuchinashi) :: Chinese Simplified
digilady :: Greek
Linus (LinusOP) :: Swedish
Felipe Cardoso (felipecardosoruff) :: Portuguese, Brazilian
RandomUser0815 :: German Informal; German
Ismael Mesquita (mesquitoliveira) :: Portuguese, Brazilian
구인회 (laskdjlaskdj12) :: Korean
LiZerui (CNLiZerui) :: Chinese Traditional
Fabrice Boyer (FabriceBoyer) :: French
mikael (bitcanon) :: Swedish
Matthias Mai (schnapsidee) :: German; German Informal
Ufuk Ayyıldız (ufukayyildiz) :: Turkish
Jan Mitrof (jan.kachlik) :: Czech
edwardsmirnov :: Russian
Mr_OSS117 :: French
shotu :: French
Cesar_Lopez_Aguillon :: Spanish
bdewoop :: German
dina davoudi (dina.davoudi) :: Persian
Angelos Chouvardas (achouvardas) :: Greek
rndrss :: Portuguese, Brazilian
rirac294 :: Russian
David Furman (thefourCraft) :: Hebrew
Pafzedog :: French
Yllelder :: Spanish
Adrian Ocneanu (aocneanu) :: Romanian
Eduardo Castanho (EduardoCastanho) :: Portuguese
VIET NAM VPS (vietnamvps) :: Vietnamese
m4tthi4s :: French
toras9000 :: Japanese
pathab :: German
MichelSchoon85 :: Dutch
Jøran Haugli (haugli92) :: Norwegian Bokmal
Vasileios Kouvelis (VasilisKouvelis) :: Greek
Dremski :: Bulgarian
Frédéric SENE (nothingfr) :: French
bendem :: French
kostasdizas :: Greek
Ricardo Schroeder (brownstone666) :: Portuguese, Brazilian
Eitan MG (EitanMG) :: Hebrew
Robin Flikkema (RobinFlikkema) :: Dutch
Michal Gurcik (mgurcik) :: Slovak
Pooyan Arab (pooyanarab) :: Persian
Ochi Darma Putra (troke12) :: Indonesian
H.-H. Peng (Hsins) :: Chinese Traditional
Mosi Wang (mosiwang) :: Chinese Traditional
骆言 (LawssssCat) :: Chinese Simplified
Stickers Gaming Shøw (StickerSGSHOW) :: French
Le Van Chinh (Chino) (lvanchinh86) :: Vietnamese
Rubens nagios (rubenix) :: Catalan
Patrick Dantas (pa-tiq) :: Portuguese, Brazilian
Michal (michalgurcik) :: Slovak
Nepomacs :: German
Rubens (rubenix) :: Catalan
m4z :: German; German Informal
TheRazvy :: Romanian
Yossi Zilber (lortens) :: Hebrew; Uzbek
desdinova :: French
Ingus Rūķis (ingus.rukis) :: Latvian
Eugene Pershin (SilentEugene) :: Russian
周盛道 (zhoushengdao) :: Chinese Simplified
hamidreza amini (hamidrezaamini2022) :: Persian
Tomislav Kraljević (tomislav.kraljevic) :: Croatian
Taygun Yıldırım (yildirimtaygun) :: Turkish
robing29 :: German
Bruno Eduardo de Jesus Barroso (brunoejb) :: Portuguese, Brazilian
Igor V Belousov (biv) :: Russian
David Bauer (davbauer) :: German
Guttorm Hveem (guttormhveem) :: Norwegian Bokmal
Minh Giang Truong (minhgiang1204) :: Vietnamese
Ioannis Ioannides (i.ioannides) :: Greek
Vadim (vadrozh) :: Russian
Flip333 :: German Informal; German
Paulo Henrique (paulohsantos114) :: Portuguese, Brazilian
Dženan (Dzenan) :: Swedish
Péter Péli (peter.peli) :: Hungarian

34
.github/workflows/analyse-php.yml vendored Normal file
View File

@@ -0,0 +1,34 @@
name: analyse-php
on: [push, pull_request]
jobs:
build:
if: ${{ github.ref != 'refs/heads/l10n_development' }}
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v1
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.1
extensions: gd, mbstring, json, curl, xml, mysql, ldap
- name: Get Composer Cache Directory
id: composer-cache
run: |
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache composer packages
uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-8.1
restore-keys: ${{ runner.os }}-composer-
- name: Install composer dependencies
run: composer install --prefer-dist --no-interaction --ansi
- name: Run static analysis check
run: composer check-static

16
.github/workflows/lint-js.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
name: lint-js
on: [push, pull_request]
jobs:
build:
if: ${{ github.ref != 'refs/heads/l10n_development' }}
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v1
- name: Install NPM deps
run: npm ci
- name: Run formatting check
run: npm run lint

19
.github/workflows/lint-php.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
name: lint-php
on: [push, pull_request]
jobs:
build:
if: ${{ github.ref != 'refs/heads/l10n_development' }}
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v1
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.1
tools: phpcs
- name: Run formatting check
run: composer lint

View File

@@ -1,41 +0,0 @@
name: phpstan
on:
push:
branches-ignore:
- l10n_master
pull_request:
branches-ignore:
- l10n_master
jobs:
build:
runs-on: ubuntu-20.04
strategy:
matrix:
php: ['7.3']
steps:
- uses: actions/checkout@v1
- name: Setup PHP
uses: shivammathur/setup-php@v2
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: Install composer dependencies
run: composer install --prefer-dist --no-interaction --ansi
- name: Run PHPStan
run: php${{ matrix.php }} ./vendor/bin/phpstan analyse --memory-limit=2G

View File

@@ -1,19 +1,14 @@
name: test-migrations
on:
push:
branches-ignore:
- l10n_master
pull_request:
branches-ignore:
- l10n_master
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-20.04
if: ${{ github.ref != 'refs/heads/l10n_development' }}
runs-on: ubuntu-22.04
strategy:
matrix:
php: ['7.3', '7.4', '8.0', '8.1']
php: ['8.0', '8.1', '8.2']
steps:
- uses: actions/checkout@v1
@@ -26,13 +21,14 @@ jobs:
- name: Get Composer Cache Directory
id: composer-cache
run: |
echo "::set-output name=dir::$(composer config cache-files-dir)"
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache composer packages
uses: actions/cache@v1
uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ matrix.php }}
restore-keys: ${{ runner.os }}-composer-
- name: Start MySQL
run: |

View File

@@ -1,19 +1,14 @@
name: phpunit
name: test-php
on:
push:
branches-ignore:
- l10n_master
pull_request:
branches-ignore:
- l10n_master
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-20.04
if: ${{ github.ref != 'refs/heads/l10n_development' }}
runs-on: ubuntu-22.04
strategy:
matrix:
php: ['7.3', '7.4', '8.0', '8.1']
php: ['8.0', '8.1', '8.2']
steps:
- uses: actions/checkout@v1
@@ -21,18 +16,19 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: gd, mbstring, json, curl, xml, mysql, ldap
extensions: gd, mbstring, json, curl, xml, mysql, ldap, gmp
- name: Get Composer Cache Directory
id: composer-cache
run: |
echo "::set-output name=dir::$(composer config cache-files-dir)"
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache composer packages
uses: actions/cache@v1
uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ matrix.php }}
restore-keys: ${{ runner.os }}-composer-
- name: Start Database
run: |
@@ -53,5 +49,5 @@ jobs:
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
- name: Run PHP tests
run: php${{ matrix.php }} ./vendor/bin/phpunit

7
.gitignore vendored
View File

@@ -1,5 +1,7 @@
/vendor
/node_modules
/.vscode
/composer
Homestead.yaml
.env
.idea
@@ -11,6 +13,7 @@ yarn-error.log
/public/js/*.map
/public/bower
/public/build/
/public/favicon.ico
/storage/images
_ide_helper.php
/storage/debugbar
@@ -20,8 +23,10 @@ yarn.lock
nbproject
.buildpath
.project
.nvmrc
.settings/
webpack-stats.json
.phpunit.result.cache
.DS_Store
phpstan.neon
phpstan.neon
esbuild-meta.json

View File

@@ -1,7 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015-present, Dan Brown and the BookStack Project contributors
https://github.com/BookStackApp/BookStack/graphs/contributors
Copyright (c) 2015-2023, Dan Brown and the BookStack Project contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,34 +1,24 @@
<?php
namespace BookStack\Http\Controllers\Auth;
namespace BookStack\Access\Controllers;
use BookStack\Auth\Access\EmailConfirmationService;
use BookStack\Auth\Access\LoginService;
use BookStack\Auth\UserRepo;
use BookStack\Access\EmailConfirmationService;
use BookStack\Access\LoginService;
use BookStack\Exceptions\ConfirmationEmailException;
use BookStack\Exceptions\UserTokenExpiredException;
use BookStack\Exceptions\UserTokenNotFoundException;
use BookStack\Http\Controllers\Controller;
use BookStack\Http\Controller;
use BookStack\Users\UserRepo;
use Exception;
use Illuminate\Http\Request;
class ConfirmEmailController extends Controller
{
protected $emailConfirmationService;
protected $loginService;
protected $userRepo;
/**
* Create a new controller instance.
*/
public function __construct(
EmailConfirmationService $emailConfirmationService,
LoginService $loginService,
UserRepo $userRepo
protected EmailConfirmationService $emailConfirmationService,
protected LoginService $loginService,
protected UserRepo $userRepo
) {
$this->emailConfirmationService = $emailConfirmationService;
$this->loginService = $loginService;
$this->userRepo = $userRepo;
}
/**
@@ -51,14 +41,28 @@ class ConfirmEmailController extends Controller
return view('auth.user-unconfirmed', ['user' => $user]);
}
/**
* Show the form for a user to provide their positive confirmation of their email.
*/
public function showAcceptForm(string $token)
{
return view('auth.register-confirm-accept', ['token' => $token]);
}
/**
* Confirms an email via a token and logs the user into the system.
*
* @throws ConfirmationEmailException
* @throws Exception
*/
public function confirm(string $token)
public function confirm(Request $request)
{
$validated = $this->validate($request, [
'token' => ['required', 'string']
]);
$token = $validated['token'];
try {
$userId = $this->emailConfirmationService->checkTokenAndGetUserId($token);
} catch (UserTokenNotFoundException $exception) {

View File

@@ -1,28 +1,14 @@
<?php
namespace BookStack\Http\Controllers\Auth;
namespace BookStack\Access\Controllers;
use BookStack\Actions\ActivityType;
use BookStack\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use BookStack\Activity\ActivityType;
use BookStack\Http\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password;
class ForgotPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset emails and
| includes a trait which assists in sending these notifications from
| your application to your users. Feel free to explore this trait.
|
*/
use SendsPasswordResetEmails;
/**
* Create a new controller instance.
*
@@ -34,6 +20,14 @@ class ForgotPasswordController extends Controller
$this->middleware('guard:standard');
}
/**
* Display the form to request a password reset link.
*/
public function showLinkRequestForm()
{
return view('auth.passwords.email');
}
/**
* Send a reset link to the given user.
*
@@ -50,7 +44,7 @@ class ForgotPasswordController extends Controller
// We will send the password reset link to this user. Once we have attempted
// to send the link, we will examine the response then see the message we
// need to show to the user. Finally, we'll send out a proper response.
$response = $this->broker()->sendResetLink(
$response = Password::broker()->sendResetLink(
$request->only('email')
);

View File

@@ -1,10 +1,10 @@
<?php
namespace BookStack\Http\Controllers\Auth;
namespace BookStack\Access\Controllers;
use BookStack\Auth\Access\LoginService;
use BookStack\Auth\User;
use BookStack\Access\LoginService;
use BookStack\Exceptions\NotFoundException;
use BookStack\Users\Models\User;
trait HandlesPartialLogins
{

View File

@@ -1,41 +1,24 @@
<?php
namespace BookStack\Http\Controllers\Auth;
namespace BookStack\Access\Controllers;
use Activity;
use BookStack\Auth\Access\LoginService;
use BookStack\Auth\Access\SocialAuthService;
use BookStack\Access\LoginService;
use BookStack\Access\SocialAuthService;
use BookStack\Exceptions\LoginAttemptEmailNeededException;
use BookStack\Exceptions\LoginAttemptException;
use BookStack\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use BookStack\Facades\Activity;
use BookStack\Http\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use ThrottlesLogins;
use AuthenticatesUsers;
/**
* Redirection paths.
*/
protected $redirectTo = '/';
protected $redirectPath = '/';
protected $redirectAfterLogout = '/login';
protected $socialAuthService;
protected $loginService;
protected SocialAuthService $socialAuthService;
protected LoginService $loginService;
/**
* Create a new controller instance.
@@ -48,22 +31,6 @@ class LoginController extends Controller
$this->socialAuthService = $socialAuthService;
$this->loginService = $loginService;
$this->redirectPath = url('/');
$this->redirectAfterLogout = url('/login');
}
public function username()
{
return config('auth.method') === 'standard' ? 'email' : 'username';
}
/**
* Get the needed authorization credentials from the request.
*/
protected function credentials(Request $request)
{
return $request->only('username', 'email', 'password');
}
/**
@@ -73,6 +40,7 @@ class LoginController extends Controller
{
$socialDrivers = $this->socialAuthService->getActiveDrivers();
$authMethod = config('auth.method');
$preventInitiation = $request->get('prevent_auto_init') === 'true';
if ($request->has('email')) {
session()->flashInput([
@@ -84,6 +52,12 @@ class LoginController extends Controller
// Store the previous location for redirect after login
$this->updateIntendedFromPrevious();
if (!$preventInitiation && $this->shouldAutoInitiate()) {
return view('auth.login-initiate', [
'authMethod' => $authMethod,
]);
}
return view('auth.login', [
'socialDrivers' => $socialDrivers,
'authMethod' => $authMethod,
@@ -92,27 +66,15 @@ class LoginController extends Controller
/**
* Handle a login request to the application.
*
* @param \Illuminate\Http\Request $request
*
* @throws \Illuminate\Validation\ValidationException
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\Http\JsonResponse
*/
public function login(Request $request)
{
$this->validateLogin($request);
$username = $request->get($this->username());
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
if (method_exists($this, 'hasTooManyLoginAttempts') &&
$this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
// Check login throttling attempts to see if they've gone over the limit
if ($this->hasTooManyLoginAttempts($request)) {
Activity::logFailedLogin($username);
return $this->sendLockoutResponse($request);
}
@@ -126,24 +88,62 @@ class LoginController extends Controller
return $this->sendLoginAttemptExceptionResponse($exception, $request);
}
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
// On unsuccessful login attempt, Increment login attempts for throttling and log failed login.
$this->incrementLoginAttempts($request);
Activity::logFailedLogin($username);
return $this->sendFailedLoginResponse($request);
// Throw validation failure for failed login
throw ValidationException::withMessages([
$this->username() => [trans('auth.failed')],
])->redirectTo('/login');
}
/**
* Logout user and perform subsequent redirect.
*/
public function logout(Request $request)
{
Auth::guard()->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
$redirectUri = $this->shouldAutoInitiate() ? '/login?prevent_auto_init=true' : '/';
return redirect($redirectUri);
}
/**
* Get the expected username input based upon the current auth method.
*/
protected function username(): string
{
return config('auth.method') === 'standard' ? 'email' : 'username';
}
/**
* Get the needed authorization credentials from the request.
*/
protected function credentials(Request $request): array
{
return $request->only('username', 'email', 'password');
}
/**
* Send the response after the user was authenticated.
* @return RedirectResponse
*/
protected function sendLoginResponse(Request $request)
{
$request->session()->regenerate();
$this->clearLoginAttempts($request);
return redirect()->intended('/');
}
/**
* Attempt to log the user into the application.
*
* @param \Illuminate\Http\Request $request
*
* @return bool
*/
protected function attemptLogin(Request $request)
protected function attemptLogin(Request $request): bool
{
return $this->loginService->attempt(
$this->credentials($request),
@@ -152,29 +152,12 @@ class LoginController extends Controller
);
}
/**
* The user has been authenticated.
*
* @param \Illuminate\Http\Request $request
* @param mixed $user
*
* @return mixed
*/
protected function authenticated(Request $request, $user)
{
return redirect()->intended($this->redirectPath());
}
/**
* Validate the user login request.
*
* @param \Illuminate\Http\Request $request
*
* @throws \Illuminate\Validation\ValidationException
*
* @return void
* @throws ValidationException
*/
protected function validateLogin(Request $request)
protected function validateLogin(Request $request): void
{
$rules = ['password' => ['required', 'string']];
$authMethod = config('auth.method');
@@ -208,22 +191,6 @@ class LoginController extends Controller
return redirect('/login');
}
/**
* Get the failed login response instance.
*
* @param \Illuminate\Http\Request $request
*
* @throws \Illuminate\Validation\ValidationException
*
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function sendFailedLoginResponse(Request $request)
{
throw ValidationException::withMessages([
$this->username() => [trans('auth.failed')],
])->redirectTo('/login');
}
/**
* Update the intended URL location from their previous URL.
* Ignores if not from the current app instance or if from certain
@@ -251,4 +218,16 @@ class LoginController extends Controller
redirect()->setIntendedUrl($previous);
}
/**
* Check if login auto-initiate should be valid based upon authentication config.
*/
protected function shouldAutoInitiate(): bool
{
$socialDrivers = $this->socialAuthService->getActiveDrivers();
$authMethod = config('auth.method');
$autoRedirect = config('auth.auto_initiate');
return $autoRedirect && count($socialDrivers) === 0 && in_array($authMethod, ['oidc', 'saml2']);
}
}

View File

@@ -1,14 +1,14 @@
<?php
namespace BookStack\Http\Controllers\Auth;
namespace BookStack\Access\Controllers;
use BookStack\Actions\ActivityType;
use BookStack\Auth\Access\LoginService;
use BookStack\Auth\Access\Mfa\BackupCodeService;
use BookStack\Auth\Access\Mfa\MfaSession;
use BookStack\Auth\Access\Mfa\MfaValue;
use BookStack\Access\LoginService;
use BookStack\Access\Mfa\BackupCodeService;
use BookStack\Access\Mfa\MfaSession;
use BookStack\Access\Mfa\MfaValue;
use BookStack\Activity\ActivityType;
use BookStack\Exceptions\NotFoundException;
use BookStack\Http\Controllers\Controller;
use BookStack\Http\Controller;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
@@ -29,6 +29,8 @@ class MfaBackupCodesController extends Controller
$downloadUrl = 'data:application/octet-stream;base64,' . base64_encode(implode("\n\n", $codes));
$this->setPageTitle(trans('auth.mfa_gen_backup_codes_title'));
return view('mfa.backup-codes-generate', [
'codes' => $codes,
'downloadUrl' => $downloadUrl,

View File

@@ -1,10 +1,10 @@
<?php
namespace BookStack\Http\Controllers\Auth;
namespace BookStack\Access\Controllers;
use BookStack\Actions\ActivityType;
use BookStack\Auth\Access\Mfa\MfaValue;
use BookStack\Http\Controllers\Controller;
use BookStack\Access\Mfa\MfaValue;
use BookStack\Activity\ActivityType;
use BookStack\Http\Controller;
use Illuminate\Http\Request;
class MfaController extends Controller
@@ -21,6 +21,8 @@ class MfaController extends Controller
->get(['id', 'method'])
->groupBy('method');
$this->setPageTitle(trans('auth.mfa_setup'));
return view('mfa.setup', [
'userMethods' => $userMethods,
]);

View File

@@ -1,15 +1,15 @@
<?php
namespace BookStack\Http\Controllers\Auth;
namespace BookStack\Access\Controllers;
use BookStack\Actions\ActivityType;
use BookStack\Auth\Access\LoginService;
use BookStack\Auth\Access\Mfa\MfaSession;
use BookStack\Auth\Access\Mfa\MfaValue;
use BookStack\Auth\Access\Mfa\TotpService;
use BookStack\Auth\Access\Mfa\TotpValidationRule;
use BookStack\Access\LoginService;
use BookStack\Access\Mfa\MfaSession;
use BookStack\Access\Mfa\MfaValue;
use BookStack\Access\Mfa\TotpService;
use BookStack\Access\Mfa\TotpValidationRule;
use BookStack\Activity\ActivityType;
use BookStack\Exceptions\NotFoundException;
use BookStack\Http\Controllers\Controller;
use BookStack\Http\Controller;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
@@ -34,6 +34,8 @@ class MfaTotpController extends Controller
$qrCodeUrl = $totp->generateUrl($totpSecret, $this->currentOrLastAttemptedUser());
$svg = $totp->generateQrCodeSvg($qrCodeUrl);
$this->setPageTitle(trans('auth.mfa_gen_totp_title'));
return view('mfa.totp-generate', [
'url' => $qrCodeUrl,
'svg' => $svg,

View File

@@ -1,14 +1,15 @@
<?php
namespace BookStack\Http\Controllers\Auth;
namespace BookStack\Access\Controllers;
use BookStack\Auth\Access\Oidc\OidcService;
use BookStack\Http\Controllers\Controller;
use BookStack\Access\Oidc\OidcException;
use BookStack\Access\Oidc\OidcService;
use BookStack\Http\Controller;
use Illuminate\Http\Request;
class OidcController extends Controller
{
protected $oidcService;
protected OidcService $oidcService;
/**
* OpenIdController constructor.
@@ -24,7 +25,14 @@ class OidcController extends Controller
*/
public function login()
{
$loginDetails = $this->oidcService->login();
try {
$loginDetails = $this->oidcService->login();
} catch (OidcException $exception) {
$this->showErrorNotification($exception->getMessage());
return redirect('/login');
}
session()->flash('oidc_state', $loginDetails['state']);
return redirect($loginDetails['url']);
@@ -45,7 +53,13 @@ class OidcController extends Controller
return redirect('/login');
}
$this->oidcService->processAuthorizeResponse($request->query('code'));
try {
$this->oidcService->processAuthorizeResponse($request->query('code'));
} catch (OidcException $oidcException) {
$this->showErrorNotification($oidcException->getMessage());
return redirect('/login');
}
return redirect()->intended();
}

View File

@@ -1,45 +1,23 @@
<?php
namespace BookStack\Http\Controllers\Auth;
namespace BookStack\Access\Controllers;
use BookStack\Auth\Access\LoginService;
use BookStack\Auth\Access\RegistrationService;
use BookStack\Auth\Access\SocialAuthService;
use BookStack\Auth\User;
use BookStack\Access\LoginService;
use BookStack\Access\RegistrationService;
use BookStack\Access\SocialAuthService;
use BookStack\Exceptions\StoppedAuthenticationException;
use BookStack\Exceptions\UserRegistrationException;
use BookStack\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\RegistersUsers;
use BookStack\Http\Controller;
use Illuminate\Contracts\Validation\Validator as ValidatorContract;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\Password;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
protected $socialAuthService;
protected $registrationService;
protected $loginService;
/**
* Where to redirect users after login / registration.
*
* @var string
*/
protected $redirectTo = '/';
protected $redirectPath = '/';
protected SocialAuthService $socialAuthService;
protected RegistrationService $registrationService;
protected LoginService $loginService;
/**
* Create a new controller instance.
@@ -55,23 +33,6 @@ class RegisterController extends Controller
$this->socialAuthService = $socialAuthService;
$this->registrationService = $registrationService;
$this->loginService = $loginService;
$this->redirectTo = url('/');
$this->redirectPath = url('/');
}
/**
* Get a validator for an incoming registration request.
*
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'min:2', 'max:255'],
'email' => ['required', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'min:8'],
]);
}
/**
@@ -114,22 +75,18 @@ class RegisterController extends Controller
$this->showSuccessNotification(trans('auth.register_success'));
return redirect($this->redirectPath());
return redirect('/');
}
/**
* Create a new user instance after a valid registration.
*
* @param array $data
*
* @return User
* Get a validator for an incoming registration request.
*/
protected function create(array $data)
protected function validator(array $data): ValidatorContract
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
return Validator::make($data, [
'name' => ['required', 'min:2', 'max:100'],
'email' => ['required', 'email', 'max:255', 'unique:users'],
'password' => ['required', Password::default()],
]);
}
}

View File

@@ -0,0 +1,98 @@
<?php
namespace BookStack\Access\Controllers;
use BookStack\Access\LoginService;
use BookStack\Activity\ActivityType;
use BookStack\Http\Controller;
use BookStack\Users\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;
use Illuminate\Validation\Rules\Password as PasswordRule;
class ResetPasswordController extends Controller
{
protected LoginService $loginService;
public function __construct(LoginService $loginService)
{
$this->middleware('guest');
$this->middleware('guard:standard');
$this->loginService = $loginService;
}
/**
* Display the password reset view for the given token.
* If no token is present, display the link request form.
*/
public function showResetForm(Request $request)
{
$token = $request->route()->parameter('token');
return view('auth.passwords.reset')->with(
['token' => $token, 'email' => $request->email]
);
}
/**
* Reset the given user's password.
*/
public function reset(Request $request)
{
$request->validate([
'token' => 'required',
'email' => 'required|email',
'password' => ['required', 'confirmed', PasswordRule::defaults()],
]);
// Here we will attempt to reset the user's password. If it is successful we
// will update the password on an actual user model and persist it to the
// database. Otherwise we will parse the error and return the response.
$credentials = $request->only('email', 'password', 'password_confirmation', 'token');
$response = Password::broker()->reset($credentials, function (User $user, string $password) {
$user->password = Hash::make($password);
$user->setRememberToken(Str::random(60));
$user->save();
$this->loginService->login($user, auth()->getDefaultDriver());
});
// If the password was successfully reset, we will redirect the user back to
// the application's home authenticated view. If there is an error we can
// redirect them back to where they came from with their error message.
return $response === Password::PASSWORD_RESET
? $this->sendResetResponse()
: $this->sendResetFailedResponse($request, $response);
}
/**
* Get the response for a successful password reset.
*/
protected function sendResetResponse(): RedirectResponse
{
$this->showSuccessNotification(trans('auth.reset_password_success'));
$this->logActivity(ActivityType::AUTH_PASSWORD_RESET_UPDATE, user());
return redirect('/');
}
/**
* Get the response for a failed password reset.
*/
protected function sendResetFailedResponse(Request $request, string $response): RedirectResponse
{
// We show invalid users as invalid tokens as to not leak what
// users may exist in the system.
if ($response === Password::INVALID_USER) {
$response = Password::INVALID_TOKEN;
}
return redirect()->back()
->withInput($request->only('email'))
->withErrors(['email' => trans($response)]);
}
}

View File

@@ -1,15 +1,15 @@
<?php
namespace BookStack\Http\Controllers\Auth;
namespace BookStack\Access\Controllers;
use BookStack\Auth\Access\Saml2Service;
use BookStack\Http\Controllers\Controller;
use BookStack\Access\Saml2Service;
use BookStack\Http\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class Saml2Controller extends Controller
{
protected $samlService;
protected Saml2Service $samlService;
/**
* Saml2Controller constructor.

View File

@@ -1,24 +1,24 @@
<?php
namespace BookStack\Http\Controllers\Auth;
namespace BookStack\Access\Controllers;
use BookStack\Auth\Access\LoginService;
use BookStack\Auth\Access\RegistrationService;
use BookStack\Auth\Access\SocialAuthService;
use BookStack\Access\LoginService;
use BookStack\Access\RegistrationService;
use BookStack\Access\SocialAuthService;
use BookStack\Exceptions\SocialDriverNotConfigured;
use BookStack\Exceptions\SocialSignInAccountNotUsed;
use BookStack\Exceptions\SocialSignInException;
use BookStack\Exceptions\UserRegistrationException;
use BookStack\Http\Controllers\Controller;
use BookStack\Http\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Laravel\Socialite\Contracts\User as SocialUser;
class SocialController extends Controller
{
protected $socialAuthService;
protected $registrationService;
protected $loginService;
protected SocialAuthService $socialAuthService;
protected RegistrationService $registrationService;
protected LoginService $loginService;
/**
* SocialController constructor.
@@ -28,7 +28,7 @@ class SocialController extends Controller
RegistrationService $registrationService,
LoginService $loginService
) {
$this->middleware('guest')->only(['getRegister', 'postRegister']);
$this->middleware('guest')->only(['register']);
$this->socialAuthService = $socialAuthService;
$this->registrationService = $registrationService;
$this->loginService = $loginService;

View File

@@ -0,0 +1,92 @@
<?php
namespace BookStack\Access\Controllers;
use Illuminate\Cache\RateLimiter;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
trait ThrottlesLogins
{
/**
* Determine if the user has too many failed login attempts.
*/
protected function hasTooManyLoginAttempts(Request $request): bool
{
return $this->limiter()->tooManyAttempts(
$this->throttleKey($request),
$this->maxAttempts()
);
}
/**
* Increment the login attempts for the user.
*/
protected function incrementLoginAttempts(Request $request): void
{
$this->limiter()->hit(
$this->throttleKey($request),
$this->decayMinutes() * 60
);
}
/**
* Redirect the user after determining they are locked out.
* @throws ValidationException
*/
protected function sendLockoutResponse(Request $request): \Symfony\Component\HttpFoundation\Response
{
$seconds = $this->limiter()->availableIn(
$this->throttleKey($request)
);
throw ValidationException::withMessages([
$this->username() => [trans('auth.throttle', [
'seconds' => $seconds,
'minutes' => ceil($seconds / 60),
])],
])->status(Response::HTTP_TOO_MANY_REQUESTS);
}
/**
* Clear the login locks for the given user credentials.
*/
protected function clearLoginAttempts(Request $request): void
{
$this->limiter()->clear($this->throttleKey($request));
}
/**
* Get the throttle key for the given request.
*/
protected function throttleKey(Request $request): string
{
return Str::transliterate(Str::lower($request->input($this->username())) . '|' . $request->ip());
}
/**
* Get the rate limiter instance.
*/
protected function limiter(): RateLimiter
{
return app(RateLimiter::class);
}
/**
* Get the maximum number of attempts to allow.
*/
public function maxAttempts(): int
{
return 5;
}
/**
* Get the number of minutes to throttle for.
*/
public function decayMinutes(): int
{
return 1;
}
}

View File

@@ -1,21 +1,23 @@
<?php
namespace BookStack\Http\Controllers\Auth;
namespace BookStack\Access\Controllers;
use BookStack\Auth\Access\UserInviteService;
use BookStack\Auth\UserRepo;
use BookStack\Access\UserInviteService;
use BookStack\Exceptions\UserTokenExpiredException;
use BookStack\Exceptions\UserTokenNotFoundException;
use BookStack\Http\Controllers\Controller;
use BookStack\Http\Controller;
use BookStack\Users\UserRepo;
use Exception;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules\Password;
class UserInviteController extends Controller
{
protected $inviteService;
protected $userRepo;
protected UserInviteService $inviteService;
protected UserRepo $userRepo;
/**
* Create a new controller instance.
@@ -55,7 +57,7 @@ class UserInviteController extends Controller
public function setPassword(Request $request, string $token)
{
$this->validate($request, [
'password' => ['required', 'min:8'],
'password' => ['required', Password::default()],
]);
try {
@@ -65,7 +67,7 @@ class UserInviteController extends Controller
}
$user = $this->userRepo->getById($userId);
$user->password = bcrypt($request->get('password'));
$user->password = Hash::make($request->get('password'));
$user->email_confirmed = true;
$user->save();

View File

@@ -1,15 +1,15 @@
<?php
namespace BookStack\Auth\Access;
namespace BookStack\Access;
use BookStack\Auth\User;
use BookStack\Exceptions\ConfirmationEmailException;
use BookStack\Notifications\ConfirmEmail;
use BookStack\Users\Models\User;
class EmailConfirmationService extends UserTokenService
{
protected $tokenTable = 'email_confirmations';
protected $expiryTime = 24;
protected string $tokenTable = 'email_confirmations';
protected int $expiryTime = 24;
/**
* Create new confirmation for a user,

View File

@@ -1,6 +1,6 @@
<?php
namespace BookStack\Auth\Access;
namespace BookStack\Access;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\UserProvider;

View File

@@ -1,9 +1,9 @@
<?php
namespace BookStack\Auth\Access;
namespace BookStack\Access;
use BookStack\Auth\Role;
use BookStack\Auth\User;
use BookStack\Users\Models\Role;
use BookStack\Users\Models\User;
use Illuminate\Support\Collection;
class GroupSyncService
@@ -28,10 +28,8 @@ class GroupSyncService
*/
protected function externalIdMatchesGroupNames(string $externalId, array $groupNames): bool
{
$externalAuthIds = explode(',', strtolower($externalId));
foreach ($externalAuthIds as $externalAuthId) {
if (in_array(trim($externalAuthId), $groupNames)) {
foreach ($this->parseRoleExternalAuthId($externalId) as $externalAuthId) {
if (in_array($externalAuthId, $groupNames)) {
return true;
}
}
@@ -39,6 +37,18 @@ class GroupSyncService
return false;
}
protected function parseRoleExternalAuthId(string $externalId): array
{
$inputIds = preg_split('/(?<!\\\),/', strtolower($externalId));
$cleanIds = [];
foreach ($inputIds as $inputId) {
$cleanIds[] = str_replace('\,', ',', trim($inputId));
}
return $cleanIds;
}
/**
* Match an array of group names to BookStack system roles.
* Formats group names to be lower-case and hyphenated.

View File

@@ -1,6 +1,6 @@
<?php
namespace BookStack\Auth\Access\Guards;
namespace BookStack\Access\Guards;
/**
* Saml2 Session Guard.

View File

@@ -1,8 +1,8 @@
<?php
namespace BookStack\Auth\Access\Guards;
namespace BookStack\Access\Guards;
use BookStack\Auth\Access\RegistrationService;
use BookStack\Access\RegistrationService;
use Illuminate\Auth\GuardHelpers;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\StatefulGuard;

View File

@@ -1,21 +1,22 @@
<?php
namespace BookStack\Auth\Access\Guards;
namespace BookStack\Access\Guards;
use BookStack\Auth\Access\LdapService;
use BookStack\Auth\Access\RegistrationService;
use BookStack\Auth\User;
use BookStack\Access\LdapService;
use BookStack\Access\RegistrationService;
use BookStack\Exceptions\JsonDebugException;
use BookStack\Exceptions\LdapException;
use BookStack\Exceptions\LoginAttemptEmailNeededException;
use BookStack\Exceptions\LoginAttemptException;
use BookStack\Exceptions\UserRegistrationException;
use BookStack\Users\Models\User;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Session\Session;
use Illuminate\Support\Str;
class LdapSessionGuard extends ExternalBaseSessionGuard
{
protected $ldapService;
protected LdapService $ldapService;
/**
* LdapSessionGuard constructor.
@@ -59,8 +60,9 @@ class LdapSessionGuard extends ExternalBaseSessionGuard
* @param array $credentials
* @param bool $remember
*
* @throws LdapException*@throws \BookStack\Exceptions\JsonDebugException
* @throws LoginAttemptException
* @throws LdapException
* @throws JsonDebugException
*
* @return bool
*/
@@ -84,7 +86,7 @@ class LdapSessionGuard extends ExternalBaseSessionGuard
try {
$user = $this->createNewFromLdapAndCreds($userDetails, $credentials);
} catch (UserRegistrationException $exception) {
throw new LoginAttemptException($exception->message);
throw new LoginAttemptException($exception->getMessage());
}
}

110
app/Access/Ldap.php Normal file
View File

@@ -0,0 +1,110 @@
<?php
namespace BookStack\Access;
/**
* Class Ldap
* An object-orientated thin abstraction wrapper for common PHP LDAP functions.
* Allows the standard LDAP functions to be mocked for testing.
*/
class Ldap
{
/**
* Connect to an LDAP server.
*
* @return resource|\LDAP\Connection|false
*/
public function connect(string $hostName)
{
return ldap_connect($hostName);
}
/**
* Set the value of an LDAP option for the given connection.
*
* @param resource|\LDAP\Connection|null $ldapConnection
*/
public function setOption($ldapConnection, int $option, mixed $value): bool
{
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 resource|\LDAP\Connection $ldapConnection
*/
public function setVersion($ldapConnection, int $version): bool
{
return $this->setOption($ldapConnection, LDAP_OPT_PROTOCOL_VERSION, $version);
}
/**
* Search LDAP tree using the provided filter.
*
* @param resource|\LDAP\Connection $ldapConnection
*
* @return resource|\LDAP\Result
*/
public function search($ldapConnection, string $baseDn, string $filter, array $attributes = null)
{
return ldap_search($ldapConnection, $baseDn, $filter, $attributes);
}
/**
* Get entries from an LDAP search result.
*
* @param resource|\LDAP\Connection $ldapConnection
* @param resource|\LDAP\Result $ldapSearchResult
*/
public function getEntries($ldapConnection, $ldapSearchResult): array|false
{
return ldap_get_entries($ldapConnection, $ldapSearchResult);
}
/**
* Search and get entries immediately.
*
* @param resource|\LDAP\Connection $ldapConnection
*/
public function searchAndGetEntries($ldapConnection, string $baseDn, string $filter, array $attributes = null): array|false
{
$search = $this->search($ldapConnection, $baseDn, $filter, $attributes);
return $this->getEntries($ldapConnection, $search);
}
/**
* Bind to LDAP directory.
*
* @param resource|\LDAP\Connection $ldapConnection
*/
public function bind($ldapConnection, string $bindRdn = null, string $bindPassword = null): bool
{
return ldap_bind($ldapConnection, $bindRdn, $bindPassword);
}
/**
* Explode an LDAP dn string into an array of components.
*/
public function explodeDn(string $dn, int $withAttrib): array|false
{
return ldap_explode_dn($dn, $withAttrib);
}
/**
* Escape a string for use in an LDAP filter.
*/
public function escape(string $value, string $ignore = '', int $flags = 0): string
{
return ldap_escape($value, $ignore, $flags);
}
}

View File

@@ -1,11 +1,11 @@
<?php
namespace BookStack\Auth\Access;
namespace BookStack\Access;
use BookStack\Auth\User;
use BookStack\Exceptions\JsonDebugException;
use BookStack\Exceptions\LdapException;
use BookStack\Uploads\UserAvatars;
use BookStack\Users\Models\User;
use ErrorException;
use Illuminate\Support\Facades\Log;
@@ -15,21 +15,19 @@ use Illuminate\Support\Facades\Log;
*/
class LdapService
{
protected $ldap;
protected $groupSyncService;
protected $ldapConnection;
protected $userAvatars;
protected $config;
protected $enabled;
/**
* LdapService constructor.
* @var resource|\LDAP\Connection
*/
public function __construct(Ldap $ldap, UserAvatars $userAvatars, GroupSyncService $groupSyncService)
{
$this->ldap = $ldap;
$this->userAvatars = $userAvatars;
$this->groupSyncService = $groupSyncService;
protected $ldapConnection;
protected array $config;
protected bool $enabled;
public function __construct(
protected Ldap $ldap,
protected UserAvatars $userAvatars,
protected GroupSyncService $groupSyncService
) {
$this->config = config('services.ldap');
$this->enabled = config('auth.method') === 'ldap';
}
@@ -54,7 +52,7 @@ class LdapService
// Clean attributes
foreach ($attributes as $index => $attribute) {
if (strpos($attribute, 'BIN;') === 0) {
if (str_starts_with($attribute, 'BIN;')) {
$attributes[$index] = substr($attribute, strlen('BIN;'));
}
}
@@ -77,7 +75,7 @@ class LdapService
* Get the details of a user from LDAP using the given username.
* User found via configurable user filter.
*
* @throws LdapException
* @throws LdapException|JsonDebugException
*/
public function getUserDetails(string $userName): ?array
{
@@ -100,7 +98,7 @@ class LdapService
'name' => $this->getUserResponseProperty($user, $displayNameAttr, $userCn),
'dn' => $user['dn'],
'email' => $this->getUserResponseProperty($user, $emailAttr, null),
'avatar'=> $thumbnailAttr ? $this->getUserResponseProperty($user, $thumbnailAttr, null) : null,
'avatar' => $thumbnailAttr ? $this->getUserResponseProperty($user, $thumbnailAttr, null) : null,
];
if ($this->config['dump_user_details']) {
@@ -121,7 +119,7 @@ class LdapService
*/
protected function getUserResponseProperty(array $userDetails, string $propertyKey, $defaultValue)
{
$isBinary = strpos($propertyKey, 'BIN;') === 0;
$isBinary = str_starts_with($propertyKey, 'BIN;');
$propertyKey = strtolower($propertyKey);
$value = $defaultValue;
@@ -165,11 +163,11 @@ class LdapService
* Bind the system user to the LDAP connection using the given credentials
* otherwise anonymous access is attempted.
*
* @param resource $connection
* @param resource|\LDAP\Connection $connection
*
* @throws LdapException
*/
protected function bindSystemUser($connection)
protected function bindSystemUser($connection): void
{
$ldapDn = $this->config['dn'];
$ldapPass = $this->config['pass'];
@@ -192,7 +190,7 @@ class LdapService
*
* @throws LdapException
*
* @return resource
* @return resource|\LDAP\Connection
*/
protected function getConnection()
{
@@ -211,8 +209,8 @@ class LdapService
$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']);
$ldapHost = $this->parseServerString($this->config['server']);
$ldapConnection = $this->ldap->connect($ldapHost);
if ($ldapConnection === false) {
throw new LdapException(trans('errors.ldap_cannot_connect'));
@@ -237,23 +235,16 @@ class LdapService
}
/**
* Parse a LDAP server string and return the host and port for a connection.
* Parse an LDAP server string and return the host suitable for a connection.
* Is flexible to formats such as 'ldap.example.com:8069' or 'ldaps://ldap.example.com'.
*/
protected function parseServerString(string $serverString): array
protected function parseServerString(string $serverString): string
{
$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];
if (str_starts_with($serverString, 'ldaps://') || str_starts_with($serverString, 'ldap://')) {
return $serverString;
}
// Otherwise, extract the port out
$hostName = $serverNameParts[0];
$ldapPort = (count($serverNameParts) > 1) ? intval($serverNameParts[1]) : 389;
return ['host' => $hostName, 'port' => $ldapPort];
return "ldap://{$serverString}";
}
/**
@@ -274,6 +265,7 @@ class LdapService
* Get the groups a user is a part of on ldap.
*
* @throws LdapException
* @throws JsonDebugException
*/
public function getUserGroups(string $userName): array
{
@@ -285,8 +277,17 @@ class LdapService
}
$userGroups = $this->groupFilter($user);
$allGroups = $this->getGroupsRecursive($userGroups, []);
return $this->getGroupsRecursive($userGroups, []);
if ($this->config['dump_user_groups']) {
throw new JsonDebugException([
'details_from_ldap' => $user,
'parsed_direct_user_groups' => $userGroups,
'parsed_recursive_user_groups' => $allGroups,
]);
}
return $allGroups;
}
/**
@@ -369,8 +370,9 @@ class LdapService
* Sync the LDAP groups to the user roles for the current user.
*
* @throws LdapException
* @throws JsonDebugException
*/
public function syncGroups(User $user, string $username)
public function syncGroups(User $user, string $username): void
{
$userLdapGroups = $this->getUserGroups($username);
$this->groupSyncService->syncUserWithFoundGroups($user, $userLdapGroups, $this->config['remove_from_groups']);

View File

@@ -1,14 +1,15 @@
<?php
namespace BookStack\Auth\Access;
namespace BookStack\Access;
use BookStack\Actions\ActivityType;
use BookStack\Auth\Access\Mfa\MfaSession;
use BookStack\Auth\User;
use BookStack\Access\Mfa\MfaSession;
use BookStack\Activity\ActivityType;
use BookStack\Exceptions\LoginAttemptException;
use BookStack\Exceptions\StoppedAuthenticationException;
use BookStack\Facades\Activity;
use BookStack\Facades\Theme;
use BookStack\Theming\ThemeEvents;
use BookStack\Users\Models\User;
use Exception;
class LoginService
@@ -149,6 +150,7 @@ class LoginService
* May interrupt the flow if extra authentication requirements are imposed.
*
* @throws StoppedAuthenticationException
* @throws LoginAttemptException
*/
public function attempt(array $credentials, string $method, bool $remember = false): bool
{

View File

@@ -1,6 +1,6 @@
<?php
namespace BookStack\Auth\Access\Mfa;
namespace BookStack\Access\Mfa;
use Illuminate\Support\Str;

View File

@@ -1,8 +1,8 @@
<?php
namespace BookStack\Auth\Access\Mfa;
namespace BookStack\Access\Mfa;
use BookStack\Auth\User;
use BookStack\Users\Models\User;
class MfaSession
{

View File

@@ -1,8 +1,8 @@
<?php
namespace BookStack\Auth\Access\Mfa;
namespace BookStack\Access\Mfa;
use BookStack\Auth\User;
use BookStack\Users\Models\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;

View File

@@ -1,6 +1,6 @@
<?php
namespace BookStack\Auth\Access\Mfa;
namespace BookStack\Access\Mfa;
use BaconQrCode\Renderer\Color\Rgb;
use BaconQrCode\Renderer\Image\SvgImageBackEnd;
@@ -8,7 +8,7 @@ use BaconQrCode\Renderer\ImageRenderer;
use BaconQrCode\Renderer\RendererStyle\Fill;
use BaconQrCode\Renderer\RendererStyle\RendererStyle;
use BaconQrCode\Writer;
use BookStack\Auth\User;
use BookStack\Users\Models\User;
use PragmaRX\Google2FA\Google2FA;
use PragmaRX\Google2FA\Support\Constants;

View File

@@ -1,6 +1,6 @@
<?php
namespace BookStack\Auth\Access\Mfa;
namespace BookStack\Access\Mfa;
use Illuminate\Contracts\Validation\Rule;

View File

@@ -1,6 +1,6 @@
<?php
namespace BookStack\Auth\Access\Oidc;
namespace BookStack\Access\Oidc;
use InvalidArgumentException;
use League\OAuth2\Client\Token\AccessToken;

View File

@@ -0,0 +1,9 @@
<?php
namespace BookStack\Access\Oidc;
use Exception;
class OidcException extends Exception
{
}

View File

@@ -1,38 +1,19 @@
<?php
namespace BookStack\Auth\Access\Oidc;
namespace BookStack\Access\Oidc;
class OidcIdToken
{
/**
* @var array
*/
protected $header;
/**
* @var array
*/
protected $payload;
/**
* @var string
*/
protected $signature;
protected array $header;
protected array $payload;
protected string $signature;
protected string $issuer;
protected array $tokenParts = [];
/**
* @var array[]|string[]
*/
protected $keys;
/**
* @var string
*/
protected $issuer;
/**
* @var array
*/
protected $tokenParts = [];
protected array $keys;
public function __construct(string $token, string $issuer, array $keys)
{
@@ -106,6 +87,14 @@ class OidcIdToken
return $this->payload;
}
/**
* Replace the existing claim data of this token with that provided.
*/
public function replaceClaims(array $claims): void
{
$this->payload = $claims;
}
/**
* Validate the structure of the given token and ensure we have the required pieces.
* As per https://datatracker.ietf.org/doc/html/rfc7519#section-7.2.

View File

@@ -1,6 +1,6 @@
<?php
namespace BookStack\Auth\Access\Oidc;
namespace BookStack\Access\Oidc;
class OidcInvalidKeyException extends \Exception
{

View File

@@ -1,6 +1,6 @@
<?php
namespace BookStack\Auth\Access\Oidc;
namespace BookStack\Access\Oidc;
use Exception;

View File

@@ -0,0 +1,9 @@
<?php
namespace BookStack\Access\Oidc;
use Exception;
class OidcIssuerDiscoveryException extends Exception
{
}

View File

@@ -1,6 +1,6 @@
<?php
namespace BookStack\Auth\Access\Oidc;
namespace BookStack\Access\Oidc;
use phpseclib3\Crypt\Common\PublicKey;
use phpseclib3\Crypt\PublicKeyLoader;
@@ -60,15 +60,17 @@ class OidcJwtSigningKey
*/
protected function loadFromJwkArray(array $jwk)
{
if ($jwk['alg'] !== 'RS256') {
throw new OidcInvalidKeyException("Only RS256 keys are currently supported. Found key using {$jwk['alg']}");
// 'alg' is optional for a JWK, but we will still attempt to validate if
// it exists otherwise presume it will be compatible.
$alg = $jwk['alg'] ?? null;
if ($jwk['kty'] !== 'RSA' || !(is_null($alg) || $alg === 'RS256')) {
throw new OidcInvalidKeyException("Only RS256 keys are currently supported. Found key using {$alg}");
}
if (empty($jwk['use'])) {
throw new OidcInvalidKeyException('A "use" parameter on the provided key is expected');
}
if ($jwk['use'] !== 'sig') {
// 'use' is optional for a JWK but we assume 'sig' where no value exists since that's what
// the OIDC discovery spec infers since 'sig' MUST be set if encryption keys come into play.
$use = $jwk['use'] ?? 'sig';
if ($use !== 'sig') {
throw new OidcInvalidKeyException("Only signature keys are currently supported. Found key for use {$jwk['use']}");
}

View File

@@ -1,6 +1,6 @@
<?php
namespace BookStack\Auth\Access\Oidc;
namespace BookStack\Access\Oidc;
use League\OAuth2\Client\Grant\AbstractGrant;
use League\OAuth2\Client\Provider\AbstractProvider;
@@ -30,6 +30,11 @@ class OidcOAuthProvider extends AbstractProvider
*/
protected $tokenEndpoint;
/**
* Scopes to use for the OIDC authorization call.
*/
protected array $scopes = ['openid', 'profile', 'email'];
/**
* Returns the base URL for authorizing a client.
*/
@@ -54,6 +59,15 @@ class OidcOAuthProvider extends AbstractProvider
return '';
}
/**
* Add an additional scope to this provider upon the default.
*/
public function addScope(string $scope): void
{
$this->scopes[] = $scope;
$this->scopes = array_unique($this->scopes);
}
/**
* Returns the default scopes used by this provider.
*
@@ -62,7 +76,7 @@ class OidcOAuthProvider extends AbstractProvider
*/
protected function getDefaultScopes(): array
{
return ['openid', 'profile', 'email'];
return $this->scopes;
}
/**

View File

@@ -1,6 +1,6 @@
<?php
namespace BookStack\Auth\Access\Oidc;
namespace BookStack\Access\Oidc;
use GuzzleHttp\Psr7\Request;
use Illuminate\Contracts\Cache\Repository;
@@ -15,40 +15,17 @@ use Psr\Http\Client\ClientInterface;
*/
class OidcProviderSettings
{
/**
* @var string
*/
public $issuer;
/**
* @var string
*/
public $clientId;
/**
* @var string
*/
public $clientSecret;
/**
* @var string
*/
public $redirectUri;
/**
* @var string
*/
public $authorizationEndpoint;
/**
* @var string
*/
public $tokenEndpoint;
public string $issuer;
public string $clientId;
public string $clientSecret;
public ?string $redirectUri;
public ?string $authorizationEndpoint;
public ?string $tokenEndpoint;
/**
* @var string[]|array[]
*/
public $keys = [];
public ?array $keys = [];
public function __construct(array $settings)
{
@@ -164,7 +141,10 @@ class OidcProviderSettings
protected function filterKeys(array $keys): array
{
return array_filter($keys, function (array $key) {
return $key['kty'] === 'RSA' && $key['use'] === 'sig' && $key['alg'] === 'RS256';
$alg = $key['alg'] ?? 'RS256';
$use = $key['use'] ?? 'sig';
return $key['kty'] === 'RSA' && $use === 'sig' && $alg === 'RS256';
});
}

View File

@@ -1,23 +1,21 @@
<?php
namespace BookStack\Auth\Access\Oidc;
namespace BookStack\Access\Oidc;
use function auth;
use BookStack\Auth\Access\LoginService;
use BookStack\Auth\Access\RegistrationService;
use BookStack\Auth\User;
use BookStack\Access\GroupSyncService;
use BookStack\Access\LoginService;
use BookStack\Access\RegistrationService;
use BookStack\Exceptions\JsonDebugException;
use BookStack\Exceptions\OpenIdConnectException;
use BookStack\Exceptions\StoppedAuthenticationException;
use BookStack\Exceptions\UserRegistrationException;
use function config;
use Exception;
use BookStack\Facades\Theme;
use BookStack\Theming\ThemeEvents;
use BookStack\Users\Models\User;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use League\OAuth2\Client\OptionProvider\HttpBasicAuthOptionProvider;
use Psr\Http\Client\ClientExceptionInterface;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use Psr\Http\Client\ClientInterface as HttpClient;
use function trans;
use function url;
/**
* Class OpenIdConnectService
@@ -25,30 +23,25 @@ use function url;
*/
class OidcService
{
protected $registrationService;
protected $loginService;
protected $httpClient;
/**
* OpenIdService constructor.
*/
public function __construct(RegistrationService $registrationService, LoginService $loginService, HttpClient $httpClient)
{
$this->registrationService = $registrationService;
$this->loginService = $loginService;
$this->httpClient = $httpClient;
public function __construct(
protected RegistrationService $registrationService,
protected LoginService $loginService,
protected HttpClient $httpClient,
protected GroupSyncService $groupService
) {
}
/**
* Initiate an authorization flow.
*
* @throws OidcException
*
* @return array{url: string, state: string}
*/
public function login(): array
{
$settings = $this->getProviderSettings();
$provider = $this->getProvider($settings);
return [
'url' => $provider->getAuthorizationUrl(),
'state' => $provider->getState(),
@@ -57,14 +50,15 @@ class OidcService
/**
* Process the Authorization response from the authorization server and
* return the matching, or new if registration active, user matched to
* the authorization server.
* Returns null if not authenticated.
* return the matching, or new if registration active, user matched to the
* authorization server. Throws if the user cannot be auth if not authenticated.
*
* @throws Exception
* @throws ClientExceptionInterface
* @throws JsonDebugException
* @throws OidcException
* @throws StoppedAuthenticationException
* @throws IdentityProviderException
*/
public function processAuthorizeResponse(?string $authorizationCode): ?User
public function processAuthorizeResponse(?string $authorizationCode): User
{
$settings = $this->getProviderSettings();
$provider = $this->getProvider($settings);
@@ -78,8 +72,7 @@ class OidcService
}
/**
* @throws OidcIssuerDiscoveryException
* @throws ClientExceptionInterface
* @throws OidcException
*/
protected function getProviderSettings(): OidcProviderSettings
{
@@ -100,7 +93,11 @@ class OidcService
// Run discovery
if ($config['discover'] ?? false) {
$settings->discoverFromIssuer($this->httpClient, Cache::store(null), 15);
try {
$settings->discoverFromIssuer($this->httpClient, Cache::store(null), 15);
} catch (OidcIssuerDiscoveryException $exception) {
throw new OidcException('OIDC Discovery Error: ' . $exception->getMessage());
}
}
$settings->validate();
@@ -113,10 +110,31 @@ class OidcService
*/
protected function getProvider(OidcProviderSettings $settings): OidcOAuthProvider
{
return new OidcOAuthProvider($settings->arrayForProvider(), [
$provider = new OidcOAuthProvider($settings->arrayForProvider(), [
'httpClient' => $this->httpClient,
'optionProvider' => new HttpBasicAuthOptionProvider(),
]);
foreach ($this->getAdditionalScopes() as $scope) {
$provider->addScope($scope);
}
return $provider;
}
/**
* Get any user-defined addition/custom scopes to apply to the authentication request.
*
* @return string[]
*/
protected function getAdditionalScopes(): array
{
$scopeConfig = $this->config()['additional_scopes'] ?: '';
$scopeArr = explode(',', $scopeConfig);
$scopeArr = array_map(fn (string $scope) => trim($scope), $scopeArr);
return array_filter($scopeArr);
}
/**
@@ -141,19 +159,43 @@ class OidcService
return implode(' ', $displayName);
}
/**
* Extract the assigned groups from the id token.
*
* @return string[]
*/
protected function getUserGroups(OidcIdToken $token): array
{
$groupsAttr = $this->config()['groups_claim'];
if (empty($groupsAttr)) {
return [];
}
$groupsList = Arr::get($token->getAllClaims(), $groupsAttr);
if (!is_array($groupsList)) {
return [];
}
return array_values(array_filter($groupsList, function ($val) {
return is_string($val);
}));
}
/**
* Extract the details of a user from an ID token.
*
* @return array{name: string, email: string, external_id: string}
* @return array{name: string, email: string, external_id: string, groups: string[]}
*/
protected function getUserDetails(OidcIdToken $token): array
{
$id = $token->getClaim('sub');
$idClaim = $this->config()['external_id_claim'];
$id = $token->getClaim($idClaim);
return [
'external_id' => $id,
'email' => $token->getClaim('email'),
'name' => $this->getUserDisplayName($token, $id),
'groups' => $this->getUserGroups($token),
];
}
@@ -161,9 +203,8 @@ class OidcService
* Processes a received access token for a user. Login the user when
* they exist, optionally registering them automatically.
*
* @throws OpenIdConnectException
* @throws OidcException
* @throws JsonDebugException
* @throws UserRegistrationException
* @throws StoppedAuthenticationException
*/
protected function processAccessTokenCallback(OidcAccessToken $accessToken, OidcProviderSettings $settings): User
@@ -175,6 +216,16 @@ class OidcService
$settings->keys,
);
$returnClaims = Theme::dispatch(ThemeEvents::OIDC_ID_TOKEN_PRE_VALIDATE, $idToken->getAllClaims(), [
'access_token' => $accessToken->getToken(),
'expires_in' => $accessToken->getExpires(),
'refresh_token' => $accessToken->getRefreshToken(),
]);
if (!is_null($returnClaims)) {
$idToken->replaceClaims($returnClaims);
}
if ($this->config()['dump_user_details']) {
throw new JsonDebugException($idToken->getAllClaims());
}
@@ -182,28 +233,34 @@ class OidcService
try {
$idToken->validate($settings->clientId);
} catch (OidcInvalidTokenException $exception) {
throw new OpenIdConnectException("ID token validate failed with error: {$exception->getMessage()}");
throw new OidcException("ID token validate failed with error: {$exception->getMessage()}");
}
$userDetails = $this->getUserDetails($idToken);
$isLoggedIn = auth()->check();
if (empty($userDetails['email'])) {
throw new OpenIdConnectException(trans('errors.oidc_no_email_address'));
throw new OidcException(trans('errors.oidc_no_email_address'));
}
if ($isLoggedIn) {
throw new OpenIdConnectException(trans('errors.oidc_already_logged_in'), '/login');
throw new OidcException(trans('errors.oidc_already_logged_in'));
}
$user = $this->registrationService->findOrRegister(
$userDetails['name'],
$userDetails['email'],
$userDetails['external_id']
);
try {
$user = $this->registrationService->findOrRegister(
$userDetails['name'],
$userDetails['email'],
$userDetails['external_id']
);
} catch (UserRegistrationException $exception) {
throw new OidcException($exception->getMessage());
}
if ($user === null) {
throw new OpenIdConnectException(trans('errors.oidc_user_not_registered', ['name' => $userDetails['external_id']]), '/login');
if ($this->shouldSyncGroups()) {
$groups = $userDetails['groups'];
$detachExisting = $this->config()['remove_from_groups'];
$this->groupService->syncUserWithFoundGroups($user, $groups, $detachExisting);
}
$this->loginService->login($user, 'oidc');
@@ -218,4 +275,12 @@ class OidcService
{
return config('oidc');
}
/**
* Check if groups should be synced.
*/
protected function shouldSyncGroups(): bool
{
return $this->config()['user_to_groups'] !== false;
}
}

View File

@@ -1,15 +1,14 @@
<?php
namespace BookStack\Auth\Access;
namespace BookStack\Access;
use BookStack\Actions\ActivityType;
use BookStack\Auth\SocialAccount;
use BookStack\Auth\User;
use BookStack\Auth\UserRepo;
use BookStack\Activity\ActivityType;
use BookStack\Exceptions\UserRegistrationException;
use BookStack\Facades\Activity;
use BookStack\Facades\Theme;
use BookStack\Theming\ThemeEvents;
use BookStack\Users\Models\User;
use BookStack\Users\UserRepo;
use Exception;
use Illuminate\Support\Str;
@@ -96,7 +95,8 @@ class RegistrationService
}
// Create the user
$newUser = $this->userRepo->registerNew($userData, $emailConfirmed);
$newUser = $this->userRepo->createWithoutActivity($userData, $emailConfirmed);
$newUser->attachDefaultRole();
// Assign social account if given
if ($socialAccount) {

View File

@@ -1,12 +1,12 @@
<?php
namespace BookStack\Auth\Access;
namespace BookStack\Access;
use BookStack\Auth\User;
use BookStack\Exceptions\JsonDebugException;
use BookStack\Exceptions\SamlException;
use BookStack\Exceptions\StoppedAuthenticationException;
use BookStack\Exceptions\UserRegistrationException;
use BookStack\Users\Models\User;
use Exception;
use OneLogin\Saml2\Auth;
use OneLogin\Saml2\Constants;
@@ -20,14 +20,11 @@ use OneLogin\Saml2\ValidationError;
*/
class Saml2Service
{
protected $config;
protected $registrationService;
protected $loginService;
protected $groupSyncService;
protected array $config;
protected RegistrationService $registrationService;
protected LoginService $loginService;
protected GroupSyncService $groupSyncService;
/**
* Saml2Service constructor.
*/
public function __construct(
RegistrationService $registrationService,
LoginService $loginService,
@@ -70,7 +67,7 @@ class Saml2Service
$returnRoute,
[],
$user->email,
null,
session()->get('saml2_session_index'),
true,
Constants::NAMEID_EMAIL_ADDRESS
);
@@ -109,9 +106,10 @@ class Saml2Service
$errors = $toolkit->getErrors();
if (!empty($errors)) {
throw new Error(
'Invalid ACS Response: ' . implode(', ', $errors)
);
$reason = $toolkit->getLastErrorReason();
$message = 'Invalid ACS Response; Errors: ' . implode(', ', $errors);
$message .= $reason ? "; Reason: {$reason}" : '';
throw new Error($message);
}
if (!$toolkit->isAuthenticated()) {
@@ -120,6 +118,7 @@ class Saml2Service
$attrs = $toolkit->getAttributes();
$id = $toolkit->getNameId();
session()->put('saml2_session_index', $toolkit->getSessionIndex());
return $this->processLoginCallback($id, $attrs);
}
@@ -168,7 +167,7 @@ class Saml2Service
*/
public function metadata(): string
{
$toolKit = $this->getToolkit();
$toolKit = $this->getToolkit(true);
$settings = $toolKit->getSettings();
$metadata = $settings->getSPMetadata();
$errors = $settings->validateMetadata($metadata);
@@ -189,7 +188,7 @@ class Saml2Service
* @throws Error
* @throws Exception
*/
protected function getToolkit(): Auth
protected function getToolkit(bool $spOnly = false): Auth
{
$settings = $this->config['onelogin'];
$overrides = $this->config['onelogin_overrides'] ?? [];
@@ -199,14 +198,14 @@ class Saml2Service
}
$metaDataSettings = [];
if ($this->config['autoload_from_metadata']) {
if (!$spOnly && $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);
return new Auth($settings, $spOnly);
}
/**

View File

@@ -1,9 +1,10 @@
<?php
namespace BookStack\Auth;
namespace BookStack\Access;
use BookStack\Interfaces\Loggable;
use BookStack\Model;
use BookStack\Activity\Models\Loggable;
use BookStack\App\Model;
use BookStack\Users\Models\User;
/**
* Class SocialAccount.

View File

@@ -1,12 +1,12 @@
<?php
namespace BookStack\Auth\Access;
namespace BookStack\Access;
use BookStack\Auth\SocialAccount;
use BookStack\Auth\User;
use BookStack\Auth\Access\handler;
use BookStack\Exceptions\SocialDriverNotConfigured;
use BookStack\Exceptions\SocialSignInAccountNotUsed;
use BookStack\Exceptions\UserRegistrationException;
use BookStack\Users\Models\User;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Str;
use Laravel\Socialite\Contracts\Factory as Socialite;

View File

@@ -1,20 +1,18 @@
<?php
namespace BookStack\Auth\Access;
namespace BookStack\Access;
use BookStack\Auth\User;
use BookStack\Notifications\UserInvite;
use BookStack\Users\Models\User;
class UserInviteService extends UserTokenService
{
protected $tokenTable = 'user_invites';
protected $expiryTime = 336; // Two weeks
protected string $tokenTable = 'user_invites';
protected int $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)
{

View File

@@ -1,10 +1,10 @@
<?php
namespace BookStack\Auth\Access;
namespace BookStack\Access;
use BookStack\Auth\User;
use BookStack\Exceptions\UserTokenExpiredException;
use BookStack\Exceptions\UserTokenNotFoundException;
use BookStack\Users\Models\User;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
@@ -14,41 +14,29 @@ class UserTokenService
{
/**
* Name of table where user tokens are stored.
*
* @var string
*/
protected $tokenTable = 'user_tokens';
protected string $tokenTable = 'user_tokens';
/**
* Token expiry time in hours.
*
* @var int
*/
protected $expiryTime = 24;
protected int $expiryTime = 24;
/**
* Delete all email confirmations that belong to a user.
*
* @param User $user
*
* @return mixed
* Delete all tokens that belong to a user.
*/
public function deleteByUser(User $user)
public function deleteByUser(User $user): void
{
return DB::table($this->tokenTable)
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
* Get the user id from a token, while checking the token exists and has not expired.
*
* @throws UserTokenNotFoundException
* @throws UserTokenExpiredException
*
* @return int
*/
public function checkTokenAndGetUserId(string $token): int
{
@@ -67,8 +55,6 @@ class UserTokenService
/**
* Creates a unique token within the email confirmation database.
*
* @return string
*/
protected function generateToken(): string
{
@@ -82,10 +68,6 @@ class UserTokenService
/**
* Generate and store a token for the given user.
*
* @param User $user
*
* @return string
*/
protected function createTokenForUser(User $user): string
{
@@ -102,10 +84,6 @@ class UserTokenService
/**
* Check if the given token exists.
*
* @param string $token
*
* @return bool
*/
protected function tokenExists(string $token): bool
{
@@ -115,12 +93,8 @@ class UserTokenService
/**
* Get a token entry for the given token.
*
* @param string $token
*
* @return object|null
*/
protected function getEntryByToken(string $token)
protected function getEntryByToken(string $token): ?stdClass
{
return DB::table($this->tokenTable)
->where('token', '=', $token)
@@ -129,10 +103,6 @@ class UserTokenService
/**
* Check if the given token entry has expired.
*
* @param stdClass $tokenEntry
*
* @return bool
*/
protected function entryExpired(stdClass $tokenEntry): bool
{

View File

@@ -1,201 +0,0 @@
<?php
namespace BookStack\Actions;
use BookStack\Auth\Permissions\PermissionService;
use BookStack\Auth\User;
use BookStack\Entities\Models\Book;
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
{
$ip = request()->ip() ?? '';
return $this->activity->newInstance()->forceFill([
'type' => strtolower($type),
'user_id' => user()->id,
'ip' => config('app.env') === 'demo' ? '127.0.0.1' : $ip,
]);
}
/**
* 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 array<string, int[]> $queryIds */
$queryIds = [$entity->getMorphClass() => [$entity->id]];
if ($entity instanceof Book) {
$queryIds[(new Chapter())->getMorphClass()] = $entity->chapters()->scopes('visible')->pluck('id');
}
if ($entity instanceof Book || $entity instanceof Chapter) {
$queryIds[(new Page())->getMorphClass()] = $entity->pages()->scopes('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 the 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

@@ -1,19 +0,0 @@
<?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();
}
}

View File

@@ -0,0 +1,113 @@
<?php
namespace BookStack\Activity;
use BookStack\Activity\Models\Activity;
use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Models\Entity;
use BookStack\Entities\Models\Page;
use BookStack\Permissions\PermissionApplicator;
use BookStack\Users\Models\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\Relation;
class ActivityQueries
{
protected PermissionApplicator $permissions;
public function __construct(PermissionApplicator $permissions)
{
$this->permissions = $permissions;
}
/**
* Gets the latest activity.
*/
public function latest(int $count = 20, int $page = 0): array
{
$activityList = $this->permissions
->restrictEntityRelationQuery(Activity::query(), '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 array<string, int[]> $queryIds */
$queryIds = [$entity->getMorphClass() => [$entity->id]];
if ($entity instanceof Book) {
$queryIds[(new Chapter())->getMorphClass()] = $entity->chapters()->scopes('visible')->pluck('id');
}
if ($entity instanceof Book || $entity instanceof Chapter) {
$queryIds[(new Page())->getMorphClass()] = $entity->pages()->scopes('visible')->pluck('id');
}
$query = Activity::query();
$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 the latest activity for a user, Filtering out similar items.
*/
public function userActivity(User $user, int $count = 20, int $page = 0): array
{
$activityList = $this->permissions
->restrictEntityRelationQuery(Activity::query(), '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
*/
protected function filterSimilar(iterable $activities): array
{
$newActivity = [];
$previousItem = null;
foreach ($activities as $activityItem) {
if (!$previousItem || !$activityItem->isSimilarTo($previousItem)) {
$newActivity[] = $activityItem;
}
$previousItem = $activityItem;
}
return $newActivity;
}
}

View File

@@ -1,6 +1,6 @@
<?php
namespace BookStack\Actions;
namespace BookStack\Activity;
class ActivityType
{
@@ -16,17 +16,26 @@ class ActivityType
const CHAPTER_MOVE = 'chapter_move';
const BOOK_CREATE = 'book_create';
const BOOK_CREATE_FROM_CHAPTER = 'book_create_from_chapter';
const BOOK_UPDATE = 'book_update';
const BOOK_DELETE = 'book_delete';
const BOOK_SORT = 'book_sort';
const BOOKSHELF_CREATE = 'bookshelf_create';
const BOOKSHELF_CREATE_FROM_BOOK = 'bookshelf_create_from_book';
const BOOKSHELF_UPDATE = 'bookshelf_update';
const BOOKSHELF_DELETE = 'bookshelf_delete';
const COMMENTED_ON = 'commented_on';
const COMMENT_CREATE = 'comment_create';
const COMMENT_UPDATE = 'comment_update';
const COMMENT_DELETE = 'comment_delete';
const PERMISSIONS_UPDATE = 'permissions_update';
const REVISION_RESTORE = 'revision_restore';
const REVISION_DELETE = 'revision_delete';
const SETTINGS_UPDATE = 'settings_update';
const MAINTENANCE_ACTION_RUN = 'maintenance_action_run';
@@ -53,4 +62,16 @@ class ActivityType
const MFA_SETUP_METHOD = 'mfa_setup_method';
const MFA_REMOVE_METHOD = 'mfa_remove_method';
const WEBHOOK_CREATE = 'webhook_create';
const WEBHOOK_UPDATE = 'webhook_update';
const WEBHOOK_DELETE = 'webhook_delete';
/**
* Get all the possible values.
*/
public static function all(): array
{
return (new \ReflectionClass(static::class))->getConstants();
}
}

View File

@@ -1,32 +1,20 @@
<?php
namespace BookStack\Actions;
namespace BookStack\Activity;
use BookStack\Activity\Models\Comment;
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);
return Comment::query()->findOrFail($id);
}
/**
@@ -35,7 +23,7 @@ class CommentRepo
public function create(Entity $entity, string $text, ?int $parent_id): Comment
{
$userId = user()->id;
$comment = $this->comment->newInstance();
$comment = new Comment();
$comment->text = $text;
$comment->html = $this->commentToHtml($text);
@@ -45,7 +33,8 @@ class CommentRepo
$comment->parent_id = $parent_id;
$entity->comments()->save($comment);
ActivityService::addForEntity($entity, ActivityType::COMMENTED_ON);
ActivityService::add(ActivityType::COMMENT_CREATE, $comment);
ActivityService::add(ActivityType::COMMENTED_ON, $entity);
return $comment;
}
@@ -60,6 +49,8 @@ class CommentRepo
$comment->html = $this->commentToHtml($text);
$comment->save();
ActivityService::add(ActivityType::COMMENT_UPDATE, $comment);
return $comment;
}
@@ -69,6 +60,8 @@ class CommentRepo
public function delete(Comment $comment): void
{
$comment->delete();
ActivityService::add(ActivityType::COMMENT_DELETE, $comment);
}
/**
@@ -82,7 +75,7 @@ class CommentRepo
'allow_unsafe_links' => false,
]);
return $converter->convertToHtml($commentText);
return $converter->convert($commentText);
}
/**
@@ -90,9 +83,8 @@ class CommentRepo
*/
protected function getNextLocalId(Entity $entity): int
{
/** @var Comment $comment */
$comment = $entity->comments(false)->orderBy('local_id', 'desc')->first();
$currentMaxId = $entity->comments()->max('local_id');
return ($comment->local_id ?? 0) + 1;
return $currentMaxId + 1;
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace BookStack\Activity\Controllers;
use BookStack\Activity\ActivityType;
use BookStack\Activity\Models\Activity;
use BookStack\Http\Controller;
use BookStack\Util\SimpleListOptions;
use Illuminate\Http\Request;
class AuditLogController extends Controller
{
public function index(Request $request)
{
$this->checkPermission('settings-manage');
$this->checkPermission('users-manage');
$sort = $request->get('sort', 'activity_date');
$order = $request->get('order', 'desc');
$listOptions = (new SimpleListOptions('', $sort, $order))->withSortOptions([
'created_at' => trans('settings.audit_table_date'),
'type' => trans('settings.audit_table_event'),
]);
$filters = [
'event' => $request->get('event', ''),
'date_from' => $request->get('date_from', ''),
'date_to' => $request->get('date_to', ''),
'user' => $request->get('user', ''),
'ip' => $request->get('ip', ''),
];
$query = Activity::query()
->with([
'entity' => fn ($query) => $query->withTrashed(),
'user',
])
->orderBy($listOptions->getSort(), $listOptions->getOrder());
if ($filters['event']) {
$query->where('type', '=', $filters['event']);
}
if ($filters['user']) {
$query->where('user_id', '=', $filters['user']);
}
if ($filters['date_from']) {
$query->where('created_at', '>=', $filters['date_from']);
}
if ($filters['date_to']) {
$query->where('created_at', '<=', $filters['date_to']);
}
if ($filters['ip']) {
$query->where('ip', 'like', $filters['ip'] . '%');
}
$activities = $query->paginate(100);
$activities->appends($request->all());
$types = ActivityType::all();
$this->setPageTitle(trans('settings.audit'));
return view('settings.audit', [
'activities' => $activities,
'filters' => $filters,
'listOptions' => $listOptions,
'activityTypes' => $types,
]);
}
}

View File

@@ -1,19 +1,18 @@
<?php
namespace BookStack\Http\Controllers;
namespace BookStack\Activity\Controllers;
use BookStack\Actions\CommentRepo;
use BookStack\Activity\CommentRepo;
use BookStack\Entities\Models\Page;
use BookStack\Http\Controller;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
class CommentController extends Controller
{
protected $commentRepo;
public function __construct(CommentRepo $commentRepo)
{
$this->commentRepo = $commentRepo;
public function __construct(
protected CommentRepo $commentRepo
) {
}
/**
@@ -42,7 +41,13 @@ class CommentController extends Controller
$this->checkPermission('comment-create-all');
$comment = $this->commentRepo->create($page, $request->get('text'), $request->get('parent_id'));
return view('comments.comment', ['comment' => $comment]);
return view('comments.comment-branch', [
'readOnly' => false,
'branch' => [
'comment' => $comment,
'children' => [],
]
]);
}
/**
@@ -62,7 +67,7 @@ class CommentController extends Controller
$comment = $this->commentRepo->update($comment, $request->get('text'));
return view('comments.comment', ['comment' => $comment]);
return view('comments.comment', ['comment' => $comment, 'readOnly' => false]);
}
/**

View File

@@ -1,11 +1,12 @@
<?php
namespace BookStack\Http\Controllers;
namespace BookStack\Activity\Controllers;
use BookStack\Activity\Models\Favouritable;
use BookStack\App\Model;
use BookStack\Entities\Models\Entity;
use BookStack\Entities\Queries\TopFavourites;
use BookStack\Interfaces\Favouritable;
use BookStack\Model;
use BookStack\Http\Controller;
use Illuminate\Http\Request;
class FavouriteController extends Controller
@@ -21,6 +22,8 @@ class FavouriteController extends Controller
$hasMoreLink = ($favourites->count() > $viewCount) ? url('/favourites?page=' . ($page + 1)) : null;
$this->setPageTitle(trans('entities.my_favourites'));
return view('common.detailed-listing-with-more', [
'title' => trans('entities.my_favourites'),
'entities' => $favourites->slice(0, $viewCount),
@@ -85,7 +88,7 @@ class FavouriteController extends Controller
$modelInstance = $model->newQuery()
->where('id', '=', $modelInfo['id'])
->first(['id', 'name']);
->first(['id', 'name', 'owned_by']);
$inaccessibleEntity = ($modelInstance instanceof Entity && !userCan('view', $modelInstance));
if (is_null($modelInstance) || $inaccessibleEntity) {

View File

@@ -1,20 +1,17 @@
<?php
namespace BookStack\Http\Controllers;
namespace BookStack\Activity\Controllers;
use BookStack\Actions\TagRepo;
use BookStack\Activity\TagRepo;
use BookStack\Http\Controller;
use BookStack\Util\SimpleListOptions;
use Illuminate\Http\Request;
class TagController extends Controller
{
protected $tagRepo;
/**
* TagController constructor.
*/
public function __construct(TagRepo $tagRepo)
{
$this->tagRepo = $tagRepo;
public function __construct(
protected TagRepo $tagRepo
) {
}
/**
@@ -22,20 +19,25 @@ class TagController extends Controller
*/
public function index(Request $request)
{
$search = $request->get('search', '');
$listOptions = SimpleListOptions::fromRequest($request, 'tags')->withSortOptions([
'name' => trans('common.sort_name'),
'usages' => trans('entities.tags_usages'),
]);
$nameFilter = $request->get('name', '');
$tags = $this->tagRepo
->queryWithTotals($search, $nameFilter)
->queryWithTotals($listOptions, $nameFilter)
->paginate(50)
->appends(array_filter([
'search' => $search,
->appends(array_filter(array_merge($listOptions->getPaginationAppends(), [
'name' => $nameFilter,
]));
])));
$this->setPageTitle(trans('entities.tags'));
return view('tags.index', [
'tags' => $tags,
'search' => $search,
'nameFilter' => $nameFilter,
'tags' => $tags,
'nameFilter' => $nameFilter,
'listOptions' => $listOptions,
]);
}
@@ -44,7 +46,7 @@ class TagController extends Controller
*/
public function getNameSuggestions(Request $request)
{
$searchTerm = $request->get('search', null);
$searchTerm = $request->get('search', '');
$suggestions = $this->tagRepo->getNameSuggestions($searchTerm);
return response()->json($suggestions);
@@ -55,8 +57,8 @@ class TagController extends Controller
*/
public function getValueSuggestions(Request $request)
{
$searchTerm = $request->get('search', null);
$tagName = $request->get('name', null);
$searchTerm = $request->get('search', '');
$tagName = $request->get('name', '');
$suggestions = $this->tagRepo->getValueSuggestions($searchTerm, $tagName);
return response()->json($suggestions);

View File

@@ -0,0 +1,65 @@
<?php
namespace BookStack\Activity\Controllers;
use BookStack\Activity\Tools\UserEntityWatchOptions;
use BookStack\App\Model;
use BookStack\Entities\Models\Entity;
use BookStack\Http\Controller;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
class WatchController extends Controller
{
public function update(Request $request)
{
$this->checkPermission('receive-notifications');
$this->preventGuestAccess();
$requestData = $this->validate($request, [
'level' => ['required', 'string'],
]);
$watchable = $this->getValidatedModelFromRequest($request);
$watchOptions = new UserEntityWatchOptions(user(), $watchable);
$watchOptions->updateLevelByName($requestData['level']);
$this->showSuccessNotification(trans('activities.watch_update_level_notification'));
return redirect()->back();
}
/**
* @throws ValidationException
* @throws Exception
*/
protected function getValidatedModelFromRequest(Request $request): Entity
{
$modelInfo = $this->validate($request, [
'type' => ['required', 'string'],
'id' => ['required', 'integer'],
]);
if (!class_exists($modelInfo['type'])) {
throw new Exception('Model not found');
}
/** @var Model $model */
$model = new $modelInfo['type']();
if (!$model instanceof Entity) {
throw new Exception('Model not an entity');
}
$modelInstance = $model->newQuery()
->where('id', '=', $modelInfo['id'])
->first(['id', 'name', 'owned_by']);
$inaccessibleEntity = ($modelInstance instanceof Entity && !userCan('view', $modelInstance));
if (is_null($modelInstance) || $inaccessibleEntity) {
throw new Exception('Model instance not found');
}
return $modelInstance;
}
}

View File

@@ -0,0 +1,146 @@
<?php
namespace BookStack\Activity\Controllers;
use BookStack\Activity\ActivityType;
use BookStack\Activity\Models\Webhook;
use BookStack\Activity\Queries\WebhooksAllPaginatedAndSorted;
use BookStack\Http\Controller;
use BookStack\Util\SimpleListOptions;
use Illuminate\Http\Request;
class WebhookController extends Controller
{
public function __construct()
{
$this->middleware([
'can:settings-manage',
]);
}
/**
* Show all webhooks configured in the system.
*/
public function index(Request $request)
{
$listOptions = SimpleListOptions::fromRequest($request, 'webhooks')->withSortOptions([
'name' => trans('common.sort_name'),
'endpoint' => trans('settings.webhooks_endpoint'),
'created_at' => trans('common.sort_created_at'),
'updated_at' => trans('common.sort_updated_at'),
'active' => trans('common.status'),
]);
$webhooks = (new WebhooksAllPaginatedAndSorted())->run(20, $listOptions);
$webhooks->appends($listOptions->getPaginationAppends());
$this->setPageTitle(trans('settings.webhooks'));
return view('settings.webhooks.index', [
'webhooks' => $webhooks,
'listOptions' => $listOptions,
]);
}
/**
* Show the view for creating a new webhook in the system.
*/
public function create()
{
$this->setPageTitle(trans('settings.webhooks_create'));
return view('settings.webhooks.create');
}
/**
* Store a new webhook in the system.
*/
public function store(Request $request)
{
$validated = $this->validate($request, [
'name' => ['required', 'max:150'],
'endpoint' => ['required', 'url', 'max:500'],
'events' => ['required', 'array'],
'active' => ['required'],
'timeout' => ['required', 'integer', 'min:1', 'max:600'],
]);
$webhook = new Webhook($validated);
$webhook->active = $validated['active'] === 'true';
$webhook->save();
$webhook->updateTrackedEvents(array_values($validated['events']));
$this->logActivity(ActivityType::WEBHOOK_CREATE, $webhook);
return redirect('/settings/webhooks');
}
/**
* Show the view to edit an existing webhook.
*/
public function edit(string $id)
{
/** @var Webhook $webhook */
$webhook = Webhook::query()
->with('trackedEvents')
->findOrFail($id);
$this->setPageTitle(trans('settings.webhooks_edit'));
return view('settings.webhooks.edit', ['webhook' => $webhook]);
}
/**
* Update an existing webhook with the provided request data.
*/
public function update(Request $request, string $id)
{
$validated = $this->validate($request, [
'name' => ['required', 'max:150'],
'endpoint' => ['required', 'url', 'max:500'],
'events' => ['required', 'array'],
'active' => ['required'],
'timeout' => ['required', 'integer', 'min:1', 'max:600'],
]);
/** @var Webhook $webhook */
$webhook = Webhook::query()->findOrFail($id);
$webhook->active = $validated['active'] === 'true';
$webhook->fill($validated)->save();
$webhook->updateTrackedEvents($validated['events']);
$this->logActivity(ActivityType::WEBHOOK_UPDATE, $webhook);
return redirect('/settings/webhooks');
}
/**
* Show the view to delete a webhook.
*/
public function delete(string $id)
{
/** @var Webhook $webhook */
$webhook = Webhook::query()->findOrFail($id);
$this->setPageTitle(trans('settings.webhooks_delete'));
return view('settings.webhooks.delete', ['webhook' => $webhook]);
}
/**
* Destroy a webhook from the system.
*/
public function destroy(string $id)
{
/** @var Webhook $webhook */
$webhook = Webhook::query()->findOrFail($id);
$webhook->trackedEvents()->delete();
$webhook->delete();
$this->logActivity(ActivityType::WEBHOOK_DELETE, $webhook);
return redirect('/settings/webhooks');
}
}

View File

@@ -0,0 +1,81 @@
<?php
namespace BookStack\Activity;
use BookStack\Activity\Models\Loggable;
use BookStack\Activity\Models\Webhook;
use BookStack\Activity\Tools\WebhookFormatter;
use BookStack\Facades\Theme;
use BookStack\Theming\ThemeEvents;
use BookStack\Users\Models\User;
use BookStack\Util\SsrUrlValidator;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class DispatchWebhookJob implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
protected Webhook $webhook;
protected User $initiator;
protected int $initiatedTime;
protected array $webhookData;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct(Webhook $webhook, string $event, Loggable|string $detail)
{
$this->webhook = $webhook;
$this->initiator = user();
$this->initiatedTime = time();
$themeResponse = Theme::dispatch(ThemeEvents::WEBHOOK_CALL_BEFORE, $event, $this->webhook, $detail, $this->initiator, $this->initiatedTime);
$this->webhookData = $themeResponse ?? WebhookFormatter::getDefault($event, $this->webhook, $detail, $this->initiator, $this->initiatedTime)->format();
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$lastError = null;
try {
(new SsrUrlValidator())->ensureAllowed($this->webhook->endpoint);
$response = Http::asJson()
->withOptions(['allow_redirects' => ['strict' => true]])
->timeout($this->webhook->timeout)
->post($this->webhook->endpoint, $this->webhookData);
} catch (\Exception $exception) {
$lastError = $exception->getMessage();
Log::error("Webhook call to endpoint {$this->webhook->endpoint} failed with error \"{$lastError}\"");
}
if (isset($response) && $response->failed()) {
$lastError = "Response status from endpoint was {$response->status()}";
Log::error("Webhook call to endpoint {$this->webhook->endpoint} failed with status {$response->status()}");
}
$this->webhook->last_called_at = now();
if ($lastError) {
$this->webhook->last_errored_at = now();
$this->webhook->last_error = $lastError;
}
$this->webhook->save();
}
}

View File

@@ -1,11 +1,13 @@
<?php
namespace BookStack\Actions;
namespace BookStack\Activity\Models;
use BookStack\Auth\User;
use BookStack\App\Model;
use BookStack\Entities\Models\Entity;
use BookStack\Model;
use BookStack\Permissions\Models\JointPermission;
use BookStack\Users\Models\User;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Support\Str;
@@ -17,6 +19,8 @@ use Illuminate\Support\Str;
* @property string $entity_type
* @property int $entity_id
* @property int $user_id
* @property Carbon $created_at
* @property Carbon $updated_at
*/
class Activity extends Model
{
@@ -40,6 +44,12 @@ class Activity extends Model
return $this->belongsTo(User::class);
}
public function jointPermissions(): HasMany
{
return $this->hasMany(JointPermission::class, 'entity_id', 'entity_id')
->whereColumn('activities.entity_type', '=', 'joint_permissions.entity_type');
}
/**
* Returns text from the language files, Looks up by using the activity key.
*/

View File

@@ -1,10 +1,11 @@
<?php
namespace BookStack\Actions;
namespace BookStack\Activity\Models;
use BookStack\Model;
use BookStack\Traits\HasCreatorAndUpdater;
use BookStack\App\Model;
use BookStack\Users\Models\HasCreatorAndUpdater;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
/**
@@ -13,8 +14,10 @@ use Illuminate\Database\Eloquent\Relations\MorphTo;
* @property string $html
* @property int|null $parent_id
* @property int $local_id
* @property string $entity_type
* @property int $entity_id
*/
class Comment extends Model
class Comment extends Model implements Loggable
{
use HasFactory;
use HasCreatorAndUpdater;
@@ -30,6 +33,14 @@ class Comment extends Model
return $this->morphTo('entity');
}
/**
* Get the parent comment this is in reply to (if existing).
*/
public function parent(): BelongsTo
{
return $this->belongsTo(Comment::class);
}
/**
* Check if a comment has been updated since creation.
*/
@@ -40,21 +51,22 @@ class Comment extends Model
/**
* Get created date as a relative diff.
*
* @return mixed
*/
public function getCreatedAttribute()
public function getCreatedAttribute(): string
{
return $this->created_at->diffForHumans();
}
/**
* Get updated date as a relative diff.
*
* @return mixed
*/
public function getUpdatedAttribute()
public function getUpdatedAttribute(): string
{
return $this->updated_at->diffForHumans();
}
public function logDescriptor(): string
{
return "Comment #{$this->local_id} (ID: {$this->id}) for {$this->entity_type} (ID: {$this->entity_id})";
}
}

View File

@@ -1,6 +1,6 @@
<?php
namespace BookStack\Interfaces;
namespace BookStack\Activity\Models;
use Illuminate\Database\Eloquent\Relations\MorphMany;

View File

@@ -0,0 +1,27 @@
<?php
namespace BookStack\Activity\Models;
use BookStack\App\Model;
use BookStack\Permissions\Models\JointPermission;
use Illuminate\Database\Eloquent\Relations\HasMany;
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();
}
public function jointPermissions(): HasMany
{
return $this->hasMany(JointPermission::class, 'entity_id', 'favouritable_id')
->whereColumn('favourites.favouritable_type', '=', 'joint_permissions.entity_type');
}
}

View File

@@ -1,6 +1,6 @@
<?php
namespace BookStack\Interfaces;
namespace BookStack\Activity\Models;
interface Loggable
{

View File

@@ -1,9 +1,11 @@
<?php
namespace BookStack\Actions;
namespace BookStack\Activity\Models;
use BookStack\Model;
use BookStack\App\Model;
use BookStack\Permissions\Models\JointPermission;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
/**
@@ -27,6 +29,12 @@ class Tag extends Model
return $this->morphTo('entity');
}
public function jointPermissions(): HasMany
{
return $this->hasMany(JointPermission::class, 'entity_id', 'entity_id')
->whereColumn('tags.entity_type', '=', 'joint_permissions.entity_type');
}
/**
* Get a full URL to start a tag name search for this tag name.
*/

View File

@@ -1,9 +1,10 @@
<?php
namespace BookStack\Actions;
namespace BookStack\Activity\Models;
use BookStack\Interfaces\Viewable;
use BookStack\Model;
use BookStack\App\Model;
use BookStack\Permissions\Models\JointPermission;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
/**
@@ -28,6 +29,12 @@ class View extends Model
return $this->morphTo();
}
public function jointPermissions(): HasMany
{
return $this->hasMany(JointPermission::class, 'entity_id', 'viewable_id')
->whereColumn('views.viewable_type', '=', 'joint_permissions.entity_type');
}
/**
* Increment the current user's view count for the given viewable model.
*/
@@ -47,12 +54,4 @@ class View extends Model
return $view->views;
}
/**
* Clear all views from the system.
*/
public static function clearAll()
{
static::query()->truncate();
}
}

View File

@@ -1,6 +1,6 @@
<?php
namespace BookStack\Interfaces;
namespace BookStack\Activity\Models;
use Illuminate\Database\Eloquent\Relations\MorphMany;

View File

@@ -0,0 +1,45 @@
<?php
namespace BookStack\Activity\Models;
use BookStack\Activity\WatchLevels;
use BookStack\Permissions\Models\JointPermission;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
/**
* @property int $id
* @property int $user_id
* @property int $watchable_id
* @property string $watchable_type
* @property int $level
* @property Carbon $created_at
* @property Carbon $updated_at
*/
class Watch extends Model
{
protected $guarded = [];
public function watchable(): MorphTo
{
return $this->morphTo();
}
public function jointPermissions(): HasMany
{
return $this->hasMany(JointPermission::class, 'entity_id', 'watchable_id')
->whereColumn('watches.watchable_type', '=', 'joint_permissions.entity_type');
}
public function getLevelName(): string
{
return WatchLevels::levelValueToName($this->level);
}
public function ignoring(): bool
{
return $this->level === WatchLevels::IGNORE;
}
}

View File

@@ -0,0 +1,85 @@
<?php
namespace BookStack\Activity\Models;
use BookStack\Activity\ActivityType;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
/**
* @property int $id
* @property string $name
* @property string $endpoint
* @property Collection $trackedEvents
* @property bool $active
* @property int $timeout
* @property string $last_error
* @property Carbon $last_called_at
* @property Carbon $last_errored_at
*/
class Webhook extends Model implements Loggable
{
use HasFactory;
protected $fillable = ['name', 'endpoint', 'timeout'];
protected $casts = [
'last_called_at' => 'datetime',
'last_errored_at' => 'datetime',
];
/**
* Define the tracked event relation a webhook.
*/
public function trackedEvents(): HasMany
{
return $this->hasMany(WebhookTrackedEvent::class);
}
/**
* Update the tracked events for a webhook from the given list of event types.
*/
public function updateTrackedEvents(array $events): void
{
$this->trackedEvents()->delete();
$eventsToStore = array_intersect($events, array_values(ActivityType::all()));
if (in_array('all', $events)) {
$eventsToStore = ['all'];
}
$trackedEvents = [];
foreach ($eventsToStore as $event) {
$trackedEvents[] = new WebhookTrackedEvent(['event' => $event]);
}
$this->trackedEvents()->saveMany($trackedEvents);
}
/**
* Check if this webhook tracks the given event.
*/
public function tracksEvent(string $event): bool
{
return $this->trackedEvents->pluck('event')->contains($event);
}
/**
* Get a URL for this webhook within the settings interface.
*/
public function getUrl(string $path = ''): string
{
return url('/settings/webhooks/' . $this->id . '/' . ltrim($path, '/'));
}
/**
* Get the string descriptor for this item.
*/
public function logDescriptor(): string
{
return "({$this->id}) {$this->name}";
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace BookStack\Activity\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
/**
* @property int $id
* @property int $webhook_id
* @property string $event
*/
class WebhookTrackedEvent extends Model
{
use HasFactory;
protected $fillable = ['event'];
}

View File

@@ -0,0 +1,42 @@
<?php
namespace BookStack\Activity\Notifications\Handlers;
use BookStack\Activity\Models\Loggable;
use BookStack\Activity\Notifications\Messages\BaseActivityNotification;
use BookStack\Entities\Models\Entity;
use BookStack\Permissions\PermissionApplicator;
use BookStack\Users\Models\User;
abstract class BaseNotificationHandler implements NotificationHandler
{
/**
* @param class-string<BaseActivityNotification> $notification
* @param int[] $userIds
*/
protected function sendNotificationToUserIds(string $notification, array $userIds, User $initiator, string|Loggable $detail, Entity $relatedModel): void
{
$users = User::query()->whereIn('id', array_unique($userIds))->get();
foreach ($users as $user) {
// Prevent sending to the user that initiated the activity
if ($user->id === $initiator->id) {
continue;
}
// Prevent sending of the user does not have notification permissions
if (!$user->can('receive-notifications')) {
continue;
}
// Prevent sending if the user does not have access to the related content
$permissions = new PermissionApplicator($user);
if (!$permissions->checkOwnableUserAccess($relatedModel, 'view')) {
continue;
}
// Send the notification
$user->notify(new $notification($detail, $initiator));
}
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace BookStack\Activity\Notifications\Handlers;
use BookStack\Activity\Models\Activity;
use BookStack\Activity\Models\Comment;
use BookStack\Activity\Models\Loggable;
use BookStack\Activity\Notifications\Messages\CommentCreationNotification;
use BookStack\Activity\Tools\EntityWatchers;
use BookStack\Activity\WatchLevels;
use BookStack\Entities\Models\Page;
use BookStack\Settings\UserNotificationPreferences;
use BookStack\Users\Models\User;
class CommentCreationNotificationHandler extends BaseNotificationHandler
{
public function handle(Activity $activity, Loggable|string $detail, User $user): void
{
if (!($detail instanceof Comment)) {
throw new \InvalidArgumentException("Detail for comment creation notifications must be a comment");
}
// Main watchers
/** @var Page $page */
$page = $detail->entity;
$watchers = new EntityWatchers($page, WatchLevels::COMMENTS);
$watcherIds = $watchers->getWatcherUserIds();
// Page owner if user preferences allow
if (!$watchers->isUserIgnoring($page->owned_by) && $page->ownedBy) {
$userNotificationPrefs = new UserNotificationPreferences($page->ownedBy);
if ($userNotificationPrefs->notifyOnOwnPageComments()) {
$watcherIds[] = $page->owned_by;
}
}
// Parent comment creator if preferences allow
$parentComment = $detail->parent()->first();
if ($parentComment && !$watchers->isUserIgnoring($parentComment->created_by) && $parentComment->createdBy) {
$parentCommenterNotificationsPrefs = new UserNotificationPreferences($parentComment->createdBy);
if ($parentCommenterNotificationsPrefs->notifyOnCommentReplies()) {
$watcherIds[] = $parentComment->created_by;
}
}
$this->sendNotificationToUserIds(CommentCreationNotification::class, $watcherIds, $user, $detail, $page);
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace BookStack\Activity\Notifications\Handlers;
use BookStack\Activity\Models\Activity;
use BookStack\Activity\Models\Loggable;
use BookStack\Users\Models\User;
interface NotificationHandler
{
/**
* Run this handler.
* Provides the activity, related activity detail/model
* along with the user that triggered the activity.
*/
public function handle(Activity $activity, string|Loggable $detail, User $user): void;
}

View File

@@ -0,0 +1,24 @@
<?php
namespace BookStack\Activity\Notifications\Handlers;
use BookStack\Activity\Models\Activity;
use BookStack\Activity\Models\Loggable;
use BookStack\Activity\Notifications\Messages\PageCreationNotification;
use BookStack\Activity\Tools\EntityWatchers;
use BookStack\Activity\WatchLevels;
use BookStack\Entities\Models\Page;
use BookStack\Users\Models\User;
class PageCreationNotificationHandler extends BaseNotificationHandler
{
public function handle(Activity $activity, Loggable|string $detail, User $user): void
{
if (!($detail instanceof Page)) {
throw new \InvalidArgumentException("Detail for page create notifications must be a page");
}
$watchers = new EntityWatchers($detail, WatchLevels::NEW);
$this->sendNotificationToUserIds(PageCreationNotification::class, $watchers->getWatcherUserIds(), $user, $detail, $detail);
}
}

View File

@@ -0,0 +1,51 @@
<?php
namespace BookStack\Activity\Notifications\Handlers;
use BookStack\Activity\ActivityType;
use BookStack\Activity\Models\Activity;
use BookStack\Activity\Models\Loggable;
use BookStack\Activity\Notifications\Messages\PageUpdateNotification;
use BookStack\Activity\Tools\EntityWatchers;
use BookStack\Activity\WatchLevels;
use BookStack\Entities\Models\Page;
use BookStack\Settings\UserNotificationPreferences;
use BookStack\Users\Models\User;
class PageUpdateNotificationHandler extends BaseNotificationHandler
{
public function handle(Activity $activity, Loggable|string $detail, User $user): void
{
if (!($detail instanceof Page)) {
throw new \InvalidArgumentException("Detail for page update notifications must be a page");
}
// Get last update from activity
$lastUpdate = $detail->activity()
->where('type', '=', ActivityType::PAGE_UPDATE)
->where('id', '!=', $activity->id)
->latest('created_at')
->first();
// Return if the same user has already updated the page in the last 15 mins
if ($lastUpdate && $lastUpdate->user_id === $user->id) {
if ($lastUpdate->created_at->gt(now()->subMinutes(15))) {
return;
}
}
// Get active watchers
$watchers = new EntityWatchers($detail, WatchLevels::UPDATES);
$watcherIds = $watchers->getWatcherUserIds();
// Add page owner if preferences allow
if (!$watchers->isUserIgnoring($detail->owned_by) && $detail->ownedBy) {
$userNotificationPrefs = new UserNotificationPreferences($detail->ownedBy);
if ($userNotificationPrefs->notifyOnOwnPageChanges()) {
$watcherIds[] = $detail->owned_by;
}
}
$this->sendNotificationToUserIds(PageUpdateNotification::class, $watcherIds, $user, $detail, $detail);
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace BookStack\Activity\Notifications\MessageParts;
use Illuminate\Contracts\Support\Htmlable;
/**
* A line of text with linked text included, intended for use
* in MailMessages. The line should have a ':link' placeholder for
* where the link should be inserted within the line.
*/
class LinkedMailMessageLine implements Htmlable
{
public function __construct(
protected string $url,
protected string $line,
protected string $linkText,
) {
}
public function toHtml(): string
{
$link = '<a href="' . e($this->url) . '">' . e($this->linkText) . '</a>';
return str_replace(':link', $link, e($this->line));
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace BookStack\Activity\Notifications\MessageParts;
use Illuminate\Contracts\Support\Htmlable;
/**
* A bullet point list of content, where the keys of the given list array
* are bolded header elements, and the values follow.
*/
class ListMessageLine implements Htmlable
{
public function __construct(
protected array $list
) {
}
public function toHtml(): string
{
$list = [];
foreach ($this->list as $header => $content) {
$list[] = '<strong>' . e($header) . '</strong> ' . e($content);
}
return implode("<br>\n", $list);
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace BookStack\Activity\Notifications\Messages;
use BookStack\Activity\Models\Loggable;
use BookStack\Activity\Notifications\MessageParts\LinkedMailMessageLine;
use BookStack\Users\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
abstract class BaseActivityNotification extends Notification
{
use Queueable;
public function __construct(
protected Loggable|string $detail,
protected User $user,
) {
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*/
abstract public function toMail(mixed $notifiable): MailMessage;
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
'activity_detail' => $this->detail,
'activity_creator' => $this->user,
];
}
/**
* Build the common reason footer line used in mail messages.
*/
protected function buildReasonFooterLine(): LinkedMailMessageLine
{
return new LinkedMailMessageLine(
url('/preferences/notifications'),
trans('notifications.footer_reason'),
trans('notifications.footer_reason_link'),
);
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace BookStack\Activity\Notifications\Messages;
use BookStack\Activity\Models\Comment;
use BookStack\Activity\Notifications\MessageParts\ListMessageLine;
use BookStack\Entities\Models\Page;
use Illuminate\Notifications\Messages\MailMessage;
class CommentCreationNotification extends BaseActivityNotification
{
public function toMail(mixed $notifiable): MailMessage
{
/** @var Comment $comment */
$comment = $this->detail;
/** @var Page $page */
$page = $comment->entity;
return (new MailMessage())
->subject(trans('notifications.new_comment_subject', ['pageName' => $page->getShortName()]))
->line(trans('notifications.new_comment_intro', ['appName' => setting('app-name')]))
->line(new ListMessageLine([
trans('notifications.detail_page_name') => $page->name,
trans('notifications.detail_commenter') => $this->user->name,
trans('notifications.detail_comment') => strip_tags($comment->html),
]))
->action(trans('notifications.action_view_comment'), $page->getUrl('#comment' . $comment->local_id))
->line($this->buildReasonFooterLine());
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace BookStack\Activity\Notifications\Messages;
use BookStack\Activity\Notifications\MessageParts\ListMessageLine;
use BookStack\Entities\Models\Page;
use Illuminate\Notifications\Messages\MailMessage;
class PageCreationNotification extends BaseActivityNotification
{
public function toMail(mixed $notifiable): MailMessage
{
/** @var Page $page */
$page = $this->detail;
return (new MailMessage())
->subject(trans('notifications.new_page_subject', ['pageName' => $page->getShortName()]))
->line(trans('notifications.new_page_intro', ['appName' => setting('app-name')]))
->line(new ListMessageLine([
trans('notifications.detail_page_name') => $page->name,
trans('notifications.detail_created_by') => $this->user->name,
]))
->action(trans('notifications.action_view_page'), $page->getUrl())
->line($this->buildReasonFooterLine());
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace BookStack\Activity\Notifications\Messages;
use BookStack\Activity\Notifications\MessageParts\ListMessageLine;
use BookStack\Entities\Models\Page;
use Illuminate\Notifications\Messages\MailMessage;
class PageUpdateNotification extends BaseActivityNotification
{
public function toMail(mixed $notifiable): MailMessage
{
/** @var Page $page */
$page = $this->detail;
return (new MailMessage())
->subject(trans('notifications.updated_page_subject', ['pageName' => $page->getShortName()]))
->line(trans('notifications.updated_page_intro', ['appName' => setting('app-name')]))
->line(new ListMessageLine([
trans('notifications.detail_page_name') => $page->name,
trans('notifications.detail_updated_by') => $this->user->name,
]))
->line(trans('notifications.updated_page_debounce'))
->action(trans('notifications.action_view_page'), $page->getUrl())
->line($this->buildReasonFooterLine());
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace BookStack\Activity\Notifications;
use BookStack\Activity\ActivityType;
use BookStack\Activity\Models\Activity;
use BookStack\Activity\Models\Loggable;
use BookStack\Activity\Notifications\Handlers\CommentCreationNotificationHandler;
use BookStack\Activity\Notifications\Handlers\NotificationHandler;
use BookStack\Activity\Notifications\Handlers\PageCreationNotificationHandler;
use BookStack\Activity\Notifications\Handlers\PageUpdateNotificationHandler;
use BookStack\Users\Models\User;
class NotificationManager
{
/**
* @var class-string<NotificationHandler>[]
*/
protected array $handlers = [];
public function handle(Activity $activity, string|Loggable $detail, User $user): void
{
$activityType = $activity->type;
$handlersToRun = $this->handlers[$activityType] ?? [];
foreach ($handlersToRun as $handlerClass) {
/** @var NotificationHandler $handler */
$handler = new $handlerClass();
$handler->handle($activity, $detail, $user);
}
}
/**
* @param class-string<NotificationHandler> $handlerClass
*/
public function registerHandler(string $activityType, string $handlerClass): void
{
if (!isset($this->handlers[$activityType])) {
$this->handlers[$activityType] = [];
}
if (!in_array($handlerClass, $this->handlers[$activityType])) {
$this->handlers[$activityType][] = $handlerClass;
}
}
public function loadDefaultHandlers(): void
{
$this->registerHandler(ActivityType::PAGE_CREATE, PageCreationNotificationHandler::class);
$this->registerHandler(ActivityType::PAGE_UPDATE, PageUpdateNotificationHandler::class);
$this->registerHandler(ActivityType::COMMENT_CREATE, CommentCreationNotificationHandler::class);
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace BookStack\Activity\Queries;
use BookStack\Activity\Models\Webhook;
use BookStack\Util\SimpleListOptions;
use Illuminate\Pagination\LengthAwarePaginator;
/**
* Get all the webhooks in the system in a paginated format.
*/
class WebhooksAllPaginatedAndSorted
{
public function run(int $count, SimpleListOptions $listOptions): LengthAwarePaginator
{
$query = Webhook::query()->select(['*'])
->withCount(['trackedEvents'])
->orderBy($listOptions->getSort(), $listOptions->getOrder());
if ($listOptions->getSearch()) {
$term = '%' . $listOptions->getSearch() . '%';
$query->where(function ($query) use ($term) {
$query->where('name', 'like', $term)
->orWhere('endpoint', 'like', $term);
});
}
return $query->paginate($count);
}
}

View File

@@ -1,39 +1,44 @@
<?php
namespace BookStack\Actions;
namespace BookStack\Activity;
use BookStack\Auth\Permissions\PermissionService;
use BookStack\Activity\Models\Tag;
use BookStack\Entities\Models\Entity;
use BookStack\Permissions\PermissionApplicator;
use BookStack\Util\SimpleListOptions;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
class TagRepo
{
protected $tag;
protected $permissionService;
public function __construct(PermissionService $ps)
{
$this->permissionService = $ps;
public function __construct(
protected PermissionApplicator $permissions
) {
}
/**
* Start a query against all tags in the system.
*/
public function queryWithTotals(string $searchTerm, string $nameFilter): Builder
public function queryWithTotals(SimpleListOptions $listOptions, string $nameFilter): Builder
{
$searchTerm = $listOptions->getSearch();
$sort = $listOptions->getSort();
if ($sort === 'name' && $nameFilter) {
$sort = 'value';
}
$query = Tag::query()
->select([
'name',
($searchTerm || $nameFilter) ? 'value' : DB::raw('COUNT(distinct value) as `values`'),
DB::raw('COUNT(id) as usages'),
DB::raw('SUM(IF(entity_type = \'BookStack\\\\Page\', 1, 0)) as page_count'),
DB::raw('SUM(IF(entity_type = \'BookStack\\\\Chapter\', 1, 0)) as chapter_count'),
DB::raw('SUM(IF(entity_type = \'BookStack\\\\Book\', 1, 0)) as book_count'),
DB::raw('SUM(IF(entity_type = \'BookStack\\\\BookShelf\', 1, 0)) as shelf_count'),
DB::raw('SUM(IF(entity_type = \'page\', 1, 0)) as page_count'),
DB::raw('SUM(IF(entity_type = \'chapter\', 1, 0)) as chapter_count'),
DB::raw('SUM(IF(entity_type = \'book\', 1, 0)) as book_count'),
DB::raw('SUM(IF(entity_type = \'bookshelf\', 1, 0)) as shelf_count'),
])
->orderBy($nameFilter ? 'value' : 'name');
->orderBy($sort, $listOptions->getOrder());
if ($nameFilter) {
$query->where('name', '=', $nameFilter);
@@ -51,28 +56,28 @@ class TagRepo
});
}
return $this->permissionService->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type');
return $this->permissions->restrictEntityRelationQuery($query, 'tags', 'entity_id', 'entity_type');
}
/**
* 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
public function getNameSuggestions(string $searchTerm): Collection
{
$query = Tag::query()
->select('*', DB::raw('count(*) as count'))
->groupBy('name');
if ($searchTerm) {
$query = $query->where('name', 'LIKE', $searchTerm . '%')->orderBy('name', 'desc');
$query = $query->where('name', 'LIKE', $searchTerm . '%')->orderBy('name', 'asc');
} else {
$query = $query->orderBy('count', 'desc')->take(50);
}
$query = $this->permissionService->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type');
$query = $this->permissions->restrictEntityRelationQuery($query, 'tags', 'entity_id', 'entity_type');
return $query->get(['name'])->pluck('name');
return $query->pluck('name');
}
/**
@@ -80,10 +85,11 @@ class TagRepo
* 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
public function getValueSuggestions(string $searchTerm, string $tagName): Collection
{
$query = Tag::query()
->select('*', DB::raw('count(*) as count'))
->where('value', '!=', '')
->groupBy('value');
if ($searchTerm) {
@@ -96,9 +102,9 @@ class TagRepo
$query = $query->where('name', '=', $tagName);
}
$query = $this->permissionService->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type');
$query = $this->permissions->restrictEntityRelationQuery($query, 'tags', 'entity_id', 'entity_type');
return $query->get(['value'])->pluck('value');
return $query->pluck('value');
}
/**

View File

@@ -0,0 +1,115 @@
<?php
namespace BookStack\Activity\Tools;
use BookStack\Activity\DispatchWebhookJob;
use BookStack\Activity\Models\Activity;
use BookStack\Activity\Models\Loggable;
use BookStack\Activity\Models\Webhook;
use BookStack\Activity\Notifications\NotificationManager;
use BookStack\Entities\Models\Entity;
use BookStack\Facades\Theme;
use BookStack\Theming\ThemeEvents;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Log;
class ActivityLogger
{
public function __construct(
protected NotificationManager $notifications
) {
$this->notifications->loadDefaultHandlers();
}
/**
* Add a generic activity event to the database.
*/
public function add(string $type, string|Loggable $detail = ''): void
{
$detailToStore = ($detail instanceof Loggable) ? $detail->logDescriptor() : $detail;
$activity = $this->newActivityForUser($type);
$activity->detail = $detailToStore;
if ($detail instanceof Entity) {
$activity->entity_id = $detail->id;
$activity->entity_type = $detail->getMorphClass();
}
$activity->save();
$this->setNotification($type);
$this->dispatchWebhooks($type, $detail);
$this->notifications->handle($activity, $detail, user());
Theme::dispatch(ThemeEvents::ACTIVITY_LOGGED, $type, $detail);
}
/**
* Get a new activity instance for the current user.
*/
protected function newActivityForUser(string $type): Activity
{
return (new Activity())->forceFill([
'type' => strtolower($type),
'user_id' => user()->id,
'ip' => IpFormatter::fromCurrentRequest()->format(),
]);
}
/**
* 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): void
{
$entity->activity()->update([
'detail' => $entity->name,
'entity_id' => null,
'entity_type' => null,
]);
}
/**
* Flashes a notification message to the session if an appropriate message is available.
*/
protected function setNotification(string $type): void
{
$notificationTextKey = 'activities.' . $type . '_notification';
if (trans()->has($notificationTextKey)) {
$message = trans($notificationTextKey);
session()->flash('success', $message);
}
}
protected function dispatchWebhooks(string $type, string|Loggable $detail): void
{
$webhooks = Webhook::query()
->whereHas('trackedEvents', function (Builder $query) use ($type) {
$query->where('event', '=', $type)
->orWhere('event', '=', 'all');
})
->where('active', '=', true)
->get();
foreach ($webhooks as $webhook) {
dispatch(new DispatchWebhookJob($webhook, $type, $detail));
}
}
/**
* 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): void
{
$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);
}
}

Some files were not shown because too many files have changed in this diff Show More